pidgin: 9aace88a: jabber: Send whitespace keepalives every...

darkrain42 at pidgin.im darkrain42 at pidgin.im
Wed Apr 21 15:10:40 EDT 2010


-----------------------------------------------------------------
Revision: 9aace88a3b513de8c7b7189fef9bf112258412b5
Ancestor: 5acc7ae0563fe6eba07c5994c034a58698732278
Author: darkrain42 at pidgin.im
Date: 2010-04-21T19:07:19
Branch: im.pidgin.pidgin
URL: http://d.pidgin.im/viewmtn/revision/info/9aace88a3b513de8c7b7189fef9bf112258412b5

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

ChangeLog: 

jabber: Send whitespace keepalives every two minutes of (outgoing) silence.

This works around stupid behavior of Openfire hopefully (otherwise we
may need to send a full IQ ping instead of a whitespace tab).  Closes #10767

-------------- next part --------------
============================================================
--- ChangeLog	780d577b9a42023415d38a090fdaf6371c551d28
+++ ChangeLog	4e82f97a5d99efe77e71894ddd98dee02190af6c
@@ -84,6 +84,10 @@ version 2.7.0 (??/??/????):
 	  BoB XEP).
 	* Present a better error message when authentication fails while trying
 	  to connect to Facebook.  (David Reiss, Facebook)
+	* Send whitespace keepalives if we haven't sent data in a while (2
+	  minutes).  This fixes an issue with Openfire disconnecting a
+	  libpurple-baesd client that has just been quiet for about 6
+	  minutes.
 
 	Yahoo/Yahoo JAPAN:
 	* Attempt to better handle transparent proxies interfering with HTTP-based
============================================================
--- libpurple/protocols/jabber/bosh.c	25556796bdf49f7ae7fc5743f962a2cbdbd1189a
+++ libpurple/protocols/jabber/bosh.c	d9e943224049cf19d50cf0b9eec4d8c6d8011133
@@ -78,13 +78,11 @@ struct _PurpleBOSHConnection {
 	} state;
 	guint8 failed_connections;
 
-	int max_inactivity;
 	int wait;
 
 	int max_requests;
 	int requests;
 
-	guint inactivity_timer;
 	guint send_timer;
 };
 
@@ -239,8 +237,6 @@ jabber_bosh_connection_destroy(PurpleBOS
 
 	if (conn->send_timer)
 		purple_timeout_remove(conn->send_timer);
-	if (conn->inactivity_timer)
-		purple_timeout_remove(conn->inactivity_timer);
 
 	purple_circ_buffer_destroy(conn->pending);
 
@@ -433,36 +429,16 @@ send_timer_cb(gpointer data)
 	return FALSE;
 }
 
-static gboolean
-bosh_inactivity_cb(gpointer data)
+void
+jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *bosh)
 {
-	PurpleBOSHConnection *bosh = data;
-	bosh->inactivity_timer = 0;
-
 	if (bosh->send_timer != 0)
 		purple_timeout_remove(bosh->send_timer);
 
 	/* clears bosh->send_timer */
 	send_timer_cb(bosh);
-
-	return FALSE;
 }
 
-static void
-restart_inactivity_timer(PurpleBOSHConnection *conn)
-{
-	if (conn->inactivity_timer != 0) {
-		purple_timeout_remove(conn->inactivity_timer);
-		conn->inactivity_timer = 0;
-	}
-
-	if (conn->max_inactivity != 0) {
-		conn->inactivity_timer =
-			purple_timeout_add_seconds(conn->max_inactivity - 5 /* rounding */,
-			                           bosh_inactivity_cb, conn);
-	}
-}
-
 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) {
 	xmlnode *child;
 	JabberStream *js = conn->js;
@@ -541,19 +517,20 @@ static void boot_response_cb(PurpleBOSHC
 	}
 
 	if (inactivity) {
-		conn->max_inactivity = atoi(inactivity);
-		if (conn->max_inactivity <= 5) {
+		js->max_inactivity = atoi(inactivity);
+		if (js->max_inactivity <= 5) {
 			purple_debug_warning("jabber", "Ignoring bogusly small inactivity: %s\n",
 			                     inactivity);
-			conn->max_inactivity = 0;
+			/* Leave it at the default */
 		} else {
-			/* TODO: Integrate this with jabber.c keepalive checks... */
 			/* TODO: Can this check fail? It shouldn't */
-			if (conn->inactivity_timer == 0) {
+			js->max_inactivity -= 5; /* rounding */
+
+			if (js->inactivity_timer == 0) {
 				purple_debug_misc("jabber", "Starting BOSH inactivity timer "
 						"for %d secs (compensating for rounding)\n",
-						conn->max_inactivity - 5);
-				restart_inactivity_timer(conn);
+						js->max_inactivity);
+				jabber_stream_restart_inactivity_timer(js);
 			}
 		}
 	}
@@ -976,7 +953,7 @@ http_connection_send_request(PurpleHTTPC
 	size_t len;
 
 	/* Sending something to the server, restart the inactivity timer */
-	restart_inactivity_timer(conn->bosh);
+	jabber_stream_restart_inactivity_timer(conn->bosh->js);
 
 	data = g_strdup_printf("POST %s HTTP/1.1\r\n"
 	                       "Host: %s\r\n"
============================================================
--- libpurple/protocols/jabber/bosh.h	4a5ae5ed92f5efebbbdbbbed136d223643aa5b3a
+++ libpurple/protocols/jabber/bosh.h	75015d5af2b5e9ca3da9c05a72e9f937a6c3e303
@@ -35,6 +35,7 @@ gboolean jabber_bosh_connection_is_ssl(P
 void jabber_bosh_connection_destroy(PurpleBOSHConnection *conn);
 
 gboolean jabber_bosh_connection_is_ssl(PurpleBOSHConnection *conn);
+void jabber_bosh_connection_send_keepalive(PurpleBOSHConnection *conn);
 
 void jabber_bosh_connection_connect(PurpleBOSHConnection *conn);
 void jabber_bosh_connection_close(PurpleBOSHConnection *conn);
============================================================
--- libpurple/protocols/jabber/jabber.c	4be8d9605180030e401a550203cc840afce68ee0
+++ libpurple/protocols/jabber/jabber.c	750dd2ba2ef135fd1b1fd0ecb3d6c96d39196aff
@@ -71,6 +71,10 @@
 #include "jingle/rtp.h"
 
 #define PING_TIMEOUT 60
+/* Send a whitespace keepalive to the server if we haven't sent
+ * anything in the last 120 seconds
+ */
+#define DEFAULT_INACTIVITY_TIME 120
 
 GList *jabber_features = NULL;
 GList *jabber_identities = NULL;
@@ -363,6 +367,9 @@ static gboolean do_jabber_send_raw(Jabbe
 	if (len == -1)
 		len = strlen(data);
 
+	if (js->state == JABBER_STREAM_CONNECTED)
+		jabber_stream_restart_inactivity_timer(js);
+
 	if (js->writeh == 0)
 		ret = jabber_do_send(js, data, len);
 	else {
@@ -889,6 +896,7 @@ jabber_stream_new(PurpleAccount *account
 	js->write_buffer = purple_circ_buffer_new(512);
 	js->old_length = 0;
 	js->keepalive_timeout = 0;
+	js->max_inactivity = DEFAULT_INACTIVITY_TIME;
 	/* Set the default protocol version to 1.0. Overridden in parser.c. */
 	js->protocol_version.major = 1;
 	js->protocol_version.minor = 0;
@@ -1583,6 +1591,8 @@ void jabber_close(PurpleConnection *gc)
 
 	if (js->keepalive_timeout != 0)
 		purple_timeout_remove(js->keepalive_timeout);
+	if (js->inactivity_timer != 0)
+		purple_timeout_remove(js->inactivity_timer);
 
 	g_free(js->srv_rec);
 	js->srv_rec = NULL;
@@ -1634,6 +1644,9 @@ void jabber_stream_set_state(JabberStrea
 		case JABBER_STREAM_CONNECTED:
 			/* Send initial presence */
 			jabber_presence_send(js, TRUE);
+			/* Start up the inactivity timer */
+			jabber_stream_restart_inactivity_timer(js);
+
 			purple_connection_set_state(js->gc, PURPLE_CONNECTED);
 			break;
 	}
@@ -1922,6 +1935,38 @@ gboolean jabber_stream_is_ssl(JabberStre
 	       (!js->bosh && js->gsc);
 }
 
+static gboolean
+inactivity_cb(gpointer data)
+{
+	JabberStream *js = data;
+
+	/* We want whatever is sent to set this.  It's okay because
+	 * the eventloop unsets it via the return FALSE.
+	 */
+	js->inactivity_timer = 0;
+
+	if (js->bosh)
+		jabber_bosh_connection_send_keepalive(js->bosh);
+	else
+		jabber_send_raw(js, "\t", 1);
+
+	return FALSE;
+}
+
+void jabber_stream_restart_inactivity_timer(JabberStream *js)
+{
+	if (js->inactivity_timer != 0) {
+		purple_timeout_remove(js->inactivity_timer);
+		js->inactivity_timer = 0;
+	}
+
+	g_return_if_fail(js->max_inactivity > 0);
+
+	js->inactivity_timer =
+		purple_timeout_add_seconds(js->max_inactivity,
+		                           inactivity_cb, js);
+}
+
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b)
 {
 	return "jabber";
============================================================
--- libpurple/protocols/jabber/jabber.h	d667d9c8a87e8c0c0475831decc2d5a5a99813a3
+++ libpurple/protocols/jabber/jabber.h	1333c8be4cee4f3c2cecc7c62bd51a25cacc0023
@@ -255,6 +255,8 @@ struct _JabberStream
 
 	/* A purple timeout tag for the keepalive */
 	guint keepalive_timeout;
+	guint max_inactivity;
+	guint inactivity_timer;
 
 	PurpleSrvResponse *srv_rec;
 	guint srv_rec_idx;
@@ -349,6 +351,13 @@ gboolean jabber_stream_is_ssl(JabberStre
  */
 gboolean jabber_stream_is_ssl(JabberStream *js);
 
+/**
+ * Restart the "we haven't sent anything in a while and should send
+ * something or the server will kick us off" timer (obviously
+ * called when sending something.  It's exposed for BOSH.)
+ */
+void jabber_stream_restart_inactivity_timer(JabberStream *js);
+
 /** PRPL functions */
 const char *jabber_list_icon(PurpleAccount *a, PurpleBuddy *b);
 const char* jabber_list_emblem(PurpleBuddy *b);


More information about the Commits mailing list