summaryrefslogtreecommitdiff
path: root/libsoup/soup-session-async.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsoup/soup-session-async.c')
-rw-r--r--libsoup/soup-session-async.c178
1 files changed, 111 insertions, 67 deletions
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index 97d4f2f1..c57d3037 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -15,6 +15,8 @@
#include "soup-address.h"
#include "soup-message-private.h"
#include "soup-misc.h"
+#include "soup-proxy-uri-resolver.h"
+#include "soup-uri.h"
/**
* SECTION:soup-session-async
@@ -108,71 +110,69 @@ soup_session_async_new_with_options (const char *optname1, ...)
return session;
}
-
-static void
-resolved_msg_addr (SoupAddress *addr, guint status, gpointer user_data)
+static gboolean
+item_failed (SoupMessageQueueItem *item, guint status)
{
- SoupMessageQueueItem *item = user_data;
- SoupSession *session = item->session;
-
if (item->removed) {
- /* Message was cancelled before its address resolved */
soup_message_queue_item_unref (item);
- return;
+ return TRUE;
}
if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
- soup_session_cancel_message (session, item->msg, status);
+ if (status != SOUP_STATUS_CANCELLED)
+ soup_session_cancel_message (item->session, item->msg, status);
soup_message_queue_item_unref (item);
- return;
+ return TRUE;
}
- item->msg_addr = g_object_ref (addr);
- item->resolving_msg_addr = FALSE;
-
- soup_message_queue_item_unref (item);
-
- /* If we got here we know session still exists */
- run_queue ((SoupSessionAsync *)session);
+ return FALSE;
}
static void
-resolve_msg_addr (SoupMessageQueueItem *item)
+resolved_proxy_addr (SoupAddress *addr, guint status, gpointer user_data)
{
- if (item->resolving_msg_addr)
+ SoupMessageQueueItem *item = user_data;
+ SoupSession *session = item->session;
+
+ if (item_failed (item, status))
return;
- item->resolving_msg_addr = TRUE;
- soup_message_queue_item_ref (item);
- soup_address_resolve_async (soup_message_get_address (item->msg),
- soup_session_get_async_context (item->session),
- item->cancellable,
- resolved_msg_addr, item);
+ item->proxy_addr = g_object_ref (addr);
+ item->resolving_proxy_addr = FALSE;
+ item->resolved_proxy_addr = TRUE;
+
+ soup_message_queue_item_unref (item);
+
+ /* If we got here we know session still exists */
+ run_queue ((SoupSessionAsync *)session);
}
static void
-resolved_proxy_addr (SoupProxyResolver *proxy_resolver, SoupMessage *msg,
- guint status, SoupAddress *proxy_addr, gpointer user_data)
+resolved_proxy_uri (SoupProxyURIResolver *proxy_resolver,
+ guint status, SoupURI *proxy_uri, gpointer user_data)
{
SoupMessageQueueItem *item = user_data;
SoupSession *session = item->session;
- if (item->removed) {
- /* Message was cancelled before its proxy addr resolved */
- soup_message_queue_item_unref (item);
+ if (item_failed (item, status))
return;
- }
- if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
- soup_session_cancel_message (session, item->msg, status);
- soup_message_queue_item_unref (item);
+ if (proxy_uri) {
+ SoupAddress *proxy_addr;
+
+ item->proxy_uri = soup_uri_copy (proxy_uri);
+ proxy_addr = soup_address_new (proxy_uri->host,
+ proxy_uri->port);
+ soup_address_resolve_async (proxy_addr,
+ soup_session_get_async_context (session),
+ item->cancellable,
+ resolved_proxy_addr, item);
+ g_object_unref (proxy_addr);
return;
}
item->resolving_proxy_addr = FALSE;
item->resolved_proxy_addr = TRUE;
- item->proxy_addr = proxy_addr ? g_object_ref (proxy_addr) : NULL;
-
soup_message_queue_item_unref (item);
/* If we got here we know session still exists */
@@ -181,17 +181,17 @@ resolved_proxy_addr (SoupProxyResolver *proxy_resolver, SoupMessage *msg,
static void
resolve_proxy_addr (SoupMessageQueueItem *item,
- SoupProxyResolver *proxy_resolver)
+ SoupProxyURIResolver *proxy_resolver)
{
if (item->resolving_proxy_addr)
return;
item->resolving_proxy_addr = TRUE;
soup_message_queue_item_ref (item);
- soup_proxy_resolver_get_proxy_async (proxy_resolver, item->msg,
- soup_session_get_async_context (item->session),
- item->cancellable,
- resolved_proxy_addr, item);
+ soup_proxy_uri_resolver_get_proxy_uri_async (
+ proxy_resolver, soup_message_get_uri (item->msg),
+ soup_session_get_async_context (item->session),
+ item->cancellable, resolved_proxy_uri, item);
}
static void
@@ -203,12 +203,68 @@ connection_closed (SoupConnection *conn, gpointer session)
do_idle_run_queue (session);
}
+typedef struct {
+ SoupSession *session;
+ SoupConnection *conn;
+ SoupMessageQueueItem *item;
+} SoupSessionAsyncTunnelData;
+
+static void
+tunnel_connected (SoupMessage *msg, gpointer user_data)
+{
+ SoupSessionAsyncTunnelData *data = user_data;
+
+ if (SOUP_MESSAGE_IS_STARTING (msg)) {
+ soup_session_send_queue_item (data->session, data->item, data->conn);
+ return;
+ }
+
+ if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
+ soup_session_connection_failed (data->session, data->conn,
+ msg->status_code);
+ goto done;
+ }
+
+ if (!soup_connection_start_ssl (data->conn)) {
+ soup_session_connection_failed (data->session, data->conn,
+ SOUP_STATUS_SSL_FAILED);
+ goto done;
+ }
+
+ g_signal_connect (data->conn, "disconnected",
+ G_CALLBACK (connection_closed), data->session);
+ soup_connection_set_state (data->conn, SOUP_CONNECTION_IDLE);
+
+ do_idle_run_queue (data->session);
+
+done:
+ g_object_unref (data->session);
+ soup_message_queue_item_unref (data->item);
+ g_slice_free (SoupSessionAsyncTunnelData, data);
+}
+
static void
-got_connection (SoupConnection *conn, guint status, gpointer user_data)
+got_connection (SoupConnection *conn, guint status, gpointer session)
{
- SoupSession *session = user_data;
+ SoupAddress *tunnel_addr;
if (status == SOUP_STATUS_OK) {
+ tunnel_addr = soup_connection_get_tunnel_addr (conn);
+ if (tunnel_addr) {
+ SoupSessionAsyncTunnelData *data;
+
+ data = g_slice_new (SoupSessionAsyncTunnelData);
+ data->session = session;
+ data->conn = conn;
+ data->item = soup_session_make_connect_message (session, tunnel_addr);
+ g_signal_connect (data->item->msg, "finished",
+ G_CALLBACK (tunnel_connected), data);
+ g_signal_connect (data->item->msg, "restarted",
+ G_CALLBACK (tunnel_connected), data);
+ soup_session_send_queue_item (session, data->item, conn);
+ return;
+ }
+
g_signal_connect (conn, "disconnected",
G_CALLBACK (connection_closed), session);
@@ -222,8 +278,9 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data)
* idle pool and then just run the queue and see what
* happens.
*/
- soup_connection_release (conn);
- }
+ soup_connection_set_state (conn, SOUP_CONNECTION_IDLE);
+ } else
+ soup_session_connection_failed (session, conn, status);
/* Even if the connection failed, we run the queue, since
* there may have been messages waiting for the connection
@@ -239,13 +296,12 @@ run_queue (SoupSessionAsync *sa)
SoupSession *session = SOUP_SESSION (sa);
SoupMessageQueue *queue = soup_session_get_queue (session);
SoupMessageQueueItem *item;
- SoupProxyResolver *proxy_resolver =
+ SoupProxyURIResolver *proxy_resolver =
soup_session_get_proxy_resolver (session);
SoupMessage *msg;
SoupMessageIOStatus cur_io_status = SOUP_MESSAGE_IO_STATUS_CONNECTING;
SoupConnection *conn;
gboolean try_pruning = TRUE, should_prune = FALSE;
- gboolean is_new;
try_again:
for (item = soup_message_queue_first (queue);
@@ -253,30 +309,29 @@ run_queue (SoupSessionAsync *sa)
item = soup_message_queue_next (queue, item)) {
msg = item->msg;
+ /* CONNECT messages are handled specially */
+ if (msg->method == SOUP_METHOD_CONNECT)
+ continue;
+
if (soup_message_get_io_status (msg) != cur_io_status ||
soup_message_io_in_progress (msg))
continue;
- if (!item->msg_addr) {
- resolve_msg_addr (item);
- continue;
- }
if (proxy_resolver && !item->resolved_proxy_addr) {
resolve_proxy_addr (item, proxy_resolver);
continue;
}
- conn = soup_session_get_connection (session, msg,
- item->proxy_addr,
- &should_prune, &is_new);
+ conn = soup_session_get_connection (session, item,
+ &should_prune);
if (!conn)
continue;
- if (is_new) {
+ if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
soup_connection_connect_async (conn, got_connection,
g_object_ref (session));
} else
- soup_connection_send_request (conn, msg);
+ soup_session_send_queue_item (session, item, conn);
}
if (item)
soup_message_queue_item_unref (item);
@@ -303,17 +358,6 @@ request_restarted (SoupMessage *req, gpointer user_data)
{
SoupMessageQueueItem *item = user_data;
- if (item->msg_addr &&
- item->msg_addr != soup_message_get_address (item->msg)) {
- g_object_unref (item->msg_addr);
- item->msg_addr = NULL;
- }
- if (item->proxy_addr) {
- g_object_unref (item->proxy_addr);
- item->proxy_addr = NULL;
- }
- item->resolved_proxy_addr = FALSE;
-
run_queue ((SoupSessionAsync *)item->session);
}