feat(xep): Begin work on SASL2
This commit is contained in:
parent
52ad9a7ddb
commit
2e60e9841e
@ -23,6 +23,7 @@ export 'package:moxxmpp/src/negotiators/sasl/errors.dart';
|
|||||||
export 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
|
export 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
|
||||||
export 'package:moxxmpp/src/negotiators/sasl/plain.dart';
|
export 'package:moxxmpp/src/negotiators/sasl/plain.dart';
|
||||||
export 'package:moxxmpp/src/negotiators/sasl/scram.dart';
|
export 'package:moxxmpp/src/negotiators/sasl/scram.dart';
|
||||||
|
export 'package:moxxmpp/src/negotiators/sasl2.dart';
|
||||||
export 'package:moxxmpp/src/negotiators/starttls.dart';
|
export 'package:moxxmpp/src/negotiators/starttls.dart';
|
||||||
export 'package:moxxmpp/src/ping.dart';
|
export 'package:moxxmpp/src/ping.dart';
|
||||||
export 'package:moxxmpp/src/presence.dart';
|
export 'package:moxxmpp/src/presence.dart';
|
||||||
|
@ -254,7 +254,8 @@ class XmppConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Register a list of negotiator with the connection.
|
/// Register a list of negotiator with the connection.
|
||||||
void registerFeatureNegotiators(List<XmppFeatureNegotiatorBase> negotiators) {
|
Future<void> registerFeatureNegotiators(
|
||||||
|
List<XmppFeatureNegotiatorBase> negotiators) async {
|
||||||
for (final negotiator in negotiators) {
|
for (final negotiator in negotiators) {
|
||||||
_log.finest('Registering ${negotiator.id}');
|
_log.finest('Registering ${negotiator.id}');
|
||||||
negotiator.register(
|
negotiator.register(
|
||||||
@ -273,6 +274,10 @@ class XmppConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_log.finest('Negotiators registered');
|
_log.finest('Negotiators registered');
|
||||||
|
|
||||||
|
for (final negotiator in _featureNegotiators.values) {
|
||||||
|
await negotiator.postRegisterCallback();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset all registered negotiators.
|
/// Reset all registered negotiators.
|
||||||
|
@ -116,6 +116,9 @@ const omemoBundlesXmlns = 'urn:xmpp:omemo:2:bundles';
|
|||||||
// XEP-0385
|
// XEP-0385
|
||||||
const simsXmlns = 'urn:xmpp:sims:1';
|
const simsXmlns = 'urn:xmpp:sims:1';
|
||||||
|
|
||||||
|
// XEP-0388
|
||||||
|
const sasl2Xmlns = 'urn:xmpp:sasl:2';
|
||||||
|
|
||||||
// XEP-0420
|
// XEP-0420
|
||||||
const sceXmlns = 'urn:xmpp:sce:1';
|
const sceXmlns = 'urn:xmpp:sce:1';
|
||||||
|
|
||||||
|
@ -7,3 +7,4 @@ const rosterNegotiator = 'im.moxxmpp.core.roster';
|
|||||||
const resourceBindingNegotiator = 'im.moxxmpp.core.resource';
|
const resourceBindingNegotiator = 'im.moxxmpp.core.resource';
|
||||||
const streamManagementNegotiator = 'im.moxxmpp.xeps.sm';
|
const streamManagementNegotiator = 'im.moxxmpp.xeps.sm';
|
||||||
const startTlsNegotiator = 'im.moxxmpp.core.starttls';
|
const startTlsNegotiator = 'im.moxxmpp.core.starttls';
|
||||||
|
const sasl2Negotiator = 'org.moxxmpp.sasl.sasl2';
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:moxlib/moxlib.dart';
|
import 'package:moxlib/moxlib.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';
|
||||||
@ -120,5 +121,11 @@ abstract class XmppFeatureNegotiatorBase {
|
|||||||
state = NegotiatorState.ready;
|
state = NegotiatorState.ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@protected
|
||||||
NegotiatorAttributes get attributes => _attributes;
|
NegotiatorAttributes get attributes => _attributes;
|
||||||
|
|
||||||
|
/// Run after all negotiators are registered. Useful for registering callbacks against
|
||||||
|
/// other negotiators.
|
||||||
|
@visibleForOverriding
|
||||||
|
Future<void> postRegisterCallback() async {}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import 'package:moxxmpp/src/negotiators/negotiator.dart';
|
|||||||
import 'package:moxxmpp/src/negotiators/sasl/errors.dart';
|
import 'package:moxxmpp/src/negotiators/sasl/errors.dart';
|
||||||
import 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
|
import 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
|
||||||
import 'package:moxxmpp/src/negotiators/sasl/nonza.dart';
|
import 'package:moxxmpp/src/negotiators/sasl/nonza.dart';
|
||||||
|
import 'package:moxxmpp/src/negotiators/sasl2.dart';
|
||||||
import 'package:moxxmpp/src/stringxml.dart';
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
import 'package:moxxmpp/src/types/result.dart';
|
import 'package:moxxmpp/src/types/result.dart';
|
||||||
|
|
||||||
@ -76,4 +77,11 @@ class SaslPlainNegotiator extends SaslNegotiator {
|
|||||||
|
|
||||||
super.reset();
|
super.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> postRegisterCallback() async {
|
||||||
|
attributes
|
||||||
|
.getNegotiatorById<Sasl2Negotiator>(sasl2Negotiator)
|
||||||
|
?.registerSaslNegotiator(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
161
packages/moxxmpp/lib/src/negotiators/sasl2.dart
Normal file
161
packages/moxxmpp/lib/src/negotiators/sasl2.dart
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
import 'package:moxxmpp/src/namespaces.dart';
|
||||||
|
import 'package:moxxmpp/src/negotiators/namespaces.dart';
|
||||||
|
import 'package:moxxmpp/src/negotiators/negotiator.dart';
|
||||||
|
import 'package:moxxmpp/src/negotiators/sasl/negotiator.dart';
|
||||||
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
|
import 'package:moxxmpp/src/types/result.dart';
|
||||||
|
|
||||||
|
typedef Sasl2FeaturesReceivedCallback = Future<List<XMLNode>> Function(XMLNode);
|
||||||
|
|
||||||
|
class NoSASLMechanismSelectedError extends NegotiatorError {
|
||||||
|
@override
|
||||||
|
bool isRecoverable() => false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A data class describing the user agent. See https://dyn.eightysoft.de/final/xep-0388.html#initiation
|
||||||
|
class UserAgent {
|
||||||
|
const UserAgent({
|
||||||
|
this.id,
|
||||||
|
this.software,
|
||||||
|
this.device,
|
||||||
|
});
|
||||||
|
|
||||||
|
/// The identifier of the software/device combo connecting. SHOULD be a UUIDv4.
|
||||||
|
final String? id;
|
||||||
|
|
||||||
|
/// The software's name that's connecting at the moment.
|
||||||
|
final String? software;
|
||||||
|
|
||||||
|
/// The name of the device.
|
||||||
|
final String? device;
|
||||||
|
|
||||||
|
XMLNode toXml() {
|
||||||
|
assert(id != null || software != null || device != null,
|
||||||
|
'A completely empty user agent makes no sense');
|
||||||
|
return XMLNode(
|
||||||
|
tag: 'user-agent',
|
||||||
|
attributes: id != null
|
||||||
|
? {
|
||||||
|
'id': id,
|
||||||
|
}
|
||||||
|
: {},
|
||||||
|
children: [
|
||||||
|
if (software != null)
|
||||||
|
XMLNode(
|
||||||
|
tag: 'software',
|
||||||
|
text: software,
|
||||||
|
),
|
||||||
|
if (device != null)
|
||||||
|
XMLNode(
|
||||||
|
tag: 'device',
|
||||||
|
text: device,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Sasl2State {
|
||||||
|
// No request has been sent yet.
|
||||||
|
idle,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A negotiator that implements XEP-0388 SASL2. Alone, it does nothing. Has to be
|
||||||
|
/// registered with other negotiators that register themselves against this one.
|
||||||
|
class Sasl2Negotiator extends XmppFeatureNegotiatorBase {
|
||||||
|
Sasl2Negotiator({
|
||||||
|
this.userAgent,
|
||||||
|
}) : super(100, false, sasl2Xmlns, sasl2Negotiator);
|
||||||
|
|
||||||
|
/// The user agent data that will be sent to the server when authenticating.
|
||||||
|
final UserAgent? userAgent;
|
||||||
|
|
||||||
|
/// List of callbacks that are registered against us. Will be called once we get
|
||||||
|
/// SASL2 features.
|
||||||
|
final List<Sasl2FeaturesReceivedCallback> _featureCallbacks =
|
||||||
|
List<Sasl2FeaturesReceivedCallback>.empty(growable: true);
|
||||||
|
|
||||||
|
/// List of SASL negotiators, sorted by their priority. The higher the priority, the
|
||||||
|
/// lower its index.
|
||||||
|
final List<SaslNegotiator> _saslNegotiators =
|
||||||
|
List<SaslNegotiator>.empty(growable: true);
|
||||||
|
|
||||||
|
/// The state the SASL2 negotiator is currently in.
|
||||||
|
Sasl2State _sasl2State = Sasl2State.idle;
|
||||||
|
|
||||||
|
/// The SASL negotiator that will negotiate authentication.
|
||||||
|
SaslNegotiator? _currentSaslNegotiator;
|
||||||
|
|
||||||
|
void registerSaslNegotiator(SaslNegotiator negotiator) {
|
||||||
|
_saslNegotiators
|
||||||
|
..add(negotiator)
|
||||||
|
..sort((a, b) => b.priority.compareTo(a.priority));
|
||||||
|
}
|
||||||
|
|
||||||
|
void registerFeaturesCallback(Sasl2FeaturesReceivedCallback callback) {
|
||||||
|
_featureCallbacks.add(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<NegotiatorState, NegotiatorError>> negotiate(
|
||||||
|
XMLNode nonza) async {
|
||||||
|
switch (_sasl2State) {
|
||||||
|
case Sasl2State.idle:
|
||||||
|
final sasl2 = nonza.firstTag('authentication', xmlns: sasl2Xmlns)!;
|
||||||
|
final mechanisms = XMLNode.xmlns(
|
||||||
|
tag: 'mechanisms',
|
||||||
|
xmlns: saslXmlns,
|
||||||
|
children: sasl2.children.where((c) => c.tag == 'mechanism').toList(),
|
||||||
|
);
|
||||||
|
for (final negotiator in _saslNegotiators) {
|
||||||
|
if (negotiator.matchesFeature([mechanisms])) {
|
||||||
|
_currentSaslNegotiator = negotiator;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must have a SASL negotiator by now
|
||||||
|
if (_currentSaslNegotiator == null) {
|
||||||
|
return Result(NoSASLMechanismSelectedError());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collect additional data by interested negotiators
|
||||||
|
final children = List<XMLNode>.empty(growable: true);
|
||||||
|
for (final callback in _featureCallbacks) {
|
||||||
|
children.addAll(
|
||||||
|
await callback(sasl2),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the authenticate nonza
|
||||||
|
final authenticate = XMLNode.xmlns(
|
||||||
|
tag: 'authenticate',
|
||||||
|
xmlns: sasl2Xmlns,
|
||||||
|
attributes: {
|
||||||
|
'mechanism': _currentSaslNegotiator!.mechanismName,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
if (userAgent != null) userAgent!.toXml(),
|
||||||
|
|
||||||
|
// TODO: Get the initial response
|
||||||
|
XMLNode(
|
||||||
|
tag: 'initial-response',
|
||||||
|
),
|
||||||
|
...children,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
attributes.sendNonza(authenticate);
|
||||||
|
return const Result(NegotiatorState.ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
return const Result(NegotiatorState.ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void reset() {
|
||||||
|
_currentSaslNegotiator = null;
|
||||||
|
_sasl2State = Sasl2State.idle;
|
||||||
|
|
||||||
|
super.reset();
|
||||||
|
}
|
||||||
|
}
|
@ -84,7 +84,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
EntityCapabilitiesManager('http://moxxmpp.example'),
|
EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
SaslScramNegotiator(10, '', '', ScramHashType.sha512),
|
SaslScramNegotiator(10, '', '', ScramHashType.sha512),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
|
@ -169,12 +169,11 @@ void main() {
|
|||||||
MessageManager(),
|
MessageManager(),
|
||||||
RosterManager(TestingRosterStateManager(null, [])),
|
RosterManager(TestingRosterStateManager(null, [])),
|
||||||
]);
|
]);
|
||||||
connection
|
await connection.registerFeatureNegotiators([
|
||||||
..registerFeatureNegotiators([
|
SaslPlainNegotiator(),
|
||||||
SaslPlainNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
]);
|
||||||
])
|
connection.setConnectionSettings(TestingManagerHolder.settings);
|
||||||
..setConnectionSettings(TestingManagerHolder.settings);
|
|
||||||
await connection.connect(
|
await connection.connect(
|
||||||
waitUntilLogin: true,
|
waitUntilLogin: true,
|
||||||
);
|
);
|
||||||
|
@ -298,7 +298,7 @@ void main() {
|
|||||||
CarbonsManager()..forceEnable(),
|
CarbonsManager()..forceEnable(),
|
||||||
EntityCapabilitiesManager('http://moxxmpp.example'),
|
EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
StreamManagementNegotiator(),
|
StreamManagementNegotiator(),
|
||||||
@ -423,7 +423,7 @@ void main() {
|
|||||||
CarbonsManager()..forceEnable(),
|
CarbonsManager()..forceEnable(),
|
||||||
//EntityCapabilitiesManager('http://moxxmpp.example'),
|
//EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
StreamManagementNegotiator(),
|
StreamManagementNegotiator(),
|
||||||
@ -580,7 +580,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
StreamManagementManager(),
|
StreamManagementManager(),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
StreamManagementNegotiator(),
|
StreamManagementNegotiator(),
|
||||||
@ -674,7 +674,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
StreamManagementManager(),
|
StreamManagementManager(),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
StreamManagementNegotiator(),
|
StreamManagementNegotiator(),
|
||||||
@ -765,7 +765,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
StreamManagementManager(),
|
StreamManagementManager(),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
StreamManagementNegotiator(),
|
StreamManagementNegotiator(),
|
||||||
|
69
packages/moxxmpp/test/xeps/xep_0388_test.dart
Normal file
69
packages/moxxmpp/test/xeps/xep_0388_test.dart
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import 'package:moxxmpp/moxxmpp.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import '../helpers/logging.dart';
|
||||||
|
import '../helpers/xmpp.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
initLogger();
|
||||||
|
|
||||||
|
test('Test simple SASL2 negotiation', () async {
|
||||||
|
final fakeSocket = StubTCPSocket([
|
||||||
|
StringExpectation(
|
||||||
|
"<stream:stream xmlns='jabber:client' version='1.0' xmlns:stream='http://etherx.jabber.org/streams' to='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>
|
||||||
|
<authentication xmlns='urn:xmpp:sasl:2'>
|
||||||
|
<mechanism>PLAIN</mechanism>
|
||||||
|
</authentication>
|
||||||
|
</stream:features>''',
|
||||||
|
),
|
||||||
|
StanzaExpectation(
|
||||||
|
"<authenticate xmlns='urn:xmpp:sasl:2' mechanism='PLAIN'><user-agent id='d4565fa7-4d72-4749-b3d3-740edbf87770'><software>moxxmpp</software><device>PapaTutuWawa's awesome device</device></user-agent><initial-response>AHBvbHlub21kaXZpc2lvbgBhYWFh</initial-response></authenticate>",
|
||||||
|
'',
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
final conn = XmppConnection(
|
||||||
|
TestingReconnectionPolicy(),
|
||||||
|
AlwaysConnectedConnectivityManager(),
|
||||||
|
fakeSocket,
|
||||||
|
)..setConnectionSettings(
|
||||||
|
ConnectionSettings(
|
||||||
|
jid: JID.fromString('polynomdivision@test.server'),
|
||||||
|
password: 'aaaa',
|
||||||
|
useDirectTLS: true,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await conn.registerManagers([
|
||||||
|
PresenceManager(),
|
||||||
|
RosterManager(TestingRosterStateManager('', [])),
|
||||||
|
DiscoManager([]),
|
||||||
|
]);
|
||||||
|
await conn.registerFeatureNegotiators([
|
||||||
|
SaslPlainNegotiator(),
|
||||||
|
ResourceBindingNegotiator(),
|
||||||
|
Sasl2Negotiator(
|
||||||
|
userAgent: const UserAgent(
|
||||||
|
id: 'd4565fa7-4d72-4749-b3d3-740edbf87770',
|
||||||
|
software: 'moxxmpp',
|
||||||
|
device: "PapaTutuWawa's awesome device",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
final result = await conn.connect(
|
||||||
|
waitUntilLogin: true,
|
||||||
|
shouldReconnect: false,
|
||||||
|
enableReconnectOnSuccess: false,
|
||||||
|
);
|
||||||
|
expect(result.isType<XmppError>(), false);
|
||||||
|
});
|
||||||
|
}
|
@ -140,7 +140,7 @@ void main() {
|
|||||||
StreamManagementManager(),
|
StreamManagementManager(),
|
||||||
EntityCapabilitiesManager('http://moxxmpp.example'),
|
EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
SaslScramNegotiator(10, '', '', ScramHashType.sha512),
|
SaslScramNegotiator(10, '', '', ScramHashType.sha512),
|
||||||
ResourceBindingNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
@ -195,7 +195,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
EntityCapabilitiesManager('http://moxxmpp.example'),
|
EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([
|
await conn.registerFeatureNegotiators([
|
||||||
SaslPlainNegotiator(),
|
SaslPlainNegotiator(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@ -254,7 +254,7 @@ void main() {
|
|||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
EntityCapabilitiesManager('http://moxxmpp.example'),
|
EntityCapabilitiesManager('http://moxxmpp.example'),
|
||||||
]);
|
]);
|
||||||
conn.registerFeatureNegotiators([SaslPlainNegotiator()]);
|
await conn.registerFeatureNegotiators([SaslPlainNegotiator()]);
|
||||||
|
|
||||||
conn.asBroadcastStream().listen((event) {
|
conn.asBroadcastStream().listen((event) {
|
||||||
if (event is AuthenticationFailedEvent &&
|
if (event is AuthenticationFailedEvent &&
|
||||||
@ -407,18 +407,17 @@ void main() {
|
|||||||
RosterManager(TestingRosterStateManager('', [])),
|
RosterManager(TestingRosterStateManager('', [])),
|
||||||
DiscoManager([]),
|
DiscoManager([]),
|
||||||
]);
|
]);
|
||||||
conn
|
await conn.registerFeatureNegotiators([
|
||||||
..registerFeatureNegotiators([
|
// SaslPlainNegotiator(),
|
||||||
// SaslPlainNegotiator(),
|
ResourceBindingNegotiator(),
|
||||||
ResourceBindingNegotiator(),
|
]);
|
||||||
])
|
conn.setConnectionSettings(
|
||||||
..setConnectionSettings(
|
ConnectionSettings(
|
||||||
ConnectionSettings(
|
jid: JID.fromString('testuser@example.org'),
|
||||||
jid: JID.fromString('testuser@example.org'),
|
password: 'abc123',
|
||||||
password: 'abc123',
|
useDirectTLS: false,
|
||||||
useDirectTLS: false,
|
),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
final result = await conn.connect(
|
final result = await conn.connect(
|
||||||
waitUntilLogin: true,
|
waitUntilLogin: true,
|
||||||
|
Loading…
Reference in New Issue
Block a user