cf2a2e3b17a01373b447f55dea17c7fa0bc91d96
[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-message-queue.h"
19 #include "soup-misc.h"
20 #include "soup-socket.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         SoupMessageQueueItem *item;
48         SoupMessageIOMode     mode;
49         GCancellable         *cancellable;
50
51         SoupMessageIOState    read_state;
52         SoupEncoding          read_encoding;
53         GByteArray           *read_meta_buf;
54         SoupMessageBody      *read_body;
55         goffset               read_length;
56         gboolean              read_eof_ok;
57
58         gboolean              need_content_sniffed, need_got_chunk;
59         SoupMessageBody      *sniff_data;
60
61         SoupMessageIOState    write_state;
62         SoupEncoding          write_encoding;
63         GString              *write_buf;
64         SoupMessageBody      *write_body;
65         SoupBuffer           *write_chunk;
66         goffset               write_body_offset;
67         goffset               write_length;
68         goffset               written;
69
70         guint read_tag, write_tag;
71         GSource *unpause_source;
72
73         SoupMessageGetHeadersFn   get_headers_cb;
74         SoupMessageParseHeadersFn parse_headers_cb;
75         gpointer                  header_data;
76         SoupMessageCompletionFn   completion_cb;
77         gpointer                  completion_data;
78 } SoupMessageIOData;
79         
80
81 /* Put these around callback invocation if there is code afterward
82  * that depends on the IO having not been cancelled.
83  */
84 #define dummy_to_make_emacs_happy {
85 #define SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK { gboolean cancelled; g_object_ref (msg);
86 #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; }
87 #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; }
88
89 #define RESPONSE_BLOCK_SIZE 8192
90
91 void
92 soup_message_io_cleanup (SoupMessage *msg)
93 {
94         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
95         SoupMessageIOData *io;
96
97         soup_message_io_stop (msg);
98
99         io = priv->io_data;
100         if (!io)
101                 return;
102         priv->io_data = NULL;
103
104         if (io->sock)
105                 g_object_unref (io->sock);
106         if (io->item)
107                 soup_message_queue_item_unref (io->item);
108
109         g_byte_array_free (io->read_meta_buf, TRUE);
110
111         g_string_free (io->write_buf, TRUE);
112         if (io->write_chunk)
113                 soup_buffer_free (io->write_chunk);
114
115         if (io->sniff_data)
116                 soup_message_body_free (io->sniff_data);
117
118         g_slice_free (SoupMessageIOData, io);
119 }
120
121 void
122 soup_message_io_stop (SoupMessage *msg)
123 {
124         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
125         SoupMessageIOData *io = priv->io_data;
126
127         if (!io)
128                 return;
129
130         if (io->read_tag) {
131                 g_signal_handler_disconnect (io->sock, io->read_tag);
132                 io->read_tag = 0;
133         }
134         if (io->write_tag) {
135                 g_signal_handler_disconnect (io->sock, io->write_tag);
136                 io->write_tag = 0;
137         }
138
139         if (io->unpause_source) {
140                 g_source_destroy (io->unpause_source);
141                 io->unpause_source = NULL;
142         }
143
144         if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
145                 soup_socket_disconnect (io->sock);
146 }
147
148 #define SOUP_MESSAGE_IO_EOL            "\r\n"
149 #define SOUP_MESSAGE_IO_EOL_LEN        2
150
151 void
152 soup_message_io_finished (SoupMessage *msg)
153 {
154         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
155         SoupMessageIOData *io = priv->io_data;
156         SoupMessageCompletionFn completion_cb = io->completion_cb;
157         gpointer completion_data = io->completion_data;
158
159         g_object_ref (msg);
160         soup_message_io_cleanup (msg);
161         if (completion_cb)
162                 completion_cb (msg, completion_data);
163         g_object_unref (msg);
164 }
165
166 static void io_read (SoupSocket *sock, SoupMessage *msg);
167
168 static gboolean
169 request_is_idempotent (SoupMessage *msg)
170 {
171         /* FIXME */
172         return (msg->method == SOUP_METHOD_GET);
173 }
174
175 static void
176 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
177 {
178         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
179         SoupMessageIOData *io = priv->io_data;
180
181         if (error && error->domain == G_TLS_ERROR) {
182                 soup_message_set_status_full (msg,
183                                               SOUP_STATUS_SSL_FAILED,
184                                               error->message);
185         } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
186                    io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
187                    io->read_meta_buf->len == 0 &&
188                    soup_connection_get_ever_used (io->item->conn) &&
189                    !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) &&
190                    request_is_idempotent (msg)) {
191                 /* Connection got closed, but we can safely try again */
192                 io->item->state = SOUP_MESSAGE_RESTARTING;
193         } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
194                 soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
195
196         if (error)
197                 g_error_free (error);
198
199         soup_message_io_finished (msg);
200 }
201
202 static gboolean
203 io_handle_sniffing (SoupMessage *msg, gboolean done_reading)
204 {
205         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
206         SoupMessageIOData *io = priv->io_data;
207         SoupBuffer *sniffed_buffer;
208         char *sniffed_mime_type;
209         GHashTable *params = NULL;
210
211         if (!priv->sniffer)
212                 return TRUE;
213
214         if (!io->sniff_data) {
215                 io->sniff_data = soup_message_body_new ();
216                 io->need_content_sniffed = TRUE;
217         }
218
219         if (io->need_content_sniffed) {
220                 if (io->sniff_data->length < priv->bytes_for_sniffing &&
221                     !done_reading)
222                         return TRUE;
223
224                 io->need_content_sniffed = FALSE;
225                 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
226                 sniffed_mime_type = soup_content_sniffer_sniff (priv->sniffer, msg, sniffed_buffer, &params);
227
228                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
229                 soup_message_content_sniffed (msg, sniffed_mime_type, params);
230                 g_free (sniffed_mime_type);
231                 if (params)
232                         g_hash_table_destroy (params);
233                 if (sniffed_buffer)
234                         soup_buffer_free (sniffed_buffer);
235                 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
236         }
237
238         if (io->need_got_chunk) {
239                 io->need_got_chunk = FALSE;
240                 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
241
242                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
243                 soup_message_got_chunk (msg, sniffed_buffer);
244                 soup_buffer_free (sniffed_buffer);
245                 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
246         }
247
248         return TRUE;
249 }
250
251 /* Reads data from io->sock into io->read_meta_buf. If @to_blank is
252  * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF").
253  * Otherwise, it reads up until a single CRLF or LF.
254  *
255  * This function is used to read metadata, and read_body_chunk() is
256  * used to read the message body contents.
257  *
258  * read_metadata, read_body_chunk, and write_data all use the same
259  * convention for return values: if they return %TRUE, it means
260  * they've completely finished the requested read/write, and the
261  * caller should move on to the next step. If they return %FALSE, it
262  * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
263  * so the caller should give up for now and wait for the socket to
264  * emit a signal, or (b) the socket returned an error, and io_error()
265  * was called to process it and cancel the I/O. So either way, if the
266  * function returns %FALSE, the caller should return immediately.
267  */
268 static gboolean
269 read_metadata (SoupMessage *msg, gboolean to_blank)
270 {
271         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
272         SoupMessageIOData *io = priv->io_data;
273         SoupSocketIOStatus status;
274         guchar read_buf[RESPONSE_BLOCK_SIZE];
275         gsize nread;
276         gboolean got_lf;
277         GError *error = NULL;
278
279         while (1) {
280                 status = soup_socket_read_until (io->sock, read_buf,
281                                                  sizeof (read_buf),
282                                                  "\n", 1, &nread, &got_lf,
283                                                  io->cancellable, &error);
284                 switch (status) {
285                 case SOUP_SOCKET_OK:
286                         g_byte_array_append (io->read_meta_buf, read_buf, nread);
287                         break;
288
289                 case SOUP_SOCKET_EOF:
290                         /* More lame server handling... deal with
291                          * servers that don't send the final chunk.
292                          */
293                         if (io->read_state == SOUP_MESSAGE_IO_STATE_CHUNK_SIZE &&
294                             io->read_meta_buf->len == 0) {
295                                 g_byte_array_append (io->read_meta_buf,
296                                                      (guchar *)"0\r\n", 3);
297                                 got_lf = TRUE;
298                                 break;
299                         } else if (io->read_state == SOUP_MESSAGE_IO_STATE_TRAILERS &&
300                                    io->read_meta_buf->len == 0) {
301                                 g_byte_array_append (io->read_meta_buf,
302                                                      (guchar *)"\r\n", 2);
303                                 got_lf = TRUE;
304                                 break;
305                         }
306                         /* else fall through */
307
308                 case SOUP_SOCKET_ERROR:
309                         io_error (io->sock, msg, error);
310                         return FALSE;
311
312                 case SOUP_SOCKET_WOULD_BLOCK:
313                         return FALSE;
314                 }
315
316                 if (got_lf) {
317                         if (!to_blank)
318                                 break;
319                         if (nread == 1 && io->read_meta_buf->len >= 2 &&
320                             !strncmp ((char *)io->read_meta_buf->data +
321                                       io->read_meta_buf->len - 2,
322                                       "\n\n", 2))
323                                 break;
324                         else if (nread == 2 && io->read_meta_buf->len >= 3 &&
325                                  !strncmp ((char *)io->read_meta_buf->data +
326                                            io->read_meta_buf->len - 3,
327                                            "\n\r\n", 3))
328                                 break;
329                 }
330         }
331
332         return TRUE;
333 }
334
335 static SoupBuffer *
336 content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
337 {
338         gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
339         char *outbuf;
340         GConverterResult result;
341         gboolean dummy_zlib_header_used = FALSE;
342
343         outbuf_length = MAX (buf->length * 2, 1024);
344         outbuf = g_malloc (outbuf_length);
345         outbuf_cur = input_cur = 0;
346
347         do {
348                 result = g_converter_convert (
349                         converter,
350                         buf->data + input_cur, buf->length - input_cur,
351                         outbuf + outbuf_cur, outbuf_length - outbuf_cur,
352                         0, &input_used, &outbuf_used, error);
353                 input_cur += input_used;
354                 outbuf_cur += outbuf_used;
355
356                 if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NO_SPACE) ||
357                     (!*error && outbuf_cur == outbuf_length)) {
358                         g_clear_error (error);
359                         outbuf_length *= 2;
360                         outbuf = g_realloc (outbuf, outbuf_length);
361                 } else if (input_cur == 0 &&
362                            !dummy_zlib_header_used &&
363                            G_IS_ZLIB_DECOMPRESSOR (converter) &&
364                            g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA)) {
365
366                         GZlibCompressorFormat format;
367                         g_object_get (G_OBJECT (converter), "format", &format, NULL);
368
369                         if (format == G_ZLIB_COMPRESSOR_FORMAT_ZLIB) {
370                                 /* Some servers (especially Apache with mod_deflate)
371                                  * return RAW compressed data without the zlib headers
372                                  * when the client claims to support deflate. For
373                                  * those cases use a dummy header (stolen from
374                                  * Mozilla's nsHTTPCompressConv.cpp) and try to
375                                  * continue uncompressing data.
376                                  */
377                                 static char dummy_zlib_header[2] = { 0x78, 0x9C };
378
379                                 g_converter_reset (converter);
380                                 result = g_converter_convert (converter,
381                                                               dummy_zlib_header, sizeof(dummy_zlib_header),
382                                                               outbuf + outbuf_cur, outbuf_length - outbuf_cur,
383                                                               0, &input_used, &outbuf_used, NULL);
384                                 dummy_zlib_header_used = TRUE;
385                                 if (result == G_CONVERTER_CONVERTED) {
386                                         g_clear_error (error);
387                                         continue;
388                                 }
389                         }
390
391                         g_free (outbuf);
392                         return NULL;
393
394                 } else if (*error) {
395                         /* GZlibDecompressor can't ever return
396                          * G_IO_ERROR_PARTIAL_INPUT unless we pass it
397                          * input_length = 0, which we don't. Other
398                          * converters might of course, so eventually
399                          * this code needs to be rewritten to deal
400                          * with that.
401                          */
402                         g_free (outbuf);
403                         return NULL;
404                 }
405         } while (input_cur < buf->length && result != G_CONVERTER_FINISHED);
406
407         if (outbuf_cur)
408                 return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
409         else {
410                 g_free (outbuf);
411                 return NULL;
412         }
413 }
414
415 static SoupBuffer *
416 content_decode (SoupMessage *msg, SoupBuffer *buf)
417 {
418         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
419         GConverter *decoder;
420         SoupBuffer *decoded;
421         GError *error = NULL;
422         GSList *d;
423
424         for (d = priv->decoders; d; d = d->next) {
425                 decoder = d->data;
426
427                 decoded = content_decode_one (buf, decoder, &error);
428                 if (error) {
429                         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED))
430                                 g_warning ("Content-Decoding error: %s\n", error->message);
431                         g_error_free (error);
432
433                         soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED);
434                         break;
435                 }
436                 if (buf)
437                         soup_buffer_free (buf);
438
439                 if (decoded)
440                         buf = decoded;
441                 else
442                         return NULL;
443         }
444
445         return buf;
446 }
447
448 /* Reads as much message body data as is available on io->sock (but no
449  * further than the end of the current message body or chunk). On a
450  * successful read, emits "got_chunk" (possibly multiple times), and
451  * (unless told not to) appends the chunk to io->read_body.
452  *
453  * See the note at read_metadata() for an explanation of the return
454  * value.
455  */
456 static gboolean
457 read_body_chunk (SoupMessage *msg)
458 {
459         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
460         SoupMessageIOData *io = priv->io_data;
461         SoupSocketIOStatus status;
462         guchar *stack_buf = NULL;
463         gsize len;
464         gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
465         gsize nread;
466         GError *error = NULL;
467         SoupBuffer *buffer;
468
469         if (!io_handle_sniffing (msg, FALSE))
470                 return FALSE;
471
472         while (read_to_eof || io->read_length > 0) {
473                 if (priv->chunk_allocator) {
474                         buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
475                         if (!buffer) {
476                                 soup_message_io_pause (msg);
477                                 return FALSE;
478                         }
479                 } else {
480                         if (!stack_buf)
481                                 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
482                         buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
483                                                   stack_buf,
484                                                   RESPONSE_BLOCK_SIZE);
485                 }
486
487                 if (read_to_eof)
488                         len = buffer->length;
489                 else
490                         len = MIN (buffer->length, io->read_length);
491
492                 status = soup_socket_read (io->sock,
493                                            (guchar *)buffer->data, len,
494                                            &nread, io->cancellable, &error);
495
496                 if (status == SOUP_SOCKET_OK && nread) {
497                         buffer->length = nread;
498                         io->read_length -= nread;
499
500                         buffer = content_decode (msg, buffer);
501                         if (!buffer)
502                                 continue;
503
504                         soup_message_body_got_chunk (io->read_body, buffer);
505
506                         if (io->need_content_sniffed) {
507                                 soup_message_body_append_buffer (io->sniff_data, buffer);
508                                 soup_buffer_free (buffer);
509                                 io->need_got_chunk = TRUE;
510                                 if (!io_handle_sniffing (msg, FALSE))
511                                         return FALSE;
512                                 continue;
513                         }
514
515                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
516                         soup_message_got_chunk (msg, buffer);
517                         soup_buffer_free (buffer);
518                         SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
519                         continue;
520                 }
521
522                 soup_buffer_free (buffer);
523                 switch (status) {
524                 case SOUP_SOCKET_OK:
525                         break;
526
527                 case SOUP_SOCKET_EOF:
528                         if (io->read_eof_ok) {
529                                 io->read_length = 0;
530                                 return TRUE;
531                         }
532                         /* else fall through */
533
534                 case SOUP_SOCKET_ERROR:
535                         io_error (io->sock, msg, error);
536                         return FALSE;
537
538                 case SOUP_SOCKET_WOULD_BLOCK:
539                         return FALSE;
540                 }
541         }
542
543         return TRUE;
544 }
545
546 /* Attempts to write @len bytes from @data. See the note at
547  * read_metadata() for an explanation of the return value.
548  */
549 static gboolean
550 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
551 {
552         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
553         SoupMessageIOData *io = priv->io_data;
554         SoupSocketIOStatus status;
555         gsize nwrote;
556         GError *error = NULL;
557         SoupBuffer *chunk;
558         const char *start;
559
560         while (len > io->written) {
561                 status = soup_socket_write (io->sock,
562                                             data + io->written,
563                                             len - io->written,
564                                             &nwrote,
565                                             io->cancellable, &error);
566                 switch (status) {
567                 case SOUP_SOCKET_EOF:
568                 case SOUP_SOCKET_ERROR:
569                         io_error (io->sock, msg, error);
570                         return FALSE;
571
572                 case SOUP_SOCKET_WOULD_BLOCK:
573                         return FALSE;
574
575                 case SOUP_SOCKET_OK:
576                         start = data + io->written;
577                         io->written += nwrote;
578
579                         if (body) {
580                                 if (io->write_length)
581                                         io->write_length -= nwrote;
582
583                                 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
584                                                          start, nwrote);
585                                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
586                                 soup_message_wrote_body_data (msg, chunk);
587                                 soup_buffer_free (chunk);
588                                 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
589                         }
590                         break;
591                 }
592         }
593
594         io->written = 0;
595         return TRUE;
596 }
597
598 static inline SoupMessageIOState
599 io_body_state (SoupEncoding encoding)
600 {
601         if (encoding == SOUP_ENCODING_CHUNKED)
602                 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
603         else
604                 return SOUP_MESSAGE_IO_STATE_BODY;
605 }
606
607 /*
608  * There are two request/response formats: the basic request/response,
609  * possibly with one or more unsolicited informational responses (such
610  * as the WebDAV "102 Processing" response):
611  *
612  *     Client                            Server
613  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
614  *      W:BODY     / R:NOT_STARTED    ->  R:BODY     / W:NOT_STARTED
615  *     [W:DONE     / R:HEADERS (1xx)  <-  R:DONE     / W:HEADERS (1xx) ...]
616  *      W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS
617  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
618  *      W:DONE     / R:DONE               R:DONE     / W:DONE
619  *     
620  * and the "Expect: 100-continue" request/response, with the client
621  * blocking halfway through its request, and then either continuing or
622  * aborting, depending on the server response:
623  *
624  *     Client                            Server
625  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
626  *      W:BLOCKING / R:HEADERS        <-  R:BLOCKING / W:HEADERS
627  *     [W:BODY     / R:BLOCKING       ->  R:BODY     / W:BLOCKING]
628  *     [W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS]
629  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
630  *      W:DONE     / R:DONE               R:DONE     / W:DONE
631  */
632
633 static void
634 io_write (SoupSocket *sock, SoupMessage *msg)
635 {
636         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
637         SoupMessageIOData *io = priv->io_data;
638
639  write_more:
640         switch (io->write_state) {
641         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
642                 return;
643
644
645         case SOUP_MESSAGE_IO_STATE_HEADERS:
646                 if (!io->write_buf->len) {
647                         io->get_headers_cb (msg, io->write_buf,
648                                             &io->write_encoding,
649                                             io->header_data);
650                         if (!io->write_buf->len) {
651                                 soup_message_io_pause (msg);
652                                 return;
653                         }
654                 }
655
656                 if (!write_data (msg, io->write_buf->str,
657                                  io->write_buf->len, FALSE))
658                         return;
659
660                 g_string_truncate (io->write_buf, 0);
661
662                 if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
663                         SoupMessageHeaders *hdrs =
664                                 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
665                                 msg->request_headers : msg->response_headers;
666                         io->write_length = soup_message_headers_get_content_length (hdrs);
667                 }
668
669                 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
670                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
671                         if (msg->status_code == SOUP_STATUS_CONTINUE) {
672                                 /* Stop and wait for the body now */
673                                 io->write_state =
674                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
675                                 io->read_state = io_body_state (io->read_encoding);
676                         } else {
677                                 /* We just wrote a 1xx response
678                                  * header, so stay in STATE_HEADERS.
679                                  * (The caller will pause us from the
680                                  * wrote_informational callback if he
681                                  * is not ready to send the final
682                                  * response.)
683                                  */
684                         }
685                 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
686                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
687                         /* Need to wait for the Continue response */
688                         io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
689                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
690                 } else {
691                         io->write_state = io_body_state (io->write_encoding);
692
693                         /* If the client was waiting for a Continue
694                          * but we sent something else, then they're
695                          * now done writing.
696                          */
697                         if (io->mode == SOUP_MESSAGE_IO_SERVER &&
698                             io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
699                                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
700                 }
701
702                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
703                 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
704                         soup_message_wrote_informational (msg);
705                         soup_message_cleanup_response (msg);
706                 } else
707                         soup_message_wrote_headers (msg);
708                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
709                 break;
710
711
712         case SOUP_MESSAGE_IO_STATE_BLOCKING:
713                 io_read (sock, msg);
714
715                 /* If io_read reached a point where we could write
716                  * again, it would have recursively called io_write.
717                  * So (a) we don't need to try to keep writing, and
718                  * (b) we can't anyway, because msg may have been
719                  * destroyed.
720                  */
721                 return;
722
723
724         case SOUP_MESSAGE_IO_STATE_BODY:
725                 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
726                 wrote_body:
727                         io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
728
729                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
730                         soup_message_wrote_body (msg);
731                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
732                         break;
733                 }
734
735                 if (!io->write_chunk) {
736                         io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
737                         if (!io->write_chunk) {
738                                 soup_message_io_pause (msg);
739                                 return;
740                         }
741                         if (io->write_chunk->length > io->write_length &&
742                             io->write_encoding != SOUP_ENCODING_EOF) {
743                                 /* App is trying to write more than it
744                                  * claimed it would; we have to truncate.
745                                  */
746                                 SoupBuffer *truncated =
747                                         soup_buffer_new_subbuffer (io->write_chunk,
748                                                                    0, io->write_length);
749                                 soup_buffer_free (io->write_chunk);
750                                 io->write_chunk = truncated;
751                         } else if (io->write_encoding == SOUP_ENCODING_EOF &&
752                                    !io->write_chunk->length)
753                                 goto wrote_body;
754                 }
755
756                 if (!write_data (msg, io->write_chunk->data,
757                                  io->write_chunk->length, TRUE))
758                         return;
759
760                 if (io->mode == SOUP_MESSAGE_IO_SERVER ||
761                     priv->msg_flags & SOUP_MESSAGE_CAN_REBUILD)
762                         soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
763                 io->write_body_offset += io->write_chunk->length;
764                 soup_buffer_free (io->write_chunk);
765                 io->write_chunk = NULL;
766
767                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
768                 soup_message_wrote_chunk (msg);
769                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
770                 break;
771
772         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
773                 if (!io->write_chunk) {
774                         io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
775                         if (!io->write_chunk) {
776                                 soup_message_io_pause (msg);
777                                 return;
778                         }
779                         g_string_append_printf (io->write_buf, "%lx\r\n",
780                                                 (unsigned long) io->write_chunk->length);
781                         io->write_body_offset += io->write_chunk->length;
782                 }
783
784                 if (!write_data (msg, io->write_buf->str,
785                                  io->write_buf->len, FALSE))
786                         return;
787
788                 g_string_truncate (io->write_buf, 0);
789
790                 if (io->write_chunk->length == 0) {
791                         /* The last chunk has no CHUNK_END... */
792                         io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
793                         break;
794                 }
795
796                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
797                 /* fall through */
798
799
800         case SOUP_MESSAGE_IO_STATE_CHUNK:
801                 if (!write_data (msg, io->write_chunk->data,
802                                  io->write_chunk->length, TRUE))
803                         return;
804
805                 if (io->mode == SOUP_MESSAGE_IO_SERVER ||
806                     priv->msg_flags & SOUP_MESSAGE_CAN_REBUILD)
807                         soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
808                 soup_buffer_free (io->write_chunk);
809                 io->write_chunk = NULL;
810
811                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
812
813                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
814                 soup_message_wrote_chunk (msg);
815                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
816
817                 /* fall through */
818
819
820         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
821                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
822                                  SOUP_MESSAGE_IO_EOL_LEN, FALSE))
823                         return;
824
825                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
826                 break;
827
828
829         case SOUP_MESSAGE_IO_STATE_TRAILERS:
830                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
831                                  SOUP_MESSAGE_IO_EOL_LEN, FALSE))
832                         return;
833
834                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
835
836                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
837                 soup_message_wrote_body (msg);
838                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
839                 /* fall through */
840
841
842         case SOUP_MESSAGE_IO_STATE_FINISHING:
843                 if (io->write_tag) {
844                         g_signal_handler_disconnect (io->sock, io->write_tag);
845                         io->write_tag = 0;
846                 }
847                 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
848
849                 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
850                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
851                         io_read (sock, msg);
852                 } else
853                         soup_message_io_finished (msg);
854                 return;
855
856
857         case SOUP_MESSAGE_IO_STATE_DONE:
858         default:
859                 g_return_if_reached ();
860         }
861
862         goto write_more;
863 }
864
865 static void
866 io_read (SoupSocket *sock, SoupMessage *msg)
867 {
868         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
869         SoupMessageIOData *io = priv->io_data;
870         guint status;
871
872  read_more:
873         switch (io->read_state) {
874         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
875                 return;
876
877
878         case SOUP_MESSAGE_IO_STATE_HEADERS:
879                 if (!read_metadata (msg, TRUE))
880                         return;
881
882                 /* We need to "rewind" io->read_meta_buf back one line.
883                  * That SHOULD be two characters (CR LF), but if the
884                  * web server was stupid, it might only be one.
885                  */
886                 if (io->read_meta_buf->len < 3 ||
887                     io->read_meta_buf->data[io->read_meta_buf->len - 2] == '\n')
888                         io->read_meta_buf->len--;
889                 else
890                         io->read_meta_buf->len -= 2;
891                 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
892                 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
893                                                io->read_meta_buf->len,
894                                                &io->read_encoding,
895                                                io->header_data);
896                 g_byte_array_set_size (io->read_meta_buf, 0);
897
898                 if (status != SOUP_STATUS_OK) {
899                         /* Either we couldn't parse the headers, or they
900                          * indicated something that would mean we wouldn't
901                          * be able to parse the body. (Eg, unknown
902                          * Transfer-Encoding.). Skip the rest of the
903                          * reading, and make sure the connection gets
904                          * closed when we're done.
905                          */
906                         soup_message_set_status (msg, status);
907                         soup_message_headers_append (msg->request_headers,
908                                                      "Connection", "close");
909                         io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
910                         break;
911                 }
912
913                 if (io->read_encoding == SOUP_ENCODING_EOF)
914                         io->read_eof_ok = TRUE;
915
916                 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
917                         SoupMessageHeaders *hdrs =
918                                 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
919                                 msg->response_headers : msg->request_headers;
920                         io->read_length = soup_message_headers_get_content_length (hdrs);
921
922                         if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
923                             !soup_message_is_keepalive (msg)) {
924                                 /* Some servers suck and send
925                                  * incorrect Content-Length values, so
926                                  * allow EOF termination in this case
927                                  * (iff the message is too short) too.
928                                  */
929                                 io->read_eof_ok = TRUE;
930                         }
931                 }
932
933                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
934                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
935                         if (msg->status_code == SOUP_STATUS_CONTINUE &&
936                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
937                                 /* Pause the reader, unpause the writer */
938                                 io->read_state =
939                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
940                                 io->write_state =
941                                         io_body_state (io->write_encoding);
942                         } else {
943                                 /* Just stay in HEADERS */
944                                 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
945                         }
946                 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
947                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
948                         /* The client requested a Continue response. The
949                          * got_headers handler may change this to something
950                          * else though.
951                          */
952                         soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
953                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
954                         io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
955                 } else {
956                         io->read_state = io_body_state (io->read_encoding);
957
958                         /* If the client was waiting for a Continue
959                          * but got something else, then it's done
960                          * writing.
961                          */
962                         if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
963                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
964                                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
965                 }
966
967                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
968                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
969                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
970                         soup_message_got_informational (msg);
971                         soup_message_cleanup_response (msg);
972                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
973                 } else {
974                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
975                         soup_message_got_headers (msg);
976                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
977                 }
978                 break;
979
980
981         case SOUP_MESSAGE_IO_STATE_BLOCKING:
982                 io_write (sock, msg);
983
984                 /* As in the io_write case, we *must* return here. */
985                 return;
986
987
988         case SOUP_MESSAGE_IO_STATE_BODY:
989                 if (!read_body_chunk (msg))
990                         return;
991
992         got_body:
993                 if (!io_handle_sniffing (msg, TRUE)) {
994                         /* If the message was paused (as opposed to
995                          * cancelled), we need to make sure we wind up
996                          * back here when it's unpaused, even if it
997                          * was doing a chunked or EOF-terminated read
998                          * before.
999                          */
1000                         if (io == priv->io_data) {
1001                                 io->read_state = SOUP_MESSAGE_IO_STATE_BODY;
1002                                 io->read_encoding = SOUP_ENCODING_CONTENT_LENGTH;
1003                                 io->read_length = 0;
1004                         }
1005                         return;
1006                 }
1007
1008                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
1009
1010                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
1011                 soup_message_got_body (msg);
1012                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
1013                 break;
1014
1015
1016         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
1017                 if (!read_metadata (msg, FALSE))
1018                         return;
1019
1020                 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
1021                 g_byte_array_set_size (io->read_meta_buf, 0);
1022
1023                 if (io->read_length > 0)
1024                         io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
1025                 else
1026                         io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
1027                 break;
1028
1029
1030         case SOUP_MESSAGE_IO_STATE_CHUNK:
1031                 if (!read_body_chunk (msg))
1032                         return;
1033
1034                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
1035                 break;
1036
1037
1038         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
1039                 if (!read_metadata (msg, FALSE))
1040                         return;
1041
1042                 g_byte_array_set_size (io->read_meta_buf, 0);
1043                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
1044                 break;
1045
1046
1047         case SOUP_MESSAGE_IO_STATE_TRAILERS:
1048                 if (!read_metadata (msg, FALSE))
1049                         return;
1050
1051                 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
1052                         goto got_body;
1053
1054                 /* FIXME: process trailers */
1055                 g_byte_array_set_size (io->read_meta_buf, 0);
1056                 break;
1057
1058
1059         case SOUP_MESSAGE_IO_STATE_FINISHING:
1060                 if (io->read_tag) {
1061                         g_signal_handler_disconnect (io->sock, io->read_tag);
1062                         io->read_tag = 0;
1063                 }
1064                 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
1065
1066                 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
1067                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1068                         io_write (sock, msg);
1069                 } else
1070                         soup_message_io_finished (msg);
1071                 return;
1072
1073
1074         case SOUP_MESSAGE_IO_STATE_DONE:
1075         default:
1076                 g_return_if_reached ();
1077         }
1078
1079         goto read_more;
1080 }
1081
1082 static SoupMessageIOData *
1083 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
1084              SoupMessageGetHeadersFn get_headers_cb,
1085              SoupMessageParseHeadersFn parse_headers_cb,
1086              gpointer header_data,
1087              SoupMessageCompletionFn completion_cb,
1088              gpointer completion_data)
1089 {
1090         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1091         SoupMessageIOData *io;
1092
1093         io = g_slice_new0 (SoupMessageIOData);
1094         io->sock = g_object_ref (sock);
1095         io->mode = mode;
1096         io->get_headers_cb   = get_headers_cb;
1097         io->parse_headers_cb = parse_headers_cb;
1098         io->header_data      = header_data;
1099         io->completion_cb    = completion_cb;
1100         io->completion_data  = completion_data;
1101
1102         io->read_meta_buf    = g_byte_array_new ();
1103         io->write_buf        = g_string_new (NULL);
1104
1105         io->read_tag  = g_signal_connect (io->sock, "readable",
1106                                           G_CALLBACK (io_read), msg);
1107         io->write_tag = g_signal_connect (io->sock, "writable",
1108                                           G_CALLBACK (io_write), msg);
1109
1110         io->read_state  = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1111         io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1112
1113         if (priv->io_data)
1114                 soup_message_io_cleanup (msg);
1115         priv->io_data = io;
1116         return io;
1117 }
1118
1119 void
1120 soup_message_io_client (SoupMessageQueueItem *item,
1121                         SoupMessageGetHeadersFn get_headers_cb,
1122                         SoupMessageParseHeadersFn parse_headers_cb,
1123                         gpointer header_data,
1124                         SoupMessageCompletionFn completion_cb,
1125                         gpointer completion_data)
1126 {
1127         SoupMessageIOData *io;
1128         SoupSocket *sock = soup_connection_get_socket (item->conn);
1129
1130         io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
1131                           get_headers_cb, parse_headers_cb, header_data,
1132                           completion_cb, completion_data);
1133
1134         io->item = item;
1135         soup_message_queue_item_ref (item);
1136         io->cancellable = item->cancellable;
1137
1138         io->read_body       = item->msg->response_body;
1139         io->write_body      = item->msg->request_body;
1140
1141         io->write_state     = SOUP_MESSAGE_IO_STATE_HEADERS;
1142         io_write (sock, item->msg);
1143 }
1144
1145 void
1146 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
1147                         SoupMessageGetHeadersFn get_headers_cb,
1148                         SoupMessageParseHeadersFn parse_headers_cb,
1149                         gpointer header_data,
1150                         SoupMessageCompletionFn completion_cb,
1151                         gpointer completion_data)
1152 {
1153         SoupMessageIOData *io;
1154
1155         io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
1156                           get_headers_cb, parse_headers_cb, header_data,
1157                           completion_cb, completion_data);
1158
1159         io->read_body       = msg->request_body;
1160         io->write_body      = msg->response_body;
1161
1162         io->read_state      = SOUP_MESSAGE_IO_STATE_HEADERS;
1163         io_read (sock, msg);
1164 }
1165
1166 void  
1167 soup_message_io_pause (SoupMessage *msg)
1168 {
1169         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1170         SoupMessageIOData *io = priv->io_data;
1171
1172         g_return_if_fail (io != NULL);
1173
1174         if (io->write_tag) {
1175                 g_signal_handler_disconnect (io->sock, io->write_tag);
1176                 io->write_tag = 0;
1177         }
1178         if (io->read_tag) {
1179                 g_signal_handler_disconnect (io->sock, io->read_tag);
1180                 io->read_tag = 0;
1181         }
1182
1183         if (io->unpause_source) {
1184                 g_source_destroy (io->unpause_source);
1185                 io->unpause_source = NULL;
1186         }
1187 }
1188
1189 static gboolean
1190 io_unpause_internal (gpointer msg)
1191 {
1192         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1193         SoupMessageIOData *io = priv->io_data;
1194
1195         g_return_val_if_fail (io != NULL, FALSE);
1196         io->unpause_source = NULL;
1197
1198         if (io->write_tag || io->read_tag)
1199                 return FALSE;
1200
1201         if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
1202                 io->write_tag = g_signal_connect (io->sock, "writable",
1203                                                   G_CALLBACK (io_write), msg);
1204         }
1205
1206         if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
1207                 io->read_tag = g_signal_connect (io->sock, "readable",
1208                                                  G_CALLBACK (io_read), msg);
1209         }
1210
1211         if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
1212                 io_write (io->sock, msg);
1213         else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
1214                 io_read (io->sock, msg);
1215
1216         return FALSE;
1217 }
1218
1219 void
1220 soup_message_io_unpause (SoupMessage *msg)
1221 {
1222         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1223         SoupMessageIOData *io = priv->io_data;
1224         gboolean non_blocking, use_thread_context;
1225         GMainContext *async_context;
1226
1227         g_return_if_fail (io != NULL);
1228
1229         g_object_get (io->sock,
1230                       SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
1231                       SOUP_SOCKET_USE_THREAD_CONTEXT, &use_thread_context,
1232                       NULL);
1233         if (use_thread_context)
1234                 async_context = g_main_context_ref_thread_default ();
1235         else {
1236                 g_object_get (io->sock,
1237                               SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1238                               NULL);
1239         }
1240
1241         if (non_blocking) {
1242                 if (!io->unpause_source) {
1243                         io->unpause_source = soup_add_completion (
1244                                 async_context, io_unpause_internal, msg);
1245                 }
1246         } else
1247                 io_unpause_internal (msg);
1248         if (async_context)
1249                 g_main_context_unref (async_context);
1250 }
1251
1252 /**
1253  * soup_message_io_in_progress:
1254  * @msg: a #SoupMessage
1255  *
1256  * Tests whether or not I/O is currently in progress on @msg.
1257  *
1258  * Return value: whether or not I/O is currently in progress.
1259  **/
1260 gboolean
1261 soup_message_io_in_progress (SoupMessage *msg)
1262 {
1263         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1264
1265         return priv->io_data != NULL;
1266 }