[libsoup] Misc SoupConnection API improvements



commit f3f1e3822459a8b1f38661177069a3a9e617bdc5
Author: Dan Winship <danw gnome org>
Date:   Sat May 29 15:05:55 2010 +0200

    Misc SoupConnection API improvements
    
    Use GCancellables in connect_async/connect_sync (plus updates needed
    for behavior changes caused by that). Make
    soup_connection_disconnect() always emit the signal if the connection
    state wasn't already DISCONNECTED, even if it wasn't yet connected
    before. Remove some dead code in clear_current_request. Remove some
    more-or-less redundant arguments in soup_message_send_request().

 libsoup/soup-connection.c        |   69 +++++++++++++++-----------------------
 libsoup/soup-connection.h        |    7 +++-
 libsoup/soup-message-client-io.c |   15 +++++---
 libsoup/soup-message-io.c        |    7 ++--
 libsoup/soup-message-private.h   |    5 +--
 libsoup/soup-session-async.c     |    3 +-
 libsoup/soup-session-sync.c      |    2 +-
 libsoup/soup-socket.c            |   12 +++++-
 8 files changed, 58 insertions(+), 62 deletions(-)
---
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 98e2730..58614ac 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -386,14 +386,6 @@ clear_current_request (SoupConnection *conn)
 	g_object_freeze_notify (G_OBJECT (conn));
 
 	priv->unused_timeout = 0;
-
-	if (priv->state == SOUP_CONNECTION_IN_USE) {
-		/* We don't use soup_connection_set_state here since
-		 * it may call clear_current_request()...
-		 */
-		priv->state = SOUP_CONNECTION_IDLE;
-		g_object_notify (G_OBJECT (conn), "state");
-	}
 	start_idle_timer (conn);
 	if (priv->cur_req) {
 		SoupMessage *cur_req = priv->cur_req;
@@ -403,8 +395,6 @@ clear_current_request (SoupConnection *conn)
 
 		if (!soup_message_is_keepalive (cur_req))
 			soup_connection_disconnect (conn);
-		else
-			soup_message_io_stop (cur_req);
 	}
 
 	g_object_thaw_notify (G_OBJECT (conn));
@@ -457,16 +447,9 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data)
 	g_slice_free (SoupConnectionAsyncConnectData, data);
 }
 
-/**
- * soup_connection_connect_async:
- * @conn: the connection
- * @callback: callback to call when the connection succeeds or fails
- * @user_data: data for @callback
- *
- * Asynchronously connects @conn.
- **/
 void
 soup_connection_connect_async (SoupConnection *conn,
+			       GCancellable *cancellable,
 			       SoupConnectionCallback callback,
 			       gpointer user_data)
 {
@@ -492,20 +475,12 @@ soup_connection_connect_async (SoupConnection *conn,
 				 SOUP_SOCKET_TIMEOUT, priv->io_timeout,
 				 "clean-dispose", TRUE,
 				 NULL);
-	soup_socket_connect_async (priv->socket, NULL,
+	soup_socket_connect_async (priv->socket, cancellable,
 				   socket_connect_result, data);
 }
 
-/**
- * soup_connection_connect_sync:
- * @conn: the connection
- *
- * Synchronously connects @conn.
- *
- * Return value: the soup status
- **/
 guint
-soup_connection_connect_sync (SoupConnection *conn)
+soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable)
 {
 	SoupConnectionPrivate *priv;
 	guint status;
@@ -525,7 +500,7 @@ soup_connection_connect_sync (SoupConnection *conn)
 				 "clean-dispose", TRUE,
 				 NULL);
 
-	status = soup_socket_connect_sync (priv->socket, NULL);
+	status = soup_socket_connect_sync (priv->socket, cancellable);
 
 	if (!SOUP_STATUS_IS_SUCCESSFUL (status))
 		goto fail;
@@ -534,7 +509,7 @@ soup_connection_connect_sync (SoupConnection *conn)
 			  G_CALLBACK (socket_disconnected), conn);
 
 	if (priv->ssl_creds && !priv->tunnel_addr) {
-		if (!soup_socket_start_ssl (priv->socket, NULL)) {
+		if (!soup_socket_start_ssl (priv->socket, cancellable)) {
 			status = SOUP_STATUS_SSL_FAILED;
 			goto fail;
 		}
@@ -594,22 +569,25 @@ void
 soup_connection_disconnect (SoupConnection *conn)
 {
 	SoupConnectionPrivate *priv;
+	SoupConnectionState old_state;
 
 	g_return_if_fail (SOUP_IS_CONNECTION (conn));
 	priv = SOUP_CONNECTION_GET_PRIVATE (conn);
 
-	soup_connection_set_state (conn, SOUP_CONNECTION_DISCONNECTED);
-	if (!priv->socket)
-		return;
+	old_state = priv->state;
+	if (old_state != SOUP_CONNECTION_DISCONNECTED)
+		soup_connection_set_state (conn, SOUP_CONNECTION_DISCONNECTED);
 
-	g_signal_handlers_disconnect_by_func (priv->socket,
-					      socket_disconnected, conn);
-	soup_socket_disconnect (priv->socket);
-	g_object_unref (priv->socket);
-	priv->socket = NULL;
+	if (priv->socket) {
+		g_signal_handlers_disconnect_by_func (priv->socket,
+						      socket_disconnected, conn);
+		soup_socket_disconnect (priv->socket);
+		g_object_unref (priv->socket);
+		priv->socket = NULL;
+	}
 
-	/* NB: this might cause conn to be destroyed. */
-	g_signal_emit (conn, signals[DISCONNECTED], 0);
+	if (old_state != SOUP_CONNECTION_DISCONNECTED)
+		g_signal_emit (conn, signals[DISCONNECTED], 0);
 }
 
 SoupSocket *
@@ -628,6 +606,14 @@ soup_connection_get_proxy_uri (SoupConnection *conn)
 	return SOUP_CONNECTION_GET_PRIVATE (conn)->proxy_uri;
 }
 
+gboolean
+soup_connection_is_via_proxy (SoupConnection *conn)
+{
+	g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE);
+
+	return SOUP_CONNECTION_GET_PRIVATE (conn)->proxy_uri != NULL;
+}
+
 SoupConnectionState
 soup_connection_get_state (SoupConnection *conn)
 {
@@ -704,6 +690,5 @@ soup_connection_send_request (SoupConnection *conn, SoupMessage *req)
 
 	if (req != priv->cur_req)
 		set_current_request (conn, req);
-	soup_message_send_request (req, priv->socket, conn,
-				   priv->proxy_uri != NULL);
+	soup_message_send_request (req, conn);
 }
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index 17b9f7b..558a465 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -6,7 +6,7 @@
 #ifndef SOUP_CONNECTION_H
 #define SOUP_CONNECTION_H 1
 
-#include <time.h>
+#include <gio/gio.h>
 
 #include "soup-types.h"
 #include "soup-misc.h"
@@ -55,9 +55,11 @@ SoupConnection *soup_connection_new            (const char       *propname1,
 						...) G_GNUC_NULL_TERMINATED;
 
 void            soup_connection_connect_async  (SoupConnection   *conn,
+						GCancellable     *cancellable,
 						SoupConnectionCallback callback,
 						gpointer          user_data);
-guint           soup_connection_connect_sync   (SoupConnection   *conn);
+guint           soup_connection_connect_sync   (SoupConnection   *conn,
+						GCancellable     *cancellable);
 SoupAddress    *soup_connection_get_tunnel_addr(SoupConnection   *conn);
 gboolean        soup_connection_start_ssl      (SoupConnection   *conn);
 
@@ -65,6 +67,7 @@ void            soup_connection_disconnect     (SoupConnection   *conn);
 
 SoupSocket     *soup_connection_get_socket     (SoupConnection   *conn);
 SoupURI        *soup_connection_get_proxy_uri  (SoupConnection   *conn);
+gboolean        soup_connection_is_via_proxy   (SoupConnection   *conn);
 
 SoupConnectionState soup_connection_get_state  (SoupConnection   *conn);
 void                soup_connection_set_state  (SoupConnection   *conn,
diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c
index 618652f..0c091e6 100644
--- a/libsoup/soup-message-client-io.c
+++ b/libsoup/soup-message-client-io.c
@@ -14,6 +14,7 @@
 
 #include "soup-message-private.h"
 #include "soup-auth.h"
+#include "soup-connection.h"
 #include "soup-headers.h"
 #include "soup-uri.h"
 
@@ -76,7 +77,7 @@ get_request_headers (SoupMessage *req, GString *header,
 		     SoupEncoding *encoding, gpointer user_data)
 {
 	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
-	gboolean proxy = GPOINTER_TO_UINT (user_data);
+	SoupConnection *conn = user_data;
 	SoupURI *uri = soup_message_get_uri (req);
 	char *uri_host;
 	char *uri_string;
@@ -92,6 +93,8 @@ get_request_headers (SoupMessage *req, GString *header,
 		/* CONNECT URI is hostname:port for tunnel destination */
 		uri_string = g_strdup_printf ("%s:%d", uri_host, uri->port);
 	} else {
+		gboolean proxy = soup_connection_is_via_proxy (conn);
+
 		/* Proxy expects full URI to destination. Otherwise
 		 * just the path.
 		 */
@@ -143,12 +146,12 @@ get_request_headers (SoupMessage *req, GString *header,
 }
 
 void
-soup_message_send_request (SoupMessage *req, SoupSocket *sock,
-			   SoupConnection *conn, gboolean is_via_proxy)
+soup_message_send_request (SoupMessage    *msg,
+			   SoupConnection *conn)
 {
-	soup_message_cleanup_response (req);
-	soup_message_io_client (req, sock, conn,
+	soup_message_cleanup_response (msg);
+	soup_message_io_client (msg, conn,
 				get_request_headers,
 				parse_response_headers,
-				GUINT_TO_POINTER (is_via_proxy));
+				conn);
 }
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 02f2e45..324b147 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -1043,19 +1043,18 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
 }
 
 void
-soup_message_io_client (SoupMessage *msg, SoupSocket *sock,
-			SoupConnection *conn,
+soup_message_io_client (SoupMessage *msg, SoupConnection *conn,
 			SoupMessageGetHeadersFn get_headers_cb,
 			SoupMessageParseHeadersFn parse_headers_cb,
 			gpointer user_data)
 {
 	SoupMessageIOData *io;
+	SoupSocket *sock = soup_connection_get_socket (conn);
 
 	io = new_iostate (msg, sock, SOUP_MESSAGE_IO_CLIENT,
 			  get_headers_cb, parse_headers_cb, user_data);
 
-	if (conn)
-		io->conn = g_object_ref (conn);
+	io->conn = g_object_ref (conn);
 
 	io->read_body       = msg->response_body;
 	io->write_body      = msg->request_body;
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index f279303..cd8a94e 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -62,14 +62,11 @@ typedef guint    (*SoupMessageParseHeadersFn)(SoupMessage      *msg,
 					      gpointer          user_data);
 
 void           soup_message_send_request        (SoupMessage       *req,
-						 SoupSocket        *sock,
-						 SoupConnection    *conn,
-						 gboolean           via_proxy);
+						 SoupConnection    *conn);
 void           soup_message_read_request        (SoupMessage       *req,
 						 SoupSocket        *sock);
 
 void soup_message_io_client  (SoupMessage               *msg,
-			      SoupSocket                *sock,
 			      SoupConnection            *conn,
 			      SoupMessageGetHeadersFn    get_headers_cb,
 			      SoupMessageParseHeadersFn  parse_headers_cb,
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index c0630ca..6df4ca4 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -336,7 +336,8 @@ run_queue (SoupSessionAsync *sa)
 			continue;
 
 		if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
-			soup_connection_connect_async (conn, got_connection,
+			soup_connection_connect_async (conn, item->cancellable,
+						       got_connection,
 						       g_object_ref (session));
 		} else
 			soup_session_send_queue_item (session, item, conn);
diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c
index 100ce38..dd3cc82 100644
--- a/libsoup/soup-session-sync.c
+++ b/libsoup/soup-session-sync.c
@@ -211,7 +211,7 @@ wait_for_connection (SoupMessageQueueItem *item)
 	conn = soup_session_get_connection (session, item, &try_pruning);
 	if (conn) {
 		if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
-			status = soup_connection_connect_sync (conn);
+			status = soup_connection_connect_sync (conn, item->cancellable);
 
 			if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
 				soup_session_connection_failed (session, conn, status);
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 871ec69..7ebe5bc 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -133,8 +133,10 @@ soup_socket_init (SoupSocket *sock)
 static void
 disconnect_internal (SoupSocketPrivate *priv)
 {
-	g_io_channel_unref (priv->iochannel);
-	priv->iochannel = NULL;
+	if (priv->iochannel) {
+		g_io_channel_unref (priv->iochannel);
+		priv->iochannel = NULL;
+	}
 	priv->sockfd = -1;
 
 	if (priv->read_src) {
@@ -672,6 +674,12 @@ idle_connect_result (gpointer user_data)
 	} else
 		status = SOUP_STATUS_OK;
 
+	/* Have to do this before calling the callback... */
+	if (sacd->cancel_id) {
+		g_signal_handler_disconnect (sacd->cancellable, sacd->cancel_id);
+		sacd->cancel_id = 0;
+	}
+
 	sacd->callback (sacd->sock, status, sacd->user_data);
 	free_sacd (sacd);
 	return FALSE;



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