feat(xep): Allow inlining CSI
This commit is contained in:
parent
4a6aa79e56
commit
fbb495dc2f
@ -5,6 +5,7 @@ import 'package:moxxmpp/src/negotiators/namespaces.dart';
|
||||
import 'package:moxxmpp/src/negotiators/negotiator.dart';
|
||||
import 'package:moxxmpp/src/stringxml.dart';
|
||||
import 'package:moxxmpp/src/types/result.dart';
|
||||
import 'package:moxxmpp/src/xeps/xep_0386.dart';
|
||||
|
||||
class CSIActiveNonza extends XMLNode {
|
||||
CSIActiveNonza()
|
||||
@ -23,7 +24,8 @@ class CSIInactiveNonza extends XMLNode {
|
||||
}
|
||||
|
||||
/// A Stub negotiator that is just for "intercepting" the stream feature.
|
||||
class CSINegotiator extends XmppFeatureNegotiatorBase {
|
||||
class CSINegotiator extends XmppFeatureNegotiatorBase
|
||||
implements Bind2FeatureNegotiator {
|
||||
CSINegotiator() : super(11, false, csiXmlns, csiNegotiator);
|
||||
|
||||
/// True if CSI is supported. False otherwise.
|
||||
@ -40,19 +42,43 @@ class CSINegotiator extends XmppFeatureNegotiatorBase {
|
||||
return const Result(NegotiatorState.done);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<XMLNode>> onBind2FeaturesReceived(
|
||||
List<String> bind2Features,
|
||||
) async {
|
||||
if (!bind2Features.contains(csiXmlns)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final active = attributes.getManagerById<CSIManager>(csiManager)!.isActive;
|
||||
return [
|
||||
if (active) CSIActiveNonza() else CSIInactiveNonza(),
|
||||
];
|
||||
}
|
||||
|
||||
@override
|
||||
void reset() {
|
||||
_supported = false;
|
||||
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> postRegisterCallback() async {
|
||||
attributes
|
||||
.getNegotiatorById<Bind2Negotiator>(bind2Negotiator)
|
||||
?.registerNegotiator(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// The manager requires a CSINegotiator to be registered as a feature negotiator.
|
||||
class CSIManager extends XmppManagerBase {
|
||||
CSIManager() : super(csiManager);
|
||||
|
||||
/// Flag indicating whether the application is currently active and the CSI
|
||||
/// traffic optimisation should be disabled (true).
|
||||
bool _isActive = true;
|
||||
bool get isActive => _isActive;
|
||||
|
||||
@override
|
||||
Future<bool> isSupported() async {
|
||||
@ -71,23 +97,31 @@ class CSIManager extends XmppManagerBase {
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells the server to top optimizing traffic
|
||||
Future<void> setActive() async {
|
||||
/// Tells the server to stop optimizing traffic.
|
||||
/// If [sendNonza] is false, then no nonza is sent. This is useful
|
||||
/// for setting up the CSI manager for Bind2.
|
||||
Future<void> setActive({bool sendNonza = true}) async {
|
||||
_isActive = true;
|
||||
|
||||
if (sendNonza) {
|
||||
final attrs = getAttributes();
|
||||
if (await isSupported()) {
|
||||
attrs.sendNonza(CSIActiveNonza());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tells the server to optimize traffic following XEP-0352
|
||||
Future<void> setInactive() async {
|
||||
/// If [sendNonza] is false, then no nonza is sent. This is useful
|
||||
/// for setting up the CSI manager for Bind2.
|
||||
Future<void> setInactive({bool sendNonza = true}) async {
|
||||
_isActive = false;
|
||||
|
||||
if (sendNonza) {
|
||||
final attrs = getAttributes();
|
||||
if (await isSupported()) {
|
||||
attrs.sendNonza(CSIInactiveNonza());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:moxxmpp/moxxmpp.dart';
|
||||
import 'package:test/test.dart';
|
||||
import '../helpers/logging.dart';
|
||||
import '../helpers/xmpp.dart';
|
||||
|
||||
class MockedCSINegotiator extends CSINegotiator {
|
||||
@ -28,6 +29,8 @@ T? getUnsupportedCSINegotiator<T extends XmppFeatureNegotiatorBase>(String id) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
initLogger();
|
||||
|
||||
group('Test the XEP-0352 implementation', () {
|
||||
test('Test setting the CSI state when CSI is unsupported', () {
|
||||
var nonzaSent = false;
|
||||
@ -111,4 +114,95 @@ void main() {
|
||||
..setInactive();
|
||||
});
|
||||
});
|
||||
|
||||
test('Test CSI with Bind2', () 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>
|
||||
<inline>
|
||||
<bind xmlns="urn:xmpp:bind:0">
|
||||
<inline>
|
||||
<feature var="urn:xmpp:csi:0" />
|
||||
</inline>
|
||||
</bind>
|
||||
</inline>
|
||||
</authentication>
|
||||
<bind xmlns="urn:ietf:params:xml:ns:xmpp-bind">
|
||||
<required/>
|
||||
</bind>
|
||||
</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>
|
||||
<bind xmlns='urn:xmpp:bind:0'>
|
||||
<inactive xmlns='urn:xmpp:csi:0' />
|
||||
</bind>
|
||||
</authenticate>''',
|
||||
'''
|
||||
<success xmlns='urn:xmpp:sasl:2'>
|
||||
<authorization-identifier>polynomdivision@test.server/test-resource</authorization-identifier>
|
||||
</success>
|
||||
''',
|
||||
),
|
||||
]);
|
||||
final conn = XmppConnection(
|
||||
TestingReconnectionPolicy(),
|
||||
AlwaysConnectedConnectivityManager(),
|
||||
fakeSocket,
|
||||
)..setConnectionSettings(
|
||||
ConnectionSettings(
|
||||
jid: JID.fromString('polynomdivision@test.server'),
|
||||
password: 'aaaa',
|
||||
useDirectTLS: true,
|
||||
),
|
||||
);
|
||||
final csi = CSIManager();
|
||||
await csi.setInactive(sendNonza: false);
|
||||
await conn.registerManagers([
|
||||
RosterManager(TestingRosterStateManager('', [])),
|
||||
DiscoManager([]),
|
||||
csi,
|
||||
]);
|
||||
await conn.registerFeatureNegotiators([
|
||||
SaslPlainNegotiator(),
|
||||
ResourceBindingNegotiator(),
|
||||
FASTSaslNegotiator(),
|
||||
Bind2Negotiator(),
|
||||
CSINegotiator(),
|
||||
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<NegotiatorError>(), false);
|
||||
expect(fakeSocket.getState(), 2);
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user