Move SoupSocket stuff out of soup-message-io.c
authorDan Winship <danw@gnome.org>
Fri, 20 Apr 2012 15:29:14 +0000 (11:29 -0400)
committerDan Winship <danw@gnome.org>
Sat, 28 Apr 2012 17:14:15 +0000 (13:14 -0400)
Add a new SoupIOStream, which wraps the SoupFilterInputStream and
GOutputStream that SoupSocket exposes. Pass that to soup-message-io
rather than the SoupSocket, and update various other things for this.

libsoup/Makefile.am
libsoup/soup-connection.c
libsoup/soup-io-stream.c [new file with mode: 0644]
libsoup/soup-io-stream.h [new file with mode: 0644]
libsoup/soup-message-client-io.c
libsoup/soup-message-io.c
libsoup/soup-message-private.h
libsoup/soup-message-server-io.c
libsoup/soup-misc-private.h
libsoup/soup-socket.c

index 8fd8ee5..ddd4b13 100644 (file)
@@ -123,6 +123,8 @@ libsoup_2_4_la_SOURCES =            \
        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                  \
index ad4e8e6..fffa954 100644 (file)
@@ -448,7 +448,7 @@ set_current_item (SoupConnection *conn, SoupMessageQueueItem *item)
        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);
 
@@ -478,7 +478,7 @@ clear_current_item (SoupConnection *conn)
                    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);
@@ -500,7 +500,7 @@ soup_connection_event (SoupConnection      *conn,
        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);
diff --git a/libsoup/soup-io-stream.c b/libsoup/soup-io-stream.c
new file mode 100644 (file)
index 0000000..7c114a9
--- /dev/null
@@ -0,0 +1,205 @@
+/* -*- 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);
+}
diff --git a/libsoup/soup-io-stream.h b/libsoup/soup-io-stream.h
new file mode 100644 (file)
index 0000000..92c24c3
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- 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__ */
index 8796e90..f6c752f 100644 (file)
@@ -18,6 +18,8 @@
 #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
@@ -142,8 +144,19 @@ 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_cleanup_response (item->msg);
-       soup_message_io_client (item,
+       soup_message_io_client (item, iostream, async_context,
                                get_request_headers,
                                parse_response_headers,
                                item,
index cfb0688..713cd17 100644 (file)
@@ -26,7 +26,6 @@
 #include "soup-message-queue.h"
 #include "soup-misc.h"
 #include "soup-misc-private.h"
-#include "soup-socket.h"
 
 typedef enum {
        SOUP_MESSAGE_IO_CLIENT,
@@ -59,7 +58,7 @@ typedef struct {
        SoupMessageIOMode     mode;
        GCancellable         *cancellable;
 
-       SoupSocket             *sock;
+       GIOStream              *iostream;
        SoupFilterInputStream  *istream;
        GInputStream           *body_istream;
        GOutputStream          *ostream;
@@ -109,12 +108,8 @@ soup_message_io_cleanup (SoupMessage *msg)
                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)
@@ -155,7 +150,7 @@ soup_message_io_stop (SoupMessage *msg)
        }
 
        if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
-               soup_socket_disconnect (io->sock);
+               g_io_stream_close (io->iostream, NULL, NULL);
 }
 
 void
@@ -181,7 +176,7 @@ request_is_idempotent (SoupMessage *msg)
 }
 
 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;
@@ -865,7 +860,7 @@ io_run (SoupMessage *msg, gpointer user_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);
@@ -946,7 +941,8 @@ soup_message_io_get_response_istream (SoupMessage  *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,
@@ -955,7 +951,6 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
 {
        SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
        SoupMessageIOData *io;
-       gboolean non_blocking, use_thread_context;
 
        io = g_slice_new0 (SoupMessageIOData);
        io->mode = mode;
@@ -965,29 +960,15 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode 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);
@@ -1003,6 +984,8 @@ new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
 
 void
 soup_message_io_client (SoupMessageQueueItem *item,
+                       GIOStream *iostream,
+                       GMainContext *async_context,
                        SoupMessageGetHeadersFn get_headers_cb,
                        SoupMessageParseHeadersFn parse_headers_cb,
                        gpointer header_data,
@@ -1010,9 +993,9 @@ soup_message_io_client (SoupMessageQueueItem *item,
                        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);
 
@@ -1029,7 +1012,8 @@ soup_message_io_client (SoupMessageQueueItem *item,
 }
 
 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,
@@ -1038,7 +1022,8 @@ soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
 {
        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);
 
index 0d34833..69490e9 100644 (file)
@@ -65,13 +65,16 @@ void soup_message_read_request (SoupMessage               *req,
                                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,
index 8b07ebf..c40ace8 100644 (file)
@@ -16,6 +16,7 @@
 #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"
@@ -248,9 +249,22 @@ soup_message_read_request (SoupMessage               *msg,
                           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);
 }
index 8836f5b..018d66a 100644 (file)
@@ -18,9 +18,8 @@ void  soup_socket_handshake_async (SoupSocket         *sock,
                                   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 */
index 2d72b38..1658d09 100644 (file)
@@ -19,6 +19,7 @@
 #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"
@@ -69,7 +70,7 @@ enum {
 
 typedef struct {
        SoupAddress *local_addr, *remote_addr;
-       GIOStream *conn;
+       GIOStream *conn, *iostream;
        GSocket *gsock;
        GInputStream *istream;
        GOutputStream *ostream;
@@ -119,17 +120,9 @@ disconnect_internal (SoupSocket *sock, gboolean close)
 {
        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);
@@ -151,12 +144,14 @@ finalize (GObject *object)
                        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);
 
@@ -517,10 +512,12 @@ finish_socket_setup (SoupSocketPrivate *priv)
 
        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);
 }
@@ -843,13 +840,21 @@ soup_socket_get_gsocket (SoupSocket *sock)
 }
 
 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,
@@ -1086,13 +1091,13 @@ soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
        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;
 }
        
@@ -1204,7 +1209,7 @@ soup_socket_disconnect (SoupSocket *sock)
                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;
@@ -1254,7 +1259,7 @@ soup_socket_is_connected (SoupSocket *sock)
        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);
 }
 
 /**
@@ -1323,22 +1328,6 @@ soup_socket_get_remote_address (SoupSocket *sock)
        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)