fix: Roster request being treated as a roster push

This commit is contained in:
PapaTutuWawa 2023-01-07 21:23:45 +01:00
parent 09d2601e85
commit 678564dbb3
6 changed files with 36 additions and 16 deletions

View File

@ -94,6 +94,7 @@ class XmppConnection {
_awaitingResponseLock = Lock(), _awaitingResponseLock = Lock(),
_xmppManagers = {}, _xmppManagers = {},
_incomingStanzaHandlers = List.empty(growable: true), _incomingStanzaHandlers = List.empty(growable: true),
_incomingEncryptionStanzaHandlers = List.empty(growable: true),
_outgoingPreStanzaHandlers = List.empty(growable: true), _outgoingPreStanzaHandlers = List.empty(growable: true),
_outgoingPostStanzaHandlers = List.empty(growable: true), _outgoingPostStanzaHandlers = List.empty(growable: true),
_reconnectionPolicy = reconnectionPolicy, _reconnectionPolicy = reconnectionPolicy,
@ -133,6 +134,7 @@ class XmppConnection {
/// Helpers /// Helpers
/// ///
final List<StanzaHandler> _incomingStanzaHandlers; final List<StanzaHandler> _incomingStanzaHandlers;
final List<StanzaHandler> _incomingEncryptionStanzaHandlers;
final List<StanzaHandler> _outgoingPreStanzaHandlers; final List<StanzaHandler> _outgoingPreStanzaHandlers;
final List<StanzaHandler> _outgoingPostStanzaHandlers; final List<StanzaHandler> _outgoingPostStanzaHandlers;
final StreamController<XmppEvent> _eventStreamController; final StreamController<XmppEvent> _eventStreamController;
@ -223,11 +225,13 @@ class XmppConnection {
} }
_incomingStanzaHandlers.addAll(manager.getIncomingStanzaHandlers()); _incomingStanzaHandlers.addAll(manager.getIncomingStanzaHandlers());
_incomingEncryptionStanzaHandlers.addAll(manager.getIncomingEncryptionStanzaHandlers());
_outgoingPreStanzaHandlers.addAll(manager.getOutgoingPreStanzaHandlers()); _outgoingPreStanzaHandlers.addAll(manager.getOutgoingPreStanzaHandlers());
_outgoingPostStanzaHandlers.addAll(manager.getOutgoingPostStanzaHandlers()); _outgoingPostStanzaHandlers.addAll(manager.getOutgoingPostStanzaHandlers());
if (sortHandlers) { if (sortHandlers) {
_incomingStanzaHandlers.sort(stanzaHandlerSortComparator); _incomingStanzaHandlers.sort(stanzaHandlerSortComparator);
_incomingEncryptionStanzaHandlers.sort(stanzaHandlerSortComparator);
_outgoingPreStanzaHandlers.sort(stanzaHandlerSortComparator); _outgoingPreStanzaHandlers.sort(stanzaHandlerSortComparator);
_outgoingPostStanzaHandlers.sort(stanzaHandlerSortComparator); _outgoingPostStanzaHandlers.sort(stanzaHandlerSortComparator);
} }
@ -634,6 +638,10 @@ class XmppConnection {
return _runStanzaHandlers(_incomingStanzaHandlers, stanza); return _runStanzaHandlers(_incomingStanzaHandlers, stanza);
} }
Future<StanzaHandlerData> _runIncomingEncryptionStanzaHandlers(Stanza stanza) async {
return _runStanzaHandlers(_incomingEncryptionStanzaHandlers, stanza);
}
Future<StanzaHandlerData> _runOutgoingPreStanzaHandlers(Stanza stanza, { StanzaHandlerData? initial }) async { Future<StanzaHandlerData> _runOutgoingPreStanzaHandlers(Stanza stanza, { StanzaHandlerData? initial }) async {
return _runStanzaHandlers(_outgoingPreStanzaHandlers, stanza, initial: initial); return _runStanzaHandlers(_outgoingPreStanzaHandlers, stanza, initial: initial);
} }
@ -673,18 +681,18 @@ class XmppConnection {
// Run the incoming stanza handlers and bounce with an error if no manager handled // Run the incoming stanza handlers and bounce with an error if no manager handled
// it. // it.
final incomingHandlers = await _runIncomingStanzaHandlers(stanza); final incomingEncryptionHandlers = await _runIncomingEncryptionStanzaHandlers(stanza);
final prefix = incomingHandlers.encrypted ? final prefix = incomingEncryptionHandlers.encrypted ?
'(Encrypted) ' : '(Encrypted) ' :
''; '';
_log.finest('<== $prefix${incomingHandlers.stanza.toXml()}'); _log.finest('<== $prefix${incomingEncryptionHandlers.stanza.toXml()}');
// See if we are waiting for this stanza // See if we are waiting for this stanza
final id = stanza.attributes['id'] as String?; final id = incomingEncryptionHandlers.stanza.attributes['id'] as String?;
var awaited = false; var awaited = false;
await _awaitingResponseLock.synchronized(() async { await _awaitingResponseLock.synchronized(() async {
if (id != null && _awaitingResponse.containsKey(id)) { if (id != null && _awaitingResponse.containsKey(id)) {
_awaitingResponse[id]!.complete(incomingHandlers.stanza); _awaitingResponse[id]!.complete(incomingEncryptionHandlers.stanza);
_awaitingResponse.remove(id); _awaitingResponse.remove(id);
awaited = true; awaited = true;
} }
@ -695,6 +703,7 @@ class XmppConnection {
} }
// Only bounce if the stanza has neither been awaited, nor handled. // Only bounce if the stanza has neither been awaited, nor handled.
final incomingHandlers = await _runIncomingStanzaHandlers(incomingEncryptionHandlers.stanza);
if (!incomingHandlers.done) { if (!incomingHandlers.done) {
handleUnhandledStanza(this, stanza); handleUnhandledStanza(this, stanza);
} }

View File

@ -31,6 +31,10 @@ abstract class XmppManagerBase {
/// Return the StanzaHandlers associated with this manager that deal with stanzas we /// Return the StanzaHandlers associated with this manager that deal with stanzas we
/// receive. /// receive.
List<StanzaHandler> getIncomingStanzaHandlers() => []; List<StanzaHandler> getIncomingStanzaHandlers() => [];
/// Return the StanzaHandlers associated with this manager that deal with stanzas we
/// may decrypt.
List<StanzaHandler> getIncomingEncryptionStanzaHandlers() => [];
/// Return the NonzaHandlers associated with this manager. /// Return the NonzaHandlers associated with this manager.
List<NonzaHandler> getNonzaHandlers() => []; List<NonzaHandler> getNonzaHandlers() => [];

View File

@ -139,6 +139,7 @@ class RosterManager extends XmppManagerBase {
} }
final query = stanza.firstTag('query', xmlns: rosterXmlns)!; final query = stanza.firstTag('query', xmlns: rosterXmlns)!;
logger.fine('Roster push: ${query.toXml()}');
final item = query.firstTag('item'); final item = query.firstTag('item');
if (item == null) { if (item == null) {
@ -199,28 +200,34 @@ class RosterManager extends XmppManagerBase {
return Result(result); return Result(result);
} }
/// Requests the roster following RFC 6121 without using roster versioning. /// Requests the roster following RFC 6121.
Future<Result<RosterRequestResult, RosterError>> requestRoster() async { Future<Result<RosterRequestResult, RosterError>> requestRoster() async {
final attrs = getAttributes(); final attrs = getAttributes();
final query = XMLNode.xmlns(
tag: 'query',
xmlns: rosterXmlns,
);
final rosterVersion = await _stateManager.getRosterVersion();
if (rosterVersion != null && rosterVersioningAvailable()) {
query.attributes['ver'] = rosterVersion;
}
final response = await attrs.sendStanza( final response = await attrs.sendStanza(
Stanza.iq( Stanza.iq(
type: 'get', type: 'get',
children: [ children: [
XMLNode.xmlns( query,
tag: 'query',
xmlns: rosterXmlns,
)
], ],
), ),
); );
if (response.attributes['type'] != 'result') { if (response.attributes['type'] != 'result') {
logger.warning('Error requesting roster without roster versioning: ${response.toXml()}'); logger.warning('Error requesting roster: ${response.toXml()}');
return Result(UnknownError()); return Result(UnknownError());
} }
final query = response.firstTag('query', xmlns: rosterXmlns); final responseQuery = response.firstTag('query', xmlns: rosterXmlns);
return _handleRosterResponse(query); return _handleRosterResponse(responseQuery);
} }
/// Requests a series of roster pushes according to RFC6121. Requires that the server /// Requests a series of roster pushes according to RFC6121. Requires that the server

View File

@ -173,7 +173,7 @@ abstract class BaseRosterStateManager {
final added = List<XmppRosterItem>.empty(growable: true); final added = List<XmppRosterItem>.empty(growable: true);
await _loadRosterCache(); await _loadRosterCache();
_currentVersion = result.ver; _currentVersion = result.ver;
for (final item in result.items) { for (final item in result.items) {
final result = _handleRosterItem(item); final result = _handleRosterItem(item);

View File

@ -53,7 +53,7 @@ abstract class BaseOmemoManager extends XmppManagerBase {
Future<bool> isSupported() async => true; Future<bool> isSupported() async => true;
@override @override
List<StanzaHandler> getIncomingStanzaHandlers() => [ List<StanzaHandler> getIncomingEncryptionStanzaHandlers() => [
StanzaHandler( StanzaHandler(
stanzaTag: 'iq', stanzaTag: 'iq',
tagXmlns: omemoXmlns, tagXmlns: omemoXmlns,

View File

@ -8,7 +8,7 @@ environment:
sdk: '>=2.17.5 <3.0.0' sdk: '>=2.17.5 <3.0.0'
dependencies: dependencies:
collection: ^1.17.0 collection: ^1.16.0
cryptography: ^2.0.5 cryptography: ^2.0.5
freezed: ^2.1.0+1 freezed: ^2.1.0+1
freezed_annotation: ^2.1.0 freezed_annotation: ^2.1.0