[libsoup] SoupSession: bind connections to messages sooner, improve conn failure case



commit 6d7e7e21e2da6109dd9ce287c2b51e312d66c2c7
Author: Dan Winship <danw gnome org>
Date:   Wed Jun 2 12:05:46 2010 +0200

    SoupSession: bind connections to messages sooner, improve conn failure case
    
    Rather than having connections be independent until a message is
    actually sent on them, assign them to queue items when they're created
    for them. This means that, eg, if another connection frees up while
    we're waiting for the first connection to connect, that we can't take
    advantage of that. But it simplifies a ton of other things.
    
    Also, if a new connection fails, don't fail every other message on
    that host; let them succeed or fail independently. When doing a
    CONNECT though, keep track of the queue item that necessitated it so
    we can error that out if the CONNECT fails, just like we would if the
    actual soup_connection_connect() had failed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=619633

 libsoup/soup-message-queue.c   |    6 ++
 libsoup/soup-message-queue.h   |    1 +
 libsoup/soup-session-async.c   |  127 +++++++++++++++++++++++-----------------
 libsoup/soup-session-private.h |    9 +--
 libsoup/soup-session-sync.c    |   75 ++++++++++++-----------
 libsoup/soup-session.c         |  113 +++++++----------------------------
 6 files changed, 144 insertions(+), 187 deletions(-)
---
diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c
index b421eff..5d01472 100644
--- a/libsoup/soup-message-queue.c
+++ b/libsoup/soup-message-queue.c
@@ -69,6 +69,12 @@ queue_message_restarted (SoupMessage *msg, gpointer user_data)
 		soup_uri_free (item->proxy_uri);
 		item->proxy_uri = NULL;
 	}
+
+	if (item->conn && !soup_message_is_keepalive (msg)) {
+		g_object_unref (item->conn);
+		item->conn = NULL;
+	}
+
 	item->state = SOUP_MESSAGE_STARTING;
 }
 
diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h
index ecb874e..7211d71 100644
--- a/libsoup/soup-message-queue.h
+++ b/libsoup/soup-message-queue.h
@@ -55,6 +55,7 @@ struct _SoupMessageQueueItem {
 	guint removed              : 1;
 	guint ref_count            : 31;
 	SoupMessageQueueItem *prev, *next;
+	SoupMessageQueueItem *related;
 };
 
 SoupMessageQueue     *soup_message_queue_new        (SoupSession          *session);
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index ee356ef..ee7fdf6 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -211,38 +211,58 @@ connection_closed (SoupConnection *conn, gpointer session)
 }
 
 static void
+message_completed (SoupMessage *msg, gpointer user_data)
+{
+	SoupMessageQueueItem *item = user_data;
+
+	if (item->state == SOUP_MESSAGE_RESTARTING)
+		soup_message_restarted (msg);
+	else {
+		item->state = SOUP_MESSAGE_FINISHED;
+		soup_message_finished (msg);
+	}
+}
+
+static void
 tunnel_message_completed (SoupMessage *msg, gpointer user_data)
 {
 	SoupMessageQueueItem *item = user_data;
 
 	if (item->state == SOUP_MESSAGE_RESTARTING) {
 		soup_message_restarted (msg);
-		if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED) {
-			soup_session_send_queue_item (item->session, item, item->conn, tunnel_message_completed);
+		if (item->conn) {
+			soup_session_send_queue_item (item->session, item, tunnel_message_completed);
 			return;
 		}
 
 		soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN);
+		item->state = SOUP_MESSAGE_FINISHED;
 	}
-
-	item->state = SOUP_MESSAGE_FINISHED;
-	soup_message_finished (msg);
+	message_completed (msg, item);
 }
 
 static void
 tunnel_connected (SoupMessage *msg, gpointer user_data)
 {
 	SoupMessageQueueItem *item = user_data;
+	SoupSession *session = item->session;
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-		soup_session_connection_failed (item->session, item->conn,
-						msg->status_code);
+		if (item->conn)
+			soup_connection_disconnect (item->conn);
+		if (msg->status_code == SOUP_STATUS_TRY_AGAIN) {
+			item->related->state = SOUP_MESSAGE_AWAITING_CONNECTION;
+			g_object_unref (item->related->conn);
+			item->related->conn = NULL;
+		} else
+			soup_message_set_status (item->related->msg, msg->status_code);
 		goto done;
 	}
 
 	if (!soup_connection_start_ssl (item->conn)) {
-		soup_session_connection_failed (item->session, item->conn,
-						SOUP_STATUS_SSL_FAILED);
+		if (item->conn)
+			soup_connection_disconnect (item->conn);
+		soup_message_set_status (item->related->msg, SOUP_STATUS_SSL_FAILED);
 		goto done;
 	}
 
@@ -250,73 +270,73 @@ tunnel_connected (SoupMessage *msg, gpointer user_data)
 			  G_CALLBACK (connection_closed), item->session);
 	soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE);
 
+	item->related->state = SOUP_MESSAGE_READY;
+
 done:
+	if (item->related->msg->status_code) {
+		item->related->state = SOUP_MESSAGE_FINISHED;
+		message_completed (item->related->msg, item->related);
+	}
+
 	do_idle_run_queue (item->session);
-	g_object_unref (item->session);
+	soup_message_queue_item_unref (item->related);
 	soup_message_queue_item_unref (item);
+	g_object_unref (session);
 }
 
 static void
 got_connection (SoupConnection *conn, guint status, gpointer user_data)
 {
-	SoupSession *session = user_data;
+	SoupMessageQueueItem *item = user_data;
+	SoupSession *session = item->session;
 	SoupAddress *tunnel_addr;
 
+	if (item->state != SOUP_MESSAGE_CONNECTING) {
+		soup_connection_disconnect (conn);
+		do_idle_run_queue (session);
+		soup_message_queue_item_unref (item);
+		g_object_unref (session);
+		return;
+	}
+
 	if (status != SOUP_STATUS_OK) {
+		soup_connection_disconnect (conn);
+		soup_message_set_status (item->msg, status);
+		message_completed (item->msg, item);
+
 		/* There may have been messages waiting for the
 		 * connection count to go down, so queue a run_queue.
 		 */
 		do_idle_run_queue (session);
 
-		soup_session_connection_failed (session, conn, status);
+		soup_message_queue_item_unref (item);
 		g_object_unref (session);
 		return;
 	}
 
 	tunnel_addr = soup_connection_get_tunnel_addr (conn);
 	if (tunnel_addr) {
-		SoupMessageQueueItem *item;
+		SoupMessageQueueItem *tunnel_item;
 
-		item = soup_session_make_connect_message (session, tunnel_addr);
-		g_signal_emit_by_name (session, "tunneling", conn);
-		g_signal_connect (item->msg, "finished",
-				  G_CALLBACK (tunnel_connected), item);
-		soup_session_send_queue_item (session, item, conn, tunnel_message_completed);
+		item->state = SOUP_MESSAGE_TUNNELING;
+
+		tunnel_item = soup_session_make_connect_message (session, conn);
+		tunnel_item->related = item;
+		g_signal_connect (tunnel_item->msg, "finished",
+				  G_CALLBACK (tunnel_connected), tunnel_item);
+		soup_session_send_queue_item (session, tunnel_item, tunnel_message_completed);
 		return;
 	}
 
+	item->state = SOUP_MESSAGE_READY;
 	g_signal_connect (conn, "disconnected",
 			  G_CALLBACK (connection_closed), session);
-
-	/* @conn has been marked reserved by SoupSession, but
-	 * we don't actually have any specific message in mind
-	 * for it. (In particular, the message we were
-	 * originally planning to queue on it may have already
-	 * been queued on some other connection that became
-	 * available while we were waiting for this one to
-	 * connect.) So we release the connection into the
-	 * idle pool and then just run the queue and see what
-	 * happens.
-	 */
-	soup_connection_set_state (conn, SOUP_CONNECTION_IDLE);
-	do_idle_run_queue (session);
+	run_queue ((SoupSessionAsync *)session);
+	soup_message_queue_item_unref (item);
 	g_object_unref (session);
 }
 
 static void
-message_completed (SoupMessage *msg, gpointer user_data)
-{
-	SoupMessageQueueItem *item = user_data;
-
-	if (item->state == SOUP_MESSAGE_RESTARTING)
-		soup_message_restarted (msg);
-	else {
-		item->state = SOUP_MESSAGE_FINISHED;
-		soup_message_finished (msg);
-	}
-}
-
-static void
 run_queue (SoupSessionAsync *sa)
 {
 	SoupSession *session = SOUP_SESSION (sa);
@@ -324,7 +344,6 @@ run_queue (SoupSessionAsync *sa)
 	SoupMessageQueueItem *item;
 	SoupProxyURIResolver *proxy_resolver;
 	SoupMessage *msg;
-	SoupConnection *conn;
 	gboolean try_pruning = TRUE, should_prune = FALSE;
 
 	soup_session_cleanup_connections (session, FALSE);
@@ -349,23 +368,25 @@ run_queue (SoupSessionAsync *sa)
 		}
 
 		if (item->state == SOUP_MESSAGE_AWAITING_CONNECTION) {
-			conn = soup_session_get_connection (session, item,
-							    &should_prune);
-			if (!conn)
+			if (!soup_session_get_connection (session, item,
+							  &should_prune))
 				continue;
 
-			if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
-				item->state = SOUP_MESSAGE_AWAITING_CONNECTION;
-				soup_connection_connect_async (conn, item->cancellable,
+			if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_NEW) {
+				item->state = SOUP_MESSAGE_CONNECTING;
+				soup_message_queue_item_ref (item);
+				g_object_ref (item->session);
+				soup_connection_connect_async (item->conn, item->cancellable,
 							       got_connection,
-							       g_object_ref (session));
+							       item);
+				continue;
 			} else
 				item->state = SOUP_MESSAGE_READY;
 		}
 
 		if (item->state == SOUP_MESSAGE_READY) {
 			item->state = SOUP_MESSAGE_RUNNING;
-			soup_session_send_queue_item (session, item, conn, message_completed);
+			soup_session_send_queue_item (session, item, message_completed);
 		}
 	}
 	if (item)
diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h
index 0a8f888..0f9c3ac 100644
--- a/libsoup/soup-session-private.h
+++ b/libsoup/soup-session-private.h
@@ -16,19 +16,14 @@ G_BEGIN_DECLS
 SoupMessageQueue     *soup_session_get_queue            (SoupSession          *session);
 
 SoupMessageQueueItem *soup_session_make_connect_message (SoupSession          *session,
-							 SoupAddress          *server_addr);
-SoupConnection       *soup_session_get_connection       (SoupSession          *session,
+							 SoupConnection       *conn);
+gboolean              soup_session_get_connection       (SoupSession          *session,
 							 SoupMessageQueueItem *item,
 							 gboolean             *try_pruning);
 gboolean              soup_session_cleanup_connections  (SoupSession          *session,
 							 gboolean              prune_idle);
-void                  soup_session_connection_failed    (SoupSession          *session,
-							 SoupConnection       *conn,
-							 guint                 status);
-
 void                  soup_session_send_queue_item      (SoupSession          *session,
 							 SoupMessageQueueItem *item,
-							 SoupConnection       *conn,
 							 SoupMessageCompletionFn completion_cb);
 
 G_END_DECLS
diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c
index b9db714..0de0b81 100644
--- a/libsoup/soup-session-sync.c
+++ b/libsoup/soup-session-sync.c
@@ -137,18 +137,16 @@ soup_session_sync_new_with_options (const char *optname1, ...)
 }
 
 static guint
-tunnel_connect (SoupSession *session, SoupConnection *conn,
-		SoupAddress *tunnel_addr)
+tunnel_connect (SoupSession *session, SoupConnection *conn)
 {
 	SoupMessageQueueItem *item;
 	guint status;
 
 	g_object_ref (conn);
 
-	g_signal_emit_by_name (session, "tunneling", conn);
-	item = soup_session_make_connect_message (session, tunnel_addr);
+	item = soup_session_make_connect_message (session, conn);
 	do {
-		soup_session_send_queue_item (session, item, conn, NULL);
+		soup_session_send_queue_item (session, item, NULL);
 		if (item->state == SOUP_MESSAGE_RESTARTING) {
 			item->state = SOUP_MESSAGE_STARTING;
 			soup_message_restarted (item->msg);
@@ -174,13 +172,13 @@ tunnel_connect (SoupSession *session, SoupConnection *conn,
 	}
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (status))
-		soup_session_connection_failed (session, conn, status);
+		soup_connection_disconnect (conn);
 
 	g_object_unref (conn);
 	return status;
 }
 
-static SoupConnection *
+static gboolean
 wait_for_connection (SoupMessageQueueItem *item)
 {
 	SoupSession *session = item->session;
@@ -188,8 +186,6 @@ wait_for_connection (SoupMessageQueueItem *item)
 	SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session);
 	gboolean try_pruning = FALSE;
 	SoupProxyURIResolver *proxy_resolver;
-	SoupAddress *tunnel_addr;
-	SoupConnection *conn;
 	guint status;
 
 	proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, msg);
@@ -201,7 +197,7 @@ wait_for_connection (SoupMessageQueueItem *item)
 		if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 			if (status != SOUP_STATUS_CANCELLED)
 				soup_session_cancel_message (session, msg, status);
-			return NULL;
+			return FALSE;
 		}
 		item->state = SOUP_MESSAGE_RESOLVED_PROXY_URI;
 
@@ -214,11 +210,9 @@ wait_for_connection (SoupMessageQueueItem *item)
 			if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 				if (status != SOUP_STATUS_CANCELLED)
 					soup_session_cancel_message (session, msg, status);
-				return NULL;
+				return FALSE;
 			}
 		}
-
-		item->state = SOUP_MESSAGE_AWAITING_CONNECTION;
 	}
 
 	g_mutex_lock (priv->lock);
@@ -226,36 +220,44 @@ wait_for_connection (SoupMessageQueueItem *item)
 	soup_session_cleanup_connections (session, FALSE);
 
  try_again:
-	conn = soup_session_get_connection (session, item, &try_pruning);
-	if (conn) {
-		if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
+	item->state = SOUP_MESSAGE_AWAITING_CONNECTION;
+	if (soup_session_get_connection (session, item, &try_pruning)) {
+		if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_NEW) {
 			item->state = SOUP_MESSAGE_CONNECTING;
-			status = soup_connection_connect_sync (conn, item->cancellable);
+			status = soup_connection_connect_sync (item->conn, item->cancellable);
 
 			if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
-				soup_session_connection_failed (session, conn, status);
-				conn = NULL;
+				soup_connection_disconnect (item->conn);
+				g_object_unref (item->conn);
+				item->conn = NULL;
 			} else if (item->state == SOUP_MESSAGE_FINISHED) {
 				/* Message was cancelled while we were
 				 * connecting.
 				 */
-				soup_connection_disconnect (conn);
-				conn = NULL;
-			} else if ((tunnel_addr = soup_connection_get_tunnel_addr (conn))) {
+				soup_connection_disconnect (item->conn);
+				g_object_unref (item->conn);
+				item->conn = NULL;
+			} else if (soup_connection_get_tunnel_addr (item->conn)) {
 				item->state = SOUP_MESSAGE_TUNNELING;
-				status = tunnel_connect (session, conn, tunnel_addr);
-				if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
-					conn = NULL;
-					if (status == SOUP_STATUS_TRY_AGAIN)
-						goto try_again;
-				} else
+				status = tunnel_connect (session, item->conn);
+				if (SOUP_STATUS_IS_SUCCESSFUL (status))
 					item->state = SOUP_MESSAGE_READY;
+				else if (status == SOUP_STATUS_TRY_AGAIN) {
+					soup_connection_disconnect (item->conn);
+					g_object_unref (item->conn);
+					item->conn = NULL;
+					goto try_again;
+				} else {
+					soup_message_set_status (item->msg, status);
+					item->state = SOUP_MESSAGE_FINISHED;
+				}
                         } else
 				item->state = SOUP_MESSAGE_READY;
-		}
+		} else
+			item->state = SOUP_MESSAGE_READY;
 
 		g_mutex_unlock (priv->lock);
-		return conn;
+		return item->conn != NULL;
 	}
 
 	if (try_pruning) {
@@ -270,7 +272,7 @@ wait_for_connection (SoupMessageQueueItem *item)
 	/* See if something bad happened */
 	if (item->state == SOUP_MESSAGE_FINISHED) {
 		g_mutex_unlock (priv->lock);
-		return NULL;
+		return FALSE;
 	}
 
 	goto try_again;
@@ -280,16 +282,17 @@ static void
 process_queue_item (SoupMessageQueueItem *item)
 {
 	SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (item->session);
-	SoupConnection *conn;
 
 	item->state = SOUP_MESSAGE_STARTING;
 	do {
-		conn = wait_for_connection (item);
-		if (!conn)
+		if (!wait_for_connection (item))
 			break;
 
-		item->state = SOUP_MESSAGE_RUNNING;
-		soup_session_send_queue_item (item->session, item, conn, NULL);
+		if (item->state == SOUP_MESSAGE_READY) {
+			item->state = SOUP_MESSAGE_RUNNING;
+			soup_session_send_queue_item (item->session, item, NULL);
+		}
+
 		if (item->state == SOUP_MESSAGE_RESTARTING) {
 			item->state = SOUP_MESSAGE_STARTING;
 			soup_message_restarted (item->msg);
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 22c91ae..bd42795 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1174,19 +1174,10 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
 void
 soup_session_send_queue_item (SoupSession *session,
 			      SoupMessageQueueItem *item,
-			      SoupConnection *conn,
 			      SoupMessageCompletionFn completion_cb)
 {
 	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
 
-	if (item->conn) {
-		if (item->conn != conn) {
-			g_object_unref (item->conn);
-			item->conn = g_object_ref (conn);
-		}
-	} else
-		item->conn = g_object_ref (conn);
-
 	if (priv->user_agent) {
 		soup_message_headers_replace (item->msg->request_headers,
 					      "User-Agent", priv->user_agent);
@@ -1201,8 +1192,8 @@ soup_session_send_queue_item (SoupSession *session,
 	}
 
 	g_signal_emit (session, signals[REQUEST_STARTED], 0,
-		       item->msg, soup_connection_get_socket (conn));
-	soup_connection_send_request (conn, item, completion_cb, item);
+		       item->msg, soup_connection_get_socket (item->conn));
+	soup_connection_send_request (item->conn, item, completion_cb, item);
 }
 
 gboolean
@@ -1261,47 +1252,12 @@ connection_disconnected (SoupConnection *conn, gpointer user_data)
 	g_object_unref (conn);
 }
 
-void
-soup_session_connection_failed (SoupSession *session,
-				SoupConnection *conn, guint status)
-{
-	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
-	SoupSessionHost *host;
-	SoupMessageQueueItem *item;
-	SoupMessage *msg;
-
-	g_mutex_lock (priv->host_lock);
-	host = g_hash_table_lookup (priv->conns, conn);
-	g_mutex_unlock (priv->host_lock);
-
-	if (host)
-		soup_connection_disconnect (conn);
-	else if (conn)
-		host = g_object_get_data (G_OBJECT (conn), "SoupSessionHost");
-	if (!host)
-		return;
-
-	if (status == SOUP_STATUS_TRY_AGAIN)
-		return;
-
-	/* Cancel any other messages waiting for a connection to it,
-	 * since they're out of luck.
-	 */
-	g_object_ref (session);
-	for (item = soup_message_queue_first (priv->queue); item; item = soup_message_queue_next (priv->queue, item)) {
-		msg = item->msg;
-		if (item->state < SOUP_MESSAGE_RUNNING &&
-		    get_host_for_message (session, msg) == host)
-			soup_session_cancel_message (session, msg, status);
-	}
-	g_object_unref (session);
-}
-
 SoupMessageQueueItem *
-soup_session_make_connect_message (SoupSession *session,
-				   SoupAddress *server_addr)
+soup_session_make_connect_message (SoupSession    *session,
+				   SoupConnection *conn)
 {
 	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+	SoupAddress *server_addr = soup_connection_get_tunnel_addr (conn);
 	SoupURI *uri;
 	SoupMessage *msg;
 	SoupMessageQueueItem *item;
@@ -1321,46 +1277,15 @@ soup_session_make_connect_message (SoupSession *session,
 	 */
 	queue_message (session, msg, NULL, NULL);
 	item = soup_message_queue_lookup (priv->queue, msg);
+	item->conn = g_object_ref (conn);
 	g_object_unref (msg);
+
+	item->conn = g_object_ref (conn);
+	g_signal_emit (session, signals[TUNNELING], 0, conn);
 	return item;
 }
 
-/**
- * soup_session_get_connection:
- * @session: a #SoupSession
- * @item: a #SoupMessageQueueItem
- * @try_pruning: on return, whether or not to try pruning a connection
- * 
- * Tries to find or create a connection for @item; this is an internal
- * method for #SoupSession subclasses.
- *
- * If there is an idle connection to the relevant host available, then
- * that connection will be returned. The connection will be set to
- * %SOUP_CONNECTION_IN_USE, so the caller must call
- * soup_connection_set_state() to set it to %SOUP_CONNECTION_IDLE if
- * it ends up not using the connection right away.
- *
- * If there is no idle connection available, but it is possible to
- * create a new connection, then one will be created and returned
- * (with state %SOUP_CONNECTION_NEW). The caller MUST then call
- * soup_connection_connect_sync() or soup_connection_connect_async()
- * to connect it. If the connection attempt fails, the caller must
- * call soup_session_connection_failed() to tell the session to free
- * the connection.
- *
- * If no connection is available and a new connection cannot be made,
- * soup_session_get_connection() will return %NULL. If @session has
- * the maximum number of open connections open, but does not have the
- * maximum number of per-host connections open to the relevant host,
- * then * try_pruning will be set to %TRUE. In this case, the caller
- * can call soup_session_try_prune_connection() to close an idle
- * connection, and then try soup_session_get_connection() again. (If
- * calling soup_session_try_prune_connection() wouldn't help, then
- * * try_pruning is left untouched; it is NOT set to %FALSE.)
- *
- * Return value: a #SoupConnection, or %NULL
- **/
-SoupConnection *
+gboolean
 soup_session_get_connection (SoupSession *session,
 			     SoupMessageQueueItem *item,
 			     gboolean *try_pruning)
@@ -1374,6 +1299,11 @@ soup_session_get_connection (SoupSession *session,
 	int num_pending = 0;
 	SoupURI *uri;
 
+	if (item->conn) {
+		g_return_val_if_fail (soup_connection_get_state (item->conn) != SOUP_CONNECTION_DISCONNECTED, FALSE);
+		return TRUE;
+	}
+
 	g_mutex_lock (priv->host_lock);
 
 	host = get_host_for_message (session, item->msg);
@@ -1381,7 +1311,8 @@ soup_session_get_connection (SoupSession *session,
 		if (soup_connection_get_state (conns->data) == SOUP_CONNECTION_IDLE) {
 			soup_connection_set_state (conns->data, SOUP_CONNECTION_IN_USE);
 			g_mutex_unlock (priv->host_lock);
-			return conns->data;
+			item->conn = g_object_ref (conns->data);
+			return TRUE;
 		} else if (soup_connection_get_state (conns->data) == SOUP_CONNECTION_CONNECTING)
 			num_pending++;
 	}
@@ -1391,18 +1322,18 @@ soup_session_get_connection (SoupSession *session,
 	 */
 	if (num_pending > host->num_messages / 2) {
 		g_mutex_unlock (priv->host_lock);
-		return NULL;
+		return FALSE;
 	}
 
 	if (host->num_conns >= priv->max_conns_per_host) {
 		g_mutex_unlock (priv->host_lock);
-		return NULL;
+		return FALSE;
 	}
 
 	if (priv->num_conns >= priv->max_conns) {
 		*try_pruning = TRUE;
 		g_mutex_unlock (priv->host_lock);
-		return NULL;
+		return FALSE;
 	}
 
 	if (item->proxy_addr) {
@@ -1434,7 +1365,6 @@ soup_session_get_connection (SoupSession *session,
 		SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
 		SOUP_CONNECTION_IDLE_TIMEOUT, priv->idle_timeout,
 		NULL);
-	g_object_set_data (G_OBJECT (conn), "SoupSessionHost", host);
 	g_signal_connect (conn, "disconnected",
 			  G_CALLBACK (connection_disconnected),
 			  session);
@@ -1448,7 +1378,8 @@ soup_session_get_connection (SoupSession *session,
 	host->connections = g_slist_prepend (host->connections, conn);
 
 	g_mutex_unlock (priv->host_lock);
-	return conn;
+	item->conn = g_object_ref (conn);
+	return TRUE;
 }
 
 SoupMessageQueue *



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]