diff options
Diffstat (limited to 'vala-xmpp/src/module/stream_error.vala')
-rw-r--r-- | vala-xmpp/src/module/stream_error.vala | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/vala-xmpp/src/module/stream_error.vala b/vala-xmpp/src/module/stream_error.vala new file mode 100644 index 00000000..73e2bb36 --- /dev/null +++ b/vala-xmpp/src/module/stream_error.vala @@ -0,0 +1,119 @@ +using Gee; + +using Xmpp.Core; + +namespace Xmpp.StreamError { + private const string NS_URI = "jabber:client"; + private const string NS_ERROR = "urn:ietf:params:xml:ns:xmpp-streams"; + + public class Module : XmppStreamModule { + public const string ID = "stream_error_module"; + + public override void attach(XmppStream stream) { + stream.received_nonza.connect(on_received_nonstanza); + } + + public override void detach(XmppStream stream) { + stream.received_nonza.disconnect(on_received_nonstanza); + } + + public static Module? get_module(XmppStream stream) { + return (Module?) stream.get_module(NS_URI, ID); + } + + public static void require(XmppStream stream) { + if (get_module(stream) == null) stream.add_module(new StreamError.Module()); + } + + public override string get_ns() { return NS_URI; } + public override string get_id() { return ID; } + + private void on_received_nonstanza(XmppStream stream, StanzaNode node) { + if (node.name == "error" && node.ns_uri == "http://etherx.jabber.org/streams") { + stream.add_flag(generate_error_flag(node)); + } + } + + private Flag generate_error_flag(StanzaNode node) { + string? subnode_name = null; + ArrayList<StanzaNode> subnodes = node.sub_nodes; + foreach (StanzaNode subnode in subnodes) { // TODO get subnode by ns + if (subnode.ns_uri == "urn:ietf:params:xml:ns:xmpp-streams" && subnode.name != "text") { + subnode_name = subnode.name; + } + } + Flag flag = new StreamError.Flag(); + flag.error_type = subnode_name; + switch (subnode_name) { + case "bad-format": + case "conflict": + case "connection-timeout": + case "bad-namespace-prefix": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.NOW; + break; + case "host-gone": + case "host-unknown": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.LATER; + break; + case "improper-addressing": + case "internal-server-error": + case "invalid-from": + case "invalid-namespace": + case "invalid-xml": + case "not-authorized": + case "not-well-formed": + case "policy-violation": + case "remote-connection-failed": + case "reset": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.NOW; + break; + case "resource-constraint": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.LATER; + break; + case "restricted-xml": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.NOW; + break; + case "see-other-host": + case "system-shutdown": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.LATER; + break; + case "undefined-condition": + case "unsupported-encoding": + case "unsupported-feature": + case "unsupported-stanza-type": + case "unsupported-version": + flag.reconnection_recomendation = StreamError.Flag.Reconnect.NOW; + break; + } + + if (subnode_name == "conflict") flag.resource_rejected = true; + return flag; + } + } + + public class Flag : XmppStreamFlag { + public const string ID = "stream_error"; + + public enum Reconnect { + UNKNOWN, + NOW, + LATER, + NEVER + } + + public string? error_type; + public Reconnect reconnection_recomendation = Reconnect.UNKNOWN; + public bool resource_rejected = false; + + public static Flag? get_flag(XmppStream stream) { + return (Flag?) stream.get_flag(NS_URI, ID); + } + + public static bool has_flag(XmppStream stream) { + return get_flag(stream) != null; + } + + public override string get_ns() { return NS_URI; } + public override string get_id() { return ID; } + } +} |