Compare commits

..

No commits in common. "dc24b3c48a5f357d4ccb65f4ad2aed8909aeeffa" and "63c84d94798eb0dec9b5ab27a015c0c91feabcf6" have entirely different histories.

25 changed files with 364 additions and 450 deletions

View File

@ -52,9 +52,5 @@ log = {
pidfile = "/tmp/prosody.pid" pidfile = "/tmp/prosody.pid"
component_ports = { 8888 }
component_interfaces = { '127.0.0.1' }
VirtualHost "localhost" VirtualHost "localhost"
Component "component.localhost"
component_secret = "abc123"

View File

@ -1,46 +0,0 @@
import 'package:logging/logging.dart';
import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp_socket_tcp/moxxmpp_socket_tcp.dart';
import 'package:test/test.dart';
class TestingTCPSocketWrapper extends TCPSocketWrapper {
@override
bool onBadCertificate(dynamic certificate, String domain) {
return true;
}
}
void main() {
Logger.root.level = Level.ALL;
Logger.root.onRecord.listen((record) {
// ignore: avoid_print
print(
'[${record.level.name}] (${record.loggerName}) ${record.time}: ${record.message}',
);
});
test('Test connecting to prosody as a component', () async {
final conn = XmppConnection(
TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(),
ComponentToServerNegotiator(),
TestingTCPSocketWrapper(),
)..connectionSettings = ConnectionSettings(
jid: JID.fromString('component.localhost'),
password: 'abc123',
host: '127.0.0.1',
port: 8888,
);
await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])),
DiscoManager([]),
]);
final result = await conn.connect(
waitUntilLogin: true,
shouldReconnect: false,
enableReconnectOnSuccess: false,
);
expect(result.isType<bool>(), true);
});
}

View File

@ -19,18 +19,20 @@ void main() {
); );
}); });
test('Test authenticating against Prosody with SASL2, Bind2, and FAST', test('Test authenticating against Prosody with SASL2, Bind2, and FAST', () async {
() async {
final conn = XmppConnection( final conn = XmppConnection(
TestingReconnectionPolicy(), TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(), AlwaysConnectedConnectivityManager(),
ClientToServerNegotiator(),
TestingTCPSocketWrapper(), TestingTCPSocketWrapper(),
)..connectionSettings = ConnectionSettings( )..setConnectionSettings(
jid: JID.fromString('testuser@localhost'), ConnectionSettings(
password: 'abc123', jid: JID.fromString('testuser@localhost'),
host: '127.0.0.1', password: 'abc123',
port: 5222, useDirectTLS: false,
host: '127.0.0.1',
port: 5222,
),
); );
final csi = CSIManager(); final csi = CSIManager();
await csi.setInactive(sendNonza: false); await csi.setInactive(sendNonza: false);
@ -59,16 +61,7 @@ void main() {
enableReconnectOnSuccess: false, enableReconnectOnSuccess: false,
); );
expect(result.isType<bool>(), true); expect(result.isType<bool>(), true);
expect( expect(conn.getNegotiatorById<Sasl2Negotiator>(sasl2Negotiator)!.state, NegotiatorState.done);
conn.getNegotiatorById<Sasl2Negotiator>(sasl2Negotiator)!.state, expect(conn.getNegotiatorById<FASTSaslNegotiator>(saslFASTNegotiator)!.fastToken != null, true,);
NegotiatorState.done,
);
expect(
conn
.getNegotiatorById<FASTSaslNegotiator>(saslFASTNegotiator)!
.fastToken !=
null,
true,
);
}); });
} }

View File

@ -7,8 +7,6 @@
- **BREAKING**: Removed `isFeatureSupported` from the manager attributes. The managers now all have a method `isFeatureSupported` that works the same - **BREAKING**: Removed `isFeatureSupported` from the manager attributes. The managers now all have a method `isFeatureSupported` that works the same
- The `PresenceManager` is now optional - The `PresenceManager` is now optional
- **BREAKING**: Removed `setConnectionSettings` and `getConnectionSettings`. Just directly acces the `connectionSettings` field. - **BREAKING**: Removed `setConnectionSettings` and `getConnectionSettings`. Just directly acces the `connectionSettings` field.
- Implement XEP-0144 for implementing components
- **BREAKING**: Remove `useDirectTLS` from `ConnectionSettings`
## 0.1.6+1 ## 0.1.6+1

View File

@ -5,9 +5,6 @@ export 'package:moxxmpp/src/connection_errors.dart';
export 'package:moxxmpp/src/connectivity.dart'; export 'package:moxxmpp/src/connectivity.dart';
export 'package:moxxmpp/src/errors.dart'; export 'package:moxxmpp/src/errors.dart';
export 'package:moxxmpp/src/events.dart'; export 'package:moxxmpp/src/events.dart';
export 'package:moxxmpp/src/handlers/base.dart';
export 'package:moxxmpp/src/handlers/client.dart';
export 'package:moxxmpp/src/handlers/component.dart';
export 'package:moxxmpp/src/iq.dart'; export 'package:moxxmpp/src/iq.dart';
export 'package:moxxmpp/src/jid.dart'; export 'package:moxxmpp/src/jid.dart';
export 'package:moxxmpp/src/managers/attributes.dart'; export 'package:moxxmpp/src/managers/attributes.dart';
@ -18,6 +15,7 @@ export 'package:moxxmpp/src/managers/namespaces.dart';
export 'package:moxxmpp/src/managers/priorities.dart'; export 'package:moxxmpp/src/managers/priorities.dart';
export 'package:moxxmpp/src/message.dart'; export 'package:moxxmpp/src/message.dart';
export 'package:moxxmpp/src/namespaces.dart'; export 'package:moxxmpp/src/namespaces.dart';
export 'package:moxxmpp/src/negotiators/handler.dart';
export 'package:moxxmpp/src/negotiators/manager.dart'; export 'package:moxxmpp/src/negotiators/manager.dart';
export 'package:moxxmpp/src/negotiators/namespaces.dart'; export 'package:moxxmpp/src/negotiators/namespaces.dart';
export 'package:moxxmpp/src/negotiators/negotiator.dart'; export 'package:moxxmpp/src/negotiators/negotiator.dart';

View File

@ -8,13 +8,15 @@ import 'package:moxxmpp/src/connection_errors.dart';
import 'package:moxxmpp/src/connectivity.dart'; import 'package:moxxmpp/src/connectivity.dart';
import 'package:moxxmpp/src/errors.dart'; import 'package:moxxmpp/src/errors.dart';
import 'package:moxxmpp/src/events.dart'; import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/handlers/base.dart';
import 'package:moxxmpp/src/iq.dart'; import 'package:moxxmpp/src/iq.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/attributes.dart'; import 'package:moxxmpp/src/managers/attributes.dart';
import 'package:moxxmpp/src/managers/base.dart'; import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/managers/data.dart'; import 'package:moxxmpp/src/managers/data.dart';
import 'package:moxxmpp/src/managers/handlers.dart'; import 'package:moxxmpp/src/managers/handlers.dart';
import 'package:moxxmpp/src/managers/namespaces.dart'; import 'package:moxxmpp/src/managers/namespaces.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/handler.dart';
import 'package:moxxmpp/src/negotiators/namespaces.dart'; import 'package:moxxmpp/src/negotiators/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart'; import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/presence.dart'; import 'package:moxxmpp/src/presence.dart';
@ -61,6 +63,23 @@ enum StanzaFromType {
none, none,
} }
/// Nonza describing the XMPP stream header.
class StreamHeaderNonza extends XMLNode {
StreamHeaderNonza(JID jid)
: super(
tag: 'stream:stream',
attributes: <String, String>{
'xmlns': stanzaXmlns,
'version': '1.0',
'xmlns:stream': streamXmlns,
'to': jid.domain,
'from': jid.toBare().toString(),
'xml:lang': 'en',
},
closeTag: false,
);
}
/// This class is a connection to the server. /// This class is a connection to the server.
class XmppConnection { class XmppConnection {
XmppConnection( XmppConnection(
@ -80,9 +99,8 @@ class XmppConnection {
_negotiationsHandler.register( _negotiationsHandler.register(
_onNegotiationsDone, _onNegotiationsDone,
handleError, handleError,
_sendStreamHeaders,
() => _isAuthenticated, () => _isAuthenticated,
sendRawXML,
() => connectionSettings,
); );
_socketStream = _socket.getDataStream(); _socketStream = _socket.getDataStream();
@ -750,7 +768,7 @@ class XmppConnection {
/// Called whenever we receive data that has been parsed as XML. /// Called whenever we receive data that has been parsed as XML.
Future<void> handleXmlStream(XmlStreamBufferObject event) async { Future<void> handleXmlStream(XmlStreamBufferObject event) async {
if (event is XmlStreamBufferHeader) { if (event is XmlStreamBufferHeader) {
await _negotiationsHandler.negotiate(event); _negotiationsHandler.setStreamHeaderId(event.attributes['id']);
return; return;
} }
@ -781,11 +799,11 @@ class XmppConnection {
// prevent this issue. // prevent this issue.
await _negotiationLock.synchronized(() async { await _negotiationLock.synchronized(() async {
if (_routingState != RoutingState.negotiating) { if (_routingState != RoutingState.negotiating) {
unawaited(handleXmlStream(event)); unawaited(handleXmlStream(XmlStreamBufferElement(node)));
return; return;
} }
await _negotiationsHandler.negotiate(event); await _negotiationsHandler.negotiate(node);
}); });
break; break;
case RoutingState.handleStanzas: case RoutingState.handleStanzas:
@ -815,6 +833,21 @@ class XmppConnection {
_eventStreamController.add(event); _eventStreamController.add(event);
} }
/// Sends a stream header to the socket.
void _sendStreamHeaders() {
_socket.write(
XMLNode(
tag: 'xml',
attributes: {'version': '1.0'},
closeTag: false,
isDeclaration: true,
children: [
StreamHeaderNonza(connectionSettings.jid),
],
).toXml(),
);
}
/// Attempt to gracefully close the session /// Attempt to gracefully close the session
Future<void> disconnect() async { Future<void> disconnect() async {
await _disconnect(state: XmppConnectionState.notConnected); await _disconnect(state: XmppConnectionState.notConnected);
@ -922,7 +955,7 @@ class XmppConnection {
await _setConnectionState(XmppConnectionState.connecting); await _setConnectionState(XmppConnectionState.connecting);
_updateRoutingState(RoutingState.negotiating); _updateRoutingState(RoutingState.negotiating);
_isAuthenticated = false; _isAuthenticated = false;
_negotiationsHandler.sendStreamHeader(); _sendStreamHeaders();
if (waitUntilLogin) { if (waitUntilLogin) {
return _connectionCompleter!.future; return _connectionCompleter!.future;

View File

@ -46,15 +46,3 @@ class NoAuthenticatorAvailableError extends XmppConnectionError {
@override @override
bool isRecoverable() => false; bool isRecoverable() => false;
} }
/// Returned by the negotiation handler if unexpected data has been received
class UnexpectedDataError extends XmppConnectionError {
@override
bool isRecoverable() => false;
}
/// Returned by the ComponentToServerNegotiator if the handshake is not successful.
class InvalidHandshakeCredentialsError extends XmppConnectionError {
@override
bool isRecoverable() => false;
}

View File

@ -1,121 +0,0 @@
import 'package:logging/logging.dart';
import 'package:meta/meta.dart';
import 'package:moxxmpp/src/buffer.dart';
import 'package:moxxmpp/src/errors.dart';
import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/settings.dart';
import 'package:moxxmpp/src/stringxml.dart';
/// A callback for when the [NegotiationsHandler] is done.
typedef NegotiationsDoneCallback = Future<void> Function();
/// A callback for the case that an error occurs while negotiating.
typedef ErrorCallback = Future<void> Function(XmppError);
/// Return true if the current connection is authenticated. If not, return false.
typedef IsAuthenticatedFunction = bool Function();
/// Send a nonza on the stream
typedef SendNonzaFunction = void Function(XMLNode);
/// Returns the connection settings.
typedef GetConnectionSettingsFunction = ConnectionSettings Function();
/// This class implements the stream feature negotiation for XmppConnection.
abstract class NegotiationsHandler {
@protected
late final Logger log;
/// Map of all negotiators registered against the handler.
@protected
final Map<String, XmppFeatureNegotiatorBase> negotiators = {};
/// Function that is called once the negotiator is done with its stream negotiations.
@protected
late final NegotiationsDoneCallback onNegotiationsDone;
/// XmppConnection's handleError method.
@protected
late final ErrorCallback handleError;
/// Returns true if the connection is authenticated. If not, returns false.
@protected
late final IsAuthenticatedFunction isAuthenticated;
/// Send a nonza over the stream.
@protected
late final SendNonzaFunction sendNonza;
/// Get the connection's settings.
@protected
late final GetConnectionSettingsFunction getConnectionSettings;
/// The id included in the last stream header.
@protected
String? streamId;
/// Set the id of the last stream header.
void setStreamHeaderId(String? id) {
streamId = id;
}
/// Returns, if registered, a negotiator with id [id].
T? getNegotiatorById<T extends XmppFeatureNegotiatorBase>(String id) =>
negotiators[id] as T?;
/// Register the parameters as the corresponding methods in this class. Also
/// initializes the logger.
void register(
NegotiationsDoneCallback onNegotiationsDone,
ErrorCallback handleError,
IsAuthenticatedFunction isAuthenticated,
SendNonzaFunction sendNonza,
GetConnectionSettingsFunction getConnectionSettings,
) {
this.onNegotiationsDone = onNegotiationsDone;
this.handleError = handleError;
this.isAuthenticated = isAuthenticated;
this.sendNonza = sendNonza;
this.getConnectionSettings = getConnectionSettings;
log = Logger(toString());
}
/// Registers the negotiator [negotiator] against this negotiations handler.
void registerNegotiator(XmppFeatureNegotiatorBase negotiator);
/// Sends the stream header.
void sendStreamHeader();
/// Runs the post-register callback of all negotiators.
Future<void> runPostRegisterCallback() async {
for (final negotiator in negotiators.values) {
await negotiator.postRegisterCallback();
}
}
Future<void> sendEventToNegotiators(XmppEvent event) async {
for (final negotiator in negotiators.values) {
await negotiator.onXmppEvent(event);
}
}
/// Remove [feature] from the stream features we are currently negotiating.
void removeNegotiatingFeature(String feature) {}
/// Resets all registered negotiators and the negotiation handler.
@mustCallSuper
void reset() {
streamId = null;
for (final negotiator in negotiators.values) {
negotiator.reset();
}
}
/// Called whenever the stream buffer outputs a new event [event].
Future<void> negotiate(XmlStreamBufferObject event) async {
if (event is XmlStreamBufferHeader) {
streamId = event.attributes['id'];
}
}
}

View File

@ -1,117 +0,0 @@
import 'dart:convert';
import 'package:cryptography/cryptography.dart';
import 'package:hex/hex.dart';
import 'package:moxxmpp/src/buffer.dart';
import 'package:moxxmpp/src/connection_errors.dart';
import 'package:moxxmpp/src/handlers/base.dart';
import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart';
/// Nonza describing the XMPP stream header.
class ComponentStreamHeaderNonza extends XMLNode {
ComponentStreamHeaderNonza(JID jid)
: assert(jid.isBare(), 'Component JID must be bare'),
super(
tag: 'stream:stream',
attributes: <String, String>{
'xmlns': componentAcceptXmlns,
'xmlns:stream': streamXmlns,
'to': jid.domain,
},
closeTag: false,
);
}
/// The states the ComponentToServerNegotiator can be in.
enum ComponentToServerState {
/// No data has been sent or received yet
idle,
/// Handshake has been sent
handshakeSent,
}
/// The ComponentToServerNegotiator is a NegotiationsHandler that allows writing
/// components that adhere to XEP-0114.
class ComponentToServerNegotiator extends NegotiationsHandler {
ComponentToServerNegotiator();
/// The state the negotiation handler is currently in
ComponentToServerState _state = ComponentToServerState.idle;
@override
void registerNegotiator(XmppFeatureNegotiatorBase negotiator) {}
@override
void sendStreamHeader() {
sendNonza(
XMLNode(
tag: 'xml',
attributes: {'version': '1.0'},
closeTag: false,
isDeclaration: true,
children: [
ComponentStreamHeaderNonza(getConnectionSettings().jid),
],
),
);
}
Future<String> _computeHandshake(String id) async {
final secret = getConnectionSettings().password;
return HEX.encode(
(await Sha1().hash(utf8.encode('$streamId$secret'))).bytes,
);
}
@override
Future<void> negotiate(XmlStreamBufferObject event) async {
switch (_state) {
case ComponentToServerState.idle:
if (event is XmlStreamBufferHeader) {
streamId = event.attributes['id'];
assert(
streamId != null,
'The server must respond with a stream header that contains an id',
);
_state = ComponentToServerState.handshakeSent;
sendNonza(
XMLNode(
tag: 'handshake',
text: await _computeHandshake(streamId!),
),
);
} else {
log.severe('Unexpected data received');
await handleError(UnexpectedDataError());
}
break;
case ComponentToServerState.handshakeSent:
if (event is XmlStreamBufferElement) {
if (event.node.tag == 'handshake' &&
event.node.children.isEmpty &&
event.node.attributes.isEmpty) {
log.info('Successfully authenticated as component');
await onNegotiationsDone();
} else {
log.warning('Handshake failed');
await handleError(InvalidHandshakeCredentialsError());
}
} else {
log.severe('Unexpected data received');
await handleError(UnexpectedDataError());
}
break;
}
}
@override
void reset() {
_state = ComponentToServerState.idle;
super.reset();
}
}

View File

@ -44,9 +44,6 @@ const userAvatarMetadataXmlns = 'urn:xmpp:avatar:metadata';
// XEP-0085 // XEP-0085
const chatStateXmlns = 'http://jabber.org/protocol/chatstates'; const chatStateXmlns = 'http://jabber.org/protocol/chatstates';
// XEP-0114
const componentAcceptXmlns = 'jabber:component:accept';
// XEP-0115 // XEP-0115
const capsXmlns = 'http://jabber.org/protocol/caps'; const capsXmlns = 'http://jabber.org/protocol/caps';

View File

@ -1,27 +1,106 @@
import 'package:logging/logging.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:moxxmpp/src/buffer.dart';
import 'package:moxxmpp/src/connection_errors.dart'; import 'package:moxxmpp/src/connection_errors.dart';
import 'package:moxxmpp/src/handlers/base.dart'; import 'package:moxxmpp/src/errors.dart';
import 'package:moxxmpp/src/jid.dart'; import 'package:moxxmpp/src/events.dart';
import 'package:moxxmpp/src/namespaces.dart';
import 'package:moxxmpp/src/negotiators/negotiator.dart'; import 'package:moxxmpp/src/negotiators/negotiator.dart';
import 'package:moxxmpp/src/stringxml.dart'; import 'package:moxxmpp/src/stringxml.dart';
/// "Nonza" describing the XMPP stream header of a client-to-server connection. /// A callback for when the [NegotiationsHandler] is done.
class ClientStreamHeaderNonza extends XMLNode { typedef NegotiationsDoneCallback = Future<void> Function();
ClientStreamHeaderNonza(JID jid)
: super( /// A callback for the case that an error occurs while negotiating.
tag: 'stream:stream', typedef ErrorCallback = Future<void> Function(XmppError);
attributes: <String, String>{
'xmlns': stanzaXmlns, /// Trigger stream headers to be sent
'version': '1.0', typedef SendStreamHeadersFunction = void Function();
'xmlns:stream': streamXmlns,
'to': jid.domain, /// Return true if the current connection is authenticated. If not, return false.
'from': jid.toBare().toString(), typedef IsAuthenticatedFunction = bool Function();
'xml:lang': 'en',
}, /// This class implements the stream feature negotiation for XmppConnection.
closeTag: false, abstract class NegotiationsHandler {
); @protected
late final Logger log;
/// Map of all negotiators registered against the handler.
@protected
final Map<String, XmppFeatureNegotiatorBase> negotiators = {};
/// Function that is called once the negotiator is done with its stream negotiations.
@protected
late final NegotiationsDoneCallback onNegotiationsDone;
/// XmppConnection's handleError method.
@protected
late final ErrorCallback handleError;
/// Sends stream headers in the stream.
@protected
late final SendStreamHeadersFunction sendStreamHeaders;
/// Returns true if the connection is authenticated. If not, returns false.
@protected
late final IsAuthenticatedFunction isAuthenticated;
/// The id included in the last stream header.
@protected
String? streamId;
/// Set the id of the last stream header.
void setStreamHeaderId(String? id) {
streamId = id;
}
/// Returns, if registered, a negotiator with id [id].
T? getNegotiatorById<T extends XmppFeatureNegotiatorBase>(String id) =>
negotiators[id] as T?;
/// Register the parameters as the corresponding methods in this class. Also
/// initializes the logger.
void register(
NegotiationsDoneCallback onNegotiationsDone,
ErrorCallback handleError,
SendStreamHeadersFunction sendStreamHeaders,
IsAuthenticatedFunction isAuthenticated,
) {
this.onNegotiationsDone = onNegotiationsDone;
this.handleError = handleError;
this.sendStreamHeaders = sendStreamHeaders;
this.isAuthenticated = isAuthenticated;
log = Logger(toString());
}
/// Registers the negotiator [negotiator] against this negotiations handler.
void registerNegotiator(XmppFeatureNegotiatorBase negotiator);
/// Runs the post-register callback of all negotiators.
Future<void> runPostRegisterCallback() async {
for (final negotiator in negotiators.values) {
await negotiator.postRegisterCallback();
}
}
Future<void> sendEventToNegotiators(XmppEvent event) async {
for (final negotiator in negotiators.values) {
await negotiator.onXmppEvent(event);
}
}
/// Remove [feature] from the stream features we are currently negotiating.
void removeNegotiatingFeature(String feature) {}
/// Resets all registered negotiators and the negotiation handler.
@mustCallSuper
void reset() {
streamId = null;
for (final negotiator in negotiators.values) {
negotiator.reset();
}
}
/// Called whenever a new nonza [nonza] is received while negotiating.
Future<void> negotiate(XMLNode nonza);
} }
/// This class implements the stream feature negotiation for usage in client to server /// This class implements the stream feature negotiation for usage in client to server
@ -55,21 +134,6 @@ class ClientToServerNegotiator extends NegotiationsHandler {
}); });
} }
@override
void sendStreamHeader() {
sendNonza(
XMLNode(
tag: 'xml',
attributes: {'version': '1.0'},
closeTag: false,
isDeclaration: true,
children: [
ClientStreamHeaderNonza(getConnectionSettings().jid),
],
),
);
}
/// Returns true if all mandatory features in [features] have been negotiated. /// Returns true if all mandatory features in [features] have been negotiated.
/// Otherwise returns false. /// Otherwise returns false.
bool _isMandatoryNegotiationDone(List<XMLNode> features) { bool _isMandatoryNegotiationDone(List<XMLNode> features) {
@ -155,7 +219,7 @@ class ClientToServerNegotiator extends NegotiationsHandler {
if (_currentNegotiator!.sendStreamHeaderWhenDone) { if (_currentNegotiator!.sendStreamHeaderWhenDone) {
_currentNegotiator = null; _currentNegotiator = null;
_streamFeatures.clear(); _streamFeatures.clear();
sendStreamHeader(); sendStreamHeaders();
} else { } else {
removeNegotiatingFeature(_currentNegotiator!.negotiatingXmlns); removeNegotiatingFeature(_currentNegotiator!.negotiatingXmlns);
_currentNegotiator = null; _currentNegotiator = null;
@ -208,16 +272,14 @@ class ClientToServerNegotiator extends NegotiationsHandler {
} }
@override @override
Future<void> negotiate(XmlStreamBufferObject event) async { Future<void> negotiate(XMLNode nonza) async {
if (event is XmlStreamBufferElement) { if (nonza.tag == 'stream:features') {
if (event.node.tag == 'stream:features') { // Store the received stream features
// Store the received stream features _streamFeatures
_streamFeatures ..clear()
..clear() ..addAll(nonza.children);
..addAll(event.node.children);
}
await _executeCurrentNegotiator(event.node);
} }
await _executeCurrentNegotiator(nonza);
} }
} }

View File

@ -4,19 +4,14 @@ class ConnectionSettings {
ConnectionSettings({ ConnectionSettings({
required this.jid, required this.jid,
required this.password, required this.password,
required this.useDirectTLS,
this.host, this.host,
this.port, this.port,
}); });
/// The JID to authenticate as.
final JID jid; final JID jid;
/// The password to use during authentication.
final String password; final String password;
final bool useDirectTLS;
/// The host to connect to. Skips DNS resolution if specified.
final String? host; final String? host;
/// The port to connect to. Skips DNS resolution if specified.
final int? port; final int? port;
} }

View File

@ -1,47 +0,0 @@
import 'package:moxxmpp/moxxmpp.dart';
import 'package:test/test.dart';
import 'helpers/logging.dart';
import 'helpers/xmpp.dart';
const exampleXmlns1 = 'im:moxxmpp:example1';
const exampleNamespace1 = 'im.moxxmpp.test.example1';
const exampleXmlns2 = 'im:moxxmpp:example2';
const exampleNamespace2 = 'im.moxxmpp.test.example2';
void main() {
initLogger();
test('Test connecting as a component', () async {
final socket = StubTCPSocket([
StringExpectation(
"<stream:stream xmlns='jabber:component:accept' xmlns:stream='http://etherx.jabber.org/streams' to='component.example.org'>",
'''
<stream:stream
xmlns:stream='http://etherx.jabber.org/streams'
xmlns='jabber:component:accept'
from='component.example.org'
id='3BF96D32'>'''),
StringExpectation(
'<handshake>ee8567f3b4c6e315345416b45ca2e47dbe921565</handshake>',
'<handshake />',
),
]);
final conn = XmppConnection(
TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(),
ComponentToServerNegotiator(),
socket,
)..connectionSettings = ConnectionSettings(
jid: JID.fromString('component.example.org'),
password: 'abc123',
);
await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])),
DiscoManager([]),
]);
final result = await conn.connect(
waitUntilLogin: true,
);
expect(result.isType<bool>(), true);
});
}

View File

@ -1,10 +1,10 @@
import 'dart:async'; import 'dart:async';
import 'package:moxxmpp/src/connection.dart'; import 'package:moxxmpp/src/connection.dart';
import 'package:moxxmpp/src/connectivity.dart'; import 'package:moxxmpp/src/connectivity.dart';
import 'package:moxxmpp/src/handlers/client.dart';
import 'package:moxxmpp/src/jid.dart'; import 'package:moxxmpp/src/jid.dart';
import 'package:moxxmpp/src/managers/attributes.dart'; import 'package:moxxmpp/src/managers/attributes.dart';
import 'package:moxxmpp/src/managers/base.dart'; import 'package:moxxmpp/src/managers/base.dart';
import 'package:moxxmpp/src/negotiators/handler.dart';
import 'package:moxxmpp/src/reconnect.dart'; import 'package:moxxmpp/src/reconnect.dart';
import 'package:moxxmpp/src/settings.dart'; import 'package:moxxmpp/src/settings.dart';
import 'package:moxxmpp/src/socket.dart'; import 'package:moxxmpp/src/socket.dart';
@ -26,6 +26,7 @@ class TestingManagerHolder {
static final ConnectionSettings settings = ConnectionSettings( static final ConnectionSettings settings = ConnectionSettings(
jid: jid, jid: jid,
password: 'abc123', password: 'abc123',
useDirectTLS: true,
); );
Future<XMLNode> _sendStanza( Future<XMLNode> _sendStanza(

View File

@ -1,7 +1,7 @@
import 'package:moxxmpp/moxxmpp.dart'; import 'package:moxxmpp/moxxmpp.dart';
import 'package:moxxmpp/src/buffer.dart';
import 'package:test/test.dart'; import 'package:test/test.dart';
import 'helpers/logging.dart'; import 'helpers/logging.dart';
//import 'helpers/xmpp.dart';
const exampleXmlns1 = 'im:moxxmpp:example1'; const exampleXmlns1 = 'im:moxxmpp:example1';
const exampleNamespace1 = 'im.moxxmpp.test.example1'; const exampleNamespace1 = 'im.moxxmpp.test.example1';
@ -53,12 +53,8 @@ void main() {
..register( ..register(
() async {}, () async {},
(_) async {}, (_) async {},
() {},
() => false, () => false,
(_) {},
() => ConnectionSettings(
jid: JID.fromString('test'),
password: 'abc123',
),
) )
..registerNegotiator(StubNegotiator1()) ..registerNegotiator(StubNegotiator1())
..registerNegotiator(StubNegotiator2()); ..registerNegotiator(StubNegotiator2());
@ -71,26 +67,20 @@ void main() {
..register( ..register(
() async {}, () async {},
(_) async {}, (_) async {},
() {},
() => false, () => false,
(_) {},
() => ConnectionSettings(
jid: JID.fromString('test'),
password: 'abc123',
),
) )
..registerNegotiator(StubNegotiator1()) ..registerNegotiator(StubNegotiator1())
..registerNegotiator(StubNegotiator2()); ..registerNegotiator(StubNegotiator2());
await negotiator.runPostRegisterCallback(); await negotiator.runPostRegisterCallback();
await negotiator.negotiate( await negotiator.negotiate(
XmlStreamBufferElement( XMLNode.fromString(
XMLNode.fromString( '''
'''
<stream:features xmlns="http://etherx.jabber.org/streams"> <stream:features xmlns="http://etherx.jabber.org/streams">
<example1 xmlns="im:moxxmpp:example1" /> <example1 xmlns="im:moxxmpp:example1" />
<example2 xmlns="im:moxxmpp:example2" /> <example2 xmlns="im:moxxmpp:example2" />
</stream:features>''', </stream:features>''',
),
), ),
); );

View File

@ -55,6 +55,7 @@ void main() {
() => ConnectionSettings( () => ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
), ),
(_) async {}, (_) async {},
getNegotiatorNullStub, getNegotiatorNullStub,
@ -156,6 +157,7 @@ void main() {
() => ConnectionSettings( () => ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
), ),
(_) async {}, (_) async {},
getNegotiatorNullStub, getNegotiatorNullStub,
@ -212,6 +214,7 @@ void main() {
() => ConnectionSettings( () => ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
), ),
(_) async {}, (_) async {},
getNegotiatorNullStub, getNegotiatorNullStub,
@ -258,6 +261,7 @@ void main() {
() => ConnectionSettings( () => ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
), ),
(_) async {}, (_) async {},
getNegotiatorNullStub, getNegotiatorNullStub,
@ -307,6 +311,7 @@ void main() {
() => ConnectionSettings( () => ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
), ),
(_) async {}, (_) async {},
getNegotiatorNullStub, getNegotiatorNullStub,

View File

@ -23,7 +23,7 @@ void main() {
); );
expect( expect(
ClientStreamHeaderNonza(JID.fromString('user@uwu.server')).toXml(), StreamHeaderNonza(JID.fromString('user@uwu.server')).toXml(),
"<stream:stream xmlns='jabber:client' version='1.0' xmlns:stream='http://etherx.jabber.org/streams' to='uwu.server' from='user@uwu.server' xml:lang='en'>", "<stream:stream xmlns='jabber:client' version='1.0' xmlns:stream='http://etherx.jabber.org/streams' to='uwu.server' from='user@uwu.server' xml:lang='en'>",
); );

View File

@ -75,6 +75,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),

View File

@ -61,6 +61,7 @@ XmppManagerAttributes mkAttributes(void Function(Stanza) callback) {
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString('hallo@example.server'), jid: JID.fromString('hallo@example.server'),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getFullJID: () => JID.fromString('hallo@example.server/uwu'), getFullJID: () => JID.fromString('hallo@example.server/uwu'),
getSocket: () => StubTCPSocket([]), getSocket: () => StubTCPSocket([]),
@ -285,6 +286,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
final sm = StreamManagementManager(); final sm = StreamManagementManager();
await conn.registerManagers([ await conn.registerManagers([
@ -408,6 +410,166 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
);
final sm = StreamManagementManager();
await conn.registerManagers([
PresenceManager(),
RosterManager(TestingRosterStateManager('', [])),
DiscoManager([]),
sm,
CarbonsManager()..forceEnable(),
//EntityCapabilitiesManager('http://moxxmpp.example'),
]);
await conn.registerFeatureNegotiators([
SaslPlainNegotiator(),
ResourceBindingNegotiator(),
StreamManagementNegotiator(),
]);
await conn.connect(
waitUntilLogin: true,
);
expect(fakeSocket.getState(), 6);
expect(await conn.getConnectionState(), XmppConnectionState.connected);
expect(
conn
.getManagerById<StreamManagementManager>(smManager)!
.isStreamManagementEnabled(),
true,
);
// Await an iq
await conn.sendStanza(
Stanza.iq(
to: 'user@example.com',
type: 'get',
),
addFrom: StanzaFromType.none,
);
expect(sm.state.s2c, 2);
});
});
group('Stream resumption', () {
test('Stanza retransmission', () async {
var stanzaCount = 0;
final attributes = mkAttributes((_) {
stanzaCount++;
});
final manager = StreamManagementManager()..register(attributes);
await manager.onXmppEvent(
StreamManagementEnabledEvent(resource: 'hallo'),
);
// Send 5 stanzas
for (var i = 0; i < 5; i++) {
await runOutgoingStanzaHandlers(manager, stanza);
}
// Only ack 3
// <a h='3' />
await manager.runNonzaHandlers(mkAck(3));
expect(manager.getUnackedStanzas().length, 2);
// Lose connection
// [ Reconnect ]
await manager.onXmppEvent(StreamResumedEvent(h: 3));
expect(stanzaCount, 2);
});
test('Resumption with prior state', () async {
var stanzaCount = 0;
final attributes = mkAttributes((_) {
stanzaCount++;
});
final manager = StreamManagementManager()..register(attributes);
// [ ... ]
await manager.onXmppEvent(
StreamManagementEnabledEvent(resource: 'hallo'),
);
await manager.setState(manager.state.copyWith(c2s: 150, s2c: 70));
// Send some stanzas but don't ack them
for (var i = 0; i < 5; i++) {
await runOutgoingStanzaHandlers(manager, stanza);
}
expect(manager.getUnackedStanzas().length, 5);
// Lose connection
// [ Reconnect ]
await manager.onXmppEvent(StreamResumedEvent(h: 150));
expect(manager.getUnackedStanzas().length, 0);
expect(stanzaCount, 5);
});
});
group('Test the negotiator', () {
test('Test successful stream enablement', () async {
final fakeSocket = StubTCPSocket([
StringExpectation(
"<stream:stream xmlns='jabber:client' version='1.0' xmlns:stream='http://etherx.jabber.org/streams' to='test.server' from='polynomdivision@test.server' xml:lang='en'>",
'''
<stream:stream
xmlns="jabber:client"
version="1.0"
xmlns:stream="http://etherx.jabber.org/streams"
from="test.server"
xml:lang="en">
<stream:features xmlns="http://etherx.jabber.org/streams">
<mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<mechanism>PLAIN</mechanism>
</mechanisms>
</stream:features>''',
),
StringExpectation(
"<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>AHBvbHlub21kaXZpc2lvbgBhYWFh</auth>",
'<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl" />',
),
StringExpectation(
"<stream:stream xmlns='jabber:client' version='1.0' xmlns:stream='http://etherx.jabber.org/streams' to='test.server' from='polynomdivision@test.server' xml:lang='en'>",
'''
<stream:stream
xmlns="jabber:client"
version="1.0"
xmlns:stream="http://etherx.jabber.org/streams"
from="test.server"
xml:lang="en">
<stream:features xmlns="http://etherx.jabber.org/streams">
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
<required/>
</bind>
<session xmlns="urn:ietf:params:xml:ns:xmpp-session">
<optional/>
</session>
<csi xmlns="urn:xmpp:csi:0"/>
<sm xmlns="urn:xmpp:sm:3"/>
</stream:features>
''',
),
StanzaExpectation(
'<iq xmlns="jabber:client" type="set" id="a"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/></iq>',
'<iq xmlns="jabber:client" type="result" id="a"><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"><jid>polynomdivision@test.server/MU29eEZn</jid></bind></iq>',
ignoreId: true,
),
StringExpectation(
"<enable xmlns='urn:xmpp:sm:3' resume='true' />",
'<enabled xmlns="urn:xmpp:sm:3" id="some-long-sm-id" resume="true" />',
)
]);
final conn = XmppConnection(
TestingReconnectionPolicy(),
AlwaysConnectedConnectivityManager(),
ClientToServerNegotiator(),
fakeSocket,
)..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -500,6 +662,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -589,6 +752,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -675,6 +839,7 @@ void main() {
..connectionSettings = ConnectionSettings( ..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
) )
..setResource('test-resource', triggerEvent: false); ..setResource('test-resource', triggerEvent: false);
await conn.registerManagers([ await conn.registerManagers([
@ -772,6 +937,7 @@ void main() {
..connectionSettings = ConnectionSettings( ..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
) )
..setResource('test-resource', triggerEvent: false); ..setResource('test-resource', triggerEvent: false);
await conn.registerManagers([ await conn.registerManagers([
@ -873,6 +1039,7 @@ void main() {
..connectionSettings = ConnectionSettings( ..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
) )
..setResource('test-resource', triggerEvent: false); ..setResource('test-resource', triggerEvent: false);
await conn.registerManagers([ await conn.registerManagers([

View File

@ -28,6 +28,7 @@ void main() {
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString('bob@xmpp.example'), jid: JID.fromString('bob@xmpp.example'),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getFullJID: () => JID.fromString('bob@xmpp.example/uwu'), getFullJID: () => JID.fromString('bob@xmpp.example/uwu'),
getSocket: () => StubTCPSocket([]), getSocket: () => StubTCPSocket([]),
@ -109,6 +110,7 @@ void main() {
..connectionSettings = ConnectionSettings( ..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
) )
..setResource('test-resource', triggerEvent: false); ..setResource('test-resource', triggerEvent: false);
await conn.registerManagers([ await conn.registerManagers([

View File

@ -54,6 +54,7 @@ void main() {
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString('some.user@example.server'), jid: JID.fromString('some.user@example.server'),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getManagerById: getManagerNullStub, getManagerById: getManagerNullStub,
getNegotiatorById: getUnsupportedCSINegotiator, getNegotiatorById: getUnsupportedCSINegotiator,
@ -97,6 +98,7 @@ void main() {
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString('some.user@example.server'), jid: JID.fromString('some.user@example.server'),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getManagerById: getManagerNullStub, getManagerById: getManagerNullStub,
getNegotiatorById: getSupportedCSINegotiator, getNegotiatorById: getSupportedCSINegotiator,
@ -172,6 +174,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
final csi = CSIManager(); final csi = CSIManager();
await csi.setInactive(sendNonza: false); await csi.setInactive(sendNonza: false);

View File

@ -49,6 +49,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -120,6 +121,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])), RosterManager(TestingRosterStateManager('', [])),

View File

@ -106,6 +106,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -184,6 +185,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -261,6 +263,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('user@server'), jid: JID.fromString('user@server'),
password: 'pencil', password: 'pencil',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -346,6 +349,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -429,6 +433,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),

View File

@ -112,6 +112,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])), RosterManager(TestingRosterStateManager('', [])),
@ -225,6 +226,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])), RosterManager(TestingRosterStateManager('', [])),

View File

@ -31,6 +31,7 @@ Future<bool> testRosterManager(
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString(bareJid), jid: JID.fromString(bareJid),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getManagerById: getManagerNullStub, getManagerById: getManagerNullStub,
getNegotiatorById: getNegotiatorNullStub, getNegotiatorById: getNegotiatorNullStub,
@ -129,6 +130,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -184,6 +186,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -241,6 +244,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('polynomdivision@test.server'), jid: JID.fromString('polynomdivision@test.server'),
password: 'aaaa', password: 'aaaa',
useDirectTLS: true,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -286,6 +290,7 @@ void main() {
getConnectionSettings: () => ConnectionSettings( getConnectionSettings: () => ConnectionSettings(
jid: JID.fromString('some.user@example.server'), jid: JID.fromString('some.user@example.server'),
password: 'password', password: 'password',
useDirectTLS: true,
), ),
getManagerById: getManagerNullStub, getManagerById: getManagerNullStub,
getNegotiatorById: getNegotiatorNullStub, getNegotiatorById: getNegotiatorNullStub,
@ -398,6 +403,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('testuser@example.org'), jid: JID.fromString('testuser@example.org'),
password: 'abc123', password: 'abc123',
useDirectTLS: false,
); );
await conn.registerManagers([ await conn.registerManagers([
PresenceManager(), PresenceManager(),
@ -491,6 +497,7 @@ void main() {
)..connectionSettings = ConnectionSettings( )..connectionSettings = ConnectionSettings(
jid: JID.fromString('testuser@example.org'), jid: JID.fromString('testuser@example.org'),
password: 'abc123', password: 'abc123',
useDirectTLS: false,
); );
await conn.registerManagers([ await conn.registerManagers([
RosterManager(TestingRosterStateManager('', [])), RosterManager(TestingRosterStateManager('', [])),