Add wrote_informational and got_informational signals.
authorDan Winship <danw@src.gnome.org>
Thu, 18 Sep 2003 17:41:29 +0000 (17:41 +0000)
committerDan Winship <danw@src.gnome.org>
Thu, 18 Sep 2003 17:41:29 +0000 (17:41 +0000)
* libsoup/soup-message.c: Add wrote_informational and
got_informational signals.

* libsoup/soup-message-client-io.c (get_request_headers): Set the
EXPECT_CONTINUE flag on the message if that header is set.

* libsoup/soup-message-server-io.c (parse_request_headers):
Likewise

* libsoup/soup-message-io.c (io_write): Set read_state to HEADERS
when blocking on an expect-continue. Emit wrote_informational
instead of wrote_headers in the 1xx case.
(io_read): Set read_state to BLOCKING, not NOT_STARTED after
reading a 100 Continue response. Emit got_informational instead of
got_headers in the 1xx case.

* libsoup/soup-session.c (soup_session_send_message): Reorder
things to deal with the fact that the message could finish right
away if there is a connection available and the server is very
close.

* libsoup/soup-status.h: Rename SOUP_STATUS_CLASS_TRANSPORT to
SOUP_STATUS_CLASS_TRANSPORT_ERROR.

ChangeLog
libsoup/soup-message-client-io.c
libsoup/soup-message-io.c
libsoup/soup-message-server-io.c
libsoup/soup-message.c
libsoup/soup-message.h
libsoup/soup-session.c
libsoup/soup-status.h

index 26642ed..fa19eb4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2003-09-18  Dan Winship  <danw@ximian.com>
+
+       * libsoup/soup-message.c: Add wrote_informational and
+       got_informational signals.
+
+       * libsoup/soup-message-client-io.c (get_request_headers): Set the
+       EXPECT_CONTINUE flag on the message if that header is set.
+
+       * libsoup/soup-message-server-io.c (parse_request_headers):
+       Likewise
+
+       * libsoup/soup-message-io.c (io_write): Set read_state to HEADERS
+       when blocking on an expect-continue. Emit wrote_informational
+       instead of wrote_headers in the 1xx case.
+       (io_read): Set read_state to BLOCKING, not NOT_STARTED after
+       reading a 100 Continue response. Emit got_informational instead of
+       got_headers in the 1xx case.
+
+       * libsoup/soup-session.c (soup_session_send_message): Reorder
+       things to deal with the fact that the message could finish right
+       away if there is a connection available and the server is very
+       close.
+
+       * libsoup/soup-status.h: Rename SOUP_STATUS_CLASS_TRANSPORT to
+       SOUP_STATUS_CLASS_TRANSPORT_ERROR.
+
 2003-09-17  Dan Winship  <danw@ximian.com>
 
        * libsoup/soup-session.c (find_oldest_connection): Fix two bugs
index e42b96a..1da52e2 100644 (file)
@@ -107,6 +107,7 @@ get_request_headers (SoupMessage *req, GString *header,
 {
        gboolean proxy = GPOINTER_TO_UINT (user_data);
        const SoupUri *uri = soup_message_get_uri (req);
+       const char *expect;
        char *uri_string;
 
        if (!strcmp (req->method, "CONNECT")) {
@@ -148,6 +149,10 @@ get_request_headers (SoupMessage *req, GString *header,
 
        soup_message_foreach_header (req->request_headers, add_header, header);
        g_string_append (header, "\r\n");
+
+       expect = soup_message_get_header (req->request_headers, "Expect");
+       if (expect && !strcmp (expect, "100-continue"))
+               req->priv->msg_flags |= SOUP_MESSAGE_EXPECT_CONTINUE;
 }
 
 void
index 7fbc56e..6c6a7fa 100644 (file)
@@ -317,19 +317,24 @@ io_write (SoupSocket *sock, SoupMessage *msg)
                                /* We just wrote a 1xx response
                                 * header, so stay in STATE_HEADERS.
                                 * (The caller will pause us from the
-                                * wrote_headers callback if he is not
-                                * ready to send the final response.)
+                                * wrote_informational callback if he
+                                * is not ready to send the final
+                                * response.)
                                 */
                        }
                } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
                           msg->priv->msg_flags & SOUP_MESSAGE_EXPECT_CONTINUE) {
                        /* Need to wait for the Continue response */
                        io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
+                       io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
                } else
                        io->write_state = io_body_state (io->write_encoding);
 
                SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
-               soup_message_wrote_headers (msg);
+               if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code))
+                       soup_message_wrote_informational (msg);
+               else
+                       soup_message_wrote_headers (msg);
                SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
                break;
 
@@ -495,9 +500,9 @@ io_read (SoupSocket *sock, SoupMessage *msg)
 
                        if (msg->status_code == SOUP_STATUS_CONTINUE &&
                            io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
-                               /* Restart the reader, unpause the writer */
+                               /* Pause the reader, unpause the writer */
                                io->read_state =
-                                       SOUP_MESSAGE_IO_STATE_NOT_STARTED;
+                                       SOUP_MESSAGE_IO_STATE_BLOCKING;
                                io->write_state =
                                        io_body_state (io->write_encoding);
                        } else {
@@ -513,7 +518,10 @@ io_read (SoupSocket *sock, SoupMessage *msg)
                        io->read_state = io_body_state (io->read_encoding);
 
                SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
-               soup_message_got_headers (msg);
+               if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code))
+                       soup_message_got_informational (msg);
+               else
+                       soup_message_got_headers (msg);
                SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
                break;
 
index f469d3b..64ffd7d 100644 (file)
@@ -29,7 +29,7 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
 {
        SoupUri *uri;
        char *req_path = NULL, *url;
-       const char *length, *enc, *req_host;
+       const char *expect, *length, *enc, *req_host;
        SoupServer *server;
 
        if (!soup_headers_parse_request (headers, headers_len,
@@ -39,6 +39,10 @@ parse_request_headers (SoupMessage *msg, char *headers, guint headers_len,
                                         &msg->priv->http_version))
                return SOUP_STATUS_BAD_REQUEST;
 
+       expect = soup_message_get_header (msg->request_headers, "Expect");
+       if (expect && !strcmp (expect, "100-continue"))
+               msg->priv->msg_flags |= SOUP_MESSAGE_EXPECT_CONTINUE;
+
        /* Handle request body encoding */
        length = soup_message_get_header (msg->request_headers,
                                          "Content-Length");
index 65459fa..80fa4aa 100644 (file)
 static GObjectClass *parent_class;
 
 enum {
+       WROTE_INFORMATIONAL,
        WROTE_HEADERS,
        WROTE_CHUNK,
        WROTE_BODY,
 
+       GOT_INFORMATIONAL,
        GOT_HEADERS,
        GOT_CHUNK,
        GOT_BODY,
@@ -106,6 +108,14 @@ class_init (GObjectClass *object_class)
        object_class->finalize = finalize;
 
        /* signals */
+       signals[WROTE_INFORMATIONAL] =
+               g_signal_new ("wrote_informational",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
+                             NULL, NULL,
+                             soup_marshal_NONE__NONE,
+                             G_TYPE_NONE, 0);
        signals[WROTE_HEADERS] =
                g_signal_new ("wrote_headers",
                              G_OBJECT_CLASS_TYPE (object_class),
@@ -131,6 +141,14 @@ class_init (GObjectClass *object_class)
                              soup_marshal_NONE__NONE,
                              G_TYPE_NONE, 0);
 
+       signals[GOT_INFORMATIONAL] =
+               g_signal_new ("got_informational",
+                             G_OBJECT_CLASS_TYPE (object_class),
+                             G_SIGNAL_RUN_FIRST,
+                             G_STRUCT_OFFSET (SoupMessageClass, got_informational),
+                             NULL, NULL,
+                             soup_marshal_NONE__NONE,
+                             G_TYPE_NONE, 0);
        signals[GOT_HEADERS] =
                g_signal_new ("got_headers",
                              G_OBJECT_CLASS_TYPE (object_class),
@@ -274,6 +292,12 @@ soup_message_set_response (SoupMessage   *msg,
 }
 
 void
+soup_message_wrote_informational (SoupMessage *msg)
+{
+       g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
+}
+
+void
 soup_message_wrote_headers (SoupMessage *msg)
 {
        g_signal_emit (msg, signals[WROTE_HEADERS], 0);
@@ -291,6 +315,12 @@ soup_message_wrote_body (SoupMessage *msg)
        g_signal_emit (msg, signals[WROTE_BODY], 0);
 }
 
+void
+soup_message_got_informational (SoupMessage *msg)
+{
+       g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
+}
+
 static void
 got_headers (SoupMessage *req)
 {
index cc9ea00..cd03617 100644 (file)
@@ -69,13 +69,15 @@ typedef struct {
        GObjectClass parent_class;
 
        /* signals */
-       void     (*wrote_headers) (SoupMessage *msg);
-       void     (*wrote_chunk)   (SoupMessage *msg);
-       void     (*wrote_body)    (SoupMessage *msg);
-       void     (*got_headers)   (SoupMessage *msg);
-       void     (*got_chunk)     (SoupMessage *msg);
-       void     (*got_body)      (SoupMessage *msg);
-       void     (*finished)      (SoupMessage *msg);
+       void     (*wrote_informational) (SoupMessage *msg);
+       void     (*wrote_headers)       (SoupMessage *msg);
+       void     (*wrote_chunk)         (SoupMessage *msg);
+       void     (*wrote_body)          (SoupMessage *msg);
+       void     (*got_informational)   (SoupMessage *msg);
+       void     (*got_headers)         (SoupMessage *msg);
+       void     (*got_chunk)           (SoupMessage *msg);
+       void     (*got_body)            (SoupMessage *msg);
+       void     (*finished)            (SoupMessage *msg);
 } SoupMessageClass;
 
 GType soup_message_get_type (void);
@@ -170,11 +172,11 @@ typedef enum {
        SOUP_MESSAGE_OVERWRITE_CHUNKS = (1 << 3),
 
        /*
-        * SOUP_MESSAGE_EXPECT_CONTINUE:
-        * The message includes an "Expect: 100-continue" header, and we
-        * should not send the body until the Continue response has been
-        * received. (This should be synchronized with the existence
-        * of the "Expect: 100-continue" header. FIXME!)
+        * SOUP_MESSAGE_EXPECT_CONTINUE: The message includes an
+        * "Expect: 100-continue" header, and we should not send the
+        * body until the Continue response has been received. (This
+        * is automatically set if there is an "Expect: 100-continue"
+        * header.)
         */
        SOUP_MESSAGE_EXPECT_CONTINUE = (1 << 4)
 } SoupMessageFlags;
@@ -255,12 +257,14 @@ void           soup_message_io_pause            (SoupMessage       *msg);
 void           soup_message_io_unpause          (SoupMessage       *msg);
 
 
-void soup_message_wrote_headers  (SoupMessage *msg);
-void soup_message_wrote_chunk    (SoupMessage *msg);
-void soup_message_wrote_body     (SoupMessage *msg);
-void soup_message_got_headers    (SoupMessage *msg);
-void soup_message_got_chunk      (SoupMessage *msg);
-void soup_message_got_body       (SoupMessage *msg);
-void soup_message_finished       (SoupMessage *msg);
+void soup_message_wrote_informational (SoupMessage *msg);
+void soup_message_wrote_headers       (SoupMessage *msg);
+void soup_message_wrote_chunk         (SoupMessage *msg);
+void soup_message_wrote_body          (SoupMessage *msg);
+void soup_message_got_informational   (SoupMessage *msg);
+void soup_message_got_headers         (SoupMessage *msg);
+void soup_message_got_chunk           (SoupMessage *msg);
+void soup_message_got_body            (SoupMessage *msg);
+void soup_message_finished            (SoupMessage *msg);
 
 #endif /*SOUP_MESSAGE_H*/
index b820357..4b33643 100644 (file)
@@ -916,14 +916,10 @@ soup_session_send_message (SoupSession *session, SoupMessage *req)
 
        soup_session_queue_message (session, req, NULL, NULL);
 
-       while (1) {
+       while (req->status != SOUP_MESSAGE_STATUS_FINISHED &&
+              !SOUP_STATUS_IS_TRANSPORT_ERROR (req->status_code))
                g_main_iteration (TRUE);
 
-               if (req->status == SOUP_MESSAGE_STATUS_FINISHED ||
-                   SOUP_STATUS_IS_TRANSPORT (req->status_code))
-                       break;
-       }
-
        return req->status_code;
 }
 
index a954bd5..f25c9ac 100644 (file)
@@ -9,7 +9,7 @@
 #define SOUP_STATUS_H 1
 
 typedef enum {
-       SOUP_STATUS_CLASS_TRANSPORT = 0,
+       SOUP_STATUS_CLASS_TRANSPORT_ERROR = 0,
        SOUP_STATUS_CLASS_INFORMATIONAL,
        SOUP_STATUS_CLASS_SUCCESS,
        SOUP_STATUS_CLASS_REDIRECT,
@@ -17,12 +17,12 @@ typedef enum {
        SOUP_STATUS_CLASS_SERVER_ERROR,
 } SoupStatusClass;
 
-#define SOUP_STATUS_IS_TRANSPORT(x)     (((x) > 0 && (x) < 100) || (x) >= 600)
-#define SOUP_STATUS_IS_INFORMATIONAL(x)  ((x) >= 100 && (x) < 200)
-#define SOUP_STATUS_IS_SUCCESSFUL(x)     ((x) >= 200 && (x) < 300)
-#define SOUP_STATUS_IS_REDIRECTION(x)    ((x) >= 300 && (x) < 400)
-#define SOUP_STATUS_IS_CLIENT_ERROR(x)   ((x) >= 400 && (x) < 500)
-#define SOUP_STATUS_IS_SERVER_ERROR(x)   ((x) >= 500 && (x) < 600)
+#define SOUP_STATUS_IS_TRANSPORT_ERROR(x) ((x) >  0   && (x) < 100)
+#define SOUP_STATUS_IS_INFORMATIONAL(x)   ((x) >= 100 && (x) < 200)
+#define SOUP_STATUS_IS_SUCCESSFUL(x)      ((x) >= 200 && (x) < 300)
+#define SOUP_STATUS_IS_REDIRECTION(x)     ((x) >= 300 && (x) < 400)
+#define SOUP_STATUS_IS_CLIENT_ERROR(x)    ((x) >= 400 && (x) < 500)
+#define SOUP_STATUS_IS_SERVER_ERROR(x)    ((x) >= 500 && (x) < 600)
 
 typedef enum {
        /* Transport Errors */