[libsoup] soup-message-io: use SoupMessageQueueItems and add SoupMessageCompletionFn
- From: Dan Winship <danw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] soup-message-io: use SoupMessageQueueItems and add SoupMessageCompletionFn
- Date: Wed, 9 Jun 2010 15:27:30 +0000 (UTC)
commit b5cc3e113a9f29f0a77cf8f634c233323844d9f7
Author: Dan Winship <danw gnome org>
Date: Sat May 29 15:24:51 2010 +0200
soup-message-io: use SoupMessageQueueItems and add SoupMessageCompletionFn
push SoupMessageQueueItem down into soup-message-io, and end the I/O
process by calling a completion callback rather than emitting the
SoupMessage signals directly, which gives the session greater control.
libsoup/soup-connection.c | 73 +++++++++++++++++++--------------
libsoup/soup-connection.h | 12 ++++--
libsoup/soup-message-client-io.c | 18 +++++---
libsoup/soup-message-io.c | 84 +++++++++++++++++++------------------
libsoup/soup-message-private.h | 44 ++++++++++++--------
libsoup/soup-message-queue.c | 2 +-
libsoup/soup-message-queue.h | 12 ++---
libsoup/soup-message-server-io.c | 10 +++-
libsoup/soup-server.c | 8 ++-
libsoup/soup-session-async.c | 43 +++++++++++++------
libsoup/soup-session-private.h | 6 +-
libsoup/soup-session-sync.c | 31 +++++++++++---
libsoup/soup-session.c | 58 ++------------------------
libsoup/soup-types.h | 5 ++
14 files changed, 214 insertions(+), 192 deletions(-)
---
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 58614ac..7174e21 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -22,6 +22,7 @@
#include "soup-marshal.h"
#include "soup-message.h"
#include "soup-message-private.h"
+#include "soup-message-queue.h"
#include "soup-misc.h"
#include "soup-socket.h"
#include "soup-ssl.h"
@@ -38,7 +39,7 @@ typedef struct {
GMainContext *async_context;
- SoupMessage *cur_req;
+ SoupMessageQueueItem *cur_item;
SoupConnectionState state;
time_t unused_timeout;
guint io_timeout, idle_timeout;
@@ -78,7 +79,7 @@ static void get_property (GObject *object, guint prop_id,
GValue *value, GParamSpec *pspec);
static void stop_idle_timer (SoupConnectionPrivate *priv);
-static void clear_current_request (SoupConnection *conn);
+static void clear_current_item (SoupConnection *conn);
/* Number of seconds after which we close a connection that hasn't yet
* been used.
@@ -116,12 +117,12 @@ dispose (GObject *object)
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
stop_idle_timer (priv);
- /* Make sure clear_current_request doesn't re-establish the timeout */
+ /* Make sure clear_current_item doesn't re-establish the timeout */
priv->idle_timeout = 0;
- if (priv->cur_req) {
- g_warning ("Disposing connection with cur_req set");
- clear_current_request (conn);
+ if (priv->cur_item) {
+ g_warning ("Disposing connection with cur_item set");
+ clear_current_item (conn);
}
if (priv->socket) {
g_warning ("Disposing connection while connected");
@@ -319,7 +320,10 @@ get_property (GObject *object, guint prop_id,
g_value_set_enum (value, priv->state);
break;
case PROP_MESSAGE:
- g_value_set_object (value, priv->cur_req);
+ if (priv->cur_item)
+ g_value_set_object (value, priv->cur_item->msg);
+ else
+ g_value_set_object (value, NULL);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -357,29 +361,29 @@ stop_idle_timer (SoupConnectionPrivate *priv)
}
static void
-set_current_request (SoupConnection *conn, SoupMessage *req)
+set_current_item (SoupConnection *conn, SoupMessageQueueItem *item)
{
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
- g_return_if_fail (priv->cur_req == NULL);
+ g_return_if_fail (priv->cur_item == NULL);
g_object_freeze_notify (G_OBJECT (conn));
stop_idle_timer (priv);
- soup_message_set_io_status (req, SOUP_MESSAGE_IO_STATUS_RUNNING);
- priv->cur_req = req;
+ soup_message_set_io_status (item->msg, SOUP_MESSAGE_IO_STATUS_RUNNING);
+ priv->cur_item = item;
g_object_notify (G_OBJECT (conn), "message");
if (priv->state == SOUP_CONNECTION_IDLE ||
- req->method != SOUP_METHOD_CONNECT)
+ item->msg->method != SOUP_METHOD_CONNECT)
soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE);
g_object_thaw_notify (G_OBJECT (conn));
}
static void
-clear_current_request (SoupConnection *conn)
+clear_current_item (SoupConnection *conn)
{
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
@@ -387,13 +391,22 @@ clear_current_request (SoupConnection *conn)
priv->unused_timeout = 0;
start_idle_timer (conn);
- if (priv->cur_req) {
- SoupMessage *cur_req = priv->cur_req;
- priv->cur_req = NULL;
+ if (priv->cur_item) {
+ SoupMessageQueueItem *item;
+
+ item = priv->cur_item;
+ priv->cur_item = NULL;
g_object_notify (G_OBJECT (conn), "message");
- if (!soup_message_is_keepalive (cur_req))
+ if (item->msg->method == SOUP_METHOD_CONNECT &&
+ SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) {
+ /* We're now effectively no longer proxying */
+ soup_uri_free (priv->proxy_uri);
+ priv->proxy_uri = NULL;
+ }
+
+ if (!soup_message_is_keepalive (item->msg))
soup_connection_disconnect (conn);
}
@@ -651,15 +664,18 @@ soup_connection_set_state (SoupConnection *conn, SoupConnectionState state)
g_return_if_fail (state >= SOUP_CONNECTION_NEW &&
state <= SOUP_CONNECTION_DISCONNECTED);
+ g_object_freeze_notify (G_OBJECT (conn));
+
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
old_state = priv->state;
priv->state = state;
if ((state == SOUP_CONNECTION_IDLE ||
state == SOUP_CONNECTION_DISCONNECTED) &&
old_state == SOUP_CONNECTION_IN_USE)
- clear_current_request (conn);
+ clear_current_item (conn);
g_object_notify (G_OBJECT (conn), "state");
+ g_object_thaw_notify (G_OBJECT (conn));
}
gboolean
@@ -670,25 +686,20 @@ soup_connection_get_ever_used (SoupConnection *conn)
return SOUP_CONNECTION_GET_PRIVATE (conn)->unused_timeout == 0;
}
-/**
- * soup_connection_send_request:
- * @conn: a #SoupConnection
- * @req: a #SoupMessage
- *
- * Sends @req on @conn. This is a low-level function, intended for use
- * by #SoupSession.
- **/
void
-soup_connection_send_request (SoupConnection *conn, SoupMessage *req)
+soup_connection_send_request (SoupConnection *conn,
+ SoupMessageQueueItem *item,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data)
{
SoupConnectionPrivate *priv;
g_return_if_fail (SOUP_IS_CONNECTION (conn));
- g_return_if_fail (SOUP_IS_MESSAGE (req));
+ g_return_if_fail (item != NULL);
priv = SOUP_CONNECTION_GET_PRIVATE (conn);
g_return_if_fail (priv->state != SOUP_CONNECTION_NEW && priv->state != SOUP_CONNECTION_DISCONNECTED);
- if (req != priv->cur_req)
- set_current_request (conn, req);
- soup_message_send_request (req, conn);
+ if (item != priv->cur_item)
+ set_current_item (conn, item);
+ soup_message_send_request (item, completion_cb, user_data);
}
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index 558a465..629676b 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -9,6 +9,7 @@
#include <gio/gio.h>
#include "soup-types.h"
+#include "soup-message-private.h"
#include "soup-misc.h"
G_BEGIN_DECLS
@@ -20,10 +21,10 @@ G_BEGIN_DECLS
#define SOUP_IS_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_CONNECTION))
#define SOUP_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_CONNECTION, SoupConnectionClass))
-typedef struct {
+struct _SoupConnection {
GObject parent;
-} SoupConnection;
+};
typedef struct {
GObjectClass parent_class;
@@ -75,8 +76,11 @@ void soup_connection_set_state (SoupConnection *conn,
gboolean soup_connection_get_ever_used (SoupConnection *conn);
-void soup_connection_send_request (SoupConnection *conn,
- SoupMessage *req);
+void soup_connection_send_request (SoupConnection *conn,
+ SoupMessageQueueItem *item,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data);
+
G_END_DECLS
diff --git a/libsoup/soup-message-client-io.c b/libsoup/soup-message-client-io.c
index 0c091e6..ef97c99 100644
--- a/libsoup/soup-message-client-io.c
+++ b/libsoup/soup-message-client-io.c
@@ -12,10 +12,12 @@
#include <stdlib.h>
#include <string.h>
+#include "soup-connection.h"
#include "soup-message-private.h"
#include "soup-auth.h"
#include "soup-connection.h"
#include "soup-headers.h"
+#include "soup-message-queue.h"
#include "soup-uri.h"
static guint
@@ -77,7 +79,7 @@ get_request_headers (SoupMessage *req, GString *header,
SoupEncoding *encoding, gpointer user_data)
{
SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
- SoupConnection *conn = user_data;
+ SoupMessageQueueItem *item = user_data;
SoupURI *uri = soup_message_get_uri (req);
char *uri_host;
char *uri_string;
@@ -93,7 +95,7 @@ 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);
+ gboolean proxy = soup_connection_is_via_proxy (item->conn);
/* Proxy expects full URI to destination. Otherwise
* just the path.
@@ -146,12 +148,14 @@ get_request_headers (SoupMessage *req, GString *header,
}
void
-soup_message_send_request (SoupMessage *msg,
- SoupConnection *conn)
+soup_message_send_request (SoupMessageQueueItem *item,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data)
{
- soup_message_cleanup_response (msg);
- soup_message_io_client (msg, conn,
+ soup_message_cleanup_response (item->msg);
+ soup_message_io_client (item,
get_request_headers,
parse_response_headers,
- conn);
+ item,
+ completion_cb, user_data);
}
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 324b147..8314f96 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -16,6 +16,7 @@
#include "soup-connection.h"
#include "soup-message.h"
#include "soup-message-private.h"
+#include "soup-message-queue.h"
#include "soup-misc.h"
#include "soup-socket.h"
#include "soup-ssl.h"
@@ -45,7 +46,7 @@ typedef enum {
typedef struct {
SoupSocket *sock;
- SoupConnection *conn;
+ SoupMessageQueueItem *item;
SoupMessageIOMode mode;
SoupMessageIOState read_state;
@@ -71,7 +72,9 @@ typedef struct {
SoupMessageGetHeadersFn get_headers_cb;
SoupMessageParseHeadersFn parse_headers_cb;
- gpointer user_data;
+ gpointer header_data;
+ SoupMessageCompletionFn completion_cb;
+ gpointer completion_data;
} SoupMessageIOData;
@@ -100,8 +103,8 @@ soup_message_io_cleanup (SoupMessage *msg)
if (io->sock)
g_object_unref (io->sock);
- if (io->conn)
- g_object_unref (io->conn);
+ if (io->item)
+ soup_message_queue_item_unref (io->item);
g_byte_array_free (io->read_meta_buf, TRUE);
@@ -115,17 +118,6 @@ soup_message_io_cleanup (SoupMessage *msg)
g_slice_free (SoupMessageIOData, io);
}
-/**
- * soup_message_io_stop:
- * @msg: a #SoupMessage
- *
- * Immediately stops I/O on msg; if the connection would be left in an
- * inconsistent state, it will be closed.
- *
- * Note: this is a low-level function that does not cause any signals
- * to be emitted on @msg; it is up to the caller to make sure that
- * @msg doesn't get "stranded".
- **/
void
soup_message_io_stop (SoupMessage *msg)
{
@@ -155,12 +147,8 @@ soup_message_io_stop (SoupMessage *msg)
if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
soup_socket_disconnect (io->sock);
- else if (io->conn) {
- SoupConnection *conn = io->conn;
- io->conn = NULL;
- soup_connection_set_state (conn, SOUP_CONNECTION_IDLE);
- g_object_unref (conn);
- }
+ else if (io->item && io->item->conn)
+ soup_connection_set_state (io->item->conn, SOUP_CONNECTION_IDLE);
}
#define SOUP_MESSAGE_IO_EOL "\r\n"
@@ -169,12 +157,15 @@ soup_message_io_stop (SoupMessage *msg)
static void
soup_message_io_finished (SoupMessage *msg)
{
+ SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+ SoupMessageIOData *io = priv->io_data;
+ SoupMessageCompletionFn completion_cb = io->completion_cb;
+ gpointer completion_data = io->completion_data;
+
g_object_ref (msg);
soup_message_io_cleanup (msg);
- if (SOUP_MESSAGE_IS_STARTING (msg))
- soup_message_restarted (msg);
- else
- soup_message_finished (msg);
+ if (completion_cb)
+ completion_cb (msg, completion_data);
g_object_unref (msg);
}
@@ -200,7 +191,7 @@ io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
} else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
io->read_meta_buf->len == 0 &&
- soup_connection_get_ever_used (io->conn) &&
+ soup_connection_get_ever_used (io->item->conn) &&
!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) &&
request_is_idempotent (msg)) {
/* Connection got closed, but we can safely try again */
@@ -589,7 +580,7 @@ io_write (SoupSocket *sock, SoupMessage *msg)
if (!io->write_buf->len) {
io->get_headers_cb (msg, io->write_buf,
&io->write_encoding,
- io->user_data);
+ io->header_data);
if (!io->write_buf->len) {
soup_message_io_pause (msg);
return;
@@ -833,7 +824,7 @@ io_read (SoupSocket *sock, SoupMessage *msg)
status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
io->read_meta_buf->len,
&io->read_encoding,
- io->user_data);
+ io->header_data);
g_byte_array_set_size (io->read_meta_buf, 0);
if (status != SOUP_STATUS_OK) {
@@ -1011,7 +1002,9 @@ static SoupMessageIOData *
new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
- gpointer user_data)
+ gpointer header_data,
+ SoupMessageCompletionFn completion_cb,
+ gpointer completion_data)
{
SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
SoupMessageIOData *io;
@@ -1021,7 +1014,9 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
io->mode = mode;
io->get_headers_cb = get_headers_cb;
io->parse_headers_cb = parse_headers_cb;
- io->user_data = user_data;
+ io->header_data = header_data;
+ io->completion_cb = completion_cb;
+ io->completion_data = completion_data;
io->read_meta_buf = g_byte_array_new ();
io->write_buf = g_string_new (NULL);
@@ -1043,36 +1038,43 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
}
void
-soup_message_io_client (SoupMessage *msg, SoupConnection *conn,
+soup_message_io_client (SoupMessageQueueItem *item,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
- gpointer user_data)
+ gpointer header_data,
+ SoupMessageCompletionFn completion_cb,
+ gpointer completion_data)
{
SoupMessageIOData *io;
- SoupSocket *sock = soup_connection_get_socket (conn);
+ SoupSocket *sock = soup_connection_get_socket (item->conn);
- io = new_iostate (msg, sock, SOUP_MESSAGE_IO_CLIENT,
- get_headers_cb, parse_headers_cb, user_data);
+ io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
+ get_headers_cb, parse_headers_cb, header_data,
+ completion_cb, completion_data);
- io->conn = g_object_ref (conn);
+ io->item = item;
+ soup_message_queue_item_ref (item);
- io->read_body = msg->response_body;
- io->write_body = msg->request_body;
+ io->read_body = item->msg->response_body;
+ io->write_body = item->msg->request_body;
io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
- io_write (sock, msg);
+ io_write (sock, item->msg);
}
void
soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
- gpointer user_data)
+ gpointer header_data,
+ SoupMessageCompletionFn completion_cb,
+ gpointer completion_data)
{
SoupMessageIOData *io;
io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
- get_headers_cb, parse_headers_cb, user_data);
+ get_headers_cb, parse_headers_cb, header_data,
+ completion_cb, completion_data);
io->read_body = msg->request_body;
io->write_body = msg->response_body;
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index cd8a94e..eba92df 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -8,7 +8,6 @@
#include "soup-message.h"
#include "soup-auth.h"
-#include "soup-connection.h"
#include "soup-content-sniffer.h"
typedef enum {
@@ -46,7 +45,7 @@ typedef struct {
} SoupMessagePrivate;
#define SOUP_MESSAGE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_MESSAGE, SoupMessagePrivate))
-#define SOUP_MESSAGE_IS_STARTING(msg) (SOUP_MESSAGE_GET_PRIVATE (msg)->io_status == SOUP_MESSAGE_IO_STATUS_QUEUED)
+#define SOUP_MESSAGE_IS_STARTING(msg) (SOUP_MESSAGE_GET_PRIVATE (msg)->io_status == SOUP_MESSAGE_IO_STATUS_QUEUED && !SOUP_STATUS_IS_TRANSPORT_ERROR ((msg)->status_code))
void soup_message_cleanup_response (SoupMessage *req);
@@ -60,23 +59,32 @@ typedef guint (*SoupMessageParseHeadersFn)(SoupMessage *msg,
guint header_len,
SoupEncoding *encoding,
gpointer user_data);
+typedef void (*SoupMessageCompletionFn) (SoupMessage *msg,
+ gpointer user_data);
+
-void soup_message_send_request (SoupMessage *req,
- SoupConnection *conn);
-void soup_message_read_request (SoupMessage *req,
- SoupSocket *sock);
-
-void soup_message_io_client (SoupMessage *msg,
- SoupConnection *conn,
- SoupMessageGetHeadersFn get_headers_cb,
- SoupMessageParseHeadersFn parse_headers_cb,
- gpointer user_data);
-void soup_message_io_server (SoupMessage *msg,
- SoupSocket *sock,
- SoupMessageGetHeadersFn get_headers_cb,
- SoupMessageParseHeadersFn parse_headers_cb,
- gpointer user_data);
-void soup_message_io_cleanup (SoupMessage *msg);
+void soup_message_send_request (SoupMessageQueueItem *item,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data);
+void soup_message_read_request (SoupMessage *req,
+ SoupSocket *sock,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data);
+
+void soup_message_io_client (SoupMessageQueueItem *item,
+ SoupMessageGetHeadersFn get_headers_cb,
+ SoupMessageParseHeadersFn parse_headers_cb,
+ gpointer headers_data,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data);
+void soup_message_io_server (SoupMessage *msg,
+ SoupSocket *sock,
+ SoupMessageGetHeadersFn get_headers_cb,
+ SoupMessageParseHeadersFn parse_headers_cb,
+ gpointer headers_data,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data);
+void soup_message_io_cleanup (SoupMessage *msg);
/* Auth handling */
void soup_message_set_auth (SoupMessage *msg,
diff --git a/libsoup/soup-message-queue.c b/libsoup/soup-message-queue.c
index 61bc5ca..6860524 100644
--- a/libsoup/soup-message-queue.c
+++ b/libsoup/soup-message-queue.c
@@ -29,7 +29,7 @@
* "removed" ones when walking the queue.
**/
-struct SoupMessageQueue {
+struct _SoupMessageQueue {
SoupSession *session;
GMutex *mutex;
diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h
index d4376a7..9588e17 100644
--- a/libsoup/soup-message-queue.h
+++ b/libsoup/soup-message-queue.h
@@ -9,16 +9,14 @@
#include <glib.h>
#include <gio/gio.h>
-#include <libsoup/soup-connection.h>
-#include <libsoup/soup-message.h>
-#include <libsoup/soup-session.h>
-G_BEGIN_DECLS
+#include "soup-connection.h"
+#include "soup-message.h"
+#include "soup-session.h"
-typedef struct SoupMessageQueue SoupMessageQueue;
-typedef struct SoupMessageQueueItem SoupMessageQueueItem;
+G_BEGIN_DECLS
-struct SoupMessageQueueItem {
+struct _SoupMessageQueueItem {
/*< public >*/
SoupSession *session;
SoupMessageQueue *queue;
diff --git a/libsoup/soup-message-server-io.c b/libsoup/soup-message-server-io.c
index bc8a1c1..573fcaf 100644
--- a/libsoup/soup-message-server-io.c
+++ b/libsoup/soup-message-server-io.c
@@ -235,10 +235,14 @@ get_response_headers (SoupMessage *msg, GString *headers,
}
void
-soup_message_read_request (SoupMessage *req, SoupSocket *sock)
+soup_message_read_request (SoupMessage *msg,
+ SoupSocket *sock,
+ SoupMessageCompletionFn completion_cb,
+ gpointer user_data)
{
- soup_message_io_server (req, sock,
+ soup_message_io_server (msg, sock,
get_response_headers,
parse_request_headers,
- sock);
+ sock,
+ completion_cb, user_data);
}
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 788bb59..e60ede9 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -709,11 +709,13 @@ soup_client_context_unref (SoupClientContext *client)
}
static void
-request_finished (SoupMessage *msg, SoupClientContext *client)
+request_finished (SoupMessage *msg, gpointer user_data)
{
+ SoupClientContext *client = user_data;
SoupServer *server = client->server;
SoupSocket *sock = client->sock;
+ soup_message_finished (msg);
g_signal_emit (server,
msg->status_code == SOUP_STATUS_IO_ERROR ?
signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
@@ -868,13 +870,13 @@ start_request (SoupServer *server, SoupClientContext *client)
g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client);
g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
- g_signal_connect (msg, "finished", G_CALLBACK (request_finished), client);
g_signal_emit (server, signals[REQUEST_STARTED], 0,
msg, client);
g_object_ref (client->sock);
- soup_message_read_request (msg, client->sock);
+ soup_message_read_request (msg, client->sock,
+ request_finished, client);
}
static void
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index 6df4ca4..57c0581 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -16,6 +16,7 @@
#include "soup-session-private.h"
#include "soup-address.h"
#include "soup-message-private.h"
+#include "soup-message-queue.h"
#include "soup-misc.h"
#include "soup-password-manager.h"
#include "soup-proxy-uri-resolver.h"
@@ -211,6 +212,24 @@ connection_closed (SoupConnection *conn, gpointer session)
}
static void
+tunnel_message_completed (SoupMessage *msg, gpointer user_data)
+{
+ SoupMessageQueueItem *item = user_data;
+
+ if (SOUP_MESSAGE_IS_STARTING (msg)) {
+ 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);
+ return;
+ }
+
+ soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN);
+ }
+
+ soup_message_finished (msg);
+}
+
+static void
tunnel_connected (SoupMessage *msg, gpointer user_data)
{
SoupMessageQueueItem *item = user_data;
@@ -238,15 +257,6 @@ done:
}
static void
-tunnel_connect_restarted (SoupMessage *msg, gpointer user_data)
-{
- SoupMessageQueueItem *item = user_data;
-
- if (SOUP_MESSAGE_IS_STARTING (msg))
- soup_session_send_queue_item (item->session, item, item->conn);
-}
-
-static void
got_connection (SoupConnection *conn, guint status, gpointer user_data)
{
SoupSession *session = user_data;
@@ -271,9 +281,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data)
g_signal_emit_by_name (session, "tunneling", conn);
g_signal_connect (item->msg, "finished",
G_CALLBACK (tunnel_connected), item);
- g_signal_connect (item->msg, "restarted",
- G_CALLBACK (tunnel_connect_restarted), item);
- soup_session_send_queue_item (session, item, conn);
+ soup_session_send_queue_item (session, item, conn, tunnel_message_completed);
return;
}
@@ -296,6 +304,15 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data)
}
static void
+message_completed (SoupMessage *msg, gpointer user_data)
+{
+ if (SOUP_MESSAGE_IS_STARTING (msg))
+ soup_message_restarted (msg);
+ else
+ soup_message_finished (msg);
+}
+
+static void
run_queue (SoupSessionAsync *sa)
{
SoupSession *session = SOUP_SESSION (sa);
@@ -340,7 +357,7 @@ run_queue (SoupSessionAsync *sa)
got_connection,
g_object_ref (session));
} else
- soup_session_send_queue_item (session, item, conn);
+ soup_session_send_queue_item (session, item, conn, message_completed);
}
if (item)
soup_message_queue_item_unref (item);
diff --git a/libsoup/soup-session-private.h b/libsoup/soup-session-private.h
index 72b79c5..0a8f888 100644
--- a/libsoup/soup-session-private.h
+++ b/libsoup/soup-session-private.h
@@ -7,8 +7,7 @@
#define SOUP_SESSION_PRIVATE_H 1
#include "soup-session.h"
-#include "soup-connection.h"
-#include "soup-message-queue.h"
+#include "soup-message-private.h"
#include "soup-proxy-uri-resolver.h"
G_BEGIN_DECLS
@@ -29,7 +28,8 @@ void soup_session_connection_failed (SoupSession *s
void soup_session_send_queue_item (SoupSession *session,
SoupMessageQueueItem *item,
- SoupConnection *conn);
+ SoupConnection *conn,
+ SoupMessageCompletionFn completion_cb);
G_END_DECLS
diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c
index dd3cc82..1743f25 100644
--- a/libsoup/soup-session-sync.c
+++ b/libsoup/soup-session-sync.c
@@ -16,6 +16,7 @@
#include "soup-session-private.h"
#include "soup-address.h"
#include "soup-message-private.h"
+#include "soup-message-queue.h"
#include "soup-misc.h"
#include "soup-password-manager.h"
#include "soup-proxy-uri-resolver.h"
@@ -146,11 +147,22 @@ tunnel_connect (SoupSession *session, SoupConnection *conn,
g_signal_emit_by_name (session, "tunneling", conn);
item = soup_session_make_connect_message (session, tunnel_addr);
- do
- soup_session_send_queue_item (session, item, conn);
- while (SOUP_MESSAGE_IS_STARTING (item->msg));
-
- status = item->msg->status_code;
+ do {
+ soup_session_send_queue_item (session, item, conn, NULL);
+ if (SOUP_MESSAGE_IS_STARTING (item->msg))
+ soup_message_restarted (item->msg) ;
+ else
+ soup_message_finished (item->msg);
+ } while (SOUP_MESSAGE_IS_STARTING (item->msg) &&
+ soup_connection_get_state (conn) != SOUP_CONNECTION_DISCONNECTED);
+
+ /* If the message was requeued but its connection was closed,
+ * return TRY_AGAIN to our caller.
+ */
+ if (SOUP_MESSAGE_IS_STARTING (item->msg))
+ status = SOUP_STATUS_TRY_AGAIN;
+ else
+ status = item->msg->status_code;
soup_message_queue_item_unref (item);
if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
@@ -226,7 +238,8 @@ wait_for_connection (SoupMessageQueueItem *item)
status = tunnel_connect (session, conn, tunnel_addr);
if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
conn = NULL;
- goto try_again;
+ if (status == SOUP_STATUS_TRY_AGAIN)
+ goto try_again;
}
}
}
@@ -264,7 +277,11 @@ process_queue_item (SoupMessageQueueItem *item)
if (!conn)
break;
- soup_session_send_queue_item (item->session, item, conn);
+ soup_session_send_queue_item (item->session, item, conn, NULL);
+ if (SOUP_MESSAGE_IS_STARTING (item->msg))
+ soup_message_restarted (item->msg);
+ else
+ soup_message_finished (item->msg);
g_cond_broadcast (priv->cond);
} while (soup_message_get_io_status (item->msg) !=
SOUP_MESSAGE_IO_STATUS_FINISHED);
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 55bcf09..0022c99 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1174,7 +1174,8 @@ redirect_handler (SoupMessage *msg, gpointer user_data)
void
soup_session_send_queue_item (SoupSession *session,
SoupMessageQueueItem *item,
- SoupConnection *conn)
+ SoupConnection *conn,
+ SoupMessageCompletionFn completion_cb)
{
SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
@@ -1201,7 +1202,7 @@ 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->msg);
+ soup_connection_send_request (conn, item, completion_cb, item);
}
gboolean
@@ -1296,51 +1297,6 @@ soup_session_connection_failed (SoupSession *session,
g_object_unref (session);
}
-static void
-tunnel_connected (SoupMessage *msg, gpointer user_data)
-{
- SoupSession *session = user_data;
-
- if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
- SoupMessageQueueItem *item =
- soup_message_queue_lookup (priv->queue, msg);
-
- /* Clear the connection's proxy_uri, since it is now
- * (effectively) directly connected.
- */
- g_object_set (item->conn,
- SOUP_CONNECTION_PROXY_URI, NULL,
- NULL);
- soup_message_queue_item_unref (item);
- }
-}
-
-static void
-tunnel_connect_restarted (SoupMessage *msg, gpointer session)
-{
- SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
- SoupMessageQueueItem *item;
-
- if (msg->status_code != SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED)
- return;
-
- item = soup_message_queue_lookup (priv->queue, msg);
- if (!item)
- return;
- if (soup_connection_get_state (item->conn) == SOUP_CONNECTION_DISCONNECTED) {
- /* We got a 407, and the session provided auth and
- * restarted the message, but the proxy closed the
- * connection, so we need to create a new one. The
- * easiest way to do this is to just give up on the
- * current msg and conn, and re-run the queue.
- */
- soup_session_cancel_message (session, msg,
- SOUP_STATUS_TRY_AGAIN);
- }
- soup_message_queue_item_unref (item);
-}
-
SoupMessageQueueItem *
soup_session_make_connect_message (SoupSession *session,
SoupAddress *server_addr)
@@ -1361,14 +1317,8 @@ soup_session_make_connect_message (SoupSession *session,
/* Call the base implementation of soup_session_queue_message
* directly, to add msg to the SoupMessageQueue and cause all
- * the right signals to be emitted. We can't use
- * queue_message's callback arg in this case because that's
- * actually implemented by the subclasses.
+ * the right signals to be emitted.
*/
- g_signal_connect (msg, "finished",
- G_CALLBACK (tunnel_connected), session);
- g_signal_connect (msg, "restarted",
- G_CALLBACK (tunnel_connect_restarted), session);
queue_message (session, msg, NULL, NULL);
item = soup_message_queue_lookup (priv->queue, msg);
g_object_unref (msg);
diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h
index def6c85..5d7cb3c 100644
--- a/libsoup/soup-types.h
+++ b/libsoup/soup-types.h
@@ -28,6 +28,11 @@ typedef struct _SoupSessionSync SoupSessionSync;
typedef struct _SoupSocket SoupSocket;
typedef struct _SoupURI SoupURI;
+/*< private >*/
+typedef struct _SoupConnection SoupConnection;
+typedef struct _SoupMessageQueue SoupMessageQueue;
+typedef struct _SoupMessageQueueItem SoupMessageQueueItem;
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]