static PurpleHTTPConnection * find_available_http_connection(PurpleBOSHConnection *conn) { int i; if (purple_debug_is_verbose()) debug_dump_http_connections(conn); /* Easy solution: Does everyone involved support pipelining? Hooray! Just use * one TCP connection! */ if (conn->pipelining) return conn->connections[0]->state == HTTP_CONN_CONNECTED ? conn->connections[0] : NULL; /* First loop, look for a connection that's ready */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && conn->connections[i]->state == HTTP_CONN_CONNECTED && conn->connections[i]->requests == 0) return conn->connections[i]; } /* Second loop, is something currently connecting? If so, just queue up. */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && conn->connections[i]->state == HTTP_CONN_CONNECTING) return NULL; } /* Third loop, is something offline that we can connect? */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && conn->connections[i]->state == HTTP_CONN_OFFLINE) { purple_debug_info("jabber", "bosh: Reconnecting httpconn " "(%i, %p)\n", i, conn->connections[i]); http_connection_connect(conn->connections[i]); return NULL; } } /* Fourth loop, look for one that's NULL and create a new connection */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (!conn->connections[i]) { conn->connections[i] = jabber_bosh_http_connection_init(conn); purple_debug_info("jabber", "bosh: Creating and connecting new httpconn " "(%i, %p)\n", i, conn->connections[i]); http_connection_connect(conn->connections[i]); return NULL; } } purple_debug_warning("jabber", "Could not find a HTTP connection!\n"); /* None available. */ return NULL; }
static void http_connection_disconnected(PurpleHTTPConnection *conn) { /* * Well, then. Fine! I never liked you anyway, server! I was cheating on you * with AIM! */ conn->state = HTTP_CONN_OFFLINE; if (conn->psc) { purple_ssl_close(conn->psc); conn->psc = NULL; } else if (conn->fd >= 0) { close(conn->fd); conn->fd = -1; } if (conn->readh) { purple_input_remove(conn->readh); conn->readh = 0; } if (conn->writeh) { purple_input_remove(conn->writeh); conn->writeh = 0; } if (conn->requests > 0 && conn->read_buf->len == 0) { purple_debug_error("jabber", "bosh: Adjusting BOSHconn requests (%d) to %d\n", conn->bosh->requests, conn->bosh->requests - conn->requests); conn->bosh->requests -= conn->requests; conn->requests = 0; } if (conn->bosh->pipelining) { /* Hmmmm, fall back to multiple connections */ conn->bosh->pipelining = FALSE; if (conn->bosh->connections[1] == NULL) { conn->bosh->connections[1] = jabber_bosh_http_connection_init(conn->bosh); http_connection_connect(conn->bosh->connections[1]); } } if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) { purple_connection_error_reason(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to establish a connection with the server")); } else { /* No! Please! Take me back. It was me, not you! I was weak! */ http_connection_connect(conn); } }
void jabber_bosh_connection_connect(PurpleBOSHConnection *bosh) { PurpleHTTPConnection *conn = bosh->connections[0]; g_return_if_fail(bosh->state == BOSH_CONN_OFFLINE); bosh->state = BOSH_CONN_BOOTING; http_connection_connect(conn); }
static PurpleHTTPConnection * find_available_http_connection(PurpleBOSHConnection *conn) { int i; if (purple_debug_is_verbose()) { for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { PurpleHTTPConnection *httpconn = conn->connections[i]; if (httpconn == NULL) purple_debug_misc("jabber", "BOSH %p->connections[%d] = (nil)\n", conn, i); else purple_debug_misc("jabber", "BOSH %p->connections[%d] = %p, state = %d" ", requests = %d\n", conn, i, httpconn, httpconn->state, httpconn->requests); } } /* Easy solution: Does everyone involved support pipelining? Hooray! Just use * one TCP connection! */ if (conn->pipelining) return conn->connections[0]->state == HTTP_CONN_CONNECTED ? conn->connections[0] : NULL; /* First loop, look for a connection that's ready */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && conn->connections[i]->state == HTTP_CONN_CONNECTED && conn->connections[i]->requests == 0) return conn->connections[i]; } /* Second loop, is something currently connecting? If so, just queue up. */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (conn->connections[i] && conn->connections[i]->state == HTTP_CONN_CONNECTING) return NULL; } /* Third loop, look for one that's NULL and create a new connection */ for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { if (!conn->connections[i]) { purple_debug_info("jabber", "bosh: Creating and connecting new httpconn\n"); conn->connections[i] = jabber_bosh_http_connection_init(conn); http_connection_connect(conn->connections[i]); return NULL; } } purple_debug_warning("jabber", "Could not find a HTTP connection!\n"); /* None available. */ return NULL; }
static void http_connection_disconnected(PurpleHTTPConnection *conn) { gboolean had_requests = FALSE; /* * Well, then. Fine! I never liked you anyway, server! I was cheating on you * with AIM! */ conn->state = HTTP_CONN_OFFLINE; if (conn->psc) { purple_ssl_close(conn->psc); conn->psc = NULL; } else if (conn->fd >= 0) { close(conn->fd); conn->fd = -1; } if (conn->readh) { purple_input_remove(conn->readh); conn->readh = 0; } if (conn->writeh) { purple_input_remove(conn->writeh); conn->writeh = 0; } had_requests = (conn->requests > 0); if (had_requests && conn->read_buf->len == 0) { purple_debug_error("jabber", "bosh: Adjusting BOSHconn requests (%d) to %d\n", conn->bosh->requests, conn->bosh->requests - conn->requests); conn->bosh->requests -= conn->requests; conn->requests = 0; } if (conn->bosh->pipelining) { /* Hmmmm, fall back to multiple connections */ jabber_bosh_disable_pipelining(conn->bosh); } if (!had_requests) /* If the server disconnected us without any requests, let's * just wait until we have something to send before we reconnect */ return; if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) { purple_connection_error_reason(conn->bosh->js->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to establish a connection with the server")); } else { /* No! Please! Take me back. It was me, not you! I was weak! */ http_connection_connect(conn); } }
static void jabber_bosh_disable_pipelining(PurpleBOSHConnection *bosh) { /* Do nothing if it's already disabled */ if (!bosh->pipelining) return; purple_debug_info("jabber", "BOSH: Disabling pipelining on conn %p\n", bosh); bosh->pipelining = FALSE; if (bosh->connections[1] == NULL) { bosh->connections[1] = jabber_bosh_http_connection_init(bosh); http_connection_connect(bosh->connections[1]); } else { /* Shouldn't happen; this should be the only place pipelining * is turned off. */ g_warn_if_reached(); } }