cpw.malu.xmpp.jingle_ft: dcd7ea4d: Update si.c to use the new socks5 listen...

malu at pidgin.im malu at pidgin.im
Thu May 6 16:45:42 EDT 2010


-----------------------------------------------------------------
Revision: dcd7ea4dc58df407789d69e90a36c5322dc30cd8
Ancestor: 8edd40ff9d29b7707182311439f25c0e8e52c802
Author: malu at pidgin.im
Date: 2010-05-06T20:32:55
Branch: im.pidgin.cpw.malu.xmpp.jingle_ft
URL: http://d.pidgin.im/viewmtn/revision/info/dcd7ea4dc58df407789d69e90a36c5322dc30cd8

Modified files:
        libpurple/protocols/jabber/si.c

ChangeLog: 

Update si.c to use the new socks5 listening stuff

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/si.c	92da5ffed83f07a21215fb12359c49e55f7bc3c6
+++ libpurple/protocols/jabber/si.c	3944118f9aeb5efcdbb4375e626d7fb7cd046fcd
@@ -38,6 +38,7 @@
 #include "ibb.h"
 #include "iq.h"
 #include "si.h"
+#include "socks5.h"
 #include "xfer.h"
 
 #define STREAMHOST_CONNECT_TIMEOUT 15
@@ -65,9 +66,7 @@ typedef struct _JabberSIXfer {
 	GList *streamhosts;
 	PurpleProxyInfo *gpi;
 
-	char *rxqueue;
-	size_t rxlen;
-	gsize rxmaxlen;
+	JabberSocks5ListenData *socks5_listen_data;
 	int local_streamhost_fd;
 
 	JabberIBBSession *ibb_session;
@@ -370,299 +369,31 @@ static void
 
 
 static void
-jabber_si_xfer_bytestreams_send_read_again_resp_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
+jabber_si_listen_connect_cb(int fd, gpointer data)
 {
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
-	int len;
+	PurpleXfer *xfer = (PurpleXfer *) data;
+	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
 
-	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len < 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
-		g_free(jsx->rxqueue);
-		jsx->rxqueue = NULL;
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-	jsx->rxlen += len;
-
-	if (jsx->rxlen < jsx->rxmaxlen)
-		return;
-
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-	g_free(jsx->rxqueue);
-	jsx->rxqueue = NULL;
-
-	/* Before actually starting sending the file, we need to wait until the
-	 * recipient sends the IQ result with <streamhost-used/>
-	 */
-	purple_debug_info("jabber", "SOCKS5 connection negotiation completed. "
-					  "Waiting for IQ result to start file transfer.\n");
+	jabber_socks5_listen_data_free(jsx->socks5_listen_data);
+	jsx->socks5_listen_data = NULL;
+	xfer->fd = fd;
+	/* waiting for <streamhost-used/> */
 }
 
 static void
-jabber_si_xfer_bytestreams_send_read_again_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
+jabber_si_listen_error_cb(gpointer data)
 {
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
-	char buffer[42]; /* 40 for DST.ADDR + 2 bytes for port number*/
-	int len;
-	char *dstaddr, *hash;
-	const char *host;
-
-	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_again_cb\n");
-
-	if(jsx->rxlen < 5) {
-		purple_debug_info("jabber", "reading the first 5 bytes\n");
-		len = read(source, buffer, 5 - jsx->rxlen);
-		if(len < 0 && errno == EAGAIN)
-			return;
-		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
-		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
-		jsx->rxlen += len;
-		return;
-	} else if(jsx->rxqueue[0] != 0x05 || jsx->rxqueue[1] != 0x01 ||
-			jsx->rxqueue[3] != 0x03 || jsx->rxqueue[4] != 40) {
-		purple_debug_info("jabber", "Invalid socks5 conn req. header[0x%x,0x%x,0x%x,0x%x,0x%x]\n",
-				  jsx->rxqueue[0], jsx->rxqueue[1], jsx->rxqueue[2],
-				  jsx->rxqueue[3], jsx->rxqueue[4]);
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	} else if(jsx->rxlen - 5 <  jsx->rxqueue[4] + 2) {
-		/* Upper-bound of 257 (jsx->rxlen = 5, jsx->rxqueue[4] = 0xFF) */
-		unsigned short to_read = jsx->rxqueue[4] + 2 - (jsx->rxlen - 5);
-		purple_debug_info("jabber", "reading %u bytes for DST.ADDR + port num (trying to read %hu now)\n",
-				  jsx->rxqueue[4] + 2, to_read);
-		len = read(source, buffer, to_read);
-		if(len < 0 && errno == EAGAIN)
-			return;
-		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
-		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
-		jsx->rxlen += len;
-	}
-
-	/* Have we not read all of DST.ADDR and the following 2-byte port number? */
-	if(jsx->rxlen - 5 < jsx->rxqueue[4] + 2)
-		return;
-
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
-	dstaddr = g_strdup_printf("%s%s@%s/%s%s", jsx->stream_id,
-			jsx->js->user->node, jsx->js->user->domain,
-			jsx->js->user->resource, xfer->who);
-
-	/* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */
-	hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1");
-
-	if(strncmp(hash, jsx->rxqueue + 5, 40) ||
-			jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) {
-		if (jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00)
-			purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.PORT"
-						     " (must be 0 - got[0x%x,0x%x]).\n",
-						     jsx->rxqueue[45], jsx->rxqueue[46]);
-		else
-			purple_debug_error("jabber", "Got SOCKS5 BS conn with the wrong DST.ADDR"
-						     " (expected '%s' - got '%.40s').\n",
-						     hash, jsx->rxqueue + 5);
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-		g_free(hash);
-		g_free(dstaddr);
-		return;
-	}
-
-	g_free(hash);
-	g_free(dstaddr);
-
-	g_free(jsx->rxqueue);
-	host = purple_network_get_my_ip(jsx->js->fd);
-
-	jsx->rxmaxlen = 5 + strlen(host) + 2;
-	jsx->rxqueue = g_malloc(jsx->rxmaxlen);
-	jsx->rxlen = 0;
-
-	jsx->rxqueue[0] = 0x05;
-	jsx->rxqueue[1] = 0x00;
-	jsx->rxqueue[2] = 0x00;
-	jsx->rxqueue[3] = 0x03;
-	jsx->rxqueue[4] = strlen(host);
-	memcpy(jsx->rxqueue + 5, host, strlen(host));
-	jsx->rxqueue[5+strlen(host)] = 0x00;
-	jsx->rxqueue[6+strlen(host)] = 0x00;
-
-	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-		jabber_si_xfer_bytestreams_send_read_again_resp_cb, xfer);
-	jabber_si_xfer_bytestreams_send_read_again_resp_cb(xfer, source,
-		PURPLE_INPUT_WRITE);
+	PurpleXfer *xfer = (PurpleXfer *) data;
+	JabberSIXfer *jsx = (JabberSIXfer *) xfer->data;
+	
+	purple_debug_info("jabber", "in jabber_si_listen_error_cb\n");
+	jabber_socks5_listen_data_free(jsx->socks5_listen_data);
+	jsx->socks5_listen_data = NULL;
+	purple_xfer_cancel_remote(xfer);
 }
 
-static void
-jabber_si_xfer_bytestreams_send_read_response_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
-{
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
-	int len;
 
-	len = write(source, jsx->rxqueue + jsx->rxlen, jsx->rxmaxlen - jsx->rxlen);
-	if (len < 0 && errno == EAGAIN)
-		return;
-	else if (len < 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
-		g_free(jsx->rxqueue);
-		jsx->rxqueue = NULL;
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-	jsx->rxlen += len;
 
-	if (jsx->rxlen < jsx->rxmaxlen)
-		return;
-
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
-	/* If we sent a "Success", wait for a response, otherwise give up and cancel */
-	if (jsx->rxqueue[1] == 0x00) {
-		xfer->watcher = purple_input_add(source, PURPLE_INPUT_READ,
-			jabber_si_xfer_bytestreams_send_read_again_cb, xfer);
-		g_free(jsx->rxqueue);
-		jsx->rxqueue = NULL;
-		jsx->rxlen = 0;
-	} else {
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-	}
-}
-
-static void
-jabber_si_xfer_bytestreams_send_read_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
-{
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
-	int i;
-	int len;
-	char buffer[256];
-
-	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_read_cb\n");
-
-	xfer->fd = source;
-
-	/** Try to read the SOCKS5 header */
-	if(jsx->rxlen < 2) {
-		purple_debug_info("jabber", "reading those first two bytes\n");
-		len = read(source, buffer, 2 - jsx->rxlen);
-		if(len < 0 && errno == EAGAIN)
-			return;
-		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
-		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
-		jsx->rxlen += len;
-		return;
-	} else if(jsx->rxlen - 2 < jsx->rxqueue[1]) {
-		/* Has a maximum value of 255 (jsx->rxlen = 2, jsx->rxqueue[1] = 0xFF) */
-		unsigned short to_read = jsx->rxqueue[1] - (jsx->rxlen - 2);
-		purple_debug_info("jabber", "reading %u bytes for auth methods (trying to read %hu now)\n",
-				  jsx->rxqueue[1], to_read);
-		len = read(source, buffer, to_read);
-		if(len < 0 && errno == EAGAIN)
-			return;
-		else if(len <= 0) {
-			purple_input_remove(xfer->watcher);
-			xfer->watcher = 0;
-			close(source);
-			purple_xfer_cancel_remote(xfer);
-			return;
-		}
-		jsx->rxqueue = g_realloc(jsx->rxqueue, len + jsx->rxlen);
-		memcpy(jsx->rxqueue + jsx->rxlen, buffer, len);
-		jsx->rxlen += len;
-	}
-
-	/* Have we not read all the auth. method bytes? */
-	if(jsx->rxlen -2 < jsx->rxqueue[1])
-		return;
-
-	purple_input_remove(xfer->watcher);
-	xfer->watcher = 0;
-
-	purple_debug_info("jabber", "checking to make sure we're socks FIVE\n");
-
-	if(jsx->rxqueue[0] != 0x05) {
-		close(source);
-		purple_xfer_cancel_remote(xfer);
-		return;
-	}
-
-	purple_debug_info("jabber", "going to test %hhu different methods\n", jsx->rxqueue[1]);
-
-	for(i=0; i<jsx->rxqueue[1]; i++) {
-
-		purple_debug_info("jabber", "testing %hhu\n", jsx->rxqueue[i+2]);
-		if(jsx->rxqueue[i+2] == 0x00) {
-			g_free(jsx->rxqueue);
-			jsx->rxlen = 0;
-			jsx->rxmaxlen = 2;
-			jsx->rxqueue = g_malloc(jsx->rxmaxlen);
-			jsx->rxqueue[0] = 0x05;
-			jsx->rxqueue[1] = 0x00;
-			xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-				jabber_si_xfer_bytestreams_send_read_response_cb,
-				xfer);
-			jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
-				source, PURPLE_INPUT_WRITE);
-			jsx->rxqueue = NULL;
-			jsx->rxlen = 0;
-			return;
-		}
-	}
-
-	g_free(jsx->rxqueue);
-	jsx->rxlen = 0;
-	jsx->rxmaxlen = 2;
-	jsx->rxqueue = g_malloc(jsx->rxmaxlen);
-	jsx->rxqueue[0] = 0x05;
-	jsx->rxqueue[1] = 0xFF;
-	xfer->watcher = purple_input_add(source, PURPLE_INPUT_WRITE,
-		jabber_si_xfer_bytestreams_send_read_response_cb, xfer);
-	jabber_si_xfer_bytestreams_send_read_response_cb(xfer,
-		source, PURPLE_INPUT_WRITE);
-}
-
 static gint
 jabber_si_compare_jid(gconstpointer a, gconstpointer b)
 {
@@ -674,39 +405,7 @@ jabber_si_compare_jid(gconstpointer a, g
 	return strcmp(sh->jid, (char *)b);
 }
 
-static void
-jabber_si_xfer_bytestreams_send_connected_cb(gpointer data, gint source,
-		PurpleInputCondition cond)
-{
-	PurpleXfer *xfer = data;
-	JabberSIXfer *jsx = xfer->data;
-	int acceptfd, flags;
 
-	purple_debug_info("jabber", "in jabber_si_xfer_bytestreams_send_connected_cb\n");
-
-	acceptfd = accept(source, NULL, 0);
-	if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
-		return;
-	else if(acceptfd == -1) {
-		purple_debug_warning("jabber", "accept: %s\n", g_strerror(errno));
-		/* Don't cancel the ft - allow it to fall to the next streamhost.*/
-		return;
-	}
-
-	purple_input_remove(xfer->watcher);
-	close(source);
-	jsx->local_streamhost_fd = -1;
-
-	flags = fcntl(acceptfd, F_GETFL);
-	fcntl(acceptfd, F_SETFL, flags | O_NONBLOCK);
-#ifndef _WIN32
-	fcntl(acceptfd, F_SETFD, FD_CLOEXEC);
-#endif
-
-	xfer->watcher = purple_input_add(acceptfd, PURPLE_INPUT_READ,
-					 jabber_si_xfer_bytestreams_send_read_cb, xfer);
-}
-
 static void
 jabber_si_connect_proxy_cb(JabberStream *js, const char *from,
                            JabberIqType type, const char *id,
@@ -804,9 +503,10 @@ jabber_si_connect_proxy_cb(JabberStream 
 	}
 
 	/* Clean up the local streamhost - it isn't going to be used.*/
-	if (xfer->watcher > 0) {
-		purple_input_remove(xfer->watcher);
-		xfer->watcher = 0;
+	if (jsx->socks5_listen_data) {
+		jabber_socks5_listen_cancel(jsx->socks5_listen_data);
+		jabber_socks5_listen_data_free(jsx->socks5_listen_data);
+		jsx->socks5_listen_data = NULL;
 	}
 	if (jsx->local_streamhost_fd >= 0) {
 		close(jsx->local_streamhost_fd);
@@ -859,14 +559,19 @@ jabber_si_xfer_bytestreams_listen_cb(int
 			purple_network_get_all_local_system_ips();
 		const char *public_ip;
 		gboolean has_public_ip = FALSE;
-		
-		jsx->local_streamhost_fd = sock;
+		gchar *dstaddr;
+		JabberID *dstjid = jabber_id_new(xfer->who);
 
 		jid = g_strdup_printf("%s@%s/%s", jsx->js->user->node,
 			jsx->js->user->domain, jsx->js->user->resource);
+		jsx->local_streamhost_fd = sock;
+
+		
 		xfer->local_port = purple_network_get_port_from_fd(sock);
 		g_snprintf(port, sizeof(port), "%hu", xfer->local_port);
-
+		dstaddr = g_strdup_printf("%s%s%s@%s/%s", jsx->stream_id, 
+			jid, dstjid->node, dstjid->domain, dstjid->resource);
+		jabber_id_free(dstjid);
 		public_ip = purple_network_get_my_ip(jsx->js->fd);
 
 		/* Include the localhost's IPs (for in-network transfers) */
@@ -895,8 +600,9 @@ jabber_si_xfer_bytestreams_listen_cb(int
 		g_free(jid);
 
 		/* The listener for the local proxy */
-		xfer->watcher = purple_input_add(sock, PURPLE_INPUT_READ,
-				jabber_si_xfer_bytestreams_send_connected_cb, xfer);
+		jsx->socks5_listen_data = jabber_socks5_listen(sock, dstaddr,
+			jabber_si_listen_connect_cb, jabber_si_listen_error_cb, xfer);
+		g_free(dstaddr);
 	}
 
 	for (tmp = jsx->js->bs_proxies; tmp; tmp = tmp->next) {
@@ -1323,6 +1029,10 @@ static void jabber_si_xfer_free(PurpleXf
 			purple_proxy_connect_cancel(jsx->connect_data);
 		if (jsx->listen_data != NULL)
 			purple_network_listen_cancel(jsx->listen_data);
+		if (jsx->socks5_listen_data != NULL) {
+			jabber_socks5_listen_cancel(jsx->socks5_listen_data);
+			jabber_socks5_listen_data_free(jsx->socks5_listen_data);
+		}
 		if (jsx->iq_id != NULL)
 			jabber_iq_remove_callback_by_id(js, jsx->iq_id);
 		if (jsx->local_streamhost_fd >= 0)
@@ -1357,7 +1067,6 @@ static void jabber_si_xfer_free(PurpleXf
 		g_free(jsx->stream_id);
 		g_free(jsx->iq_id);
 		/* XXX: free other stuff */
-		g_free(jsx->rxqueue);
 		g_free(jsx);
 		xfer->data = NULL;
 	}


More information about the Commits mailing list