libpurple/protocols/jabber/jabber.c

branch
xep-0198
changeset 39094
5d298b8113ef
parent 38794
d121a4418d1f
child 39724
72a35ff95941
--- a/libpurple/protocols/jabber/jabber.c	Thu Dec 28 21:08:56 2017 -0600
+++ b/libpurple/protocols/jabber/jabber.c	Wed May 09 10:01:34 2018 +0300
@@ -68,6 +68,7 @@
 #include "xdata.h"
 #include "pep.h"
 #include "adhoccommands.h"
+#include "stream_management.h"
 
 #include "jingle/jingle.h"
 #include "jingle/rtp.h"
@@ -312,6 +313,13 @@
 		jabber_stream_set_state(js, JABBER_STREAM_AUTHENTICATING);
 		jabber_auth_start_old(js);
 	}
+
+	/* Stream management */
+	if (xmlnode_get_child_with_namespace(packet, "sm", NS_STREAM_MANAGEMENT)
+	    && (js->sm_state == SM_DISABLED) )
+	{
+		jabber_sm_enable(js);
+	}
 }
 
 static void jabber_stream_handle_error(JabberStream *js, xmlnode *packet)
@@ -340,6 +348,8 @@
 	name = (*packet)->name;
 	xmlns = xmlnode_get_namespace(*packet);
 
+	jabber_sm_inbound(js, *packet);
+
 	if(purple_strequal((*packet)->name, "iq")) {
 		jabber_iq_parse(js, *packet);
 	} else if(purple_strequal((*packet)->name, "presence")) {
@@ -370,6 +380,8 @@
 				tls_init(js);
 			/* TODO: Handle <failure/>, I guess? */
 		}
+	} else if (purple_strequal(xmlns, NS_STREAM_MANAGEMENT)) {
+		jabber_sm_process_packet(js, *packet);
 	} else {
 		purple_debug_warning("jabber", "Unknown packet: %s\n", (*packet)->name);
 	}
@@ -583,6 +595,28 @@
 	return (len < 0 ? (int)strlen(buf) : len);
 }
 
+/* Checks whether a packet may be a stanza (not strictly: returns TRUE
+   if there's no namespace, assuming that the default namespace is
+   jabber:client or jabber:server). */
+gboolean
+jabber_is_stanza(xmlnode *packet) {
+	const char *name;
+	const char *xmlns;
+
+	g_return_val_if_fail(packet != NULL, FALSE);
+	g_return_val_if_fail(packet->name != NULL, FALSE);
+
+	name = packet->name;
+	xmlns = xmlnode_get_namespace(packet);
+
+	return ((purple_strequal(name, "message")
+	         || purple_strequal(name, "iq")
+	         || purple_strequal(name, "presence"))
+	        && ((xmlns == NULL)
+	            || purple_strequal(xmlns, NS_XMPP_CLIENT)
+	            || purple_strequal(xmlns, NS_XMPP_SERVER)));
+}
+
 void jabber_send_signal_cb(PurpleConnection *pc, xmlnode **packet,
                            gpointer unused)
 {
@@ -601,13 +635,13 @@
 		return;
 
 	if (js->bosh)
-		if (purple_strequal((*packet)->name, "message") ||
-				purple_strequal((*packet)->name, "iq") ||
-				purple_strequal((*packet)->name, "presence"))
+		if (jabber_is_stanza(*packet))
 			xmlnode_set_namespace(*packet, NS_XMPP_CLIENT);
 	txt = xmlnode_to_str(*packet, &len);
 	jabber_send_raw(js, txt, len);
 	g_free(txt);
+
+	jabber_sm_outbound(js, *packet);
 }
 
 void jabber_send(JabberStream *js, xmlnode *packet)
@@ -1015,6 +1049,8 @@
 	if (purple_presence_is_idle(presence))
 		js->idle = purple_presence_get_idle_time(presence);
 
+	js->sm_state = SM_DISABLED;
+
 	return js;
 }
 
@@ -1597,8 +1633,10 @@
 
 	if (js->bosh)
 		jabber_bosh_connection_close(js->bosh);
-	else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0)
+	else if ((js->gsc && js->gsc->fd > 0) || js->fd > 0) {
+		jabber_sm_ack_send(js);
 		jabber_send_raw(js, "</stream:stream>", -1);
+	}
 
 	if (js->srv_query_data)
 		purple_srv_cancel(js->srv_query_data);
@@ -3896,12 +3934,15 @@
 	jabber_si_init();
 
 	jabber_auth_init();
+
+	jabber_sm_init();
 }
 
 static void
 jabber_do_uninit(void)
 {
 	/* reverse order of jabber_do_init */
+	jabber_sm_uninit();
 	jabber_bosh_uninit();
 	jabber_data_uninit();
 	jabber_si_uninit();

mercurial