xmpp: Make stream resumption send the last h value

This commit is contained in:
PapaTutuWawa 2022-01-02 12:52:15 +01:00
parent d3bc449ced
commit af89387b3b
4 changed files with 42 additions and 14 deletions

View File

@ -89,6 +89,7 @@ class XmppConnection {
// final List<String> _serverFeatures = List.empty(growable: true);
late RoutingState _routingState;
late String _resource;
late String _dataBuffer;
// Negotiators
late final AuthenticationNegotiator _authenticator;
@ -106,6 +107,7 @@ class XmppConnection {
this._eventStreamController = StreamController();
this._resource = "";
this._dataBuffer = "";
}
// Returns true if the stream supports the XMLNS @feature.
@ -169,22 +171,33 @@ class XmppConnection {
}
void _filterOutStreamBegin(data, EventSink sink) {
if (data.startsWith("<?xml version='1.0'?>")) {
data = data.substring(21);
String toParse = this._dataBuffer + data;
if (toParse.startsWith("<?xml version='1.0'?>")) {
toParse = toParse.substring(21);
}
if (data.startsWith("<stream:stream")) {
data = data + "</stream:stream>";
if (toParse.startsWith("<stream:stream")) {
toParse = toParse + "</stream:stream>";
} else {
if (data.endsWith("</stream:stream>")) {
if (toParse.endsWith("</stream:stream>")) {
// TODO: Maybe destroy the stream
data = data.substring(0, data.length - 16);
toParse = toParse.substring(0, toParse.length - 16);
}
}
XmlDocument
.parse("<root>$data</root>")
.getElement("root")!
// TODO: Test this
final document;
try {
document = XmlDocument.parse("<root>$toParse</root>");
this._dataBuffer = "";
} catch (ex) {
// TODO: Maybe don't just assume that we haven't received everything, i.e. check the
// error message
this._dataBuffer = this._dataBuffer + data;
return;
}
document.getElement("root")!
.childElements
.forEach((element) => sink.add(XMLNode.fromXmlElement(element)));
}
@ -344,7 +357,7 @@ class XmppConnection {
// Try to resume the last stream
// TODO
this._routingState = RoutingState.PERFORM_STREAM_RESUMPTION;
this.sendRawXML(StreamManagementResumeNonza(this.settings.streamResumptionId!, 0 /*TODO*/));
this.sendRawXML(StreamManagementResumeNonza(this.settings.streamResumptionId!, this.settings.lasth!));
} else {
// Try to enable SM
this._routingState = RoutingState.BIND_RESOURCE_PRE_SM;
@ -368,6 +381,7 @@ class XmppConnection {
// TODO: Synchronize the h values
if (node.tag == "resumed") {
print("Stream Resumption successful!");
this.sendEvent(StreamManagementResumptionSuccessfulEvent());
this._resource = this.settings.resource!;
this._routingState = RoutingState.HANDLE_STANZAS;
this._setConnectionState(ConnectionState.CONNECTED);
@ -390,7 +404,7 @@ class XmppConnection {
final id = node.attributes["id"];
if (id != null && [ "true", "1" ].indexOf(node.attributes["resume"]) != -1) {
print("Stream resumption possible!");
this.sendEvent(StreamResumptionEvent(id: id, resource: this._resource));
this.sendEvent(StreamManagementEnabledEvent(id: id, resource: this._resource));
}
this.streamManager = StreamManager(connection: this, streamResumptionId: id);

View File

@ -33,9 +33,20 @@ class ChatMarkerEvent extends XmppEvent {
}
// Triggered when we received a Stream resumption ID
class StreamResumptionEvent extends XmppEvent {
// TODO: Make the id optional since a server doesn't have to support resumption
class StreamManagementEnabledEvent extends XmppEvent {
final String resource;
final String id;
StreamResumptionEvent({ required this.id, required this.resource });
StreamManagementEnabledEvent({ required this.id, required this.resource });
}
// Triggered when we send out an ack
class StreamManagementAckSentEvent extends XmppEvent {
final int h;
StreamManagementAckSentEvent({ required this.h });
}
// Triggered when we were able to successfully resume a stream
class StreamManagementResumptionSuccessfulEvent extends XmppEvent {}

View File

@ -6,7 +6,8 @@ class ConnectionSettings {
final bool useDirectTLS;
final bool allowPlainAuth;
final String? streamResumptionId;
final int? lasth;
final String? resource;
ConnectionSettings({ required this.jid, required this.password, required this.useDirectTLS, required this.allowPlainAuth, this.streamResumptionId, this.resource });
ConnectionSettings({ required this.jid, required this.password, required this.useDirectTLS, required this.allowPlainAuth, this.streamResumptionId, this.resource, this.lasth });
}

View File

@ -1,6 +1,7 @@
import "dart:collection";
import "dart:math";
import "package:moxxyv2/xmpp/events.dart";
import "package:moxxyv2/xmpp/stanzas/stanza.dart";
import "package:moxxyv2/xmpp/nonzas/sm.dart";
import "package:moxxyv2/xmpp/connection.dart";
@ -21,6 +22,7 @@ class StreamManager {
bool canResume() => this.streamResumptionId != "";
void handleAckRequest() {
this.connection.sendEvent(StreamManagementAckSentEvent(h: this._serverStanzaSeq - 1));
this.connection.sendRawXML(StreamManagementAckNonza(this._serverStanzaSeq - 1));
}