| author | Stephen Paul Weber
<singpolyma@singpolyma.net> 2023-10-14 23:53:58 UTC |
| committer | Stephen Paul Weber
<singpolyma@singpolyma.net> 2023-10-14 23:53:58 UTC |
| parent | c887f7d7f632fe1d13eba19f2c637db26c42be7e |
| xmpp/Caps.hx | +3 | -9 |
| xmpp/Client.hx | +46 | -51 |
| xmpp/GenericStream.hx | +8 | -11 |
| xmpp/Stanza.hx | +5 | -0 |
| xmpp/streams/XmppJsStream.hx | +22 | -1 |
diff --git a/xmpp/Caps.hx b/xmpp/Caps.hx index cc57ba8..b3fe1c1 100644 --- a/xmpp/Caps.hx +++ b/xmpp/Caps.hx @@ -41,21 +41,15 @@ class Caps { this.features = features; } - public function discoReply(stanza: Stanza):Stanza { - final reply = new Stanza("iq", { - type: "result", - id: stanza.attr.get("id"), - to: stanza.attr.get("from") - }); - final query = reply.tag("query", { xmlns: "http://jabber.org/protocol/disco#info" }); + public function discoReply():Stanza { + final query = new Stanza("query", { xmlns: "http://jabber.org/protocol/disco#info" }); for (identity in identities) { identity.addToDisco(query); } for (feature in features) { query.tag("feature", { "var": feature }).up(); } - query.up(); - return reply; + return query; } public function addC(stanza: Stanza): Stanza { diff --git a/xmpp/Client.hx b/xmpp/Client.hx index d0b90d6..157409d 100644 --- a/xmpp/Client.hx +++ b/xmpp/Client.hx @@ -53,6 +53,10 @@ class Client extends xmpp.EventEmitter { stream.on("status/online", this.onConnected); } + public function accountId() { + return JID.parse(jid).asBare().asString(); + } + public function start() { persistence.getChats(jid, (protoChats) -> { for (protoChat in protoChats) { @@ -175,75 +179,73 @@ class Client extends xmpp.EventEmitter { return EventUnhandled; // Allow others to get this event as well }); - this.stream.on("iq", function(event) { - final stanza:Stanza = event.stanza; + this.stream.onIq(Set, "jingle", "urn:xmpp:jingle:1", (stanza) -> { final from = stanza.attr.get("from") == null ? null : JID.parse(stanza.attr.get("from")); - final jingle = stanza.getChild("jingle", "urn:xmpp:jingle:1"); - if (stanza.attr.get("type") == "set" && jingle != null) { - // First, jingle requires useless replies to every iq - sendStanza(new Stanza("iq", { type: "result", to: stanza.attr.get("from"), id: stanza.attr.get("id") })); - final chat = getDirectChat(from.asBare().asString()); - final session = chat.jingleSessions.get(jingle.attr.get("sid")); - - if (jingle.attr.get("action") == "session-initiate") { - if (session != null) { - try { - chat.jingleSessions.set(session.sid, session.initiate(stanza)); - } catch (e) { - chat.jingleSessions.remove(session.sid); - } - } else { - final newSession = xmpp.jingle.InitiatedSession.fromSessionInitiate(this, stanza); - chat.jingleSessions.set(newSession.sid, newSession); - chatActivity(chat); - newSession.ring(); - } - } + final chat = getDirectChat(from.asBare().asString()); + final session = chat.jingleSessions.get(jingle.attr.get("sid")); - if (session != null && jingle.attr.get("action") == "session-accept") { + if (jingle.attr.get("action") == "session-initiate") { + if (session != null) { try { chat.jingleSessions.set(session.sid, session.initiate(stanza)); } catch (e) { - trace("session-accept failed", e); + chat.jingleSessions.remove(session.sid); } + } else { + final newSession = xmpp.jingle.InitiatedSession.fromSessionInitiate(this, stanza); + chat.jingleSessions.set(newSession.sid, newSession); + chatActivity(chat); + newSession.ring(); } + } - if (session != null && jingle.attr.get("action") == "session-terminate") { - session.terminate(); - chat.jingleSessions.remove(jingle.attr.get("sid")); + if (session != null && jingle.attr.get("action") == "session-accept") { + try { + chat.jingleSessions.set(session.sid, session.initiate(stanza)); + } catch (e) { + trace("session-accept failed", e); } + } - if (session != null && jingle.attr.get("action") == "content-add") { - session.contentAdd(stanza); - } + if (session != null && jingle.attr.get("action") == "session-terminate") { + session.terminate(); + chat.jingleSessions.remove(jingle.attr.get("sid")); + } - if (session != null && jingle.attr.get("action") == "content-accept") { - session.contentAccept(stanza); - } + if (session != null && jingle.attr.get("action") == "content-add") { + session.contentAdd(stanza); + } - if (session != null && jingle.attr.get("action") == "transport-info") { - session.transportInfo(stanza); - } - return EventHandled; + if (session != null && jingle.attr.get("action") == "content-accept") { + session.contentAccept(stanza); } - if (stanza.attr.get("type") == "get" && stanza.getChild("query", "http://jabber.org/protocol/disco#info") != null) { - stream.sendStanza(caps.discoReply(stanza)); - return EventHandled; + if (session != null && jingle.attr.get("action") == "transport-info") { + session.transportInfo(stanza); } + // jingle requires useless replies to every iq + return IqResult; + }); + + + this.stream.onIq(Get, "query", "http://jabber.org/protocol/disco#info", (stanza) -> { + return IqResultElement(caps.discoReply()); + }); + + this.stream.onIq(Set, "query", "jabber:iq:roster", (stanza) -> { if ( stanza.attr.get("from") != null && stanza.attr.get("from") != JID.parse(jid).domain ) { - return EventUnhandled; + return IqNoResult; } var roster = new RosterGet(); roster.handleResponse(stanza); var items = roster.getResult(); - if (items.length == 0) return EventUnhandled; + if (items.length == 0) return IqNoResult; for (item in items) { if (item.subscription != "remove") { @@ -253,14 +255,7 @@ class Client extends xmpp.EventEmitter { } this.trigger("chats/update", chats); - var reply = new Stanza("iq", { - type: "result", - id: stanza.attr.get("id"), - to: stanza.attr.get("from") - }); - sendStanza(reply); - - return EventHandled; + return IqResult; }); this.stream.on("presence", function(event) { diff --git a/xmpp/GenericStream.hx b/xmpp/GenericStream.hx index a1e8aea..f025879 100644 --- a/xmpp/GenericStream.hx +++ b/xmpp/GenericStream.hx @@ -3,6 +3,12 @@ package xmpp; import xmpp.Stanza; import xmpp.EventEmitter; +enum IqResult { + IqResultElement(element:Stanza); + IqResult; + IqNoResult; +} + abstract class GenericStream extends EventEmitter { public function new() { @@ -14,6 +20,7 @@ abstract class GenericStream extends EventEmitter { abstract public function connect(jid:String):Void; abstract public function sendStanza(stanza:Stanza):Void; abstract public function newId():String; + abstract public function onIq(type:IqRequestType, tag:String, xmlns:String, handler:(Stanza)->IqResult):Void; public function sendIq(stanza:Stanza, callback:(stanza:Stanza)->Void):Void { var id = newId(); @@ -37,17 +44,7 @@ abstract class GenericStream extends EventEmitter { var id = stanza.attr.get("id"); trigger('iq-response/$id', { stanza: stanza }); } else { - if (trigger('iq', { stanza: stanza }) == EventUnhandled) { - var reply = new Stanza("iq", { - type: "error", - id: stanza.attr.get("id"), - to: stanza.attr.get("from") - }) - .tag("error", { type: "cancel" }) - .tag("service-unavailable", { xmlns: "urn:ietf:params:xml:ns:xmpp-stanzas" }) - .up().up(); - sendStanza(reply); - } + // These are handled by onIq instead } } else if (name == "message" || name == "presence") { trigger(name, { stanza: stanza }); diff --git a/xmpp/Stanza.hx b/xmpp/Stanza.hx index 7e10bb0..8916de4 100644 --- a/xmpp/Stanza.hx +++ b/xmpp/Stanza.hx @@ -278,3 +278,8 @@ class Stanza implements NodeInterface { }; } } + +enum IqRequestType { + Get; + Set; +} diff --git a/xmpp/streams/XmppJsStream.hx b/xmpp/streams/XmppJsStream.hx index 201e78c..1d85252 100644 --- a/xmpp/streams/XmppJsStream.hx +++ b/xmpp/streams/XmppJsStream.hx @@ -14,9 +14,13 @@ extern class XmppJsClient { function start():Promise<Dynamic>; function on(eventName:String, callback:(Dynamic)->Void):Void; function send(stanza:XmppJsXml):Void; + var iqCallee:{ + get: (String, String, ({stanza: XmppJsXml})->Any)->Void, + set: (String, String, ({stanza: XmppJsXml})->Any)->Void, + }; } -@:jsRequire("@xmpp/jid", "JID") +@:jsRequire("@xmpp/jid", "jid") extern class XmppJsJID { function new(jid:String); function toString():String; @@ -201,6 +205,23 @@ class XmppJsStream extends GenericStream { return XmppJsId.id(); } + private function fromIqResult(result: IqResult): Any { + switch (result) { + case IqResultElement(el): return convertFromStanza(el); + case IqResult: return true; + case IqNoResult: return false; + } + } + + public function onIq(type:IqRequestType, tag:String, xmlns:String, handler:(Stanza)->IqResult) { + switch (type) { + case Get: + client.iqCallee.get(xmlns, tag, (el) -> fromIqResult(handler(convertToStanza(el.stanza)))); + case Set: + client.iqCallee.set(xmlns, tag, (el) -> fromIqResult(handler(convertToStanza(el.stanza)))); + } + } + /* State handlers */ private function onOnline(event) {