soup-filter-input-stream.h \
soup-form.c \
soup-headers.c \
+ soup-io-stream.h \
+ soup-io-stream.c \
soup-logger.c \
soup-marshal.h \
soup-marshal.c \
if (item->msg->method == SOUP_METHOD_CONNECT) {
g_signal_emit (conn, signals[EVENT], 0,
G_SOCKET_CLIENT_PROXY_NEGOTIATING,
- soup_socket_get_iostream (priv->socket));
+ soup_socket_get_connection (priv->socket));
} else if (priv->state == SOUP_CONNECTION_IDLE)
soup_connection_set_state (conn, SOUP_CONNECTION_IN_USE);
SOUP_STATUS_IS_SUCCESSFUL (item->msg->status_code)) {
g_signal_emit (conn, signals[EVENT], 0,
G_SOCKET_CLIENT_PROXY_NEGOTIATED,
- soup_socket_get_iostream (priv->socket));
+ soup_socket_get_connection (priv->socket));
/* We're now effectively no longer proxying */
soup_uri_free (priv->proxy_uri);
SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
if (!connection && priv->socket)
- connection = soup_socket_get_iostream (priv->socket);
+ connection = soup_socket_get_connection (priv->socket);
g_signal_emit (conn, signals[EVENT], 0,
event, connection);
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-io-stream.c
+ *
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gio/gio.h>
+
+#include "soup-io-stream.h"
+#include "soup-filter-input-stream.h"
+
+struct _SoupIOStreamPrivate {
+ GIOStream *base_iostream;
+ gboolean close_on_dispose;
+
+ GInputStream *istream;
+ GOutputStream *ostream;
+ gboolean disposing;
+};
+
+enum {
+ PROP_0,
+
+ PROP_BASE_IOSTREAM,
+ PROP_CLOSE_ON_DISPOSE
+};
+
+G_DEFINE_TYPE (SoupIOStream, soup_io_stream, G_TYPE_IO_STREAM)
+
+static void
+soup_io_stream_init (SoupIOStream *stream)
+{
+ stream->priv = G_TYPE_INSTANCE_GET_PRIVATE (stream,
+ SOUP_TYPE_IO_STREAM,
+ SoupIOStreamPrivate);
+}
+
+static void
+soup_io_stream_set_property (GObject *object, guint prop_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ SoupIOStream *siostream = SOUP_IO_STREAM (object);
+ GIOStream *io;
+
+ switch (prop_id) {
+ case PROP_BASE_IOSTREAM:
+ io = siostream->priv->base_iostream = g_value_dup_object (value);
+ if (io) {
+ siostream->priv->istream =
+ soup_filter_input_stream_new (g_io_stream_get_input_stream (io));
+ siostream->priv->ostream =
+ g_object_ref (g_io_stream_get_output_stream (io));
+ } else {
+ g_clear_object (&siostream->priv->istream);
+ g_clear_object (&siostream->priv->ostream);
+ }
+ break;
+ case PROP_CLOSE_ON_DISPOSE:
+ siostream->priv->close_on_dispose = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+soup_io_stream_get_property (GObject *object, guint prop_id,
+ GValue *value, GParamSpec *pspec)
+{
+ SoupIOStream *siostream = SOUP_IO_STREAM (object);
+
+ switch (prop_id) {
+ case PROP_BASE_IOSTREAM:
+ g_value_set_object (value, siostream->priv->base_iostream);
+ break;
+ case PROP_CLOSE_ON_DISPOSE:
+ g_value_set_boolean (value, siostream->priv->close_on_dispose);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+soup_io_stream_dispose (GObject *object)
+{
+ SoupIOStream *siostream = SOUP_IO_STREAM (object);
+
+ siostream->priv->disposing = TRUE;
+
+ G_OBJECT_CLASS (soup_io_stream_parent_class)->dispose (object);
+}
+
+static void
+soup_io_stream_finalize (GObject *object)
+{
+ SoupIOStream *siostream = SOUP_IO_STREAM (object);
+
+ if (siostream->priv->base_iostream)
+ g_object_unref (siostream->priv->base_iostream);
+
+ G_OBJECT_CLASS (soup_io_stream_parent_class)->finalize (object);
+}
+
+static GInputStream *
+soup_io_stream_get_input_stream (GIOStream *stream)
+{
+ return SOUP_IO_STREAM (stream)->priv->istream;
+}
+
+static GOutputStream *
+soup_io_stream_get_output_stream (GIOStream *stream)
+{
+ return SOUP_IO_STREAM (stream)->priv->ostream;
+}
+
+
+static gboolean
+soup_io_stream_close (GIOStream *stream,
+ GCancellable *cancellable,
+ GError **error)
+{
+ SoupIOStream *siostream = SOUP_IO_STREAM (stream);
+
+ if (siostream->priv->disposing &&
+ !siostream->priv->close_on_dispose)
+ return TRUE;
+
+ return g_io_stream_close (siostream->priv->base_iostream,
+ cancellable, error);
+}
+
+static void
+soup_io_stream_close_async (GIOStream *stream,
+ int io_priority,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_io_stream_close_async (SOUP_IO_STREAM (stream)->priv->base_iostream,
+ io_priority, cancellable, callback, user_data);
+}
+
+static gboolean
+soup_io_stream_close_finish (GIOStream *stream,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_io_stream_close_finish (SOUP_IO_STREAM (stream)->priv->base_iostream,
+ result, error);
+}
+
+static void
+soup_io_stream_class_init (SoupIOStreamClass *stream_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (stream_class);
+ GIOStreamClass *io_stream_class = G_IO_STREAM_CLASS (stream_class);
+
+ g_type_class_add_private (stream_class, sizeof (SoupIOStreamPrivate));
+
+ object_class->set_property = soup_io_stream_set_property;
+ object_class->get_property = soup_io_stream_get_property;
+ object_class->dispose = soup_io_stream_dispose;
+ object_class->finalize = soup_io_stream_finalize;
+
+ io_stream_class->get_input_stream = soup_io_stream_get_input_stream;
+ io_stream_class->get_output_stream = soup_io_stream_get_output_stream;
+ io_stream_class->close_fn = soup_io_stream_close;
+ io_stream_class->close_async = soup_io_stream_close_async;
+ io_stream_class->close_finish = soup_io_stream_close_finish;
+
+ g_object_class_install_property (
+ object_class, PROP_BASE_IOSTREAM,
+ g_param_spec_object ("base-iostream",
+ "Base IOStream",
+ "Base GIOStream",
+ G_TYPE_IO_STREAM,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (
+ object_class, PROP_CLOSE_ON_DISPOSE,
+ g_param_spec_boolean ("close-on-dispose",
+ "Close base stream",
+ "Close base GIOStream when closing",
+ TRUE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT_ONLY));
+}
+
+GIOStream *
+soup_io_stream_new (GIOStream *base_iostream,
+ gboolean close_on_dispose)
+{
+ return g_object_new (SOUP_TYPE_IO_STREAM,
+ "base-iostream", base_iostream,
+ "close-on-dispose", close_on_dispose,
+ NULL);
+}
--- /dev/null
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2012 Red Hat, Inc.
+ */
+
+#ifndef __SOUP_IO_STREAM_H__
+#define __SOUP_IO_STREAM_H__ 1
+
+#include <libsoup/soup-types.h>
+
+G_BEGIN_DECLS
+
+#define SOUP_TYPE_IO_STREAM (soup_io_stream_get_type ())
+#define SOUP_IO_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_IO_STREAM, SoupIOStream))
+#define SOUP_IO_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_IO_STREAM, SoupIOStreamClass))
+#define SOUP_IS_IO_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_IO_STREAM))
+#define SOUP_IS_IO_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_IO_STREAM))
+#define SOUP_IO_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_IO_STREAM, SoupIOStreamClass))
+
+typedef struct _SoupIOStreamPrivate SoupIOStreamPrivate;
+
+typedef struct {
+ GIOStream parent;
+
+ SoupIOStreamPrivate *priv;
+} SoupIOStream;
+
+typedef struct {
+ GIOStreamClass parent_class;
+
+} SoupIOStreamClass;
+
+GType soup_io_stream_get_type (void);
+
+GIOStream *soup_io_stream_new (GIOStream *base_iostream,
+ gboolean close_on_dispose);
+
+G_END_DECLS
+
+#endif /* __SOUP_IO_STREAM_H__ */
#include "soup-connection.h"
#include "soup-headers.h"
#include "soup-message-queue.h"
+#include "soup-misc-private.h"
+#include "soup-session-async.h"
#include "soup-uri.h"
static guint
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_cleanup_response (item->msg);
- soup_message_io_client (item,
+ soup_message_io_client (item, iostream, async_context,
get_request_headers,
parse_response_headers,
item,
#include "soup-message-queue.h"
#include "soup-misc.h"
#include "soup-misc-private.h"
-#include "soup-socket.h"
typedef enum {
SOUP_MESSAGE_IO_CLIENT,
SoupMessageIOMode mode;
GCancellable *cancellable;
- SoupSocket *sock;
+ GIOStream *iostream;
SoupFilterInputStream *istream;
GInputStream *body_istream;
GOutputStream *ostream;
return;
priv->io_data = NULL;
- if (io->sock)
- g_object_unref (io->sock);
- if (io->istream)
- g_object_remove_weak_pointer (G_OBJECT (io->istream), (gpointer *)&io->istream);
- if (io->ostream)
- g_object_remove_weak_pointer (G_OBJECT (io->ostream), (gpointer *)&io->ostream);
+ if (io->iostream)
+ g_object_unref (io->iostream);
if (io->body_istream)
g_object_unref (io->body_istream);
if (io->body_ostream)
}
if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
- soup_socket_disconnect (io->sock);
+ g_io_stream_close (io->iostream, NULL, NULL);
}
void
}
static void
-io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
+io_error (SoupMessage *msg, GError *error)
{
SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
SoupMessageIOData *io = priv->io_data;
io->io_source = soup_message_io_get_source (msg, NULL, io_run, msg);
g_source_attach (io->io_source, io->async_context);
} else if (error) {
- io_error (io->sock, msg, error);
+ io_error (msg, error);
}
g_object_unref (msg);
static SoupMessageIOData *
-new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
+new_iostate (SoupMessage *msg, GIOStream *iostream,
+ GMainContext *async_context, SoupMessageIOMode mode,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer header_data,
{
SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
SoupMessageIOData *io;
- gboolean non_blocking, use_thread_context;
io = g_slice_new0 (SoupMessageIOData);
io->mode = mode;
io->completion_cb = completion_cb;
io->completion_data = completion_data;
- io->sock = g_object_ref (sock);
- io->istream = SOUP_FILTER_INPUT_STREAM (soup_socket_get_input_stream (sock));
- if (io->istream)
- g_object_add_weak_pointer (G_OBJECT (io->istream), (gpointer *)&io->istream);
- io->ostream = soup_socket_get_output_stream (sock);
- if (io->ostream)
- g_object_add_weak_pointer (G_OBJECT (io->ostream), (gpointer *)&io->ostream);
-
- g_object_get (io->sock,
- SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
- SOUP_SOCKET_USE_THREAD_CONTEXT, &use_thread_context,
- NULL);
- io->blocking = !non_blocking;
-
- if (use_thread_context) {
- io->async_context = g_main_context_get_thread_default ();
- if (io->async_context)
- g_main_context_ref (io->async_context);
- } else {
- g_object_get (io->sock,
- SOUP_SOCKET_ASYNC_CONTEXT, &io->async_context,
- NULL);
- }
+ io->iostream = g_object_ref (iostream);
+ io->istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (iostream));
+ io->ostream = g_io_stream_get_output_stream (iostream);
+
+ if (async_context) {
+ io->async_context = g_main_context_ref (async_context);
+ io->blocking = FALSE;
+ } else
+ io->blocking = TRUE;
io->read_header_buf = g_byte_array_new ();
io->write_buf = g_string_new (NULL);
void
soup_message_io_client (SoupMessageQueueItem *item,
+ GIOStream *iostream,
+ GMainContext *async_context,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer header_data,
gpointer completion_data)
{
SoupMessageIOData *io;
- SoupSocket *sock = soup_connection_get_socket (item->conn);
- io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
+ io = new_iostate (item->msg, iostream, async_context,
+ SOUP_MESSAGE_IO_CLIENT,
get_headers_cb, parse_headers_cb, header_data,
completion_cb, completion_data);
}
void
-soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
+soup_message_io_server (SoupMessage *msg,
+ GIOStream *iostream, GMainContext *async_context,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer header_data,
{
SoupMessageIOData *io;
- io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
+ io = new_iostate (msg, iostream, async_context,
+ SOUP_MESSAGE_IO_SERVER,
get_headers_cb, parse_headers_cb, header_data,
completion_cb, completion_data);
gpointer user_data);
void soup_message_io_client (SoupMessageQueueItem *item,
+ GIOStream *iostream,
+ GMainContext *async_context,
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,
+ GIOStream *iostream,
+ GMainContext *async_context,
SoupMessageGetHeadersFn get_headers_cb,
SoupMessageParseHeadersFn parse_headers_cb,
gpointer headers_data,
#include "soup-address.h"
#include "soup-auth.h"
#include "soup-headers.h"
+#include "soup-misc-private.h"
#include "soup-multipart.h"
#include "soup-server.h"
#include "soup-socket.h"
SoupMessageCompletionFn completion_cb,
gpointer user_data)
{
- soup_message_io_server (msg, sock,
+ GMainContext *async_context;
+ GIOStream *iostream;
+
+ g_object_get (sock,
+ SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
+ NULL);
+ if (!async_context)
+ async_context = g_main_context_ref (g_main_context_default ());
+
+ iostream = soup_socket_get_iostream (sock);
+
+ soup_message_io_server (msg, iostream, async_context,
get_response_headers,
parse_request_headers,
sock,
completion_cb, user_data);
+ if (async_context)
+ g_main_context_unref (async_context);
}
SoupSocketCallback callback,
gpointer user_data);
-GSocket *soup_socket_get_gsocket (SoupSocket *sock);
-GIOStream *soup_socket_get_iostream (SoupSocket *sock);
-GInputStream *soup_socket_get_input_stream (SoupSocket *sock);
-GOutputStream *soup_socket_get_output_stream (SoupSocket *sock);
+GSocket *soup_socket_get_gsocket (SoupSocket *sock);
+GIOStream *soup_socket_get_connection (SoupSocket *sock);
+GIOStream *soup_socket_get_iostream (SoupSocket *sock);
#endif /* SOUP_URI_PRIVATE_H */
#include "soup-socket.h"
#include "soup-address.h"
#include "soup-filter-input-stream.h"
+#include "soup-io-stream.h"
#include "soup-marshal.h"
#include "soup-misc.h"
#include "soup-misc-private.h"
typedef struct {
SoupAddress *local_addr, *remote_addr;
- GIOStream *conn;
+ GIOStream *conn, *iostream;
GSocket *gsock;
GInputStream *istream;
GOutputStream *ostream;
{
SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
- if (priv->gsock) {
- if (close)
- g_socket_close (priv->gsock, NULL);
- g_object_unref (priv->gsock);
- priv->gsock = NULL;
- }
- if (priv->conn) {
- if (G_IS_TLS_CONNECTION (priv->conn))
- g_signal_handlers_disconnect_by_func (priv->conn, soup_socket_peer_certificate_changed, sock);
- g_clear_object (&priv->conn);
- }
+ g_clear_object (&priv->gsock);
+ if (priv->conn && close)
+ g_io_stream_close (priv->conn, NULL, NULL);
if (priv->read_src) {
g_source_destroy (priv->read_src);
g_warning ("Disposing socket %p during connect", object);
g_object_unref (priv->connect_cancel);
}
- if (priv->conn) {
+ if (priv->gsock) {
if (priv->clean_dispose)
g_warning ("Disposing socket %p while still connected", object);
disconnect_internal (SOUP_SOCKET (object), TRUE);
}
+ g_clear_object (&priv->conn);
+ g_clear_object (&priv->iostream);
g_clear_object (&priv->istream);
g_clear_object (&priv->ostream);
if (!priv->conn)
priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock);
+ if (!priv->iostream)
+ priv->iostream = soup_io_stream_new (priv->conn, FALSE);
if (!priv->istream)
- priv->istream = soup_filter_input_stream_new (g_io_stream_get_input_stream (priv->conn));
+ priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
if (!priv->ostream)
- priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->conn));
+ priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
g_socket_set_timeout (priv->gsock, priv->timeout);
}
}
GIOStream *
-soup_socket_get_iostream (SoupSocket *sock)
+soup_socket_get_connection (SoupSocket *sock)
{
g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
return SOUP_SOCKET_GET_PRIVATE (sock)->conn;
}
+GIOStream *
+soup_socket_get_iostream (SoupSocket *sock)
+{
+ g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
+
+ return SOUP_SOCKET_GET_PRIVATE (sock)->iostream;
+}
+
static GSource *
soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond,
GPollableSourceFunc callback, gpointer user_data,
g_signal_connect (priv->conn, "notify::peer-certificate",
G_CALLBACK (soup_socket_peer_certificate_changed), sock);
- if (priv->istream)
- g_object_unref (priv->istream);
- if (priv->ostream)
- g_object_unref (priv->ostream);
+ g_clear_object (&priv->istream);
+ g_clear_object (&priv->ostream);
+ g_clear_object (&priv->iostream);
+ priv->iostream = soup_io_stream_new (priv->conn, FALSE);
+ priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
+ priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
- priv->istream = soup_filter_input_stream_new (g_io_stream_get_input_stream (priv->conn));
- priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->conn));
return TRUE;
}
g_cancellable_cancel (priv->connect_cancel);
return;
} else if (g_mutex_trylock (&priv->iolock)) {
- if (priv->conn)
+ if (priv->gsock)
disconnect_internal (sock, TRUE);
else
already_disconnected = TRUE;
g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
priv = SOUP_SOCKET_GET_PRIVATE (sock);
- return priv->conn != NULL;
+ return priv->conn && !g_io_stream_is_closed (priv->conn);
}
/**
return priv->remote_addr;
}
-GInputStream *
-soup_socket_get_input_stream (SoupSocket *sock)
-{
- g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
-
- return SOUP_SOCKET_GET_PRIVATE (sock)->istream;
-}
-
-GOutputStream *
-soup_socket_get_output_stream (SoupSocket *sock)
-{
- g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
-
- return SOUP_SOCKET_GET_PRIVATE (sock)->ostream;
-}
-
static gboolean
socket_read_watch (GObject *pollable, gpointer user_data)