static void got_connection (SoupConnection *conn, guint status, gpointer session) { SoupAddress *tunnel_addr; if (status != SOUP_STATUS_OK) { /* 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); /* session may be destroyed at this point */ return; } 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_emit_by_name (session, "tunneling", conn); 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); /* @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); }
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: soup_message_queue_item_unref (data->item); g_slice_free (SoupSessionAsyncTunnelData, data); }
static void queue_message (SoupSession *session, SoupMessage *req, SoupSessionCallback callback, gpointer user_data) { SOUP_SESSION_CLASS (soup_session_async_parent_class)->queue_message (session, req, callback, user_data); do_idle_run_queue (session); }
static void connection_closed (SoupConnection *conn, gpointer session) { /* Run the queue in case anyone was waiting for a connection * to be closed. */ do_idle_run_queue (session); }
static void got_connection (SoupConnection *conn, guint status, gpointer 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_session_set_item_status (session, item, status); item->state = SOUP_MESSAGE_FINISHING; soup_connection_disconnect (conn); do_idle_run_queue (session); soup_message_queue_item_unref (item); g_object_unref (session); return; } tunnel_addr = soup_connection_get_tunnel_addr (conn); if (tunnel_addr) { SoupMessageQueueItem *tunnel_item; item->state = SOUP_MESSAGE_TUNNELING; tunnel_item = soup_session_make_connect_message (session, conn); tunnel_item->related = 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); 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) item->state = SOUP_MESSAGE_FINISHING; do_idle_run_queue (item->session); }
static void tunnel_message_completed (SoupMessage *msg, gpointer user_data) { SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; if (item->state == SOUP_MESSAGE_RESTARTING) { soup_message_restarted (msg); if (item->conn) { soup_session_send_queue_item (session, item, tunnel_message_completed); return; } soup_message_set_status (msg, SOUP_STATUS_TRY_AGAIN); } item->state = SOUP_MESSAGE_FINISHED; if (!SOUP_STATUS_IS_SUCCESSFUL (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)) { if (item->conn) soup_connection_disconnect (item->conn); soup_message_set_status (item->related->msg, SOUP_STATUS_SSL_FAILED); goto done; } g_signal_connect (item->conn, "disconnected", G_CALLBACK (connection_closed), item->session); soup_connection_set_state (item->conn, SOUP_CONNECTION_IDLE); soup_connection_set_state (item->conn, SOUP_CONNECTION_IN_USE); item->related->state = SOUP_MESSAGE_READY; done: soup_message_finished (msg); if (item->related->msg->status_code) item->related->state = SOUP_MESSAGE_FINISHING; do_idle_run_queue (item->session); soup_message_queue_item_unref (item->related); soup_session_unqueue_item (session, item); soup_message_queue_item_unref (item); g_object_unref (session); }
static void queue_message (SoupSession *session, SoupMessage *req, SoupSessionCallback callback, gpointer user_data) { SoupMessageQueueItem *item; SOUP_SESSION_CLASS (soup_session_async_parent_class)->queue_message (session, req, callback, user_data); item = soup_message_queue_lookup (soup_session_get_queue (session), req); g_return_if_fail (item != NULL); g_signal_connect (req, "restarted", G_CALLBACK (request_restarted), item); g_signal_connect_after (req, "finished", G_CALLBACK (final_finished), item); do_idle_run_queue (session); }
static gboolean item_failed (SoupMessageQueueItem *item, guint status) { if (item->removed) { soup_message_queue_item_unref (item); return TRUE; } if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { item->state = SOUP_MESSAGE_FINISHING; if (!item->msg->status_code) soup_session_set_item_status (item->session, item, status); do_idle_run_queue (item->session); soup_message_queue_item_unref (item); return TRUE; } return FALSE; }
static void final_finished (SoupMessage *req, gpointer user_data) { SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; g_object_ref (session); if (!SOUP_MESSAGE_IS_STARTING (req)) { g_signal_handlers_disconnect_by_func (req, final_finished, item); g_signal_handlers_disconnect_by_func (req, request_restarted, item); if (item->callback) item->callback (session, req, item->callback_data); g_object_unref (req); soup_message_queue_item_unref (item); } do_idle_run_queue (session); g_object_unref (session); }
static void process_queue_item (SoupMessageQueueItem *item, gboolean *should_prune, gboolean loop) { SoupSession *session = item->session; SoupProxyURIResolver *proxy_resolver; do { switch (item->state) { case SOUP_MESSAGE_STARTING: proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, item->msg); if (!proxy_resolver) { item->state = SOUP_MESSAGE_AWAITING_CONNECTION; break; } resolve_proxy_addr (item, proxy_resolver); return; case SOUP_MESSAGE_AWAITING_CONNECTION: if (!soup_session_get_connection (session, item, should_prune)) return; if (soup_connection_get_state (item->conn) != SOUP_CONNECTION_NEW) { item->state = SOUP_MESSAGE_READY; break; } item->state = SOUP_MESSAGE_CONNECTING; soup_message_queue_item_ref (item); g_object_ref (session); soup_connection_connect_async (item->conn, item->cancellable, got_connection, item); return; case SOUP_MESSAGE_READY: item->state = SOUP_MESSAGE_RUNNING; soup_session_send_queue_item (session, item, message_completed); break; case SOUP_MESSAGE_RESTARTING: item->state = SOUP_MESSAGE_STARTING; soup_message_restarted (item->msg); break; case SOUP_MESSAGE_FINISHING: item->state = SOUP_MESSAGE_FINISHED; soup_message_finished (item->msg); if (item->state != SOUP_MESSAGE_FINISHED) break; g_object_ref (session); soup_session_unqueue_item (session, item); if (item->callback) item->callback (session, item->msg, item->callback_data); g_object_unref (item->msg); do_idle_run_queue (session); g_object_unref (session); return; default: /* Nothing to do with this message in any * other state. */ return; } } while (loop && item->state != SOUP_MESSAGE_FINISHED); }