feat(xep): Improve the ergonomics of Bind2 negotiators
This commit is contained in:
parent
ec6b5ab753
commit
b354ca8d0a
@ -28,7 +28,7 @@ enum _StreamManagementNegotiatorState {
|
|||||||
/// StreamManagementManager at least once before connecting, if stream resumption
|
/// StreamManagementManager at least once before connecting, if stream resumption
|
||||||
/// is wanted.
|
/// is wanted.
|
||||||
class StreamManagementNegotiator extends Sasl2FeatureNegotiator
|
class StreamManagementNegotiator extends Sasl2FeatureNegotiator
|
||||||
implements Bind2FeatureNegotiator {
|
implements Bind2FeatureNegotiatorInterface {
|
||||||
StreamManagementNegotiator()
|
StreamManagementNegotiator()
|
||||||
: super(10, false, smXmlns, streamManagementNegotiator);
|
: super(10, false, smXmlns, streamManagementNegotiator);
|
||||||
|
|
||||||
@ -256,6 +256,9 @@ class StreamManagementNegotiator extends Sasl2FeatureNegotiator
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onBind2Success(XMLNode response) async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<XMLNode>> onSasl2FeaturesReceived(XMLNode sasl2Features) async {
|
Future<List<XMLNode>> onSasl2FeaturesReceived(XMLNode sasl2Features) async {
|
||||||
final inline = sasl2Features.firstTag('inline')!;
|
final inline = sasl2Features.firstTag('inline')!;
|
||||||
|
@ -9,11 +9,8 @@ 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/namespaces.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/sasl2.dart';
|
|
||||||
import 'package:moxxmpp/src/stanza.dart';
|
import 'package:moxxmpp/src/stanza.dart';
|
||||||
import 'package:moxxmpp/src/stringxml.dart';
|
import 'package:moxxmpp/src/stringxml.dart';
|
||||||
import 'package:moxxmpp/src/types/result.dart';
|
|
||||||
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
|
import 'package:moxxmpp/src/xeps/xep_0030/xep_0030.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0297.dart';
|
import 'package:moxxmpp/src/xeps/xep_0297.dart';
|
||||||
import 'package:moxxmpp/src/xeps/xep_0386.dart';
|
import 'package:moxxmpp/src/xeps/xep_0386.dart';
|
||||||
@ -202,9 +199,8 @@ class CarbonsManager extends XmppManagerBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CarbonsNegotiator extends Sasl2FeatureNegotiator
|
class CarbonsNegotiator extends Bind2FeatureNegotiator {
|
||||||
implements Bind2FeatureNegotiator {
|
CarbonsNegotiator() : super(0, carbonsXmlns, carbonsNegotiator);
|
||||||
CarbonsNegotiator() : super(0, false, carbonsXmlns, carbonsNegotiator);
|
|
||||||
|
|
||||||
/// Flag indicating whether we requested to enable carbons inline (true) or not
|
/// Flag indicating whether we requested to enable carbons inline (true) or not
|
||||||
/// (false).
|
/// (false).
|
||||||
@ -214,42 +210,26 @@ class CarbonsNegotiator extends Sasl2FeatureNegotiator
|
|||||||
final Logger _log = Logger('CarbonsNegotiator');
|
final Logger _log = Logger('CarbonsNegotiator');
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool canInlineFeature(List<XMLNode> features) => true;
|
Future<void> onBind2Success(XMLNode response) async {
|
||||||
|
if (!_requestedEnablement) {
|
||||||
@override
|
return;
|
||||||
Future<List<XMLNode>> onSasl2FeaturesReceived(XMLNode sasl2Features) async {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<Result<bool, NegotiatorError>> onSasl2Success(XMLNode response) async {
|
|
||||||
if (_requestedEnablement) {
|
|
||||||
final enabled = response
|
|
||||||
.firstTag('bound', xmlns: bind2Xmlns)
|
|
||||||
?.firstTag('enabled', xmlns: carbonsXmlns);
|
|
||||||
final cm = attributes.getManagerById<CarbonsManager>(carbonsManager)!;
|
|
||||||
if (enabled != null) {
|
|
||||||
_log.finest('Successfully enabled Message Carbons inline');
|
|
||||||
cm.setEnabled();
|
|
||||||
} else {
|
|
||||||
_log.warning('Failed to enable Message Carbons inline');
|
|
||||||
cm.setDisabled();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return const Result(true);
|
final enabled = response.firstTag('enabled', xmlns: carbonsXmlns);
|
||||||
}
|
final cm = attributes.getManagerById<CarbonsManager>(carbonsManager)!;
|
||||||
|
if (enabled != null) {
|
||||||
@override
|
_log.finest('Successfully enabled Message Carbons inline');
|
||||||
Future<Result<NegotiatorState, NegotiatorError>> negotiate(
|
cm.setEnabled();
|
||||||
XMLNode nonza,
|
} else {
|
||||||
) async {
|
_log.warning('Failed to enable Message Carbons inline');
|
||||||
return const Result(NegotiatorState.done);
|
cm.setDisabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<XMLNode>> onBind2FeaturesReceived(
|
Future<List<XMLNode>> onBind2FeaturesReceived(
|
||||||
List<String> bind2Features) async {
|
List<String> bind2Features,
|
||||||
|
) async {
|
||||||
if (!bind2Features.contains(carbonsXmlns)) {
|
if (!bind2Features.contains(carbonsXmlns)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -263,16 +243,6 @@ class CarbonsNegotiator extends Sasl2FeatureNegotiator
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Future<void> postRegisterCallback() async {
|
|
||||||
attributes
|
|
||||||
.getNegotiatorById<Sasl2Negotiator>(sasl2Negotiator)
|
|
||||||
?.registerNegotiator(this);
|
|
||||||
attributes
|
|
||||||
.getNegotiatorById<Bind2Negotiator>(bind2Negotiator)
|
|
||||||
?.registerNegotiator(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void reset() {
|
void reset() {
|
||||||
_requestedEnablement = false;
|
_requestedEnablement = false;
|
||||||
|
@ -25,7 +25,7 @@ class CSIInactiveNonza extends XMLNode {
|
|||||||
|
|
||||||
/// A Stub negotiator that is just for "intercepting" the stream feature.
|
/// A Stub negotiator that is just for "intercepting" the stream feature.
|
||||||
class CSINegotiator extends XmppFeatureNegotiatorBase
|
class CSINegotiator extends XmppFeatureNegotiatorBase
|
||||||
implements Bind2FeatureNegotiator {
|
implements Bind2FeatureNegotiatorInterface {
|
||||||
CSINegotiator() : super(11, false, csiXmlns, csiNegotiator);
|
CSINegotiator() : super(11, false, csiXmlns, csiNegotiator);
|
||||||
|
|
||||||
/// True if CSI is supported. False otherwise.
|
/// True if CSI is supported. False otherwise.
|
||||||
@ -50,12 +50,16 @@ class CSINegotiator extends XmppFeatureNegotiatorBase
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_supported = true;
|
||||||
final active = attributes.getManagerById<CSIManager>(csiManager)!.isActive;
|
final active = attributes.getManagerById<CSIManager>(csiManager)!.isActive;
|
||||||
return [
|
return [
|
||||||
if (active) CSIActiveNonza() else CSIInactiveNonza(),
|
if (active) CSIActiveNonza() else CSIInactiveNonza(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> onBind2Success(XMLNode response) async {}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void reset() {
|
void reset() {
|
||||||
_supported = false;
|
_supported = false;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:meta/meta.dart';
|
||||||
import 'package:moxxmpp/src/namespaces.dart';
|
import 'package:moxxmpp/src/namespaces.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';
|
||||||
@ -9,10 +10,43 @@ import 'package:moxxmpp/src/types/result.dart';
|
|||||||
/// An interface that allows registering against Bind2's feature list in order to
|
/// An interface that allows registering against Bind2's feature list in order to
|
||||||
/// negotiate features inline with Bind2.
|
/// negotiate features inline with Bind2.
|
||||||
// ignore: one_member_abstracts
|
// ignore: one_member_abstracts
|
||||||
abstract class Bind2FeatureNegotiator {
|
abstract class Bind2FeatureNegotiatorInterface {
|
||||||
/// Called by the Bind2 negotiator when Bind2 features are received. The returned
|
/// Called by the Bind2 negotiator when Bind2 features are received. The returned
|
||||||
/// [XMLNode]s are added to Bind2's bind request.
|
/// [XMLNode]s are added to Bind2's bind request.
|
||||||
Future<List<XMLNode>> onBind2FeaturesReceived(List<String> bind2Features);
|
Future<List<XMLNode>> onBind2FeaturesReceived(List<String> bind2Features);
|
||||||
|
|
||||||
|
/// Called by the Bind2 negotiator when Bind2 results are received.
|
||||||
|
Future<void> onBind2Success(XMLNode result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A class that allows for simple negotiators that only registers itself against
|
||||||
|
/// the Bind2 negotiator. You only have to implement the functions required by
|
||||||
|
/// [Bind2FeatureNegotiatorInterface].
|
||||||
|
abstract class Bind2FeatureNegotiator extends XmppFeatureNegotiatorBase
|
||||||
|
implements Bind2FeatureNegotiatorInterface {
|
||||||
|
Bind2FeatureNegotiator(
|
||||||
|
int priority,
|
||||||
|
String negotiatingXmlns,
|
||||||
|
String id,
|
||||||
|
) : super(priority, false, negotiatingXmlns, id);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool matchesFeature(List<XMLNode> features) => false;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<Result<NegotiatorState, NegotiatorError>> negotiate(
|
||||||
|
XMLNode nonza,
|
||||||
|
) async {
|
||||||
|
return const Result(NegotiatorState.done);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mustCallSuper
|
||||||
|
@override
|
||||||
|
Future<void> postRegisterCallback() async {
|
||||||
|
attributes
|
||||||
|
.getNegotiatorById<Bind2Negotiator>(bind2Negotiator)!
|
||||||
|
.registerNegotiator(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A negotiator implementing XEP-0386. This negotiator is useless on its own
|
/// A negotiator implementing XEP-0386. This negotiator is useless on its own
|
||||||
@ -21,15 +55,15 @@ class Bind2Negotiator extends Sasl2FeatureNegotiator {
|
|||||||
Bind2Negotiator() : super(0, false, bind2Xmlns, bind2Negotiator);
|
Bind2Negotiator() : super(0, false, bind2Xmlns, bind2Negotiator);
|
||||||
|
|
||||||
/// A list of negotiators that can work with Bind2.
|
/// A list of negotiators that can work with Bind2.
|
||||||
final List<Bind2FeatureNegotiator> _negotiators =
|
final List<Bind2FeatureNegotiatorInterface> _negotiators =
|
||||||
List<Bind2FeatureNegotiator>.empty(growable: true);
|
List<Bind2FeatureNegotiatorInterface>.empty(growable: true);
|
||||||
|
|
||||||
/// A tag to sent to the server when requesting Bind2.
|
/// A tag to sent to the server when requesting Bind2.
|
||||||
String? tag;
|
String? tag;
|
||||||
|
|
||||||
/// Register [negotiator] against the Bind2 negotiator to append data to the Bind2
|
/// Register [negotiator] against the Bind2 negotiator to append data to the Bind2
|
||||||
/// negotiation.
|
/// negotiation.
|
||||||
void registerNegotiator(Bind2FeatureNegotiator negotiator) {
|
void registerNegotiator(Bind2FeatureNegotiatorInterface negotiator) {
|
||||||
_negotiators.add(negotiator);
|
_negotiators.add(negotiator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,8 +121,14 @@ class Bind2Negotiator extends Sasl2FeatureNegotiator {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<Result<bool, NegotiatorError>> onSasl2Success(XMLNode response) async {
|
Future<Result<bool, NegotiatorError>> onSasl2Success(XMLNode response) async {
|
||||||
attributes.removeNegotiatingFeature(bindXmlns);
|
final bound = response.firstTag('bound', xmlns: bind2Xmlns);
|
||||||
|
if (bound != null) {
|
||||||
|
for (final negotiator in _negotiators) {
|
||||||
|
await negotiator.onBind2Success(bound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes.removeNegotiatingFeature(bindXmlns);
|
||||||
return const Result(true);
|
return const Result(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,8 @@ void main() {
|
|||||||
expect(result.isType<NegotiatorError>(), false);
|
expect(result.isType<NegotiatorError>(), false);
|
||||||
expect(conn.resource, 'test-resource');
|
expect(conn.resource, 'test-resource');
|
||||||
expect(
|
expect(
|
||||||
conn.getManagerById<CarbonsManager>(carbonsManager)!.isEnabled, true);
|
conn.getManagerById<CarbonsManager>(carbonsManager)!.isEnabled,
|
||||||
|
true,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -204,5 +204,9 @@ void main() {
|
|||||||
);
|
);
|
||||||
expect(result.isType<NegotiatorError>(), false);
|
expect(result.isType<NegotiatorError>(), false);
|
||||||
expect(fakeSocket.getState(), 2);
|
expect(fakeSocket.getState(), 2);
|
||||||
|
expect(
|
||||||
|
conn.getNegotiatorById<CSINegotiator>(csiNegotiator)!.isSupported,
|
||||||
|
true,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user