diff libpurple/protocols/jabber/jabber.c @ 29772:3ac7f10d13d4

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
author Paul Aurich <paul@darkrain42.org>
date Wed, 21 Apr 2010 19:07:19 +0000
parents 9134be6baaef
children 552616f49f94
line wrap: on
line diff
--- a/libpurple/protocols/jabber/jabber.c	Wed Apr 21 17:43:36 2010 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Apr 21 19:07:19 2010 +0000
@@ -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 @@
 	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 @@
 	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 @@
 
 	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 @@
 		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 @@
 	       (!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";