Merge libsoup-2.4 branch to trunk
[platform/upstream/libsoup.git] / libsoup / soup-message-io.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-message-io.c: HTTP message I/O
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "soup-connection.h"
16 #include "soup-message.h"
17 #include "soup-message-private.h"
18 #include "soup-misc.h"
19 #include "soup-socket.h"
20 #include "soup-ssl.h"
21
22 typedef enum {
23         SOUP_MESSAGE_IO_CLIENT,
24         SOUP_MESSAGE_IO_SERVER
25 } SoupMessageIOMode;
26
27 typedef enum {
28         SOUP_MESSAGE_IO_STATE_NOT_STARTED,
29         SOUP_MESSAGE_IO_STATE_HEADERS,
30         SOUP_MESSAGE_IO_STATE_BLOCKING,
31         SOUP_MESSAGE_IO_STATE_BODY,
32         SOUP_MESSAGE_IO_STATE_CHUNK_SIZE,
33         SOUP_MESSAGE_IO_STATE_CHUNK,
34         SOUP_MESSAGE_IO_STATE_CHUNK_END,
35         SOUP_MESSAGE_IO_STATE_TRAILERS,
36         SOUP_MESSAGE_IO_STATE_FINISHING,
37         SOUP_MESSAGE_IO_STATE_DONE
38 } SoupMessageIOState;
39
40 #define SOUP_MESSAGE_IO_STATE_ACTIVE(state) \
41         (state != SOUP_MESSAGE_IO_STATE_NOT_STARTED && \
42          state != SOUP_MESSAGE_IO_STATE_BLOCKING && \
43          state != SOUP_MESSAGE_IO_STATE_DONE)
44
45 typedef struct {
46         SoupSocket           *sock;
47         SoupConnection       *conn;
48         SoupMessageIOMode     mode;
49
50         SoupMessageIOState    read_state;
51         SoupEncoding          read_encoding;
52         GByteArray           *read_meta_buf;
53         SoupMessageBody      *read_body;
54         guint                 read_length;
55
56         SoupMessageIOState    write_state;
57         SoupEncoding          write_encoding;
58         GString              *write_buf;
59         SoupMessageBody      *write_body;
60         SoupBuffer           *write_chunk;
61         gsize                 write_body_offset;
62         guint                 written;
63
64         guint read_tag, write_tag, err_tag;
65
66         SoupMessageGetHeadersFn   get_headers_cb;
67         SoupMessageParseHeadersFn parse_headers_cb;
68         gpointer                  user_data;
69 } SoupMessageIOData;
70         
71
72 /* Put these around callback invocation if there is code afterward
73  * that depends on the IO having not been cancelled.
74  */
75 #define dummy_to_make_emacs_happy {
76 #define SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK { gboolean cancelled; g_object_ref (msg);
77 #define SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED cancelled = (priv->io_data != io); g_object_unref (msg); if (cancelled || (!io->read_tag && !io->write_tag)) return; }
78 #define SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED(val) cancelled = (priv->io_data != io); g_object_unref (msg); if (cancelled || (!io->read_tag && !io->write_tag)) return val; }
79
80 #define RESPONSE_BLOCK_SIZE 8192
81
82 void
83 soup_message_io_cleanup (SoupMessage *msg)
84 {
85         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
86         SoupMessageIOData *io;
87
88         soup_message_io_stop (msg);
89
90         io = priv->io_data;
91         if (!io)
92                 return;
93         priv->io_data = NULL;
94
95         if (io->sock)
96                 g_object_unref (io->sock);
97         if (io->conn)
98                 g_object_unref (io->conn);
99
100         g_byte_array_free (io->read_meta_buf, TRUE);
101
102         g_string_free (io->write_buf, TRUE);
103         if (io->write_chunk)
104                 soup_buffer_free (io->write_chunk);
105
106         g_slice_free (SoupMessageIOData, io);
107 }
108
109 /**
110  * soup_message_io_stop:
111  * @msg: a #SoupMessage
112  *
113  * Immediately stops I/O on msg; if the connection would be left in an
114  * inconsistent state, it will be closed.
115  *
116  * Note: this is a low-level function that does not cause any signals
117  * to be emitted on @msg; it is up to the caller to make sure that
118  * @msg doesn't get "stranded".
119  **/
120 void
121 soup_message_io_stop (SoupMessage *msg)
122 {
123         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
124         SoupMessageIOData *io = priv->io_data;
125
126         if (!io)
127                 return;
128
129         if (io->read_tag) {
130                 g_signal_handler_disconnect (io->sock, io->read_tag);
131                 io->read_tag = 0;
132         }
133         if (io->write_tag) {
134                 g_signal_handler_disconnect (io->sock, io->write_tag);
135                 io->write_tag = 0;
136         }
137         if (io->err_tag) {
138                 g_signal_handler_disconnect (io->sock, io->err_tag);
139                 io->err_tag = 0;
140         }
141
142         if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
143                 soup_socket_disconnect (io->sock);
144         else if (io->conn) {
145                 SoupConnection *conn = io->conn;
146                 io->conn = NULL;
147                 soup_connection_release (conn);
148                 g_object_unref (conn);
149         }
150 }
151
152 #define SOUP_MESSAGE_IO_EOL            "\r\n"
153 #define SOUP_MESSAGE_IO_EOL_LEN        2
154 #define SOUP_MESSAGE_IO_DOUBLE_EOL     "\r\n\r\n"
155 #define SOUP_MESSAGE_IO_DOUBLE_EOL_LEN 4
156
157 static void
158 soup_message_io_finished (SoupMessage *msg)
159 {
160         g_object_ref (msg);
161         soup_message_io_cleanup (msg);
162         if (SOUP_MESSAGE_IS_STARTING (msg))
163                 soup_message_restarted (msg);
164         else
165                 soup_message_finished (msg);
166         g_object_unref (msg);
167 }
168
169 static void io_read (SoupSocket *sock, SoupMessage *msg);
170
171 static void
172 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
173 {
174         if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) {
175                 if (error && error->domain == SOUP_SSL_ERROR) {
176                         soup_message_set_status_full (msg,
177                                                       SOUP_STATUS_SSL_FAILED,
178                                                       error->message);
179                 } else
180                         soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
181         }
182         if (error)
183                 g_error_free (error);
184
185         soup_message_io_finished (msg);
186 }
187
188 static void
189 io_disconnected (SoupSocket *sock, SoupMessage *msg)
190 {
191         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
192         SoupMessageIOData *io = priv->io_data;
193
194         /* Closing the connection to signify EOF is sometimes ok */
195         if (io->read_state == SOUP_MESSAGE_IO_STATE_BODY &&
196             io->read_encoding == SOUP_ENCODING_EOF) {
197                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
198                 io_read (sock, msg);
199                 return;
200         }
201
202         io_error (sock, msg, NULL);
203 }
204
205 /* Reads data from io->sock into io->read_meta_buf up until @boundary.
206  * (This function is used to read metadata, and read_body_chunk() is
207  * used to read the message body contents.)
208  *
209  * read_metadata, read_body_chunk, and write_data all use the same
210  * convention for return values: if they return %TRUE, it means
211  * they've completely finished the requested read/write, and the
212  * caller should move on to the next step. If they return %FALSE, it
213  * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
214  * so the caller should give up for now and wait for the socket to
215  * emit a signal, or (b) the socket returned an error, and io_error()
216  * was called to process it and cancel the I/O. So either way, if the
217  * function returns %FALSE, the caller should return immediately.
218  */
219 static gboolean
220 read_metadata (SoupMessage *msg, const char *boundary)
221 {
222         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
223         SoupMessageIOData *io = priv->io_data;
224         SoupSocketIOStatus status;
225         guchar read_buf[RESPONSE_BLOCK_SIZE];
226         guint boundary_len = strlen (boundary);
227         gsize nread;
228         gboolean done;
229         GError *error = NULL;
230
231         do {
232                 status = soup_socket_read_until (io->sock, read_buf,
233                                                  sizeof (read_buf),
234                                                  boundary, boundary_len,
235                                                  &nread, &done, NULL, &error);
236                 switch (status) {
237                 case SOUP_SOCKET_OK:
238                         g_byte_array_append (io->read_meta_buf, read_buf, nread);
239                         break;
240
241                 case SOUP_SOCKET_ERROR:
242                 case SOUP_SOCKET_EOF:
243                         io_error (io->sock, msg, error);
244                         return FALSE;
245
246                 case SOUP_SOCKET_WOULD_BLOCK:
247                         return FALSE;
248                 }
249         } while (!done);
250
251         return TRUE;
252 }
253
254 /* Reads as much message body data as is available on io->sock (but no
255  * further than the end of the current message body or chunk). On a
256  * successful read, emits "got_chunk" (possibly multiple times), and
257  * if %SOUP_MESSAGE_OVERWRITE_CHUNKS wasn't set, appends the chunk
258  * to io->read_body.
259  *
260  * See the note at read_metadata() for an explanation of the return
261  * value.
262  */
263 static gboolean
264 read_body_chunk (SoupMessage *msg)
265 {
266         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
267         SoupMessageIOData *io = priv->io_data;
268         SoupSocketIOStatus status;
269         guchar read_buf[RESPONSE_BLOCK_SIZE];
270         guint len = sizeof (read_buf);
271         gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
272         gsize nread;
273         GError *error = NULL;
274         SoupBuffer *buffer;
275
276         while (read_to_eof || io->read_length > 0) {
277                 if (!read_to_eof)
278                         len = MIN (len, io->read_length);
279
280                 status = soup_socket_read (io->sock, read_buf, len,
281                                            &nread, NULL, &error);
282
283                 switch (status) {
284                 case SOUP_SOCKET_OK:
285                         if (!nread)
286                                 break;
287
288                         buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
289                                                   read_buf, nread);
290                         if (!(priv->msg_flags & SOUP_MESSAGE_OVERWRITE_CHUNKS))
291                                 soup_message_body_append_buffer (io->read_body, buffer);
292
293                         io->read_length -= nread;
294
295                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
296                         soup_message_got_chunk (msg, buffer);
297                         soup_buffer_free (buffer);
298                         SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
299                         break;
300
301                 case SOUP_SOCKET_EOF:
302                         if (read_to_eof)
303                                 return TRUE;
304                         /* else fall through */
305
306                 case SOUP_SOCKET_ERROR:
307                         io_error (io->sock, msg, error);
308                         return FALSE;
309
310                 case SOUP_SOCKET_WOULD_BLOCK:
311                         return FALSE;
312                 }
313         }
314
315         return TRUE;
316 }
317
318 /* Attempts to write @len bytes from @data. See the note at
319  * read_metadata() for an explanation of the return value.
320  */
321 static gboolean
322 write_data (SoupMessage *msg, const char *data, guint len)
323 {
324         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
325         SoupMessageIOData *io = priv->io_data;
326         SoupSocketIOStatus status;
327         gsize nwrote;
328         GError *error = NULL;
329
330         while (len > io->written) {
331                 status = soup_socket_write (io->sock,
332                                             data + io->written,
333                                             len - io->written,
334                                             &nwrote, NULL, &error);
335                 switch (status) {
336                 case SOUP_SOCKET_EOF:
337                 case SOUP_SOCKET_ERROR:
338                         io_error (io->sock, msg, error);
339                         return FALSE;
340
341                 case SOUP_SOCKET_WOULD_BLOCK:
342                         return FALSE;
343
344                 case SOUP_SOCKET_OK:
345                         io->written += nwrote;
346                         break;
347                 }
348         }
349
350         io->written = 0;
351         return TRUE;
352 }
353
354 static inline SoupMessageIOState
355 io_body_state (SoupEncoding encoding)
356 {
357         if (encoding == SOUP_ENCODING_CHUNKED)
358                 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
359         else
360                 return SOUP_MESSAGE_IO_STATE_BODY;
361 }
362
363 /*
364  * There are two request/response formats: the basic request/response,
365  * possibly with one or more unsolicited informational responses (such
366  * as the WebDAV "102 Processing" response):
367  *
368  *     Client                            Server
369  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
370  *      W:BODY     / R:NOT_STARTED    ->  R:BODY     / W:NOT_STARTED
371  *     [W:DONE     / R:HEADERS (1xx)  <-  R:DONE     / W:HEADERS (1xx) ...]
372  *      W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS
373  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
374  *      W:DONE     / R:DONE               R:DONE     / W:DONE
375  *     
376  * and the "Expect: 100-continue" request/response, with the client
377  * blocking halfway through its request, and then either continuing or
378  * aborting, depending on the server response:
379  *
380  *     Client                            Server
381  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
382  *      W:BLOCKING / R:HEADERS        <-  R:BLOCKING / W:HEADERS
383  *     [W:BODY     / R:BLOCKING       ->  R:BODY     / W:BLOCKING]
384  *     [W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS]
385  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
386  *      W:DONE     / R:DONE               R:DONE     / W:DONE
387  */
388
389 static void
390 io_write (SoupSocket *sock, SoupMessage *msg)
391 {
392         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
393         SoupMessageIOData *io = priv->io_data;
394
395  write_more:
396         switch (io->write_state) {
397         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
398                 return;
399
400
401         case SOUP_MESSAGE_IO_STATE_HEADERS:
402                 if (!io->write_buf->len) {
403                         io->get_headers_cb (msg, io->write_buf,
404                                             &io->write_encoding,
405                                             io->user_data);
406                         if (!io->write_buf->len) {
407                                 soup_message_io_pause (msg);
408                                 return;
409                         }
410                 }
411
412                 if (!write_data (msg, io->write_buf->str, io->write_buf->len))
413                         return;
414
415                 g_string_truncate (io->write_buf, 0);
416
417                 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
418                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
419                         if (msg->status_code == SOUP_STATUS_CONTINUE) {
420                                 /* Stop and wait for the body now */
421                                 io->write_state =
422                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
423                                 io->read_state = io_body_state (io->read_encoding);
424                         } else {
425                                 /* We just wrote a 1xx response
426                                  * header, so stay in STATE_HEADERS.
427                                  * (The caller will pause us from the
428                                  * wrote_informational callback if he
429                                  * is not ready to send the final
430                                  * response.)
431                                  */
432                         }
433                 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
434                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
435                         /* Need to wait for the Continue response */
436                         io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
437                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
438                 } else {
439                         io->write_state = io_body_state (io->write_encoding);
440
441                         /* If the client was waiting for a Continue
442                          * but we sent something else, then they're
443                          * now done writing.
444                          */
445                         if (io->mode == SOUP_MESSAGE_IO_SERVER &&
446                             io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
447                                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
448                 }
449
450                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
451                 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
452                         soup_message_wrote_informational (msg);
453                         soup_message_cleanup_response (msg);
454                 } else
455                         soup_message_wrote_headers (msg);
456                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
457                 break;
458
459
460         case SOUP_MESSAGE_IO_STATE_BLOCKING:
461                 io_read (sock, msg);
462
463                 /* If io_read reached a point where we could write
464                  * again, it would have recursively called io_write.
465                  * So (a) we don't need to try to keep writing, and
466                  * (b) we can't anyway, because msg may have been
467                  * destroyed.
468                  */
469                 return;
470
471
472         case SOUP_MESSAGE_IO_STATE_BODY:
473                 if (!io->write_chunk)
474                         io->write_chunk = soup_message_body_flatten (io->write_body);
475                 if (!write_data (msg, io->write_chunk->data,
476                                  io->write_chunk->length))
477                         return;
478                 soup_buffer_free (io->write_chunk);
479                 io->write_chunk = NULL;
480
481                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
482
483                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
484                 soup_message_wrote_body (msg);
485                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
486                 break;
487
488
489         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
490                 if (!io->write_chunk) {
491                         io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
492                         if (!io->write_chunk) {
493                                 soup_message_io_pause (msg);
494                                 return;
495                         }
496                         g_string_append_printf (io->write_buf, "%lx\r\n",
497                                                 (unsigned long) io->write_chunk->length);
498                         io->write_body_offset += io->write_chunk->length;
499                 }
500
501                 if (!write_data (msg, io->write_buf->str, io->write_buf->len))
502                         return;
503
504                 g_string_truncate (io->write_buf, 0);
505
506                 if (io->write_chunk->length == 0) {
507                         /* The last chunk has no CHUNK_END... */
508                         io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
509                         break;
510                 }
511
512                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
513                 /* fall through */
514
515
516         case SOUP_MESSAGE_IO_STATE_CHUNK:
517                 if (!write_data (msg, io->write_chunk->data,
518                                  io->write_chunk->length))
519                         return;
520
521                 soup_buffer_free (io->write_chunk);
522                 io->write_chunk = NULL;
523
524                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
525
526                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
527                 soup_message_wrote_chunk (msg);
528                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
529
530                 /* fall through */
531
532
533         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
534                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
535                                  SOUP_MESSAGE_IO_EOL_LEN))
536                         return;
537
538                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
539                 break;
540
541
542         case SOUP_MESSAGE_IO_STATE_TRAILERS:
543                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
544                                  SOUP_MESSAGE_IO_EOL_LEN))
545                         return;
546
547                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
548
549                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
550                 soup_message_wrote_body (msg);
551                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
552                 /* fall through */
553
554
555         case SOUP_MESSAGE_IO_STATE_FINISHING:
556                 if (io->write_tag) {
557                         g_signal_handler_disconnect (io->sock, io->write_tag);
558                         io->write_tag = 0;
559                 }
560                 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
561
562                 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
563                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
564                         io_read (sock, msg);
565                 } else
566                         soup_message_io_finished (msg);
567                 return;
568
569
570         case SOUP_MESSAGE_IO_STATE_DONE:
571         default:
572                 g_return_if_reached ();
573         }
574
575         goto write_more;
576 }
577
578 static void
579 io_read (SoupSocket *sock, SoupMessage *msg)
580 {
581         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
582         SoupMessageIOData *io = priv->io_data;
583         guint status;
584
585  read_more:
586         switch (io->read_state) {
587         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
588                 return;
589
590
591         case SOUP_MESSAGE_IO_STATE_HEADERS:
592                 if (!read_metadata (msg, SOUP_MESSAGE_IO_DOUBLE_EOL))
593                         return;
594
595                 io->read_meta_buf->len -= SOUP_MESSAGE_IO_EOL_LEN;
596                 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
597                 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
598                                                io->read_meta_buf->len,
599                                                &io->read_encoding,
600                                                io->user_data);
601                 g_byte_array_set_size (io->read_meta_buf, 0);
602
603                 if (status != SOUP_STATUS_OK) {
604                         /* Either we couldn't parse the headers, or they
605                          * indicated something that would mean we wouldn't
606                          * be able to parse the body. (Eg, unknown
607                          * Transfer-Encoding.). Skip the rest of the
608                          * reading, and make sure the connection gets
609                          * closed when we're done.
610                          */
611                         soup_message_set_status (msg, status);
612                         soup_message_headers_append (msg->request_headers,
613                                                      "Connection", "close");
614                         io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
615                         break;
616                 }
617
618                 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
619                         SoupMessageHeaders *hdrs =
620                                 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
621                                 msg->response_headers : msg->request_headers;
622                         io->read_length = soup_message_headers_get_content_length (hdrs);
623                 }
624
625                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
626                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
627                         if (msg->status_code == SOUP_STATUS_CONTINUE &&
628                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
629                                 /* Pause the reader, unpause the writer */
630                                 io->read_state =
631                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
632                                 io->write_state =
633                                         io_body_state (io->write_encoding);
634                         } else {
635                                 /* Just stay in HEADERS */
636                                 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
637                         }
638                 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
639                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
640                         /* The client requested a Continue response. The
641                          * got_headers handler may change this to something
642                          * else though.
643                          */
644                         soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
645                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
646                         io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
647                 } else {
648                         io->read_state = io_body_state (io->read_encoding);
649
650                         /* If the client was waiting for a Continue
651                          * but got something else, then it's done
652                          * writing.
653                          */
654                         if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
655                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
656                                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
657                 }
658
659                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
660                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
661                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
662                         soup_message_got_informational (msg);
663                         soup_message_cleanup_response (msg);
664                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
665                 } else {
666                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
667                         soup_message_got_headers (msg);
668                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
669                 }
670                 break;
671
672
673         case SOUP_MESSAGE_IO_STATE_BLOCKING:
674                 io_write (sock, msg);
675
676                 /* As in the io_write case, we *must* return here. */
677                 return;
678
679
680         case SOUP_MESSAGE_IO_STATE_BODY:
681                 if (!read_body_chunk (msg))
682                         return;
683
684         got_body:
685                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
686
687                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
688                 soup_message_got_body (msg);
689                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
690                 break;
691
692
693         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
694                 if (!read_metadata (msg, SOUP_MESSAGE_IO_EOL))
695                         return;
696
697                 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
698                 g_byte_array_set_size (io->read_meta_buf, 0);
699
700                 if (io->read_length > 0)
701                         io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
702                 else
703                         io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
704                 break;
705
706
707         case SOUP_MESSAGE_IO_STATE_CHUNK:
708                 if (!read_body_chunk (msg))
709                         return;
710
711                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
712                 break;
713
714
715         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
716                 if (!read_metadata (msg, SOUP_MESSAGE_IO_EOL))
717                         return;
718
719                 g_byte_array_set_size (io->read_meta_buf, 0);
720                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
721                 break;
722
723
724         case SOUP_MESSAGE_IO_STATE_TRAILERS:
725                 if (!read_metadata (msg, SOUP_MESSAGE_IO_EOL))
726                         return;
727
728                 if (io->read_meta_buf->len == SOUP_MESSAGE_IO_EOL_LEN)
729                         goto got_body;
730
731                 /* FIXME: process trailers */
732                 g_byte_array_set_size (io->read_meta_buf, 0);
733                 break;
734
735
736         case SOUP_MESSAGE_IO_STATE_FINISHING:
737                 if (io->read_tag) {
738                         g_signal_handler_disconnect (io->sock, io->read_tag);
739                         io->read_tag = 0;
740                 }
741                 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
742
743                 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
744                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
745                         io_write (sock, msg);
746                 } else
747                         soup_message_io_finished (msg);
748                 return;
749
750
751         case SOUP_MESSAGE_IO_STATE_DONE:
752         default:
753                 g_return_if_reached ();
754         }
755
756         goto read_more;
757 }
758
759 static SoupMessageIOData *
760 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
761              SoupMessageGetHeadersFn get_headers_cb,
762              SoupMessageParseHeadersFn parse_headers_cb,
763              gpointer user_data)
764 {
765         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
766         SoupMessageIOData *io;
767
768         io = g_slice_new0 (SoupMessageIOData);
769         io->sock = g_object_ref (sock);
770         io->mode = mode;
771         io->get_headers_cb   = get_headers_cb;
772         io->parse_headers_cb = parse_headers_cb;
773         io->user_data        = user_data;
774
775         io->read_meta_buf    = g_byte_array_new ();
776         io->write_buf        = g_string_new (NULL);
777
778         io->read_tag  = g_signal_connect (io->sock, "readable",
779                                           G_CALLBACK (io_read), msg);
780         io->write_tag = g_signal_connect (io->sock, "writable",
781                                           G_CALLBACK (io_write), msg);
782         io->err_tag   = g_signal_connect (io->sock, "disconnected",
783                                           G_CALLBACK (io_disconnected), msg);
784
785         io->read_state  = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
786         io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
787
788         if (priv->io_data)
789                 soup_message_io_cleanup (msg);
790         priv->io_data = io;
791         return io;
792 }
793
794 void
795 soup_message_io_client (SoupMessage *msg, SoupSocket *sock,
796                         SoupConnection *conn,
797                         SoupMessageGetHeadersFn get_headers_cb,
798                         SoupMessageParseHeadersFn parse_headers_cb,
799                         gpointer user_data)
800 {
801         SoupMessageIOData *io;
802
803         io = new_iostate (msg, sock, SOUP_MESSAGE_IO_CLIENT,
804                           get_headers_cb, parse_headers_cb, user_data);
805
806         if (conn)
807                 io->conn = g_object_ref (conn);
808
809         io->read_body       = msg->response_body;
810         io->write_body      = msg->request_body;
811
812         io->write_state     = SOUP_MESSAGE_IO_STATE_HEADERS;
813         io_write (sock, msg);
814 }
815
816 void
817 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
818                         SoupMessageGetHeadersFn get_headers_cb,
819                         SoupMessageParseHeadersFn parse_headers_cb,
820                         gpointer user_data)
821 {
822         SoupMessageIOData *io;
823
824         io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
825                           get_headers_cb, parse_headers_cb, user_data);
826
827         io->read_body       = msg->request_body;
828         io->write_body      = msg->response_body;
829
830         io->read_state      = SOUP_MESSAGE_IO_STATE_HEADERS;
831         io_read (sock, msg);
832 }
833
834 void  
835 soup_message_io_pause (SoupMessage *msg)
836 {
837         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
838         SoupMessageIOData *io = priv->io_data;
839
840         g_return_if_fail (io != NULL);
841
842         if (io->write_tag) {
843                 g_signal_handler_disconnect (io->sock, io->write_tag);
844                 io->write_tag = 0;
845         }
846         if (io->read_tag) {
847                 g_signal_handler_disconnect (io->sock, io->read_tag);
848                 io->read_tag = 0;
849         }
850 }
851
852 static gboolean
853 io_unpause_internal (gpointer msg)
854 {
855         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
856         SoupMessageIOData *io = priv->io_data;
857
858         g_return_val_if_fail (io != NULL, FALSE);
859
860         if (io->write_tag || io->read_tag)
861                 return FALSE;
862
863         if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
864                 io->write_tag = g_signal_connect (io->sock, "writable",
865                                                   G_CALLBACK (io_write), msg);
866         }
867
868         if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
869                 io->read_tag = g_signal_connect (io->sock, "readable",
870                                                  G_CALLBACK (io_read), msg);
871         }
872
873         if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
874                 io_write (io->sock, msg);
875         else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
876                 io_read (io->sock, msg);
877
878         return FALSE;
879 }
880
881 void
882 soup_message_io_unpause (SoupMessage *msg)
883 {
884         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
885         SoupMessageIOData *io = priv->io_data;
886         gboolean non_blocking;
887         GMainContext *async_context;
888
889         g_return_if_fail (io != NULL);
890
891         g_object_get (io->sock,
892                       SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
893                       SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
894                       NULL);
895         if (non_blocking)
896                 soup_add_idle (async_context, io_unpause_internal, msg);
897         else
898                 io_unpause_internal (msg);
899         if (async_context)
900                 g_main_context_unref (async_context);
901 }
902
903 /**
904  * soup_message_io_in_progress:
905  * @msg: a #SoupMessage
906  *
907  * Tests whether or not I/O is currently in progress on @msg.
908  *
909  * Return value: whether or not I/O is currently in progress.
910  **/
911 gboolean
912 soup_message_io_in_progress (SoupMessage *msg)
913 {
914         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
915
916         return priv->io_data != NULL;
917 }