Example #1
0
static void
soup_input_stream_send_async_internal (GInputStream        *stream,
				       int                  io_priority,
				       GCancellable        *cancellable,
				       GAsyncReadyCallback  callback,
				       gpointer             user_data)
{
  SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);

  g_object_ref (stream);
  priv->outstanding_callback = callback;

  /* If the session uses the default GMainContext, then we can do
   * async I/O directly. But if it has its own main context, it's
   * easier to just run it in another thread.
   */
  if (soup_session_get_async_context (priv->session))
    {
      soup_input_stream_send_async_in_thread (stream, io_priority, cancellable,
					      wrapper_callback, user_data);
      return;
    }

  priv->got_headers_cb = send_async_finished;
  priv->finished_cb = send_async_finished;

  soup_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
  priv->result = g_simple_async_result_new (G_OBJECT (stream),
					    wrapper_callback, user_data,
					    soup_input_stream_send_async);
}
Example #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);
}
Example #3
0
/**
 * soup_input_stream_new:
 * @session: the #SoupSession to use
 * @msg: the #SoupMessage whose response will be streamed
 * 
 * Prepares to send @msg over @session, and returns a #GInputStream
 * that can be used to read the response.
 *
 * @msg may not be sent until the first read call; if you need to look
 * at the status code or response headers before reading the body, you
 * can use soup_input_stream_send() or soup_input_stream_send_async()
 * to force the message to be sent and the response headers read.
 *
 * If @msg gets a non-2xx result, the first read (or send) will return
 * an error with type %SOUP_INPUT_STREAM_HTTP_ERROR.
 *
 * Internally, #SoupInputStream is implemented using asynchronous I/O,
 * so if you are using the synchronous API (eg,
 * g_input_stream_read()), you should create a new #GMainContext and
 * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
 * you don't, then synchronous #GInputStream calls will cause the main
 * loop to be run recursively.) The async #GInputStream API works fine
 * with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
 *
 * Returns: a new #GInputStream.
 **/
GInputStream *
soup_input_stream_new (SoupSession *session, SoupMessage *msg)
{
  SoupInputStream *stream;
  SoupInputStreamPrivate *priv;

  g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);

  stream = g_object_new (SOUP_TYPE_INPUT_STREAM, NULL);
  priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);

  priv->session = g_object_ref (session);
  priv->async_context = soup_session_get_async_context (session);
  priv->msg = g_object_ref (msg);

  g_signal_connect (msg, "got_headers",
		    G_CALLBACK (soup_input_stream_got_headers), stream);
  g_signal_connect (msg, "got_chunk",
		    G_CALLBACK (soup_input_stream_got_chunk), stream);
  g_signal_connect (msg, "finished",
		    G_CALLBACK (soup_input_stream_finished), stream);

  soup_input_stream_queue_message (stream);
  return G_INPUT_STREAM (stream);
}
Example #4
0
static void
do_idle_run_queue (SoupSession *session)
{
	SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (session);

	if (!priv->idle_run_queue_source) {
		priv->idle_run_queue_source = soup_add_completion (
			soup_session_get_async_context (session),
			idle_run_queue, session);
	}
}
Example #5
0
static void
resolve_proxy_addr (SoupMessageQueueItem *item,
		    SoupProxyURIResolver *proxy_resolver)
{
	item->state = SOUP_MESSAGE_RESOLVING_PROXY_URI;

	soup_message_queue_item_ref (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);
}
Example #6
0
static void
soup_input_stream_read_async (GInputStream        *stream,
			      void                *buffer,
			      gsize                count,
			      int                  io_priority,
			      GCancellable        *cancellable,
			      GAsyncReadyCallback  callback,
			      gpointer             user_data)
{
  SoupInputStreamPrivate *priv = SOUP_INPUT_STREAM_GET_PRIVATE (stream);
  GSimpleAsyncResult *result;

  /* If the session uses the default GMainContext, then we can do
   * async I/O directly. But if it has its own main context, we fall
   * back to the async-via-sync-in-another-thread implementation.
   */
  if (soup_session_get_async_context (priv->session))
    {
      G_INPUT_STREAM_CLASS (soup_input_stream_parent_class)->
	read_async (stream, buffer, count, io_priority,
		    cancellable, callback, user_data);
      return;
    }

  result = g_simple_async_result_new (G_OBJECT (stream),
				      callback, user_data,
				      soup_input_stream_read_async);

  if (priv->finished)
    {
      g_simple_async_result_set_op_res_gssize (result, 0);
      g_simple_async_result_complete_in_idle (result);
      g_object_unref (result);
      return;
    }

  if (priv->leftover_bufsize)
    {
      gsize nread = read_from_leftover (priv, buffer, count);
      g_simple_async_result_set_op_res_gssize (result, nread);
      g_simple_async_result_complete_in_idle (result);
      g_object_unref (result);
      return;
    }

  priv->result = result;

  priv->got_chunk_cb = read_async_done;
  priv->finished_cb = read_async_done;
  priv->cancelled_cb = read_async_done;
  soup_input_stream_prepare_for_io (stream, cancellable, buffer, count);
}
Example #7
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;
}
Example #8
0
static void
resolve_proxy_addr (SoupMessageQueueItem *item,
		    SoupProxyURIResolver *proxy_resolver)
{
	if (item->resolving_proxy_addr)
		return;
	item->resolving_proxy_addr = TRUE;

	soup_message_queue_item_ref (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);
}
Example #9
0
static guint
send_message (SoupSession *session, SoupMessage *req)
{
	GMainContext *async_context =
		soup_session_get_async_context (session);

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

	queue_message (session, req, NULL, NULL);

	while (soup_message_get_io_status (req) != SOUP_MESSAGE_IO_STATUS_FINISHED &&
	       !SOUP_STATUS_IS_TRANSPORT_ERROR (req->status_code))
		g_main_context_iteration (async_context, TRUE);

	return req->status_code;
}
Example #10
0
/**
 * soup_output_stream_new:
 * @session: the #SoupSession to use
 * @msg: the #SoupMessage whose request will be streamed
 * @size: the total size of the request body, or -1 if not known
 * 
 * Prepares to send @msg over @session, and returns a #GOutputStream
 * that can be used to write the response. The server's response will
 * be available in @msg after calling soup_output_stream_close()
 * (which will return a %SOUP_OUTPUT_STREAM_HTTP_ERROR #GError if the
 * status is not 2xx).
 *
 * If you know the total number of bytes that will be written, pass
 * that in @size. Otherwise, pass -1. (If you pass a size, you MUST
 * write that many bytes to the stream; Trying to write more than
 * that, or closing the stream without having written enough, will
 * result in an error.
 *
 * In some situations, the request will not actually be sent until you
 * call g_output_stream_close(). (In fact, currently this is *always*
 * true.)
 *
 * Internally, #SoupOutputStream is implemented using asynchronous
 * I/O, so if you are using the synchronous API (eg,
 * g_output_stream_write()), you should create a new #GMainContext and
 * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
 * you don't, then synchronous #GOutputStream calls will cause the
 * main loop to be run recursively.) The async #GOutputStream API
 * works fine with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
 *
 * Returns: a new #GOutputStream.
 **/
GOutputStream *
soup_output_stream_new (SoupSession *session, SoupMessage *msg, goffset size)
{
  SoupOutputStream *stream;
  SoupOutputStreamPrivate *priv;

  g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);

  stream = g_object_new (SOUP_TYPE_OUTPUT_STREAM, NULL);
  priv = SOUP_OUTPUT_STREAM_GET_PRIVATE (stream);

  priv->session = g_object_ref (session);
  priv->async_context = soup_session_get_async_context (session);
  priv->msg = g_object_ref (msg);
  priv->size = size;

  return G_OUTPUT_STREAM (stream);
}
Example #11
0
static void
auth_required (SoupSession *session, SoupMessage *msg,
	       SoupAuth *auth, gboolean retrying)
{
	SoupSessionFeature *password_manager;

	password_manager = soup_session_get_feature_for_message (
		session, SOUP_TYPE_PASSWORD_MANAGER, msg);
	if (password_manager) {
		soup_session_pause_message (session, msg);
		g_object_ref (auth);
		soup_password_manager_get_passwords_async (
			SOUP_PASSWORD_MANAGER (password_manager),
			msg, auth, retrying,
			soup_session_get_async_context (session),
			NULL, /* FIXME cancellable */
			got_passwords, session);
	} else {
		SOUP_SESSION_CLASS (soup_session_async_parent_class)->
			auth_required (session, msg, auth, retrying);
	}
}
Example #12
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;
}
Example #13
0
void
soup_message_send_request (SoupMessageQueueItem      *item,
			   SoupMessageCompletionFn    completion_cb,
			   gpointer                   user_data)
{
	GMainContext *async_context;
	GIOStream *iostream;

	if (SOUP_IS_SESSION_ASYNC (item->session)) {
		async_context = soup_session_get_async_context (item->session);
		if (!async_context)
			async_context = g_main_context_default ();
	} else
		async_context = NULL;
	iostream = soup_socket_get_iostream (soup_connection_get_socket (item->conn));

	soup_message_io_client (item, iostream, async_context,
				get_request_headers,
				parse_response_headers,
				item,
				completion_cb, user_data);
}