cpw.malu.xmpp.jingle_ft: 1be689a6: Add a timeout when attempting to connect...

malu at pidgin.im malu at pidgin.im
Tue Apr 14 14:50:34 EDT 2009


-----------------------------------------------------------------
Revision: 1be689a6f36b6dd2b33065e584ce180e50f27da9
Ancestor: 03153e057327c53dbe50f6ccb4c2f014f1cf88cb
Author: malu at pidgin.im
Date: 2009-04-14T18:45:29
Branch: im.pidgin.cpw.malu.xmpp.jingle_ft
URL: http://d.pidgin.im/viewmtn/revision/info/1be689a6f36b6dd2b33065e584ce180e50f27da9

Modified files:
        libpurple/protocols/jabber/jingle/s5b.c

ChangeLog: 

Add a timeout when attempting to connect to a streamhost
Try the next streamhost on timeout

-------------- next part --------------
============================================================
--- libpurple/protocols/jabber/jingle/s5b.c	9f9cb4002730781d7bd1a207c3f562916c3a5248
+++ libpurple/protocols/jabber/jingle/s5b.c	d18d4f3814413c43c47de0e6143f81bc51406f25
@@ -24,6 +24,9 @@
 #include "network.h"
 #include "xmlnode.h"
 
+
+#define STREAMHOST_CONNECT_TIMEOUT_MILLIS 200
+
 /* auxillary functions to handle JabberBytestreamsStreamhosts, maybe this
  should be in a separtate module, used by si.c and other places as well */
 
@@ -136,6 +139,7 @@ struct _JingleS5BPrivate {
 	PurpleProxyConnectData *connect_data;
 	PurpleNetworkListenData *listen_data;
 	PurpleProxyInfo *ppi;
+	guint connect_timeout;
 	int watcher;
 	char *rxqueue;
 	size_t rxlen;
@@ -148,6 +152,8 @@ struct _JingleS5BPrivate {
 	JingleS5BErrorCallback *error_cb;
 	JingleContent *connect_content; /* used for the connect callback */
 	JingleContent *error_content;  /* used for the error callback */
+	gboolean is_connected_to_remote;
+	gboolean is_remote_connected;
 };
 
 #define JINGLE_S5B_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), JINGLE_TYPE_S5B, JingleS5BPrivate))
@@ -261,6 +267,9 @@ jingle_s5b_finalize (GObject *s5b)
 	if (priv->ppi)
 		purple_proxy_info_destroy(priv->ppi);
 
+	if (priv->connect_timeout)
+		purple_timeout_remove(priv->connect_timeout);
+	
 	G_OBJECT_CLASS(parent_class)->finalize(s5b);
 }
 
@@ -452,6 +461,7 @@ jingle_s5b_send_read_again_resp_cb(gpoin
 					  "Waiting for IQ result to start file transfer.\n");
 	/* set the local fd as connected */
 	s5b->priv->local_fd = source;
+	s5b->priv->is_remote_connected = TRUE;
 	
 	g_free(data);
 }
@@ -857,9 +867,14 @@ jingle_s5b_transport_accept_cb(JabberStr
 	JingleSession *session = cd->session;
 	JingleS5B *s5b = cd->s5b;
 	
+	purple_debug_info("jingle-s5b", 
+		"in jingle_s5b_transport_accept_cb: is connected to remote %d,"
+		" remote is connected %d\n", jingle_s5b_is_connected_to_remote(s5b),
+		jingle_s5b_remote_is_connected(s5b));
+	
 	if (type == JABBER_IQ_RESULT) {
-		if ((!jingle_session_is_initiator(session) &&
-			jingle_s5b_remote_is_connected(s5b)) ||
+		if (!(!jingle_session_is_initiator(session) &&
+			jingle_s5b_is_connected_to_remote(s5b)) ||
 			!jingle_s5b_remote_is_connected(s5b)) {
 			/* unless we are the receiver and the receiver could connect,
 				now we shall "surrender" to other side and signal the content
@@ -889,7 +904,14 @@ jingle_s5b_connect_cb(gpointer data, gin
 	
 	s5b->priv->connect_data = NULL;
 	s5b->priv->remote_fd = source;
+	s5b->priv->is_connected_to_remote = TRUE;
 	
+	/* cancel timeout if set */
+	if (s5b->priv->connect_timeout) {
+		purple_timeout_remove(s5b->priv->connect_timeout);
+		s5b->priv->connect_timeout = 0;
+	}
+
 	/* set the currently tried streamhost as the successfull one */
 	s5b->priv->successfull_remote_streamhost =
 		(JabberBytestreamsStreamhost *) s5b->priv->remaining_streamhosts->data;
@@ -903,10 +925,35 @@ jingle_s5b_connect_cb(gpointer data, gin
 	jabber_iq_send(result);
 }
 	
+static void jingle_s5b_attempt_connect_internal(gpointer data);
+
 static void
-jingle_s5b_attempt_connect_internal(JingleSession *session, JingleS5B *s5b)
+jingle_s5b_connect_timeout_cb(gpointer data)
 {
+	JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+	
+	purple_debug_info("jingle-s5b", "in jingle_s5b_connect_timeout_cb\n");
+	/* cancel timeout */
+	purple_timeout_remove(s5b->priv->connect_timeout);
+	
+	/* advance streamhost "counter" */
 	if (s5b->priv->remaining_streamhosts) {
+		s5b->priv->remaining_streamhosts = 
+			s5b->priv->remaining_streamhosts->data;
+		purple_debug_info("jingle-s5b", "trying next streamhost\n");
+		/* if remaining_streamhost is NULL here, this call will result in a
+		 streamhost error (and potentially fallback to IBB) */
+		jingle_s5b_attempt_connect_internal(data);
+	}
+}
+
+static void
+jingle_s5b_attempt_connect_internal(gpointer data)
+{
+	JingleSession *session = ((JingleS5BConnectData *) data)->session;
+	JingleS5B *s5b = ((JingleS5BConnectData *) data)->s5b;
+	
+	if (s5b->priv->remaining_streamhosts) {
 		JabberStream *js = jingle_session_get_js(session);
 		const gchar *who = jingle_session_get_remote_jid(session);
 		JabberID *dstjid = jabber_id_new(who);
@@ -941,10 +988,6 @@ jingle_s5b_attempt_connect_internal(Jing
 		hash = jabber_calculate_data_sha1sum(dstaddr, strlen(dstaddr));
 		purple_debug_info("jingle-s5b", "connecting with hash: %s\n", hash);
 		
-		data = g_new0(JingleS5BConnectData, 1);
-		data->session = session;
-		data->s5b = s5b;
-		
 		s5b->priv->connect_data = 
 			purple_proxy_connect_socks5(NULL, s5b->priv->ppi, hash, 0, 
 				jingle_s5b_connect_cb, data);
@@ -952,16 +995,30 @@ jingle_s5b_attempt_connect_internal(Jing
 		g_free(dstaddr);
 		
 		/* add timeout */
+		/* we should add a longer timeout if the next streamhost candidate
+		 is a proxy and we have local candidates ourselves, to allow the other
+		 end a chance to connect to use before reverting to a proxy */
+		s5b->priv->connect_timeout =
+			purple_timeout_add(STREAMHOST_CONNECT_TIMEOUT_MILLIS,
+				jingle_s5b_connect_timeout_cb, data);
 		
 		g_free(dstjid);
+	} else {
+		/* send streamhost error */
+		
+		g_free(data);
 	}
 }
 
 void
 jingle_s5b_attempt_connect(JingleSession *session, JingleS5B *s5b)
 {
+	JingleS5BConnectData *data = g_new0(JingleS5BConnectData, 1);
+	
+	data->session = session;
+	data->s5b = s5b;
 	s5b->priv->remaining_streamhosts = s5b->priv->remote_streamhosts;
-	jingle_s5b_attempt_connect_internal(session, s5b);
+	jingle_s5b_attempt_connect_internal(data);
 }
 
 void
@@ -980,18 +1037,23 @@ jingle_s5b_stop_connection_attempts(Jing
 		purple_input_remove(s5b->priv->watcher);
 		s5b->priv->watcher = 0;
 	}
+	
+	if (s5b->priv->connect_timeout) {
+		purple_timeout_remove(s5b->priv->connect_timeout);
+		s5b->priv->connect_timeout = 0;
+	}
 }
 
 gboolean
 jingle_s5b_is_connected_to_remote(const JingleS5B *s5b)
 {
-	return s5b->priv->remote_fd;
+	return s5b->priv->is_connected_to_remote;
 }
 
 gboolean
 jingle_s5b_remote_is_connected(const JingleS5B *s5b)
 {
-	return s5b->priv->local_fd;
+	return s5b->priv->is_remote_connected;
 }
 	
 void
@@ -1010,6 +1072,11 @@ jingle_s5b_surrender(JingleS5B *s5b)
 		purple_input_remove(s5b->priv->watcher);
 		s5b->priv->watcher = 0;
 	}
+	
+	if (s5b->priv->connect_timeout) {
+		purple_timeout_remove(s5b->priv->connect_timeout);
+		s5b->priv->connect_timeout = 0;
+	}
 }
 
 void
@@ -1028,4 +1095,9 @@ jingle_s5b_take_command(JingleS5B *s5b)
 		purple_input_remove(s5b->priv->watcher);
 		s5b->priv->watcher = 0;
 	}
+	
+	if (s5b->priv->connect_timeout) {
+		purple_timeout_remove(s5b->priv->connect_timeout);
+		s5b->priv->connect_timeout = 0;
+	}
 }
\ No newline at end of file


More information about the Commits mailing list