示例#1
0
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);
}
示例#2
0
static void
resolved_proxy_uri (SoupProxyURIResolver *proxy_resolver,
		    guint status, SoupURI *proxy_uri, gpointer user_data)
{
	SoupMessageQueueItem *item = user_data;
	SoupSession *session = item->session;

	if (item_failed (item, status))
		return;

	if (proxy_uri) {
		SoupAddress *proxy_addr;

		item->state = SOUP_MESSAGE_RESOLVING_PROXY_ADDRESS;

		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->state = SOUP_MESSAGE_AWAITING_CONNECTION;
	soup_message_queue_item_unref (item);

	/* If we got here we know session still exists */
	run_queue ((SoupSessionAsync *)session);
}
示例#3
0
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);
}
示例#4
0
static void
message_finished (SoupMessage *msg, gpointer user_data)
{
	SoupMessageQueueItem *item = user_data;
	SoupSession *session = item->session;
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);

	if (item->conn) {
		g_object_unref (item->conn);
		item->conn = NULL;
	}

	if (!SOUP_MESSAGE_IS_STARTING (msg)) {
		soup_message_queue_remove (priv->queue, item);
		g_signal_handlers_disconnect_by_func (msg, message_finished, item);
		/* g_signal_handlers_disconnect_by_func doesn't work if you
		 * have a metamarshal, meaning it doesn't work with
		 * soup_message_add_header_handler()
		 */
		g_signal_handlers_disconnect_matched (msg, G_SIGNAL_MATCH_DATA,
						      0, 0, NULL, NULL, session);
		g_signal_emit (session, signals[REQUEST_UNQUEUED], 0, msg);
		soup_message_queue_item_unref (item);
	}
}
示例#5
0
static void
run_queue (SoupSessionAsync *sa)
{
	SoupSession *session = SOUP_SESSION (sa);
	SoupMessageQueue *queue = soup_session_get_queue (session);
	SoupMessageQueueItem *item;
	SoupProxyURIResolver *proxy_resolver;
	SoupMessage *msg;
	SoupConnection *conn;
	gboolean try_pruning = TRUE, should_prune = FALSE;

	soup_session_cleanup_connections (session, FALSE);

 try_again:
	for (item = soup_message_queue_first (queue);
	     item && !should_prune;
	     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_io_in_progress (msg))
			continue;

		if (!item->resolved_proxy_addr) {
			proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, msg);
			if (proxy_resolver) {
				resolve_proxy_addr (item, proxy_resolver);
				continue;
			} else
				item->resolved_proxy_addr = TRUE;
		}

		conn = soup_session_get_connection (session, item,
						    &should_prune);
		if (!conn)
			continue;

		if (soup_connection_get_state (conn) == SOUP_CONNECTION_NEW) {
			soup_connection_connect_async (conn, got_connection,
						       session);
		} else
			soup_session_send_queue_item (session, item, conn);
	}
	if (item)
		soup_message_queue_item_unref (item);

	if (try_pruning && should_prune) {
		/* There is at least one message in the queue that
		 * could be sent if we pruned an idle connection from
		 * some other server.
		 */
		if (soup_session_cleanup_connections (session, TRUE)) {
			try_pruning = should_prune = FALSE;
			goto try_again;
		}
	}
}
示例#6
0
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)) {
		if (status != SOUP_STATUS_CANCELLED)
			soup_session_cancel_message (item->session, item->msg, status);
		soup_message_queue_item_unref (item);
		return TRUE;
	}

	return FALSE;
}
示例#7
0
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);
}
示例#8
0
static gboolean
queue_message_callback (gpointer data)
{
	SoupMessageQueueItem *item = data;

	item->callback (item->session, item->msg, item->callback_data);
	soup_message_queue_item_unref (item);
	return FALSE;
}
示例#9
0
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;
}
示例#10
0
static gpointer
queue_message_thread (gpointer data)
{
	SoupMessageQueueItem *item = data;

	soup_session_process_queue_item (item->session, item, NULL, TRUE);
	if (item->callback) {
		soup_add_completion (soup_session_get_async_context (item->session),
				     queue_message_callback, item);
	} else
		soup_message_queue_item_unref (item);

	return NULL;
}
示例#11
0
/**
 * soup_message_queue_next:
 * @queue: a #SoupMessageQueue
 * @item: a #SoupMessageQueueItem
 *
 * Unrefs @item and gets the next item after it in @queue. As with
 * soup_message_queue_first(), you must unref the returned item
 * yourself with soup_message_queue_unref_item() if you do not finish
 * walking the queue.
 *
 * Return value: the next item in @queue.
 **/ 
SoupMessageQueueItem *
soup_message_queue_next (SoupMessageQueue *queue, SoupMessageQueueItem *item)
{
	SoupMessageQueueItem *next;

	g_mutex_lock (queue->mutex);

	next = item->next;
	while (next && next->removed)
		next = next->next;
	if (next)
		next->ref_count++;

	g_mutex_unlock (queue->mutex);
	soup_message_queue_item_unref (item);
	return next;
}
示例#12
0
static void
resolved_proxy_addr (SoupAddress *addr, guint status, gpointer user_data)
{
	SoupMessageQueueItem *item = user_data;
	SoupSession *session = item->session;

	if (item_failed (item, status))
		return;

	item->proxy_addr = g_object_ref (addr);
	item->state = SOUP_MESSAGE_AWAITING_CONNECTION;

	soup_message_queue_item_unref (item);

	/* If we got here we know session still exists */
	run_queue ((SoupSessionAsync *)session);
}
示例#13
0
static void
cancel_message (SoupSession *session, SoupMessage *msg, guint status_code)
{
	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
	SoupMessageQueueItem *item;

	item = soup_message_queue_lookup (priv->queue, msg);
	if (item) {
		if (item->cancellable)
			g_cancellable_cancel (item->cancellable);
		soup_message_queue_item_unref (item);
	}

	soup_message_io_stop (msg);
	soup_message_set_status (msg, status_code);
	soup_message_finished (msg);
}
示例#14
0
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);
}
示例#15
0
static guint
send_message (SoupSession *session, SoupMessage *req)
{
	SoupMessageQueueItem *item;
	GMainContext *async_context =
		soup_session_get_async_context (session);

	/* Balance out the unref that queuing will eventually do */
	g_object_ref (req);

	queue_message (session, req, NULL, NULL);

	item = soup_message_queue_lookup (soup_session_get_queue (session), req);
	g_return_val_if_fail (item != NULL, SOUP_STATUS_MALFORMED);

	while (item->state != SOUP_MESSAGE_FINISHED)
		g_main_context_iteration (async_context, TRUE);

	soup_message_queue_item_unref (item);

	return req->status_code;
}
示例#16
0
static void
run_queue (SoupSessionAsync *sa)
{
	SoupSession *session = SOUP_SESSION (sa);
	SoupMessageQueue *queue = soup_session_get_queue (session);
	SoupMessageQueueItem *item;
	SoupMessage *msg;
	gboolean try_pruning = TRUE, should_prune = FALSE;

	g_object_ref (session);
	soup_session_cleanup_connections (session, FALSE);

 try_again:
	for (item = soup_message_queue_first (queue);
	     item && !should_prune;
	     item = soup_message_queue_next (queue, item)) {
		msg = item->msg;

		/* CONNECT messages are handled specially */
		if (msg->method != SOUP_METHOD_CONNECT)
			process_queue_item (item, &should_prune, TRUE);
	}
	if (item)
		soup_message_queue_item_unref (item);

	if (try_pruning && should_prune) {
		/* There is at least one message in the queue that
		 * could be sent if we pruned an idle connection from
		 * some other server.
		 */
		if (soup_session_cleanup_connections (session, TRUE)) {
			try_pruning = should_prune = FALSE;
			goto try_again;
		}
	}

	g_object_unref (session);
}
示例#17
0
void
soup_message_io_cleanup (SoupMessage *msg)
{
	SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
	SoupMessageIOData *io;

	soup_message_io_stop (msg);

	io = priv->io_data;
	if (!io)
		return;
	priv->io_data = NULL;

	if (io->iostream)
		g_object_unref (io->iostream);
	if (io->body_istream)
		g_object_unref (io->body_istream);
	if (io->body_ostream)
		g_object_unref (io->body_ostream);
	if (io->async_context)
		g_main_context_unref (io->async_context);
	if (io->item)
		soup_message_queue_item_unref (io->item);

	g_byte_array_free (io->read_header_buf, TRUE);

	g_string_free (io->write_buf, TRUE);
	if (io->write_chunk)
		soup_buffer_free (io->write_chunk);

	if (io->async_close_wait) {
		g_cancellable_cancel (io->async_close_wait);
		g_clear_object (&io->async_close_wait);
	}
	g_clear_error (&io->async_close_error);

	g_slice_free (SoupMessageIOData, io);
}
static void
authenticate_auth (SoupAuthManager *manager, SoupAuth *auth,
		   SoupMessage *msg, gboolean prior_auth_failed,
		   gboolean proxy, gboolean can_interact)
{
	SoupAuthManagerPrivate *priv = manager->priv;
	SoupURI *uri;

	if (proxy) {
		SoupMessageQueue *queue;
		SoupMessageQueueItem *item;

		queue = soup_session_get_queue (priv->session);
		item = soup_message_queue_lookup (queue, msg);
		if (item) {
			uri = soup_connection_get_proxy_uri (item->conn);
			soup_message_queue_item_unref (item);
		} else
			uri = NULL;

		if (!uri)
			return;
	} else
		uri = soup_message_get_uri (msg);

	/* If a password is specified explicitly in the URI, use it
	 * even if the auth had previously already been authenticated.
	 */
	if (uri->password && uri->user) {
		soup_auth_authenticate (auth, uri->user, uri->password);
		soup_uri_set_password (uri, NULL);
		soup_uri_set_user (uri, NULL);
	} else if (!soup_auth_is_authenticated (auth) && can_interact) {
		g_signal_emit (manager, signals[AUTHENTICATE], 0,
			       msg, auth, prior_auth_failed);
	}
}
示例#19
0
static void
cancel_message (SoupSession *session, SoupMessage *msg,
		guint status_code)
{
	SoupMessageQueue *queue;
	SoupMessageQueueItem *item;
	gboolean dummy;

	SOUP_SESSION_CLASS (soup_session_async_parent_class)->
		cancel_message (session, msg, status_code);

	queue = soup_session_get_queue (session);
	item = soup_message_queue_lookup (queue, msg);
	if (!item || item->state != SOUP_MESSAGE_FINISHING)
		return;

	/* Force it to finish immediately, so that
	 * soup_session_abort (session); g_object_unref (session);
	 * will work.
	 */
	process_queue_item (item, &dummy, FALSE);

	soup_message_queue_item_unref (item);
}