[libsoup] soup-message-io: add soup_message_io_steal()



commit 0ebeb24f7935729deb29acc54b59b4af8fec09e1
Author: Dan Winship <danw gnome org>
Date:   Wed Dec 10 15:36:55 2014 +0100

    soup-message-io: add soup_message_io_steal()
    
    Add a method to allow a GIOStream to be stolen from the I/O system
    mid-request.

 libsoup/soup-message-io.c      |   50 ++++++++++++++++++++++++++++++++++++---
 libsoup/soup-message-private.h |   21 +++++++++++-----
 libsoup/soup-server.c          |   14 ++++++----
 libsoup/soup-session.c         |    5 ++-
 4 files changed, 71 insertions(+), 19 deletions(-)
---
diff --git a/libsoup/soup-message-io.c b/libsoup/soup-message-io.c
index 4629568..021a5ec 100644
--- a/libsoup/soup-message-io.c
+++ b/libsoup/soup-message-io.c
@@ -156,7 +156,7 @@ soup_message_io_finished (SoupMessage *msg)
        SoupMessageIOData *io = priv->io_data;
        SoupMessageCompletionFn completion_cb;
        gpointer completion_data;
-       gboolean complete;
+       SoupMessageIOCompletion completion;
 
        if (!io)
                return;
@@ -164,16 +164,44 @@ soup_message_io_finished (SoupMessage *msg)
        completion_cb = io->completion_cb;
        completion_data = io->completion_data;
 
-       complete = (io->read_state >= SOUP_MESSAGE_IO_STATE_FINISHING &&
-                   io->write_state >= SOUP_MESSAGE_IO_STATE_FINISHING);
+       if ((io->read_state >= SOUP_MESSAGE_IO_STATE_FINISHING &&
+            io->write_state >= SOUP_MESSAGE_IO_STATE_FINISHING))
+               completion = SOUP_MESSAGE_IO_COMPLETE;
+       else
+               completion = SOUP_MESSAGE_IO_INTERRUPTED;
 
        g_object_ref (msg);
        soup_message_io_cleanup (msg);
        if (completion_cb)
-               completion_cb (msg, complete, completion_data);
+               completion_cb (msg, completion, completion_data);
        g_object_unref (msg);
 }
 
+GIOStream *
+soup_message_io_steal (SoupMessage *msg)
+{
+       SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
+       SoupMessageIOData *io = priv->io_data;
+       SoupMessageCompletionFn completion_cb;
+       gpointer completion_data;
+       GIOStream *iostream;
+
+       if (!io || !io->iostream)
+               return NULL;
+
+       iostream = g_object_ref (io->iostream);
+       completion_cb = io->completion_cb;
+       completion_data = io->completion_data;
+
+       g_object_ref (msg);
+       soup_message_io_cleanup (msg);
+       if (completion_cb)
+               completion_cb (msg, SOUP_MESSAGE_IO_STOLEN, completion_data);
+       g_object_unref (msg);
+
+       return iostream;
+}
+
 static gboolean
 read_headers (SoupMessage *msg, gboolean blocking,
              GCancellable *cancellable, GError **error)
@@ -407,6 +435,13 @@ io_write (SoupMessage *msg, gboolean blocking,
                        }
 
                        soup_message_wrote_informational (msg);
+
+                       /* If this was "101 Switching Protocols", then
+                        * the server probably stole the connection...
+                        */
+                       if (io != priv->io_data)
+                               return FALSE;
+
                        soup_message_cleanup_response (msg);
                        break;
                }
@@ -611,6 +646,13 @@ io_read (SoupMessage *msg, gboolean blocking,
                         * bail out here rather than parsing encoding, etc
                         */
                        soup_message_got_informational (msg);
+
+                       /* If this was "101 Switching Protocols", then
+                        * the session may have stolen the connection...
+                        */
+                       if (io != priv->io_data)
+                               return FALSE;
+
                        soup_message_cleanup_response (msg);
                        break;
                } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
diff --git a/libsoup/soup-message-private.h b/libsoup/soup-message-private.h
index 9860dee..a9457bc 100644
--- a/libsoup/soup-message-private.h
+++ b/libsoup/soup-message-private.h
@@ -48,6 +48,11 @@ typedef struct {
 
 void             soup_message_cleanup_response (SoupMessage      *msg);
 
+typedef enum {
+       SOUP_MESSAGE_IO_COMPLETE,
+       SOUP_MESSAGE_IO_INTERRUPTED,
+       SOUP_MESSAGE_IO_STOLEN
+} SoupMessageIOCompletion;
 
 typedef void     (*SoupMessageGetHeadersFn)  (SoupMessage      *msg,
                                              GString          *headers,
@@ -60,7 +65,7 @@ typedef guint    (*SoupMessageParseHeadersFn)(SoupMessage      *msg,
                                              gpointer          user_data,
                                              GError          **error);
 typedef void     (*SoupMessageCompletionFn)  (SoupMessage      *msg,
-                                             gboolean          io_complete,
+                                             SoupMessageIOCompletion completion,
                                              gpointer          user_data);
 
 
@@ -89,7 +94,6 @@ void soup_message_io_server    (SoupMessage               *msg,
                                gpointer                   headers_data,
                                SoupMessageCompletionFn    completion_cb,
                                gpointer                   user_data);
-void soup_message_io_cleanup   (SoupMessage               *msg);
 
 /* Auth handling */
 void           soup_message_set_auth       (SoupMessage *msg,
@@ -100,11 +104,14 @@ void           soup_message_set_proxy_auth (SoupMessage *msg,
 SoupAuth      *soup_message_get_proxy_auth (SoupMessage *msg);
 
 /* I/O */
-void                soup_message_io_stop        (SoupMessage          *msg);
-void                soup_message_io_finished    (SoupMessage          *msg);
-void                soup_message_io_pause       (SoupMessage          *msg);
-void                soup_message_io_unpause     (SoupMessage          *msg);
-gboolean            soup_message_io_in_progress (SoupMessage          *msg);
+void       soup_message_io_stop        (SoupMessage *msg);
+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_io_in_progress (SoupMessage *msg);
+GIOStream *soup_message_io_steal       (SoupMessage *msg);
+
 
 gboolean soup_message_io_run_until_write  (SoupMessage   *msg,
                                           gboolean       blocking,
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 65957b9..7c85532 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -1159,23 +1159,26 @@ soup_client_context_unref (SoupClientContext *client)
 }
 
 static void
-request_finished (SoupMessage *msg, gboolean io_complete, gpointer user_data)
+request_finished (SoupMessage *msg, SoupMessageIOCompletion completion, gpointer user_data)
 {
        SoupClientContext *client = user_data;
        SoupServer *server = client->server;
        SoupSocket *sock = client->sock;
+       gboolean failed;
 
        soup_message_finished (msg);
 
+       failed = (completion == SOUP_MESSAGE_IO_INTERRUPTED ||
+                 msg->status_code == SOUP_STATUS_IO_ERROR);
        g_signal_emit (server,
-                      (!io_complete || msg->status_code == SOUP_STATUS_IO_ERROR) ?
-                      signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
+                      failed ? signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
                       0, msg, client);
 
-       soup_client_context_cleanup (client);
-       if (io_complete && soup_socket_is_connected (sock) &&
+       if (completion == SOUP_MESSAGE_IO_COMPLETE &&
+           soup_socket_is_connected (sock) &&
            soup_message_is_keepalive (msg)) {
                /* Start a new request */
+               soup_client_context_cleanup (client);
                start_request (server, client);
        } else {
                soup_socket_disconnect (sock);
@@ -2600,4 +2603,3 @@ soup_server_unpause_message (SoupServer *server,
 
        soup_message_io_unpause (msg);
 }
-
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 377d420..77756c1 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -1570,7 +1570,7 @@ soup_session_set_item_status (SoupSession          *session,
 
 
 static void
-message_completed (SoupMessage *msg, gboolean io_complete, gpointer user_data)
+message_completed (SoupMessage *msg, SoupMessageIOCompletion completion, gpointer user_data)
 {
        SoupMessageQueueItem *item = user_data;
 
@@ -1676,7 +1676,8 @@ tunnel_handshake_complete (GObject      *object,
 }
 
 static void
-tunnel_message_completed (SoupMessage *msg, gboolean io_complete, gpointer user_data)
+tunnel_message_completed (SoupMessage *msg, SoupMessageIOCompletion completion,
+                         gpointer user_data)
 {
        SoupMessageQueueItem *tunnel_item = user_data;
        SoupMessageQueueItem *item = tunnel_item->related;


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