# HG changeset patch # User Paul Aurich # Date 1271876839 0 # Node ID 3ac7f10d13d47cad13a179f1954e8a950e8c6462 # Parent fb270a3d07323b4823989354e8fe71301f67a7d4 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 diff -r fb270a3d0732 -r 3ac7f10d13d4 ChangeLog --- a/ChangeLog Wed Apr 21 17:43:36 2010 +0000 +++ b/ChangeLog Wed Apr 21 19:07:19 2010 +0000 @@ -84,6 +84,10 @@ 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 diff -r fb270a3d0732 -r 3ac7f10d13d4 libpurple/protocols/jabber/bosh.c --- a/libpurple/protocols/jabber/bosh.c Wed Apr 21 17:43:36 2010 +0000 +++ b/libpurple/protocols/jabber/bosh.c Wed Apr 21 19:07:19 2010 +0000 @@ -78,13 +78,11 @@ } state; guint8 failed_connections; - int max_inactivity; int wait; int max_requests; int requests; - guint inactivity_timer; guint send_timer; }; @@ -239,8 +237,6 @@ 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,34 +429,14 @@ 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) { @@ -541,19 +517,20 @@ } 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 @@ 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" diff -r fb270a3d0732 -r 3ac7f10d13d4 libpurple/protocols/jabber/bosh.h --- a/libpurple/protocols/jabber/bosh.h Wed Apr 21 17:43:36 2010 +0000 +++ b/libpurple/protocols/jabber/bosh.h Wed Apr 21 19:07:19 2010 +0000 @@ -35,6 +35,7 @@ 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); diff -r fb270a3d0732 -r 3ac7f10d13d4 libpurple/protocols/jabber/jabber.c --- 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"; diff -r fb270a3d0732 -r 3ac7f10d13d4 libpurple/protocols/jabber/jabber.h --- a/libpurple/protocols/jabber/jabber.h Wed Apr 21 17:43:36 2010 +0000 +++ b/libpurple/protocols/jabber/jabber.h Wed Apr 21 19:07:19 2010 +0000 @@ -255,6 +255,8 @@ /* 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(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);