comparison libpurple/protocols/jabber/bosh.c @ 31582:bb91133708fe

jabber: Make the BOSH parsing a little more resilient and add more diagnostic output
author Paul Aurich <paul@darkrain42.org>
date Mon, 10 Jan 2011 03:34:00 +0000
parents dbd0012e72cb
children 6826925abd6d
comparison
equal deleted inserted replaced
31581:dbd0012e72cb 31582:bb91133708fe
109 109
110 gboolean headers_done; 110 gboolean headers_done;
111 111
112 }; 112 };
113 113
114 static void
115 debug_dump_http_connections(PurpleBOSHConnection *conn)
116 {
117 int i;
118
119 g_return_if_fail(conn != NULL);
120
121 for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) {
122 PurpleHTTPConnection *httpconn = conn->connections[i];
123 if (httpconn == NULL)
124 purple_debug_misc("jabber", "BOSH %p->connections[%d] = (nil)\n",
125 conn, i);
126 else
127 purple_debug_misc("jabber", "BOSH %p->connections[%d] = %p, state = %d"
128 ", requests = %d\n", conn, i, httpconn,
129 httpconn->state, httpconn->requests);
130 }
131 }
132
114 static void http_connection_connect(PurpleHTTPConnection *conn); 133 static void http_connection_connect(PurpleHTTPConnection *conn);
115 static void http_connection_send_request(PurpleHTTPConnection *conn, 134 static void http_connection_send_request(PurpleHTTPConnection *conn,
116 const GString *req); 135 const GString *req);
117 static gboolean send_timer_cb(gpointer data); 136 static gboolean send_timer_cb(gpointer data);
118 137
261 static PurpleHTTPConnection * 280 static PurpleHTTPConnection *
262 find_available_http_connection(PurpleBOSHConnection *conn) 281 find_available_http_connection(PurpleBOSHConnection *conn)
263 { 282 {
264 int i; 283 int i;
265 284
266 if (purple_debug_is_verbose()) { 285 if (purple_debug_is_verbose())
267 for (i = 0; i < NUM_HTTP_CONNECTIONS; ++i) { 286 debug_dump_http_connections(conn);
268 PurpleHTTPConnection *httpconn = conn->connections[i];
269 if (httpconn == NULL)
270 purple_debug_misc("jabber", "BOSH %p->connections[%d] = (nil)\n",
271 conn, i);
272 else
273 purple_debug_misc("jabber", "BOSH %p->connections[%d] = %p, state = %d"
274 ", requests = %d\n", conn, i, httpconn,
275 httpconn->state, httpconn->requests);
276 }
277 }
278 287
279 /* Easy solution: Does everyone involved support pipelining? Hooray! Just use 288 /* Easy solution: Does everyone involved support pipelining? Hooray! Just use
280 * one TCP connection! */ 289 * one TCP connection! */
281 if (conn->pipelining) 290 if (conn->pipelining)
282 return conn->connections[0]->state == HTTP_CONN_CONNECTED ? 291 return conn->connections[0]->state == HTTP_CONN_CONNECTED ?
610 } 619 }
611 620
612 static void 621 static void
613 connection_common_established_cb(PurpleHTTPConnection *conn) 622 connection_common_established_cb(PurpleHTTPConnection *conn)
614 { 623 {
624 purple_debug_misc("jabber", "bosh: httpconn %p re-connected\n", conn);
625
615 /* Indicate we're ready and reset some variables */ 626 /* Indicate we're ready and reset some variables */
616 conn->state = HTTP_CONN_CONNECTED; 627 conn->state = HTTP_CONN_CONNECTED;
617 if (conn->requests != 0) 628 if (conn->requests != 0)
618 purple_debug_error("jabber", "bosh: httpconn %p has %d requests, != 0\n", 629 purple_debug_error("jabber", "bosh: httpconn %p has %d requests, != 0\n",
619 conn, conn->requests); 630 conn, conn->requests);
623 g_string_free(conn->read_buf, TRUE); 634 g_string_free(conn->read_buf, TRUE);
624 conn->read_buf = NULL; 635 conn->read_buf = NULL;
625 } 636 }
626 conn->headers_done = FALSE; 637 conn->headers_done = FALSE;
627 conn->handled_len = conn->body_len = 0; 638 conn->handled_len = conn->body_len = 0;
639
640 if (purple_debug_is_verbose())
641 debug_dump_http_connections(conn->bosh);
628 642
629 if (conn->bosh->js->reinit) 643 if (conn->bosh->js->reinit)
630 jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL); 644 jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
631 else if (conn->bosh->state == BOSH_CONN_ONLINE) { 645 else if (conn->bosh->state == BOSH_CONN_ONLINE) {
632 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n"); 646 purple_debug_info("jabber", "BOSH session already exists. Trying to reuse it.\n");
708 { 722 {
709 const char *cursor; 723 const char *cursor;
710 724
711 cursor = conn->read_buf->str + conn->handled_len; 725 cursor = conn->read_buf->str + conn->handled_len;
712 726
727 /* TODO: Chunked encoding :/ */
713 if (!conn->headers_done) { 728 if (!conn->headers_done) {
714 const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length"); 729 const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length:");
715 const char *end_of_headers = strstr(cursor, "\r\n\r\n"); 730 const char *end_of_headers = strstr(cursor, "\r\n\r\n");
716 731
717 /* Make sure Content-Length is in headers, not body */ 732 /* Make sure Content-Length is in headers, not body */
718 if (content_length && (!end_of_headers || content_length < end_of_headers)) { 733 if (content_length && (!end_of_headers || content_length < end_of_headers)) {
719 const char *sep;
720 int len; 734 int len;
721 735
722 if ((sep = strstr(content_length, ": ")) == NULL || 736 if (strstr(content_length, "\r\n") == NULL)
723 strstr(sep, "\r\n") == NULL)
724 /* 737 /*
725 * The packet ends in the middle of the Content-Length line. 738 * The packet ends in the middle of the Content-Length line.
726 * We'll try again later when we have more. 739 * We'll try again later when we have more.
727 */ 740 */
728 return; 741 return;
729 742
730 len = atoi(sep + 2); 743 len = atoi(content_length + strlen("\r\nContent-Length:"));
731 if (len == 0) 744 if (len == 0)
732 purple_debug_warning("jabber", "Found mangled Content-Length header.\n"); 745 purple_debug_warning("jabber", "Found mangled Content-Length header, or server returned 0-length response.\n");
733 746
734 conn->body_len = len; 747 conn->body_len = len;
735 } 748 }
736 749
737 if (end_of_headers) { 750 if (end_of_headers) {