changeset 31587:365ec0996ca0

merge of '2efa9b7fc41104668975df54e8be8a7171383794' and '88aea2f701d6cff5efc151d40ef06257da67cf3d'
author Paul Aurich <paul@darkrain42.org>
date Mon, 10 Jan 2011 05:20:06 +0000
parents d5b710c91104 (current diff) 6826925abd6d (diff)
children be5cb357c7b5 7986f4e5a05f
files ChangeLog
diffstat 5 files changed, 124 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Mon Jan 10 03:30:05 2011 +0000
+++ b/ChangeLog	Mon Jan 10 05:20:06 2011 +0000
@@ -9,6 +9,7 @@
 	  calls to stop sending audio and video. (Jakub Adam) (#12758)
 	* Perl bindings now respect LDFLAGS. (Peter Volkov, Markos Chandras)
 	  (#12638)
+	* Added AddTrust External Root CA.  (#11554)
 
 	Groupwise:
 	* Don't show two windows when using "Get Info" on a buddy. (Gabriel Burt;
@@ -46,6 +47,8 @@
 	XMPP:
 	* Don't crash when receiving an unexpected/invalid jingle transport type.
 	  (Nikita Kozlov) (#13136)
+	* Handle Connection: Close headers for BOSH, when the server does not
+	  terminate the connection itself. (#13008)
 
 	Yahoo!/Yahoo! JAPAN:
 	* Fix a crash when an account disconnects before a p2p session is
--- a/libpurple/protocols/jabber/bosh.c	Mon Jan 10 03:30:05 2011 +0000
+++ b/libpurple/protocols/jabber/bosh.c	Mon Jan 10 05:20:06 2011 +0000
@@ -108,8 +108,27 @@
 	int requests; /* number of outstanding HTTP requests */
 
 	gboolean headers_done;
+	gboolean close;
+};
 
-};
+static void
+debug_dump_http_connections(PurpleBOSHConnection *conn)
+{
+	int i;
+
+	g_return_if_fail(conn != NULL);
+
+	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);
+	}
+}
 
 static void http_connection_connect(PurpleHTTPConnection *conn);
 static void http_connection_send_request(PurpleHTTPConnection *conn,
@@ -263,18 +282,8 @@
 {
 	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);
-		}
-	}
+	if (purple_debug_is_verbose())
+		debug_dump_http_connections(conn);
 
 	/* Easy solution: Does everyone involved support pipelining? Hooray! Just use
 	 * one TCP connection! */
@@ -300,8 +309,9 @@
 	/* 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);
+			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;
@@ -444,6 +454,25 @@
 	send_timer_cb(bosh);
 }
 
+static void
+jabber_bosh_disable_pipelining(PurpleBOSHConnection *bosh)
+{
+	/* Do nothing if it's already disabled */
+	if (!bosh->pipelining)
+		return;
+
+	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();
+	}
+}
+
 static void jabber_bosh_connection_received(PurpleBOSHConnection *conn, xmlnode *node) {
 	xmlnode *child;
 	JabberStream *js = conn->js;
@@ -611,6 +640,8 @@
 static void
 connection_common_established_cb(PurpleHTTPConnection *conn)
 {
+	purple_debug_misc("jabber", "bosh: httpconn %p re-connected\n", conn);
+
 	/* Indicate we're ready and reset some variables */
 	conn->state = HTTP_CONN_CONNECTED;
 	if (conn->requests != 0)
@@ -622,9 +653,13 @@
 		g_string_free(conn->read_buf, TRUE);
 		conn->read_buf = NULL;
 	}
+	conn->close = FALSE;
 	conn->headers_done = FALSE;
 	conn->handled_len = conn->body_len = 0;
 
+	if (purple_debug_is_verbose())
+		debug_dump_http_connections(conn->bosh);
+
 	if (conn->bosh->js->reinit)
 		jabber_bosh_connection_send(conn->bosh, PACKET_NORMAL, NULL);
 	else if (conn->bosh->state == BOSH_CONN_ONLINE) {
@@ -671,11 +706,7 @@
 
 	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]);
-		}
+		jabber_bosh_disable_pipelining(conn->bosh);
 	}
 
 	if (++conn->bosh->failed_connections == MAX_FAILED_CONNECTIONS) {
@@ -704,30 +735,49 @@
 
 	cursor = conn->read_buf->str + conn->handled_len;
 
+	if (purple_debug_is_verbose())
+		purple_debug_misc("jabber", "BOSH server sent: %s\n", cursor);
+
+	/* TODO: Chunked encoding and check response version :/ */
 	if (!conn->headers_done) {
-		const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length");
+		const char *content_length = purple_strcasestr(cursor, "\r\nContent-Length:");
+		const char *connection = purple_strcasestr(cursor, "\r\nConnection:");
 		const char *end_of_headers = strstr(cursor, "\r\n\r\n");
 
 		/* Make sure Content-Length is in headers, not body */
 		if (content_length && (!end_of_headers || content_length < end_of_headers)) {
-			const char *sep;
 			int len;
 
-			if ((sep = strstr(content_length, ": ")) == NULL ||
-					strstr(sep, "\r\n") == NULL)
+			if (strstr(content_length, "\r\n") == NULL)
 				/*
 				 * The packet ends in the middle of the Content-Length line.
 				 * We'll try again later when we have more.
 				 */
 				return;
 
-			len = atoi(sep + 2);
+			len = atoi(content_length + strlen("\r\nContent-Length:"));
 			if (len == 0)
-				purple_debug_warning("jabber", "Found mangled Content-Length header.\n");
+				purple_debug_warning("jabber", "Found mangled Content-Length header, or server returned 0-length response.\n");
 
 			conn->body_len = len;
 		}
 
+		if (connection && (!end_of_headers || content_length < end_of_headers)) {
+			const char *tmp;
+			if (strstr(connection, "\r\n") == NULL)
+				return;
+
+
+			tmp = connection + strlen("\r\nConnection:");
+			while (*tmp && (*tmp == ' ' || *tmp == '\t'))
+				++tmp;
+
+			if (!g_ascii_strncasecmp(tmp, "close", strlen("close"))) {
+				conn->close = TRUE;
+				jabber_bosh_disable_pipelining(conn->bosh);
+			}
+		}
+
 		if (end_of_headers) {
 			conn->headers_done = TRUE;
 			conn->handled_len = end_of_headers - conn->read_buf->str + 4;
@@ -752,6 +802,14 @@
 	http_received_cb(conn->read_buf->str + conn->handled_len, conn->body_len,
 	                 conn->bosh);
 
+	/* Connection: Close? */
+	if (conn->close && conn->state == HTTP_CONN_CONNECTED) {
+		if (purple_debug_is_verbose())
+			purple_debug_misc("jabber", "bosh (%p), server sent Connection: "
+			                            "close\n", conn);
+		http_connection_disconnected(conn);
+	}
+
 	if (conn->bosh->state == BOSH_CONN_ONLINE &&
 			(conn->bosh->requests == 0 || conn->bosh->pending->bufused > 0)) {
 		purple_debug_misc("jabber", "BOSH: Sending an empty request\n");
@@ -791,10 +849,11 @@
 
 	if (cnt == 0 || (cnt < 0 && errno != EAGAIN)) {
 		if (cnt < 0)
-			purple_debug_info("jabber", "bosh read=%d, errno=%d, error=%s\n",
-			                  cnt, errno, g_strerror(errno));
+			purple_debug_info("jabber", "BOSH (%p) read=%d, errno=%d, error=%s\n",
+			                  conn, cnt, errno, g_strerror(errno));
 		else
-			purple_debug_info("jabber", "bosh server closed the connection\n");
+			purple_debug_info("jabber", "BOSH server closed the connection (%p)\n",
+			                  conn);
 
 		/*
 		 * If the socket is closed, the processing really needs to know about
@@ -911,6 +970,9 @@
 	else
 		ret = write(conn->fd, data, len);
 
+	if (purple_debug_is_verbose())
+		purple_debug_misc("jabber", "BOSH (%p): wrote %d bytes\n", conn, ret);
+
 	return ret;
 }
 
@@ -975,7 +1037,10 @@
 
 	if (purple_debug_is_unsafe() && purple_debug_is_verbose())
 		/* Will contain passwords for SASL PLAIN and is verbose */
-		purple_debug_misc("jabber", "BOSH: Sending %s\n", data);
+		purple_debug_misc("jabber", "BOSH (%p): Sending %s\n", conn, data);
+	else if (purple_debug_is_verbose())
+		purple_debug_misc("jabber", "BOSH (%p): Sending request of "
+		                            "%" G_GSIZE_FORMAT " bytes.\n", conn, len);
 
 	if (conn->writeh == 0)
 		ret = http_connection_do_send(conn, data, len);
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Mon Jan 10 03:30:05 2011 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Mon Jan 10 05:20:06 2011 +0000
@@ -530,6 +530,7 @@
     Push "xmpp"
     Call un.UnregisterURIHandler
 
+    Delete "$INSTDIR\ca-certs\AddTrust_External_Root.pem"
     Delete "$INSTDIR\ca-certs\America_Online_Root_Certification_Authority_1.pem"
     Delete "$INSTDIR\ca-certs\AOL_Member_CA.pem"
     Delete "$INSTDIR\ca-certs\CAcert_Class3.pem"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/share/ca-certs/AddTrust_External_Root.pem	Mon Jan 10 05:20:06 2011 +0000
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
+MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
+IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
+MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
+bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
+dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
+H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
+uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
+mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
+a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
+E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
+WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
+VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
+Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
+cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
+IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
+AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
+YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
+Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
+c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
+mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
--- a/share/ca-certs/Makefile.am	Mon Jan 10 03:30:05 2011 +0000
+++ b/share/ca-certs/Makefile.am	Mon Jan 10 05:20:06 2011 +0000
@@ -1,4 +1,5 @@
 CERTIFICATES = \
+		AddTrust_External_Root.pem \
 		America_Online_Root_Certification_Authority_1.pem \
 		CAcert_Root.pem \
 		CAcert_Class3.pem \