feat(xep): Also potentially return "generic" stanza errors
This commit is contained in:
parent
77a1acb0e7
commit
a928c5c877
@ -17,6 +17,7 @@
|
||||
- **BREAKING**: Removed `PresenceReceivedEvent`. Use a manager registering handlers with priority greater than `[PresenceManager.presenceHandlerPriority]` instead.
|
||||
- **BREAKING**: `ChatState.toString()` is now `ChatState.toName()`
|
||||
- **BREAKING**: Overriding `BaseOmemoManager` is no longer required. `OmemoManager` now takes callback methods instead.
|
||||
- Removed `ErrorResponseDiscoError` from the possible XEP-0030 errors.
|
||||
|
||||
## 0.3.1
|
||||
|
||||
|
@ -47,28 +47,57 @@ class StanzaDetails {
|
||||
final TypedMap<StanzaHandlerExtension>? postSendExtensions;
|
||||
}
|
||||
|
||||
/// A simple description of the <error /> element that may be inside a stanza
|
||||
class StanzaError {
|
||||
StanzaError(this.type, this.error);
|
||||
String type;
|
||||
String error;
|
||||
/// A general error type for errors.
|
||||
abstract class StanzaError {
|
||||
static StanzaError? fromXMLNode(XMLNode node) {
|
||||
final error = node.firstTag('error');
|
||||
if (error == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final specificError = error.firstTagByXmlns(fullStanzaXmlns);
|
||||
if (specificError == null) {
|
||||
return UnknownStanzaError();
|
||||
}
|
||||
|
||||
switch (specificError.tag) {
|
||||
case RemoteServerNotFoundError.tag:
|
||||
return RemoteServerNotFoundError();
|
||||
case RemoteServerTimeoutError.tag:
|
||||
return RemoteServerTimeoutError();
|
||||
case ServiceUnavailableError.tag:
|
||||
return ServiceUnavailableError();
|
||||
}
|
||||
|
||||
return UnknownStanzaError();
|
||||
}
|
||||
|
||||
/// Returns a StanzaError if [stanza] contains a <error /> element. If not, returns
|
||||
/// null.
|
||||
static StanzaError? fromStanza(Stanza stanza) {
|
||||
final error = stanza.firstTag('error');
|
||||
if (error == null) return null;
|
||||
|
||||
final stanzaError = error.firstTagByXmlns(fullStanzaXmlns);
|
||||
if (stanzaError == null) return null;
|
||||
|
||||
return StanzaError(
|
||||
error.attributes['type']! as String,
|
||||
stanzaError.tag,
|
||||
);
|
||||
return fromXMLNode(stanza);
|
||||
}
|
||||
}
|
||||
|
||||
/// Recipient does not provide a given service.
|
||||
/// https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions-service-unavailable
|
||||
class ServiceUnavailableError extends StanzaError {
|
||||
static const tag = 'service-unavailable';
|
||||
}
|
||||
|
||||
/// Could not connect to the remote server.
|
||||
/// https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions-remote-server-not-found
|
||||
class RemoteServerNotFoundError extends StanzaError {
|
||||
static const tag = 'remote-server-not-found';
|
||||
}
|
||||
|
||||
/// The connection to the remote server timed out.
|
||||
/// https://xmpp.org/rfcs/rfc6120.html#stanzas-error-conditions-remote-server-timeout
|
||||
class RemoteServerTimeoutError extends StanzaError {
|
||||
static const tag = 'remote-server-timeout';
|
||||
}
|
||||
|
||||
/// An unknown error.
|
||||
class UnknownStanzaError extends StanzaError {}
|
||||
|
||||
class Stanza extends XMLNode {
|
||||
// ignore: use_super_parameters
|
||||
Stanza({
|
||||
|
@ -1,7 +1,10 @@
|
||||
abstract class DiscoError {}
|
||||
import 'package:moxxmpp/src/stanza.dart';
|
||||
|
||||
/// Base type for disco-related errors.
|
||||
abstract class DiscoError extends StanzaError {}
|
||||
|
||||
/// An unspecified error that is not covered by another [DiscoError].
|
||||
class UnknownDiscoError extends DiscoError {}
|
||||
|
||||
/// The received disco response is invalid in some shape or form.
|
||||
class InvalidResponseDiscoError extends DiscoError {}
|
||||
|
||||
class ErrorResponseDiscoError extends DiscoError {}
|
||||
|
@ -44,11 +44,11 @@ class DiscoManager extends XmppManagerBase {
|
||||
final Map<DiscoCacheKey, DiscoInfo> _discoInfoCache = {};
|
||||
|
||||
/// The tracker for tracking disco#info queries that are in flight.
|
||||
final WaitForTracker<DiscoCacheKey, Result<DiscoError, DiscoInfo>>
|
||||
final WaitForTracker<DiscoCacheKey, Result<StanzaError, DiscoInfo>>
|
||||
_discoInfoTracker = WaitForTracker();
|
||||
|
||||
/// The tracker for tracking disco#info queries that are in flight.
|
||||
final WaitForTracker<DiscoCacheKey, Result<DiscoError, List<DiscoItem>>>
|
||||
final WaitForTracker<DiscoCacheKey, Result<StanzaError, List<DiscoItem>>>
|
||||
_discoItemsTracker = WaitForTracker();
|
||||
|
||||
/// Cache lock
|
||||
@ -67,7 +67,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
List<String> get features => _features;
|
||||
|
||||
@visibleForTesting
|
||||
WaitForTracker<DiscoCacheKey, Result<DiscoError, DiscoInfo>>
|
||||
WaitForTracker<DiscoCacheKey, Result<StanzaError, DiscoInfo>>
|
||||
get infoTracker => _discoInfoTracker;
|
||||
|
||||
@override
|
||||
@ -231,7 +231,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
|
||||
Future<void> _exitDiscoInfoCriticalSection(
|
||||
DiscoCacheKey key,
|
||||
Result<DiscoError, DiscoInfo> result,
|
||||
Result<StanzaError, DiscoInfo> result,
|
||||
bool shouldCache,
|
||||
) async {
|
||||
await _cacheLock.synchronized(() async {
|
||||
@ -252,7 +252,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
///
|
||||
/// [shouldCache] indicates whether the successful result of the disco#info query
|
||||
/// should be cached (true) or not(false).
|
||||
Future<Result<DiscoError, DiscoInfo>> discoInfoQuery(
|
||||
Future<Result<StanzaError, DiscoInfo>> discoInfoQuery(
|
||||
JID entity, {
|
||||
String? node,
|
||||
bool shouldEncrypt = false,
|
||||
@ -263,7 +263,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
final ecm = getAttributes()
|
||||
.getManagerById<EntityCapabilitiesManager>(entityCapabilitiesManager);
|
||||
final ffuture = await _cacheLock
|
||||
.synchronized<Future<Future<Result<DiscoError, DiscoInfo>>?>?>(
|
||||
.synchronized<Future<Future<Result<StanzaError, DiscoInfo>>?>?>(
|
||||
() async {
|
||||
// Check if we already know what the JID supports
|
||||
if (_discoInfoCache.containsKey(cacheKey)) {
|
||||
@ -297,16 +297,18 @@ class DiscoManager extends XmppManagerBase {
|
||||
shouldEncrypt: shouldEncrypt,
|
||||
),
|
||||
))!;
|
||||
final query = stanza.firstTag('query');
|
||||
if (query == null) {
|
||||
final result = Result<DiscoError, DiscoInfo>(InvalidResponseDiscoError());
|
||||
|
||||
// Error handling
|
||||
if (stanza.attributes['type'] == 'error') {
|
||||
final result =
|
||||
Result<StanzaError, DiscoInfo>(StanzaError.fromXMLNode(stanza));
|
||||
await _exitDiscoInfoCriticalSection(cacheKey, result, shouldCache);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (stanza.attributes['type'] == 'error') {
|
||||
//final error = stanza.firstTag('error');
|
||||
final result = Result<DiscoError, DiscoInfo>(ErrorResponseDiscoError());
|
||||
final query = stanza.firstTag('query');
|
||||
if (query == null) {
|
||||
final result = Result<DiscoError, DiscoInfo>(InvalidResponseDiscoError());
|
||||
await _exitDiscoInfoCriticalSection(cacheKey, result, shouldCache);
|
||||
return result;
|
||||
}
|
||||
@ -322,7 +324,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
}
|
||||
|
||||
/// Sends a disco items query to the (full) jid [entity], optionally with node=[node].
|
||||
Future<Result<DiscoError, List<DiscoItem>>> discoItemsQuery(
|
||||
Future<Result<StanzaError, List<DiscoItem>>> discoItemsQuery(
|
||||
JID entity, {
|
||||
String? node,
|
||||
bool shouldEncrypt = false,
|
||||
@ -340,19 +342,18 @@ class DiscoManager extends XmppManagerBase {
|
||||
),
|
||||
))!;
|
||||
|
||||
final query = stanza.firstTag('query');
|
||||
if (query == null) {
|
||||
// Error handling
|
||||
if (stanza.attributes['type'] == 'error') {
|
||||
final result =
|
||||
Result<DiscoError, List<DiscoItem>>(InvalidResponseDiscoError());
|
||||
Result<StanzaError, List<DiscoItem>>(StanzaError.fromXMLNode(stanza));
|
||||
await _discoItemsTracker.resolve(key, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (stanza.attributes['type'] == 'error') {
|
||||
//final error = stanza.firstTag('error');
|
||||
//print("Disco Items error: " + error.toXml());
|
||||
final query = stanza.firstTag('query');
|
||||
if (query == null) {
|
||||
final result =
|
||||
Result<DiscoError, List<DiscoItem>>(ErrorResponseDiscoError());
|
||||
Result<DiscoError, List<DiscoItem>>(InvalidResponseDiscoError());
|
||||
await _discoItemsTracker.resolve(key, result);
|
||||
return result;
|
||||
}
|
||||
@ -419,7 +420,7 @@ class DiscoManager extends XmppManagerBase {
|
||||
/// [entity] supports the disco feature [feature]. If not, returns false.
|
||||
Future<bool> supportsFeature(JID entity, String feature) async {
|
||||
final info = await discoInfoQuery(entity);
|
||||
if (info.isType<DiscoError>()) return false;
|
||||
if (info.isType<StanzaError>()) return false;
|
||||
|
||||
return info.get<DiscoInfo>().features.contains(feature);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user