[libsoup/carlosgc/io-split: 4/5] Turn soup-message-io into an interface




commit e5f222d2bdb927b120c5c3890b6e320c0d901876
Author: Carlos Garcia Campos <cgarcia igalia com>
Date:   Thu Apr 22 11:17:32 2021 +0200

    Turn soup-message-io into an interface

 docs/reference/meson.build           |   2 +
 libsoup/meson.build                  |   1 +
 libsoup/soup-client-message-io.c     |  99 +++++++++++++
 libsoup/soup-client-message-io.h     |  71 +++++++++
 libsoup/soup-connection.c            |   8 +-
 libsoup/soup-connection.h            |   8 +-
 libsoup/soup-message-io-completion.h |  18 +++
 libsoup/soup-message-io-data.h       |  11 +-
 libsoup/soup-message-io.c            | 271 ++++++++++++++++++-----------------
 libsoup/soup-message-private.h       |  29 +---
 libsoup/soup-message.c               | 111 +++++++++++++-
 libsoup/soup-types.h                 |   1 +
 12 files changed, 453 insertions(+), 177 deletions(-)
---
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 10e64bb8..38792607 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -38,6 +38,8 @@ ignore_headers = [
   'soup-uri-utils-private.h',
   'soup-session-feature-private.h',
   'soup-message-metrics-private.h',
+  'soup-client-message-io.h',
+  'soup-message-io-completion.h',
 ]
 
 mkdb_args = [
diff --git a/libsoup/meson.build b/libsoup/meson.build
index 7bdaf0ac..ceafe5a1 100644
--- a/libsoup/meson.build
+++ b/libsoup/meson.build
@@ -51,6 +51,7 @@ soup_sources = [
   'soup-body-input-stream.c',
   'soup-body-output-stream.c',
   'soup-client-input-stream.c',
+  'soup-client-message-io.c',
   'soup-connection.c',
   'soup-date-utils.c',
   'soup-filter-input-stream.c',
diff --git a/libsoup/soup-client-message-io.c b/libsoup/soup-client-message-io.c
new file mode 100644
index 00000000..1db0c2e3
--- /dev/null
+++ b/libsoup/soup-client-message-io.c
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "soup-client-message-io.h"
+
+void
+soup_client_message_io_destroy (SoupClientMessageIO *io)
+{
+        if (!io)
+                return;
+
+        io->funcs->destroy (io);
+}
+
+void
+soup_client_message_io_finished (SoupClientMessageIO *io)
+{
+        io->funcs->finished (io);
+}
+
+void
+soup_client_message_io_stolen (SoupClientMessageIO *io)
+{
+        io->funcs->stolen (io);
+}
+
+void
+soup_client_message_io_send_item (SoupClientMessageIO       *io,
+                                  SoupMessageQueueItem      *item,
+                                  SoupMessageIOCompletionFn  completion_cb,
+                                  gpointer                   user_data)
+{
+        io->funcs->send_item (io, item, completion_cb, user_data);
+}
+
+void
+soup_client_message_io_pause (SoupClientMessageIO *io)
+{
+        io->funcs->pause (io);
+}
+
+void
+soup_client_message_io_unpause (SoupClientMessageIO *io)
+{
+        io->funcs->unpause (io);
+}
+
+gboolean
+soup_client_message_io_is_paused (SoupClientMessageIO *io)
+{
+        return io->funcs->is_paused (io);
+}
+
+void
+soup_client_message_io_run (SoupClientMessageIO *io,
+                            gboolean             blocking)
+{
+        io->funcs->run (io, blocking);
+}
+
+gboolean
+soup_client_message_io_run_until_read (SoupClientMessageIO *io,
+                                       GCancellable        *cancellable,
+                                       GError             **error)
+{
+        return io->funcs->run_until_read (io, cancellable, error);
+}
+
+void
+soup_client_message_io_run_until_read_async (SoupClientMessageIO *io,
+                                             int                  io_priority,
+                                             GCancellable        *cancellable,
+                                             GAsyncReadyCallback  callback,
+                                             gpointer             user_data)
+{
+        io->funcs->run_until_read_async (io, io_priority, cancellable, callback, user_data);
+}
+
+gboolean
+soup_client_message_io_run_until_finish (SoupClientMessageIO *io,
+                                         gboolean             blocking,
+                                         GCancellable        *cancellable,
+                                         GError             **error)
+{
+        return io->funcs->run_until_finish (io, blocking, cancellable, error);
+}
+
+GInputStream *
+soup_client_message_io_get_response_stream (SoupClientMessageIO *io,
+                                            GError             **error)
+{
+        return io->funcs->get_response_stream (io, error);
+}
diff --git a/libsoup/soup-client-message-io.h b/libsoup/soup-client-message-io.h
new file mode 100644
index 00000000..22f9bc47
--- /dev/null
+++ b/libsoup/soup-client-message-io.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ */
+
+#pragma once
+
+#include "soup-message-io-data.h"
+#include "soup-message-queue-item.h"
+
+typedef struct _SoupClientMessageIO SoupClientMessageIO;
+
+typedef struct {
+        void          (*destroy)              (SoupClientMessageIO       *io);
+        void          (*finished)             (SoupClientMessageIO       *io);
+        void          (*stolen)               (SoupClientMessageIO       *io);
+        void          (*send_item)            (SoupClientMessageIO       *io,
+                                               SoupMessageQueueItem      *item,
+                                               SoupMessageIOCompletionFn  completion_cb,
+                                               gpointer                   user_data);
+        GInputStream *(*get_response_stream)  (SoupClientMessageIO       *io,
+                                               GError                   **error);
+        void          (*pause)                (SoupClientMessageIO       *io);
+        void          (*unpause)              (SoupClientMessageIO       *io);
+        gboolean      (*is_paused)            (SoupClientMessageIO       *io);
+        void          (*run)                  (SoupClientMessageIO       *io,
+                                               gboolean                   blocking);
+        gboolean      (*run_until_read)       (SoupClientMessageIO       *io,
+                                               GCancellable              *cancellable,
+                                               GError                   **error);
+        void          (*run_until_read_async) (SoupClientMessageIO       *io,
+                                               int                        io_priority,
+                                               GCancellable              *cancellable,
+                                               GAsyncReadyCallback        callback,
+                                               gpointer                   user_data);
+        gboolean      (*run_until_finish)     (SoupClientMessageIO       *io,
+                                               gboolean                   blocking,
+                                               GCancellable              *cancellable,
+                                               GError                   **error);
+} SoupClientMessageIOFuncs;
+
+struct _SoupClientMessageIO {
+        const SoupClientMessageIOFuncs *funcs;
+};
+
+void          soup_client_message_io_destroy              (SoupClientMessageIO       *io);
+void          soup_client_message_io_finished             (SoupClientMessageIO       *io);
+void          soup_client_message_io_stolen               (SoupClientMessageIO       *io);
+void          soup_client_message_io_send_item            (SoupClientMessageIO       *io,
+                                                           SoupMessageQueueItem      *item,
+                                                           SoupMessageIOCompletionFn  completion_cb,
+                                                           gpointer                   user_data);
+void          soup_client_message_io_pause                (SoupClientMessageIO       *io);
+void          soup_client_message_io_unpause              (SoupClientMessageIO       *io);
+gboolean      soup_client_message_io_is_paused            (SoupClientMessageIO       *io);
+void          soup_client_message_io_run                  (SoupClientMessageIO       *io,
+                                                           gboolean                   blocking);
+gboolean      soup_client_message_io_run_until_read       (SoupClientMessageIO       *io,
+                                                           GCancellable              *cancellable,
+                                                           GError                   **error);
+void          soup_client_message_io_run_until_read_async (SoupClientMessageIO       *io,
+                                                           int                        io_priority,
+                                                           GCancellable              *cancellable,
+                                                           GAsyncReadyCallback        callback,
+                                                           gpointer                   user_data);
+gboolean      soup_client_message_io_run_until_finish     (SoupClientMessageIO       *io,
+                                                           gboolean                   blocking,
+                                                           GCancellable              *cancellable,
+                                                           GError                   **error);
+GInputStream *soup_client_message_io_get_response_stream  (SoupClientMessageIO       *io,
+                                                          GError                    **error);
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 3e52da6d..1c36fb89 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -32,7 +32,7 @@ typedef struct {
        gboolean ssl;
 
        SoupMessage *current_msg;
-        SoupClientMessageIOData *io_data;
+        SoupClientMessageIO *io_data;
        SoupConnectionState state;
        time_t       unused_timeout;
        GSource     *idle_timeout_src;
@@ -85,7 +85,7 @@ soup_connection_finalize (GObject *object)
 
        g_clear_pointer (&priv->proxy_uri, g_uri_unref);
        g_clear_pointer (&priv->socket_props, soup_socket_properties_unref);
-        g_clear_pointer (&priv->io_data, soup_client_message_io_data_free);
+        g_clear_pointer (&priv->io_data, soup_client_message_io_destroy);
        g_clear_object (&priv->remote_connectable);
        g_clear_object (&priv->current_msg);
 
@@ -1030,7 +1030,7 @@ soup_connection_get_ever_used (SoupConnection *conn)
        return priv->unused_timeout == 0;
 }
 
-SoupClientMessageIOData *
+SoupClientMessageIO *
 soup_connection_setup_message_io (SoupConnection *conn,
                                   SoupMessage    *msg)
 {
@@ -1057,7 +1057,7 @@ soup_connection_message_io_finished (SoupConnection *conn,
         SoupConnectionPrivate *priv = soup_connection_get_instance_private (conn);
 
         g_assert (priv->current_msg == msg);
-        g_clear_pointer (&priv->io_data, soup_client_message_io_data_free);
+        g_clear_pointer (&priv->io_data, soup_client_message_io_destroy);
 }
 
 GTlsCertificate *
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index bc0550d9..ca4dcd5a 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -65,10 +65,10 @@ void            soup_connection_set_reusable   (SoupConnection   *conn,
 
 gboolean        soup_connection_get_ever_used  (SoupConnection   *conn);
 
-SoupClientMessageIOData *soup_connection_setup_message_io    (SoupConnection *conn,
-                                                              SoupMessage    *msg);
-void                     soup_connection_message_io_finished (SoupConnection *conn,
-                                                              SoupMessage    *msg);
+SoupClientMessageIO *soup_connection_setup_message_io    (SoupConnection *conn,
+                                                          SoupMessage    *msg);
+void                 soup_connection_message_io_finished (SoupConnection *conn,
+                                                          SoupMessage    *msg);
 
 GTlsCertificate     *soup_connection_get_tls_certificate        (SoupConnection *conn);
 GTlsCertificateFlags soup_connection_get_tls_certificate_errors (SoupConnection *conn);
diff --git a/libsoup/soup-message-io-completion.h b/libsoup/soup-message-io-completion.h
new file mode 100644
index 00000000..78b8b88f
--- /dev/null
+++ b/libsoup/soup-message-io-completion.h
@@ -0,0 +1,18 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+
+typedef enum {
+        SOUP_MESSAGE_IO_COMPLETE,
+        SOUP_MESSAGE_IO_INTERRUPTED,
+        SOUP_MESSAGE_IO_STOLEN
+} SoupMessageIOCompletion;
+
+typedef void (*SoupMessageIOCompletionFn) (GObject                *msg,
+                                           SoupMessageIOCompletion completion,
+                                           gpointer                user_data);
diff --git a/libsoup/soup-message-io-data.h b/libsoup/soup-message-io-data.h
index f2b7a9ce..80722239 100644
--- a/libsoup/soup-message-io-data.h
+++ b/libsoup/soup-message-io-data.h
@@ -9,6 +9,7 @@
 #include "soup-filter-input-stream.h"
 #include "soup-message-headers.h"
 #include "soup-message-io-source.h"
+#include "soup-message-io-completion.h"
 
 typedef enum {
        SOUP_MESSAGE_IO_STATE_NOT_STARTED,
@@ -32,16 +33,6 @@ typedef enum {
        (SOUP_MESSAGE_IO_STATE_ACTIVE (state) && \
         state != SOUP_MESSAGE_IO_STATE_BODY_DONE)
 
-typedef enum {
-       SOUP_MESSAGE_IO_COMPLETE,
-        SOUP_MESSAGE_IO_INTERRUPTED,
-        SOUP_MESSAGE_IO_STOLEN
-} SoupMessageIOCompletion;
-
-typedef void (*SoupMessageIOCompletionFn) (GObject                *msg,
-                                          SoupMessageIOCompletion completion,
-                                          gpointer                user_data);
-
 typedef struct {
        GIOStream              *iostream;
        SoupFilterInputStream  *istream;
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 8e318ad6..4ab32ee7 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -27,10 +27,12 @@
 #include "soup-message-private.h"
 #include "soup-message-metrics-private.h"
 #include "soup-message-queue-item.h"
+#include "soup-client-message-io.h"
 #include "soup-misc.h"
 #include "soup-uri-utils-private.h"
 
-struct _SoupClientMessageIOData {
+typedef struct {
+        SoupClientMessageIO iface;
        SoupMessageIOData base;
 
         SoupMessageQueueItem *item;
@@ -40,16 +42,15 @@ struct _SoupClientMessageIOData {
 #ifdef HAVE_SYSPROF
         gint64 begin_time_nsec;
 #endif
-};
+} SoupClientMessageIOData;
 
 #define RESPONSE_BLOCK_SIZE 8192
 #define HEADER_SIZE_LIMIT (64 * 1024)
 
-void
-soup_client_message_io_data_free (SoupClientMessageIOData *io)
+static void
+soup_client_message_io_data_destroy (SoupClientMessageIO *iface)
 {
-       if (!io)
-               return;
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
 
        soup_message_io_data_cleanup (&io->base);
        soup_message_queue_item_unref (io->item);
@@ -66,9 +67,10 @@ soup_client_message_io_data_get_priority (SoupClientMessageIOData *io)
        return g_task_get_priority (io->item->task);
 }
 
-void
-soup_client_message_io_finished (SoupClientMessageIOData *io)
+static void
+soup_client_message_io_data_finished (SoupClientMessageIO *iface)
 {
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
        SoupMessageIOCompletionFn completion_cb;
        gpointer completion_data;
        SoupMessageIOCompletion completion;
@@ -90,9 +92,10 @@ soup_client_message_io_finished (SoupClientMessageIOData *io)
        g_object_unref (msg);
 }
 
-void
-soup_client_message_io_stolen (SoupClientMessageIOData *io)
+static void
+soup_client_message_io_data_stolen (SoupClientMessageIO *iface)
 {
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
        SoupMessageIOCompletionFn completion_cb;
        gpointer completion_data;
         SoupMessage *msg;
@@ -162,7 +165,7 @@ request_body_stream_wrote_data_cb (SoupMessage *msg,
                                    guint        count,
                                    gboolean     is_metadata)
 {
-        SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *client_io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
 
         if (client_io->metrics) {
                 client_io->metrics->request_body_bytes_sent += count;
@@ -186,7 +189,7 @@ request_body_stream_wrote_cb (GOutputStream *ostream,
 
        nwrote = g_output_stream_splice_finish (ostream, result, &error);
 
-       io = soup_message_get_io_data (msg);
+       io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
        if (!io || !io->base.async_wait || io->base.body_ostream != ostream) {
                g_clear_error (&error);
                g_object_unref (msg);
@@ -216,7 +219,7 @@ closed_async (GObject      *source,
        SoupClientMessageIOData *io;
        GCancellable *async_wait;
 
-       io = soup_message_get_io_data (msg);
+       io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
        if (!io || !io->base.async_wait || io->base.body_ostream != body_ostream) {
                g_object_unref (msg);
                return;
@@ -317,11 +320,13 @@ write_headers (SoupMessage          *msg,
  * socket not writable, write is complete, etc).
  */
 static gboolean
-io_write (SoupMessage *msg, gboolean blocking,
-         GCancellable *cancellable, GError **error)
+io_write (SoupClientMessageIOData *client_io,
+          gboolean                 blocking,
+         GCancellable            *cancellable,
+          GError                 **error)
 {
-       SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
        SoupMessageIOData *io = &client_io->base;
+        SoupMessage *msg = client_io->item->msg;
        SoupSessionFeature *logger;
        gssize nwrote;
 
@@ -510,7 +515,7 @@ static void
 response_network_stream_read_data_cb (SoupMessage *msg,
                                       guint        count)
 {
-        SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *client_io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
 
         if (client_io->base.read_state < SOUP_MESSAGE_IO_STATE_BODY_START)
                 client_io->metrics->response_header_bytes_received += count;
@@ -525,11 +530,13 @@ response_network_stream_read_data_cb (SoupMessage *msg,
  * socket not readable, read is complete, etc).
  */
 static gboolean
-io_read (SoupMessage *msg, gboolean blocking,
-        GCancellable *cancellable, GError **error)
+io_read (SoupClientMessageIOData *client_io,
+         gboolean                 blocking,
+        GCancellable            *cancellable,
+         GError                 **error)
 {
-       SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
        SoupMessageIOData *io = &client_io->base;
+        SoupMessage *msg = client_io->item->msg;
        gboolean succeeded;
         gboolean is_first_read;
         gushort extra_bytes;
@@ -599,7 +606,7 @@ io_read (SoupMessage *msg, gboolean blocking,
                        /* If this was "101 Switching Protocols", then
                         * the session may have stolen the connection...
                         */
-                       if (client_io != soup_message_get_io_data (msg))
+                       if (client_io != (SoupClientMessageIOData *)soup_message_get_io_data (msg))
                                return FALSE;
 
                        soup_message_cleanup_response (msg);
@@ -701,12 +708,14 @@ io_read (SoupMessage *msg, gboolean blocking,
 static gboolean
 request_is_restartable (SoupMessage *msg, GError *error)
 {
-       SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
-       SoupMessageIOData *io = &client_io->base;
+       SoupClientMessageIOData *client_io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
+       SoupMessageIOData *io;
 
        if (!client_io)
                return FALSE;
 
+        io = &client_io->base;
+
        return (io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
                io->read_header_buf->len == 0 &&
                soup_connection_get_ever_used (client_io->item->conn) &&
@@ -718,12 +727,15 @@ request_is_restartable (SoupMessage *msg, GError *error)
 }
 
 static gboolean
-io_run_until (SoupMessage *msg, gboolean blocking,
-             SoupMessageIOState read_state, SoupMessageIOState write_state,
-             GCancellable *cancellable, GError **error)
+io_run_until (SoupClientMessageIOData *client_io,
+              gboolean                 blocking,
+             SoupMessageIOState       read_state,
+              SoupMessageIOState       write_state,
+             GCancellable            *cancellable,
+              GError                 **error)
 {
-       SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
        SoupMessageIOData *io = &client_io->base;
+        SoupMessage *msg = client_io->item->msg;
        gboolean progress = TRUE, done;
        GError *my_error = NULL;
 
@@ -738,13 +750,14 @@ io_run_until (SoupMessage *msg, gboolean blocking,
 
        g_object_ref (msg);
 
-       while (progress && soup_message_get_io_data (msg) == client_io && !io->paused && !io->async_wait &&
+       while (progress && (SoupClientMessageIOData *)soup_message_get_io_data (msg) == client_io &&
+               !io->paused && !io->async_wait &&
               (io->read_state < read_state || io->write_state < write_state)) {
 
                if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
-                       progress = io_read (msg, blocking, cancellable, &my_error);
+                       progress = io_read (client_io, blocking, cancellable, &my_error);
                else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
-                       progress = io_write (msg, blocking, cancellable, &my_error);
+                       progress = io_write (client_io, blocking, cancellable, &my_error);
                else
                        progress = FALSE;
        }
@@ -753,7 +766,7 @@ io_run_until (SoupMessage *msg, gboolean blocking,
                g_propagate_error (error, my_error);
                g_object_unref (msg);
                return FALSE;
-       } else if (soup_message_get_io_data (msg) != client_io) {
+       } else if ((SoupClientMessageIOData *)soup_message_get_io_data (msg) != client_io) {
                g_set_error_literal (error, G_IO_ERROR,
                                     G_IO_ERROR_CANCELLED,
                                     _("Operation was cancelled"));
@@ -818,7 +831,7 @@ soup_message_io_finish (SoupMessage  *msg,
                        GError       *error)
 {
        if (request_is_restartable (msg, error)) {
-               SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+               SoupClientMessageIOData *io = (SoupClientMessageIOData *)soup_message_get_io_data (msg);
 
                /* Connection got closed, but we can safely try again. */
                io->item->state = SOUP_MESSAGE_RESTARTING;
@@ -829,19 +842,22 @@ soup_message_io_finish (SoupMessage  *msg,
        soup_message_io_finished (msg);
 }
 
+static void soup_client_message_io_data_run (SoupClientMessageIO *iface, gboolean blocking);
+
 static gboolean
 io_run_ready (SoupMessage *msg, gpointer user_data)
 {
-       soup_message_io_run (msg, FALSE);
+       soup_client_message_io_data_run (soup_message_get_io_data (msg), FALSE);
        return FALSE;
 }
 
-void
-soup_message_io_run (SoupMessage *msg,
-                    gboolean     blocking)
+static void
+soup_client_message_io_data_run (SoupClientMessageIO *iface,
+                                 gboolean             blocking)
 {
-       SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *client_io = (SoupClientMessageIOData *)iface;
        SoupMessageIOData *io = &client_io->base;
+        SoupMessage *msg = client_io->item->msg;
        GError *error = NULL;
 
        if (io->io_source) {
@@ -852,7 +868,7 @@ soup_message_io_run (SoupMessage *msg,
 
        g_object_ref (msg);
 
-       if (io_run_until (msg, blocking,
+       if (io_run_until (client_io, blocking,
                          SOUP_MESSAGE_IO_STATE_DONE,
                          SOUP_MESSAGE_IO_STATE_DONE,
                          client_io->item->cancellable, &error)) {
@@ -867,7 +883,7 @@ soup_message_io_run (SoupMessage *msg,
                                       soup_client_message_io_data_get_priority (client_io));
                g_source_attach (io->io_source, g_main_context_get_thread_default ());
        } else {
-               if (soup_message_get_io_data (msg) == client_io)
+               if ((SoupClientMessageIOData *)soup_message_get_io_data (msg) == client_io)
                        soup_message_io_finish (msg, error);
                g_error_free (error);
 
@@ -876,27 +892,27 @@ soup_message_io_run (SoupMessage *msg,
        g_object_unref (msg);
 }
 
-gboolean
-soup_message_io_run_until_read (SoupMessage  *msg,
-                               GCancellable *cancellable,
-                               GError      **error)
+static gboolean
+soup_client_message_io_data_run_until_read (SoupClientMessageIO *iface,
+                                            GCancellable        *cancellable,
+                                            GError             **error)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+        SoupMessage *msg = io->item->msg;
 
-       if (io_run_until (msg, TRUE,
+       if (io_run_until (io, TRUE,
                          SOUP_MESSAGE_IO_STATE_BODY,
                          SOUP_MESSAGE_IO_STATE_ANY,
                          cancellable, error))
                return TRUE;
 
-       if (soup_message_get_io_data (msg) == io)
+       if ((SoupClientMessageIOData *)soup_message_get_io_data (msg) == io)
                soup_message_io_finish (msg, *error);
 
        return FALSE;
 }
 
-static void io_run_until_read_async (SoupMessage *msg,
-                                     GTask       *task);
+static void io_run_until_read_async (SoupClientMessageIOData *io, GTask *task);
 
 static gboolean
 io_run_until_read_ready (SoupMessage *msg,
@@ -904,16 +920,16 @@ io_run_until_read_ready (SoupMessage *msg,
 {
         GTask *task = user_data;
 
-        io_run_until_read_async (msg, task);
+        io_run_until_read_async ((SoupClientMessageIOData *)soup_message_get_io_data (msg), task);
         return FALSE;
 }
 
 static void
-io_run_until_read_async (SoupMessage *msg,
-                         GTask       *task)
+io_run_until_read_async (SoupClientMessageIOData *client_io,
+                         GTask                   *task)
 {
-        SoupClientMessageIOData *client_io = soup_message_get_io_data (msg);
        SoupMessageIOData *io = &client_io->base;
+        SoupMessage *msg = client_io->item->msg;
         GError *error = NULL;
 
         if (io->io_source) {
@@ -922,7 +938,7 @@ io_run_until_read_async (SoupMessage *msg,
                 io->io_source = NULL;
         }
 
-        if (io_run_until (msg, FALSE,
+        if (io_run_until (client_io, FALSE,
                           SOUP_MESSAGE_IO_STATE_BODY,
                           SOUP_MESSAGE_IO_STATE_ANY,
                           g_task_get_cancellable (task),
@@ -942,42 +958,37 @@ io_run_until_read_async (SoupMessage *msg,
                 return;
         }
 
-        if (soup_message_get_io_data (msg) == client_io)
+        if ((SoupClientMessageIOData *)soup_message_get_io_data (msg) == client_io)
                 soup_message_io_finish (msg, error);
 
         g_task_return_error (task, error);
         g_object_unref (task);
 }
 
-void
-soup_message_io_run_until_read_async (SoupMessage        *msg,
-                                     int                 io_priority,
-                                      GCancellable       *cancellable,
-                                      GAsyncReadyCallback callback,
-                                      gpointer            user_data)
+static void
+soup_client_message_io_data_run_until_read_async (SoupClientMessageIO *iface,
+                                                  int                  io_priority,
+                                                  GCancellable        *cancellable,
+                                                  GAsyncReadyCallback  callback,
+                                                  gpointer             user_data)
 {
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+        SoupMessage *msg = io->item->msg;
         GTask *task;
 
         task = g_task_new (msg, cancellable, callback, user_data);
        g_task_set_priority (task, io_priority);
-        io_run_until_read_async (msg, task);
+        io_run_until_read_async (io, task);
 }
 
-gboolean
-soup_message_io_run_until_read_finish (SoupMessage  *msg,
-                                       GAsyncResult *result,
-                                       GError      **error)
-{
-        return g_task_propagate_boolean (G_TASK (result), error);
-}
-
-gboolean
-soup_message_io_run_until_finish (SoupMessage   *msg,
-                                 gboolean       blocking,
-                                 GCancellable  *cancellable,
-                                 GError       **error)
+static gboolean
+soup_client_message_io_data_run_until_finish (SoupClientMessageIO *iface,
+                                              gboolean             blocking,
+                                              GCancellable        *cancellable,
+                                              GError             **error)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+        SoupMessage *msg = io->item->msg;
        gboolean success;
 
        g_object_ref (msg);
@@ -987,7 +998,7 @@ soup_message_io_run_until_finish (SoupMessage   *msg,
                        io->base.read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
        }
 
-       success = io_run_until (msg, blocking,
+       success = io_run_until (io, blocking,
                                SOUP_MESSAGE_IO_STATE_DONE,
                                SOUP_MESSAGE_IO_STATE_DONE,
                                cancellable, error);
@@ -997,35 +1008,36 @@ soup_message_io_run_until_finish (SoupMessage   *msg,
 }
 
 static void
-client_stream_eof (SoupClientInputStream *stream, gpointer user_data)
+client_stream_eof (SoupClientInputStream   *stream,
+                   SoupClientMessageIOData *io)
 {
-       SoupMessage *msg = user_data;
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
-
        if (io && io->base.read_state == SOUP_MESSAGE_IO_STATE_BODY)
                io->base.read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE;
 }
 
-GInputStream *
-soup_message_io_get_response_istream (SoupMessage  *msg,
-                                     GError      **error)
+static GInputStream *
+soup_client_message_io_data_get_response_stream (SoupClientMessageIO *iface,
+                                                 GError             **error)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+        SoupMessage *msg = io->item->msg;
        GInputStream *client_stream;
 
        client_stream = soup_client_input_stream_new (io->base.body_istream, msg);
        g_signal_connect (client_stream, "eof",
-                         G_CALLBACK (client_stream_eof), msg);
+                         G_CALLBACK (client_stream_eof), io);
 
        return client_stream;
 }
 
-void
-soup_client_message_io_data_send_item (SoupClientMessageIOData   *io,
+static void
+soup_client_message_io_data_send_item (SoupClientMessageIO       *iface,
                                        SoupMessageQueueItem      *item,
                                        SoupMessageIOCompletionFn  completion_cb,
                                        gpointer                   user_data)
 {
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+
         io->item = soup_message_queue_item_ref (item);
        io->base.completion_cb = completion_cb;
        io->base.completion_data = user_data;
@@ -1042,64 +1054,65 @@ soup_client_message_io_data_send_item (SoupClientMessageIOData   *io,
 #endif
 }
 
-SoupClientMessageIOData *
-soup_client_message_io_data_new (GIOStream *stream)
-{
-       SoupClientMessageIOData *io;
-
-       io = g_slice_new0 (SoupClientMessageIOData);
-       io->base.iostream = g_object_ref (stream);
-       io->base.istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->base.iostream));
-       io->base.ostream = g_io_stream_get_output_stream (io->base.iostream);
-
-       io->base.read_header_buf = g_byte_array_new ();
-       io->base.write_buf = g_string_new (NULL);
-
-       io->base.read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
-       io->base.write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
-
-        return io;
-}
-
-void
-soup_message_io_pause (SoupMessage *msg)
+static void
+soup_client_message_io_data_pause (SoupClientMessageIO *iface)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
 
-       g_return_if_fail (io != NULL);
        g_return_if_fail (io->base.read_state < SOUP_MESSAGE_IO_STATE_BODY);
 
        soup_message_io_data_pause (&io->base);
 }
 
-void
-soup_message_io_unpause (SoupMessage *msg)
+static void
+soup_client_message_io_data_unpause (SoupClientMessageIO *iface)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
 
-       g_return_if_fail (io != NULL);
        g_return_if_fail (io->base.read_state < SOUP_MESSAGE_IO_STATE_BODY);
        io->base.paused = FALSE;
 }
 
-/**
- * soup_message_io_in_progress:
- * @msg: a #SoupMessage
- *
- * Tests whether or not I/O is currently in progress on @msg.
- *
- * Returns: whether or not I/O is currently in progress.
- **/
-gboolean
-soup_message_io_in_progress (SoupMessage *msg)
+static gboolean
+soup_client_message_io_data_is_paused (SoupClientMessageIO *iface)
 {
-       return soup_message_get_io_data (msg) != NULL;
+        SoupClientMessageIOData *io = (SoupClientMessageIOData *)iface;
+
+       return io->base.paused;
 }
 
-gboolean
-soup_message_is_io_paused (SoupMessage *msg)
+static const SoupClientMessageIOFuncs io_funcs = {
+        soup_client_message_io_data_destroy,
+        soup_client_message_io_data_finished,
+        soup_client_message_io_data_stolen,
+        soup_client_message_io_data_send_item,
+        soup_client_message_io_data_get_response_stream,
+        soup_client_message_io_data_pause,
+        soup_client_message_io_data_unpause,
+        soup_client_message_io_data_is_paused,
+        soup_client_message_io_data_run,
+        soup_client_message_io_data_run_until_read,
+        soup_client_message_io_data_run_until_read_async,
+        soup_client_message_io_data_run_until_finish
+};
+
+SoupClientMessageIO *
+soup_client_message_io_data_new (GIOStream *stream)
 {
-       SoupClientMessageIOData *io = soup_message_get_io_data (msg);
+       SoupClientMessageIOData *io;
+
+       io = g_slice_new0 (SoupClientMessageIOData);
+       io->base.iostream = g_object_ref (stream);
+       io->base.istream = SOUP_FILTER_INPUT_STREAM (g_io_stream_get_input_stream (io->base.iostream));
+       io->base.ostream = g_io_stream_get_output_stream (io->base.iostream);
+
+       io->base.read_header_buf = g_byte_array_new ();
+       io->base.write_buf = g_string_new (NULL);
+
+       io->base.read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
+       io->base.write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
+
+        io->iface.funcs = &io_funcs;
 
-       return io && io->base.paused;
+        return (SoupClientMessageIO *)io;
 }
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 10dd232a..d8cfa0bb 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -8,15 +8,12 @@
 
 #include "soup-filter-input-stream.h"
 #include "soup-message.h"
-#include "soup-message-io-data.h"
+#include "soup-client-message-io.h"
 #include "auth/soup-auth.h"
 #include "soup-content-processor.h"
 #include "content-sniffer/soup-content-sniffer.h"
 #include "soup-session.h"
 
-typedef struct _SoupClientMessageIOData SoupClientMessageIOData;
-void soup_client_message_io_data_free (SoupClientMessageIOData *io);
-
 void             soup_message_set_status       (SoupMessage      *msg,
                                                guint             status_code,
                                                const char       *reason_phrase);
@@ -48,29 +45,15 @@ SoupAuth      *soup_message_get_proxy_auth (SoupMessage *msg);
 GUri          *soup_message_get_uri_for_auth (SoupMessage *msg);
 
 /* I/O */
-SoupClientMessageIOData *soup_client_message_io_data_new       (GIOStream                 *stream);
-void                     soup_client_message_io_data_send_item (SoupClientMessageIOData   *io,
-                                                                SoupMessageQueueItem      *item,
-                                                                SoupMessageIOCompletionFn  completion_cb,
-                                                                gpointer                   user_data);
-void       soup_client_message_io_finished (SoupClientMessageIOData *io);
-void       soup_client_message_io_stolen   (SoupClientMessageIOData *io);
+SoupClientMessageIO *soup_client_message_io_data_new       (GIOStream                 *stream);
 void       soup_message_io_run         (SoupMessage *msg,
                                        gboolean     blocking);
 void       soup_message_io_finished    (SoupMessage *msg);
-void       soup_message_io_cleanup     (SoupMessage *msg);
 void       soup_message_io_pause       (SoupMessage *msg);
 void       soup_message_io_unpause     (SoupMessage *msg);
 gboolean   soup_message_is_io_paused   (SoupMessage *msg);
 gboolean   soup_message_io_in_progress (SoupMessage *msg);
 
-gboolean soup_message_io_read_headers          (SoupMessage           *msg,
-                                                SoupFilterInputStream *stream,
-                                                GByteArray            *buffer,
-                                                gboolean               blocking,
-                                                GCancellable          *cancellable,
-                                                GError               **error);
-
 gboolean soup_message_io_run_until_finish      (SoupMessage        *msg,
                                                 gboolean            blocking,
                                                 GCancellable       *cancellable,
@@ -88,12 +71,6 @@ gboolean soup_message_io_run_until_read_finish (SoupMessage        *msg,
                                                 GAsyncResult       *result,
                                                 GError            **error);
 
-typedef gboolean (*SoupMessageSourceFunc) (SoupMessage *, gpointer);
-GSource *soup_message_io_get_source       (SoupMessage           *msg,
-                                          GCancellable          *cancellable,
-                                          SoupMessageSourceFunc  callback,
-                                          gpointer               user_data);
-
 GInputStream *soup_message_io_get_response_istream (SoupMessage  *msg,
                                                    GError      **error);
 
@@ -129,7 +106,7 @@ SoupConnection *soup_message_get_connection (SoupMessage    *msg);
 void            soup_message_set_connection (SoupMessage    *msg,
                                             SoupConnection *conn);
 
-SoupClientMessageIOData *soup_message_get_io_data (SoupMessage             *msg);
+SoupClientMessageIO *soup_message_get_io_data (SoupMessage             *msg);
 
 SoupContentSniffer *soup_message_get_content_sniffer    (SoupMessage        *msg);
 void                soup_message_set_content_sniffer    (SoupMessage        *msg,
diff --git a/libsoup/soup-message.c b/libsoup/soup-message.c
index c39ad4b8..d761ce86 100644
--- a/libsoup/soup-message.c
+++ b/libsoup/soup-message.c
@@ -59,7 +59,7 @@ struct _SoupMessage {
 };
 
 typedef struct {
-       SoupClientMessageIOData *io_data;
+       SoupClientMessageIO *io_data;
 
         SoupMessageHeaders *request_headers;
        SoupMessageHeaders *response_headers;
@@ -2135,7 +2135,7 @@ soup_message_get_priority (SoupMessage *msg)
        return priv->priority;
 }
 
-SoupClientMessageIOData *
+SoupClientMessageIO *
 soup_message_get_io_data (SoupMessage *msg)
 {
        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
@@ -2155,6 +2155,100 @@ soup_message_io_finished (SoupMessage *msg)
         soup_client_message_io_finished (g_steal_pointer (&priv->io_data));
 }
 
+void
+soup_message_io_pause (SoupMessage *msg)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        g_return_if_fail (priv->io_data != NULL);
+
+        soup_client_message_io_pause (priv->io_data);
+}
+
+void
+soup_message_io_unpause (SoupMessage *msg)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        g_return_if_fail (priv->io_data != NULL);
+
+        soup_client_message_io_unpause (priv->io_data);
+}
+
+gboolean
+soup_message_is_io_paused (SoupMessage *msg)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return priv->io_data && soup_client_message_io_is_paused (priv->io_data);
+}
+
+/**
+ * soup_message_io_in_progress:
+ * @msg: a #SoupMessage
+ *
+ * Tests whether or not I/O is currently in progress on @msg.
+ *
+ * Returns: whether or not I/O is currently in progress.
+ **/
+gboolean
+soup_message_io_in_progress (SoupMessage *msg)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return priv->io_data != NULL;
+}
+
+void
+soup_message_io_run (SoupMessage *msg,
+                     gboolean     blocking)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        soup_client_message_io_run (priv->io_data, blocking);
+}
+
+gboolean
+soup_message_io_run_until_read (SoupMessage  *msg,
+                                GCancellable *cancellable,
+                                GError      **error)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return soup_client_message_io_run_until_read (priv->io_data, cancellable, error);
+}
+
+void
+soup_message_io_run_until_read_async (SoupMessage        *msg,
+                                      int                 io_priority,
+                                      GCancellable       *cancellable,
+                                      GAsyncReadyCallback callback,
+                                      gpointer            user_data)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        soup_client_message_io_run_until_read_async (priv->io_data, io_priority, cancellable, callback, 
user_data);
+}
+
+gboolean
+soup_message_io_run_until_read_finish (SoupMessage  *msg,
+                                       GAsyncResult *result,
+                                       GError      **error)
+{
+        return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+gboolean
+soup_message_io_run_until_finish (SoupMessage  *msg,
+                                  gboolean      blocking,
+                                  GCancellable *cancellable,
+                                  GError      **error)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return soup_client_message_io_run_until_finish (priv->io_data, blocking, cancellable, error);
+}
+
 void
 soup_message_send_item (SoupMessage              *msg,
                         SoupMessageQueueItem     *item,
@@ -2164,8 +2258,17 @@ soup_message_send_item (SoupMessage              *msg,
         SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
 
         priv->io_data = soup_connection_setup_message_io (priv->connection, msg);
-        soup_client_message_io_data_send_item (priv->io_data, item,
-                                               completion_cb, user_data);
+        soup_client_message_io_send_item (priv->io_data, item,
+                                          completion_cb, user_data);
+}
+
+GInputStream *
+soup_message_io_get_response_istream (SoupMessage  *msg,
+                                      GError      **error)
+{
+        SoupMessagePrivate *priv = soup_message_get_instance_private (msg);
+
+        return soup_client_message_io_get_response_stream (priv->io_data, error);
 }
 
 SoupContentSniffer *
diff --git a/libsoup/soup-types.h b/libsoup/soup-types.h
index 8ce0505f..dec4ffaa 100644
--- a/libsoup/soup-types.h
+++ b/libsoup/soup-types.h
@@ -35,6 +35,7 @@ typedef struct _SoupWebsocketExtension  SoupWebsocketExtension;
 typedef struct _SoupConnection        SoupConnection;
 typedef struct _SoupMessageQueue      SoupMessageQueue;
 typedef struct _SoupMessageQueueItem  SoupMessageQueueItem;
+typedef struct _SoupClientMessageIO   SoupClientMessageIO;
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]