cpw.darkrain42.xmpp.bosh: 42b48d18: Jabber BOSH: more fixes.

paul at darkrain42.org paul at darkrain42.org
Sat Jan 17 23:55:50 EST 2009


-----------------------------------------------------------------
Revision: 42b48d18527b01b2ce8d375b6a104fb81abef2aa
Ancestor: 0098a78f82c93a34ff44fee055c56c1eaf466da9
Author: paul at darkrain42.org
Date: 2008-12-04T23:59:44
Branch: im.pidgin.cpw.darkrain42.xmpp.bosh
URL: http://d.pidgin.im/viewmtn/revision/info/42b48d18527b01b2ce8d375b6a104fb81abef2aa

Modified files:
        libpurple/protocols/jabber/bosh.c
        libpurple/protocols/jabber/bosh.h
        libpurple/protocols/jabber/jabber.c
        libpurple/protocols/jabber/libxmpp.c

ChangeLog: 

Jabber BOSH: more fixes.

Clean up some more of the structures and leaks
Add jabber_bosh_(un)?init functions
Properly send raw data (and add a _close function that terminates the stream)
Normalize HTTP headers
Throw a few more connection errors

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/bosh.c	44aa033d1b66ab3d8725cd7d3833747a76727ca6
+++ libpurple/protocols/jabber/bosh.c	3f62e7ff3c81d4a1b7c7bae85113ce0b17788f76
@@ -19,6 +19,7 @@
  *
  */
 #include "internal.h"
+#include "core.h"
 #include "cipher.h"
 #include "debug.h"
 #include "prpl.h"
@@ -37,20 +38,19 @@ typedef void (*PurpleBOSHConnectionRecei
 typedef void (*PurpleBOSHConnectionConnectFunction)(PurpleBOSHConnection *conn);
 typedef void (*PurpleBOSHConnectionReceiveFunction)(PurpleBOSHConnection *conn, xmlnode *node);
 
+static char *bosh_useragent = NULL;
+
 struct _PurpleBOSHConnection {
     /* decoded URL */
     char *host;
     int port;
     char *path; 
-    char *user;
-    char *passwd;
     
     int rid;
     char *sid;
     int wait;
         
     JabberStream *js;
-    PurpleAccount *account;
     gboolean pipelining;
     PurpleHTTPConnection *conn_a;
     PurpleHTTPConnection *conn_b;
@@ -64,16 +64,14 @@ struct _PurpleHTTPConnection {
     int fd;
     char *host;
     int port;
-    int handle;
     int ie_handle;
-    PurpleConnection *conn;
     GQueue *requests;
     
     PurpleHTTPResponse *current_response;
     char *current_data;
     int current_len;
     
-    int pih;
+    int pih; /* what? */
     PurpleHTTPConnectionConnectFunction connect_cb;
     PurpleHTTPConnectionConnectFunction disconnect_cb;
     void *userdata;
@@ -108,17 +106,38 @@ static void jabber_bosh_http_connection_
 static PurpleHTTPConnection* jabber_bosh_http_connection_init(const char *host, int port);
 static void jabber_bosh_http_connection_connect(PurpleHTTPConnection *conn);
 static void jabber_bosh_http_connection_send_request(PurpleHTTPConnection *conn, PurpleHTTPRequest *req);
-static void jabber_bosh_http_connection_clean(PurpleHTTPConnection *conn);
+static void jabber_bosh_http_connection_destroy(PurpleHTTPConnection *conn);
 
-static void jabber_bosh_http_request_init(PurpleHTTPRequest *req, const char *method, const char *path, PurpleHTTPRequestCallback cb, void *userdata);
+static PurpleHTTPRequest* jabber_bosh_http_request_init(const char *method, const char *path, PurpleHTTPRequestCallback cb, void *userdata);
 static void jabber_bosh_http_request_add_to_header(PurpleHTTPRequest *req, const char *field, const char *value);
 static void jabber_bosh_http_request_set_data(PurpleHTTPRequest *req, char *data, int len);
-static void jabber_bosh_http_request_clean(PurpleHTTPRequest *req);
+static void jabber_bosh_http_request_destroy(PurpleHTTPRequest *req);
 
-static void jabber_bosh_http_response_init(PurpleHTTPResponse *res);
-static void jabber_bosh_http_response_clean(PurpleHTTPResponse *res);
+static PurpleHTTPResponse* jabber_bosh_http_response_init(void);
+static void jabber_bosh_http_response_destroy(PurpleHTTPResponse *res);
 
-PurpleBOSHConnection* jabber_bosh_connection_init(JabberStream *js, const char *url) {
+void jabber_bosh_init(void)
+{
+	GHashTable *ui_info = purple_core_get_ui_info();
+	const char *ui_version = NULL;
+
+	if (ui_info)
+		ui_version = g_hash_table_lookup(ui_info, "version");
+
+	if (ui_version)
+		bosh_useragent = g_strdup_printf("%s (libpurple " VERSION ")", ui_version);
+	else
+		bosh_useragent = g_strdup("libpurple " VERSION);
+}
+
+void jabber_bosh_uninit(void)
+{
+	g_free(bosh_useragent);
+	bosh_useragent = NULL;
+}
+
+PurpleBOSHConnection* jabber_bosh_connection_init(JabberStream *js, const char *url)
+{
 	PurpleBOSHConnection *conn;
 	char *host, *path, *user, *passwd;
 	int port;
@@ -132,16 +151,18 @@ PurpleBOSHConnection* jabber_bosh_connec
 	conn->host = host;
 	conn->port = port;
 	conn->path = path;
-	conn->user = user;
-	conn->passwd = passwd;
 	conn->pipelining = TRUE;
 
-	if (conn->user || conn->passwd) {
-		purple_debug_info("jabber", "Ignoring unsupported BOSH HTTP "
-				"Authentication username and password.\n");
+	if ((user && user[0] != '\0') || (passwd && passwd[0] != '\0')) {
+		purple_debug_info("jabber", "Ignoring unexpected username and password "
+		                            "in BOSH URL.\n");
 	}
 
+	g_free(user);
+	g_free(passwd);
+
 	conn->js = js;
+	/* FIXME: This doesn't seem very random */
 	conn->rid = rand() % 100000 + 1728679472;
 	conn->ready = FALSE;
 	conn->conn_a = jabber_bosh_http_connection_init(conn->host, conn->port);
@@ -150,6 +171,35 @@ PurpleBOSHConnection* jabber_bosh_connec
 	return conn;
 }
 
+void jabber_bosh_connection_destroy(PurpleBOSHConnection *conn)
+{
+	g_free(conn->host);
+	g_free(conn->path);
+
+	if (conn->conn_a)
+		jabber_bosh_http_connection_destroy(conn->conn_a);
+	if (conn->conn_b)
+		jabber_bosh_http_connection_destroy(conn->conn_b);
+
+	g_free(conn);
+}
+
+void jabber_bosh_connection_close(PurpleBOSHConnection *conn)
+{
+	xmlnode *packet = xmlnode_new("body");
+	char *tmp;
+
+	xmlnode_set_attrib(packet, "type", "terminate");
+	xmlnode_set_attrib(packet, "xmlns", "http://jabber.org/protocol/httpbind");
+	xmlnode_set_attrib(packet, "sid", conn->sid);
+	tmp = g_strdup_printf("%d", ++conn->rid);
+	xmlnode_set_attrib(packet, "rid", tmp);
+	g_free(tmp);
+
+	jabber_bosh_connection_send_native(conn, packet);
+	xmlnode_free(packet);
+}
+
 static void jabber_bosh_connection_stream_restart(PurpleBOSHConnection *conn) {
 	xmlnode *restart = xmlnode_new("body");
 	char *tmp = NULL;
@@ -164,6 +214,7 @@ static void jabber_bosh_connection_strea
 	xmlnode_set_attrib(restart, "xmlns:xmpp", "urn:xmpp:xbosh"); 
 	
 	jabber_bosh_connection_send_native(conn, restart);
+	xmlnode_free(restart);
 }
 
 static gboolean jabber_bosh_connection_error_check(PurpleBOSHConnection *conn, xmlnode *node) {
@@ -242,20 +293,22 @@ static void jabber_bosh_connection_boot_
 		int major = atoi(version);
 		int minor = atoi(dot + 1);
 
+		purple_debug_info("jabber", "BOSH connection manager version %s\n", version);
+
 		if (major > 1 || (major == 1 && minor >= 6)) {
 			xmlnode *packet = xmlnode_get_child(node, "features");
 			conn->js->use_bosh = TRUE;
 			conn->receive_cb = jabber_bosh_connection_auth_response;
 			jabber_stream_features_parse(conn->js, packet);		
 		} else {
-			purple_debug_info("jabber", "Unsupported version of BOSH protocol. The connection manager must at least support version 1.6!\n");
-			/* XXX This *must* handle this by killing the connection and
-			 * reporting an error. */
+			purple_connection_error_reason(conn->js->gc,
+			                  PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+			                  _("Unsupported version of BOSH protocol"));
 		}
 
 		g_free(version);
 	} else {
-		purple_debug_info("jabber", "Missing version in session creation response!\n");	
+		purple_debug_info("jabber", "Missing version in BOSH initiation\n");
 	}
 }
 
@@ -279,6 +332,7 @@ static void jabber_bosh_connection_boot(
 	
 	conn->receive_cb = jabber_bosh_connection_boot_response;
 	jabber_bosh_connection_send_native(conn, init);
+	xmlnode_free(init);
 }
 
 static void jabber_bosh_connection_http_received_cb(PurpleHTTPRequest *req, PurpleHTTPResponse *res, void *userdata) {
@@ -312,16 +366,35 @@ void jabber_bosh_connection_send(PurpleB
 		if (conn->ready == TRUE) xmlnode_set_attrib(node, "xmlns", "jabber:client");
 	}
 	jabber_bosh_connection_send_native(conn, packet);
+	xmlnode_free(packet);
 }
 
+void jabber_bosh_connection_send_raw(PurpleBOSHConnection *conn,
+        const char *data, int len)
+{
+	xmlnode *node = xmlnode_from_str(data, len);
+	if (node) {
+		jabber_bosh_connection_send(conn, node);
+		xmlnode_free(node);
+	} else {
+		/*
+		 * This best emulates what a normal XMPP server would do
+		 * if you send bad XML.
+		 */
+		purple_connection_error_reason(conn->js->gc,
+		        PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		        _("Cannot send malformed XML"));
+	}
+}
+
 static void jabber_bosh_connection_send_native(PurpleBOSHConnection *conn, xmlnode *node) {
-	PurpleHTTPRequest *request = g_new0(PurpleHTTPRequest, 1);
+	PurpleHTTPRequest *request;
 	
 	char *txt = xmlnode_to_formatted_str(node, NULL);
 	printf("\njabber_bosh_connection_send\n%s\n", txt);
 	g_free(txt);
 	
-	jabber_bosh_http_request_init(request, "POST", g_strdup_printf("/%s", conn->path), jabber_bosh_connection_http_received_cb, conn);
+	request = jabber_bosh_http_request_init("POST", g_strdup_printf("/%s", conn->path), jabber_bosh_connection_http_received_cb, conn);
 	jabber_bosh_http_request_add_to_header(request, "Content-Encoding", "text/xml; charset=utf-8");
 	request->data = xmlnode_to_str(node, &(request->data_len));
 	jabber_bosh_http_request_add_to_header(request, "Content-Length", g_strdup_printf("%d", (int)strlen(request->data)));
@@ -377,7 +450,7 @@ static void jabber_bosh_http_connection_
 			value = beginning + 1;
 		} else if (*beginning == '\r') {
 			*beginning = 0;
-			g_hash_table_replace(header, g_strdup(field), g_strdup(value));
+			g_hash_table_replace(header, g_ascii_strdown(field, -1), g_strdup(value));
 			value = field = 0;
 			++beginning;
 		}
@@ -415,11 +488,11 @@ static void jabber_bosh_http_connection_
 			/* check for header footer */
 			char *found = g_strstr_len(conn->current_data, conn->current_len, "\r\n\r\n");
 			if (found) {
-				// new response
-				response = conn->current_response = g_new0(PurpleHTTPResponse, 1);
-				jabber_bosh_http_response_init(response);
+				/* New response */
+				response = conn->current_response = jabber_bosh_http_response_init();
 				jabber_bosh_http_connection_receive_parse_header(response, &(conn->current_data), &(conn->current_len));
-				response->data_len = atoi(g_hash_table_lookup(response->header, "Content-Length"));
+				/* XXX: Crash if there is no Content-Length header */
+				response->data_len = atoi(g_hash_table_lookup(response->header, "content-length"));
 			} else {
 				printf("\nDid not receive HTTP header\n");
 			}
@@ -445,61 +518,97 @@ static void jabber_bosh_http_connection_
 					if (request->cb) request->cb(request, response, conn->userdata);
 					else purple_debug_info("jabber", "missing request callback!\n");
 					
-					jabber_bosh_http_request_clean(request);
-					jabber_bosh_http_response_clean(response);
+					jabber_bosh_http_request_destroy(request);
+					jabber_bosh_http_response_destroy(response);
 					conn->current_response = NULL;
-					g_free(request);
-					g_free(response);
 				} else {
 					purple_debug_info("jabber", "received HTTP response but haven't requested anything yet.\n");
 				}
 			}
 		}
 	} else if (len == 0) {
-		purple_input_remove(conn->ie_handle);
-		if (conn->disconnect_cb) conn->disconnect_cb(conn);
+		if (conn->ie_handle) {
+			purple_input_remove(conn->ie_handle);
+			conn->ie_handle = 0;
+		}
+		if (conn->disconnect_cb)
+			conn->disconnect_cb(conn);
 	} else {
 		purple_debug_info("jabber", "jabber_bosh_http_connection_receive: problem receiving data (%d)\n", len);
 	}
 }
 
-PurpleHTTPConnection *jabber_bosh_http_connection_init(const char *host, int port)
+static PurpleHTTPConnection* jabber_bosh_http_connection_init(const char *host, int port)
 {
 	PurpleHTTPConnection *conn = g_new0(PurpleHTTPConnection, 1);
 	conn->host = g_strdup(host);
 	conn->port = port;
+	conn->fd = -1;
 	conn->requests = g_queue_new();
 
 	return conn;
 }
 
-void jabber_bosh_http_connection_clean(PurpleHTTPConnection *conn) {
-	g_queue_free(conn->requests);
+static void jabber_bosh_http_connection_destroy(PurpleHTTPConnection *conn)
+{
+	g_free(conn->current_data);
+	g_free(conn->host);
+
+	if (conn->requests) {
+		g_queue_foreach(conn->requests, (GFunc)jabber_bosh_http_request_destroy, NULL);
+		g_queue_free(conn->requests);
+	}
+
+	if (conn->current_response)
+		jabber_bosh_http_response_destroy(conn->current_response);
+
+	if (conn->ie_handle)
+			purple_input_remove(conn->ie_handle);
+	if (conn->fd > 0)
+			close(conn->fd);
+
+	g_free(conn);
 }
 
-static void jabber_bosh_http_connection_callback(gpointer data, gint source, const gchar *error) {
+static void jabber_bosh_http_connection_callback(gpointer data, gint source, const gchar *error)
+{
 	PurpleHTTPConnection *conn = data;
+	PurpleBOSHConnection *bosh_conn = conn->userdata;
+	PurpleConnection *gc = bosh_conn->js->gc;
+
 	if (source < 0) {
-		purple_debug_info("jabber", "Couldn't connect becasue of: %s\n", error);
+		gchar *tmp;
+		tmp = g_strdup_printf(_("Could not establish a connection with the server:\n%s"),
+		        error);
+		purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+		g_free(tmp);
 		return;
 	}
+
 	conn->fd = source;
-	if (conn->connect_cb) conn->connect_cb(conn);
-	else purple_debug_info("jabber", "No connect callback for HTTP connection.\n");
-	conn->ie_handle = purple_input_add(conn->fd, PURPLE_INPUT_READ, jabber_bosh_http_connection_receive, conn);
+
+	if (conn->connect_cb)
+		conn->connect_cb(conn);
+
+	conn->ie_handle = purple_input_add(conn->fd, PURPLE_INPUT_READ,
+	        jabber_bosh_http_connection_receive, conn);
 }
 
-void jabber_bosh_http_connection_connect(PurpleHTTPConnection *conn) {
+static void jabber_bosh_http_connection_connect(PurpleHTTPConnection *conn)
+{
 	PurpleBOSHConnection *bosh_conn = conn->userdata;
 	PurpleConnection *gc = bosh_conn->js->gc;
 	PurpleAccount *account = purple_connection_get_account(gc);
 
-	if((purple_proxy_connect(&(conn->handle), account, conn->host, conn->port, jabber_bosh_http_connection_callback, conn)) == NULL) {
-		purple_debug_info("jabber", "Unable to connect to %s.\n", conn->host);
+	if ((purple_proxy_connect(conn, account, conn->host, conn->port, jabber_bosh_http_connection_callback, conn)) == NULL) {
+		purple_connection_error_reason(gc,
+		    PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+		    _("Unable to create socket"));
 	}
 }
 
-static void jabber_bosh_http_connection_send_request_add_field_to_string(gpointer key, gpointer value, gpointer user_data) {
+static void jabber_bosh_http_connection_send_request_add_field_to_string(gpointer key, gpointer value, gpointer user_data)
+{
 	char **ppacket = user_data;
 	char *tmp = *ppacket;
 	char *field = key;
@@ -512,7 +621,8 @@ void jabber_bosh_http_connection_send_re
 	char *packet;
 	char *tmp;
 	jabber_bosh_http_request_add_to_header(req, "Host", conn->host);
-	jabber_bosh_http_request_add_to_header(req, "User-Agent", "libpurple");
+	jabber_bosh_http_request_add_to_header(req, "User-Agent", bosh_useragent);
+
 	packet = tmp = g_strdup_printf("%s %s HTTP/1.1\r\n", req->method, req->path);
 	g_hash_table_foreach(req->header, jabber_bosh_http_connection_send_request_add_field_to_string, &packet);
 	tmp = packet;
@@ -522,12 +632,16 @@ void jabber_bosh_http_connection_send_re
 	g_queue_push_tail(conn->requests, req);
 }
 
-void jabber_bosh_http_request_init(PurpleHTTPRequest *req, const char *method, const char *path, PurpleHTTPRequestCallback cb, void *userdata) {
+static PurpleHTTPRequest* jabber_bosh_http_request_init(const char *method,
+        const char *path, PurpleHTTPRequestCallback cb, void *userdata)
+{
+	PurpleHTTPRequest *req = g_new(PurpleHTTPRequest, 1);
 	req->method = g_strdup(method);
 	req->path = g_strdup(path);
 	req->cb = cb;
 	req->userdata = userdata;
-	req->header = g_hash_table_new(g_str_hash, g_str_equal);
+	req->header = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	return req;
 }
 
 static void jabber_bosh_http_request_add_to_header(PurpleHTTPRequest *req, const char *field, const char *value) {
@@ -541,20 +655,25 @@ void jabber_bosh_http_request_set_data(P
 	req->data_len = len;
 }
 
-void jabber_bosh_http_request_clean(PurpleHTTPRequest *req) {
+static void jabber_bosh_http_request_destroy(PurpleHTTPRequest *req)
+{
 	g_hash_table_destroy(req->header);
 	g_free(req->method);
 	g_free(req->path);
 	g_free(req->data);
+	g_free(req);
 }
 
-void jabber_bosh_http_response_init(PurpleHTTPResponse *res) {
-	res->status = 0;
-	res->header = g_hash_table_new(g_str_hash, g_str_equal);
+static PurpleHTTPResponse* jabber_bosh_http_response_init(void)
+{
+	PurpleHTTPResponse *res = g_new0(PurpleHTTPResponse, 1);
+	res->header = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+	return res;
 }
 
-
-void jabber_bosh_http_response_clean(PurpleHTTPResponse *res) {
+static void jabber_bosh_http_response_destroy(PurpleHTTPResponse *res)
+{
 	g_hash_table_destroy(res->header);
 	g_free(res->data);
+	g_free(res);
 }
============================================================
--- libpurple/protocols/jabber/bosh.h	c87e1756ecee914264277778be583d8f55962d24
+++ libpurple/protocols/jabber/bosh.h	8762bed96aa1807750ed885fa3a2d369c5ae0bd3
@@ -26,7 +26,14 @@ typedef struct _PurpleBOSHConnection Pur
 
 #include "jabber.h"
 
+void jabber_bosh_init(void);
+void jabber_bosh_uninit(void);
+
 PurpleBOSHConnection* jabber_bosh_connection_init(JabberStream *js, const char *url);
+void jabber_bosh_connection_destroy(PurpleBOSHConnection *conn);
+
 void jabber_bosh_connection_connect(PurpleBOSHConnection *conn);
+void jabber_bosh_connection_close(PurpleBOSHConnection *conn);
 void jabber_bosh_connection_send(PurpleBOSHConnection *conn, xmlnode *node);
+void jabber_bosh_connection_send_raw(PurpleBOSHConnection *conn, const char *data, int len);
 #endif /* _PURPLE_JABBER_BOSH_H_ */
============================================================
--- libpurple/protocols/jabber/jabber.c	ac7d7877aba174d0a042300ce1742b5c8c6cf0b6
+++ libpurple/protocols/jabber/jabber.c	731fa7238927b1c6eb72593b0caf6e03543852f0
@@ -391,16 +391,10 @@ void jabber_send_raw(JabberStream *js, c
 	if (len == -1)
 		len = strlen(data);
 
-	if (js->use_bosh) {
-		xmlnode *xnode = xmlnode_from_str(data, len);
-		if (xnode) jabber_bosh_connection_send(js->bosh, xnode);
-		else {
-			purple_connection_error_reason(js->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
-							_("Someone tried to send non-XML in a Jabber world."));
-		}
-	} else {
+	if (js->use_bosh)
+		jabber_bosh_connection_send_raw(js->bosh, data, len);
+	else
 		do_jabber_send_raw(js, data, len);
-	}
 }
 
 int jabber_prpl_send_raw(PurpleConnection *gc, const char *buf, int len)
@@ -421,9 +415,13 @@ void jabber_send(JabberStream *js, xmlno
 	if(NULL == packet)
 		return;
 
-	txt = xmlnode_to_str(packet, &len);
-	jabber_send_raw(js, txt, len);
-	g_free(txt);
+	if (js->use_bosh)
+		jabber_bosh_connection_send(js->bosh, packet);
+	else {
+		txt = xmlnode_to_str(packet, &len);
+		jabber_send_raw(js, txt, len);
+		g_free(txt);
+	}
 }
 
 static void jabber_pong_cb(JabberStream *js, xmlnode *packet, gpointer unused)
@@ -592,6 +590,7 @@ txt_resolved_cb(PurpleTxtResponse *resp,
 		if (!strcmp(token[0], "_xmpp-client-xbosh")) {
 			purple_debug_info("jabber","Found alternative connection method using %s at %s.\n", token[0], token[1]);
 			js->bosh = jabber_bosh_connection_init(js, token[1]);
+			js->use_bosh = TRUE;
 			g_strfreev(token);
 			break;
 		}
@@ -1342,8 +1341,12 @@ void jabber_close(PurpleConnection *gc)
 	 * if we were forcibly disconnected because it will crash
 	 * on some SSL backends.
 	 */
-	if (!gc->disconnect_timeout)
-		jabber_send_raw(js, "</stream:stream>", -1);
+	if (!gc->disconnect_timeout) {
+		if (js->use_bosh)
+			jabber_bosh_connection_close(js->bosh);
+		else
+			jabber_send_raw(js, "</stream:stream>", -1);
+	}
 
 	if (js->srv_query_data)
 		purple_srv_cancel(js->srv_query_data);
@@ -1359,6 +1362,9 @@ void jabber_close(PurpleConnection *gc)
 		close(js->fd);
 	}
 
+	if (js->bosh)
+		jabber_bosh_connection_destroy(js->bosh);
+
 	jabber_buddy_remove_all_pending_buddy_info_requests(js);
 
 	jabber_parser_free(js);
============================================================
--- libpurple/protocols/jabber/libxmpp.c	d3b44e74835751fa6faabf516be00ab88fe46084
+++ libpurple/protocols/jabber/libxmpp.c	187a32c8669c1fa0eb7a179af8e2fb4853884591
@@ -150,6 +150,7 @@ static gboolean unload_plugin(PurplePlug
 	purple_signal_unregister(plugin, "jabber-sending-text");
 
 	/* reverse order of init_plugin */
+	jabber_bosh_uninit();
 	jabber_data_uninit();
 	/* PEP things should be uninit via jabber_pep_uninit, not here */
 	jabber_pep_uninit();
@@ -293,6 +294,7 @@ init_plugin(PurplePlugin *plugin)
 	/* PEP things should be init via jabber_pep_init, not here */
 	jabber_pep_init();
 	jabber_data_init();
+	jabber_bosh_init();
 
 	#warning implement adding and retrieving own features via IPC API
 


More information about the Commits mailing list