xmpp: Rework the stanza handler

This commit is contained in:
2022-03-11 21:39:42 +01:00
parent 648b83fc08
commit ae643e7009
27 changed files with 663 additions and 307 deletions

View File

@@ -1,8 +1,9 @@
import "package:test/test.dart";
import "package:moxxyv2/xmpp/stanza.dart";
import "package:moxxyv2/xmpp/managers/handlers.dart";
import "package:moxxyv2/xmpp/stringxml.dart";
import "package:moxxyv2/xmpp/managers/handlers.dart";
import "package:moxxyv2/xmpp/managers/data.dart";
final stanza1 = Stanza.iq(children: [
XMLNode.xmlns(tag: "tag", xmlns: "owo")
@@ -13,7 +14,7 @@ final stanza2 = Stanza.message(children: [
void main() {
test("match all", () {
final handler = StanzaHandler(callback: (_) async => true);
final handler = StanzaHandler(callback: (stanza, _) async => StanzaHandlerData(true,stanza));
expect(handler.matches(Stanza.iq()), true);
expect(handler.matches(Stanza.message()), true);
@@ -22,7 +23,10 @@ void main() {
expect(handler.matches(stanza2), true);
});
test("xmlns matching", () {
final handler = StanzaHandler(callback: (_) async => true, tagXmlns: "owo");
final handler = StanzaHandler(
callback: (stanza, _) async => StanzaHandlerData(true, stanza),
tagXmlns: "owo"
);
expect(handler.matches(Stanza.iq()), false);
expect(handler.matches(Stanza.message()), false);
@@ -32,9 +36,9 @@ void main() {
});
test("stanzaTag matching", () {
bool run = false;
final handler = StanzaHandler(callback: (_) async {
final handler = StanzaHandler(callback: (stanza, _) async {
run = true;
return true;
return StanzaHandlerData(true, stanza);
}, stanzaTag: "iq");
expect(handler.matches(Stanza.iq()), true);
@@ -43,11 +47,14 @@ void main() {
expect(handler.matches(stanza1), true);
expect(handler.matches(stanza2), false);
handler.callback(stanza2);
handler.callback(stanza2, StanzaHandlerData(false, stanza2));
expect(run, true);
});
test("tagName matching", () {
final handler = StanzaHandler(callback: (_) async => true, tagName: "tag");
final handler = StanzaHandler(
callback: (stanza, _) async => StanzaHandlerData(true, stanza),
tagName: "tag"
);
expect(handler.matches(Stanza.iq()), false);
expect(handler.matches(Stanza.message()), false);
@@ -56,7 +63,12 @@ void main() {
expect(handler.matches(stanza2), false);
});
test("combined matching", () {
final handler = StanzaHandler(callback: (_) async => true, tagName: "tag", stanzaTag: "iq", tagXmlns: "owo");
final handler = StanzaHandler(
callback: (stanza, _) async => StanzaHandlerData(true, stanza),
tagName: "tag",
stanzaTag: "iq",
tagXmlns: "owo"
);
expect(handler.matches(Stanza.iq()), false);
expect(handler.matches(Stanza.message()), false);
@@ -64,4 +76,18 @@ void main() {
expect(handler.matches(stanza1), true);
expect(handler.matches(stanza2), false);
});
test("sorting", () {
final handlerList = [
StanzaHandler(callback: (stanza, _) async => StanzaHandlerData(true, stanza), tagName: "1", priority: 100),
StanzaHandler(callback: (stanza, _) async => StanzaHandlerData(true, stanza), tagName: "2"),
StanzaHandler(callback: (stanza, _) async => StanzaHandlerData(true, stanza), tagName: "3", priority: 50)
];
handlerList.sort(stanzaHandlerSortComparator);
expect(handlerList[0].tagName, "1");
expect(handlerList[1].tagName, "3");
expect(handlerList[2].tagName, "2");
});
}

View File

@@ -1,9 +1,10 @@
import "package:moxxyv2/xmpp/managers/attributes.dart";
import "package:moxxyv2/xmpp/stringxml.dart";
import "package:moxxyv2/xmpp/events.dart";
import "package:moxxyv2/xmpp/stanza.dart";
import "package:moxxyv2/xmpp/settings.dart";
import "package:moxxyv2/xmpp/jid.dart";
import "package:moxxyv2/xmpp/managers/attributes.dart";
import "package:moxxyv2/xmpp/managers/data.dart";
import "package:moxxyv2/xmpp/xeps/xep_0198/xep_0198.dart";
import "package:moxxyv2/xmpp/xeps/xep_0198/state.dart";
@@ -11,6 +12,18 @@ import "../helpers/xml.dart";
import "package:test/test.dart";
Future<void> runIncomingStanzaHandlers(StreamManagementManager man, Stanza stanza) async {
for (final handler in man.getIncomingStanzaHandlers()) {
if (handler.matches(stanza)) await handler.callback(stanza, StanzaHandlerData(false, stanza));
}
}
Future<void> runOutgoingStanzaHandlers(StreamManagementManager man, Stanza stanza) async {
for (final handler in man.getOutgoingStanzaHandlers()) {
if (handler.matches(stanza)) await handler.callback(stanza, StanzaHandlerData(false, stanza));
}
}
void main() {
final stanza = Stanza(
to: "some.user@server.example",
@@ -46,14 +59,14 @@ void main() {
manager.onXmppEvent(StreamManagementEnabledEvent(id: "0", resource: "h"));
// Receive a fake stanza
await manager.runStanzaHandlers(stanza);
await manager.runStanzaHandlers(stanza);
await runIncomingStanzaHandlers(manager, stanza);
await runIncomingStanzaHandlers(manager, stanza);
expect(manager.state.s2c, 2, reason: "The S2C counter must count correctly");
// Send some fake stanzas
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
runOutgoingStanzaHandlers(manager, stanza);
runOutgoingStanzaHandlers(manager, stanza);
runOutgoingStanzaHandlers(manager, stanza);
expect(manager.state.c2s, 3, reason: "The C2S counter must count correctly");
final ack = XMLNode.xmlns(tag: "a", xmlns: "urn:xmpp:sm:3", attributes: { "h": "3" });
@@ -63,7 +76,7 @@ void main() {
expect(manager.state.s2c, 2, reason: "Sending stanzas must not change the S2C counter");
// Send a stanza which we will not acknowledge
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
runOutgoingStanzaHandlers(manager, stanza);
expect(manager.state.c2s, 4, reason: "Sending a stanza must increment the C2S counter");
await manager.runNonzaHandlers(ack);
manager.onTimerElapsed(null, ignoreTimestamps: true);
@@ -101,9 +114,9 @@ void main() {
manager.register(attributes);
// Send some stanzas
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
manager.onXmppEvent(StanzaSentEvent(stanza: stanza));
runOutgoingStanzaHandlers(manager, stanza);
runOutgoingStanzaHandlers(manager, stanza);
runOutgoingStanzaHandlers(manager, stanza);
// Simulate a resumption
manager.onXmppEvent(StreamResumedEvent(h: 2));

View File

@@ -9,8 +9,9 @@ import "package:moxxyv2/xmpp/presence.dart";
import "package:moxxyv2/xmpp/roster.dart";
import "package:moxxyv2/xmpp/events.dart";
import "package:moxxyv2/xmpp/managers/attributes.dart";
import "package:moxxyv2/xmpp/managers/handlers.dart";
import "package:moxxyv2/xmpp/managers/data.dart";
import "package:moxxyv2/xmpp/xeps/xep_0030/xep_0030.dart";
import "package:moxxyv2/xmpp/xeps/xep_0030/cachemanager.dart";
import "helpers/xmpp.dart";
@@ -40,14 +41,9 @@ Future<bool> testRosterManager(String bareJid, String resource, String stanzaStr
));
final stanza = Stanza.fromXMLNode(XMLNode.fromString(stanzaString));
await Future.forEach(
roster.getStanzaHandlers(),
(StanzaHandler handler) async {
if (handler.matches(stanza)) {
await handler.callback(stanza);
}
}
);
for (final handler in roster.getIncomingStanzaHandlers()) {
if (handler.matches(stanza)) await handler.callback(stanza, StanzaHandlerData(false, stanza));
}
return eventTriggered;
}
@@ -216,6 +212,7 @@ void main() {
),
]
);
// TODO: This test is broken since we query the server and enable carbons
final XmppConnection conn = XmppConnection(socket: fakeSocket);
conn.setConnectionSettings(ConnectionSettings(
jid: JID.fromString("polynomdivision@test.server"),
@@ -225,6 +222,7 @@ void main() {
));
conn.registerManager(RosterManager());
conn.registerManager(DiscoManager());
conn.registerManager(DiscoCacheManager());
conn.registerManager(PresenceManager());
await conn.connect();
@@ -509,14 +507,10 @@ void main() {
// NOTE: Based on https://gultsch.de/gajim_roster_push_and_message_interception.html
// NOTE: Added a from attribute as a server would add it itself.
final maliciousStanza = Stanza.fromXMLNode(XMLNode.fromString("<iq type=\"set\" from=\"eve@siacs.eu/bbbbb\" to=\"some.user@example.server/aaaaa\"><query xmlns='jabber:iq:roster'><item subscription=\"both\" jid=\"eve@siacs.eu\" name=\"Bob\" /></query></iq>"));
await Future.forEach(
roster.getStanzaHandlers(),
(StanzaHandler handler) async {
if (handler.matches(maliciousStanza)) {
await handler.callback(maliciousStanza);
}
}
);
for (final handler in roster.getIncomingStanzaHandlers()) {
if (handler.matches(maliciousStanza)) await handler.callback(maliciousStanza, StanzaHandlerData(false, maliciousStanza));
}
expect(eventTriggered, false, reason: "Was able to inject a malicious roster push");
});