1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-message-io.c: HTTP message I/O
5 * Copyright (C) 2000-2003, Ximian, Inc.
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"
23 SOUP_MESSAGE_IO_CLIENT,
24 SOUP_MESSAGE_IO_SERVER
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
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)
47 SoupMessageQueueItem *item;
48 SoupMessageIOMode mode;
49 GCancellable *cancellable;
51 SoupMessageIOState read_state;
52 SoupEncoding read_encoding;
53 GByteArray *read_meta_buf;
54 SoupMessageBody *read_body;
58 gboolean need_content_sniffed, need_got_chunk;
59 SoupMessageBody *sniff_data;
61 SoupMessageIOState write_state;
62 SoupEncoding write_encoding;
64 SoupMessageBody *write_body;
65 SoupBuffer *write_chunk;
66 goffset write_body_offset;
70 guint read_tag, write_tag;
71 GSource *unpause_source;
73 SoupMessageGetHeadersFn get_headers_cb;
74 SoupMessageParseHeadersFn parse_headers_cb;
76 SoupMessageCompletionFn completion_cb;
77 gpointer completion_data;
81 /* Put these around callback invocation if there is code afterward
82 * that depends on the IO having not been cancelled.
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; }
89 #define RESPONSE_BLOCK_SIZE 8192
92 soup_message_io_cleanup (SoupMessage *msg)
94 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
95 SoupMessageIOData *io;
97 soup_message_io_stop (msg);
102 priv->io_data = NULL;
105 g_object_unref (io->sock);
107 soup_message_queue_item_unref (io->item);
109 g_byte_array_free (io->read_meta_buf, TRUE);
111 g_string_free (io->write_buf, TRUE);
113 soup_buffer_free (io->write_chunk);
116 soup_message_body_free (io->sniff_data);
118 g_slice_free (SoupMessageIOData, io);
122 soup_message_io_stop (SoupMessage *msg)
124 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
125 SoupMessageIOData *io = priv->io_data;
131 g_signal_handler_disconnect (io->sock, io->read_tag);
135 g_signal_handler_disconnect (io->sock, io->write_tag);
139 if (io->unpause_source) {
140 g_source_destroy (io->unpause_source);
141 io->unpause_source = NULL;
144 if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
145 soup_socket_disconnect (io->sock);
148 #define SOUP_MESSAGE_IO_EOL "\r\n"
149 #define SOUP_MESSAGE_IO_EOL_LEN 2
152 soup_message_io_finished (SoupMessage *msg)
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;
160 soup_message_io_cleanup (msg);
162 completion_cb (msg, completion_data);
163 g_object_unref (msg);
166 static void io_read (SoupSocket *sock, SoupMessage *msg);
169 request_is_idempotent (SoupMessage *msg)
172 return (msg->method == SOUP_METHOD_GET);
176 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
178 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
179 SoupMessageIOData *io = priv->io_data;
181 if (error && error->domain == G_TLS_ERROR) {
182 soup_message_set_status_full (msg,
183 SOUP_STATUS_SSL_FAILED,
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);
197 g_error_free (error);
199 soup_message_io_finished (msg);
203 io_handle_sniffing (SoupMessage *msg, gboolean done_reading)
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;
214 if (!io->sniff_data) {
215 io->sniff_data = soup_message_body_new ();
216 io->need_content_sniffed = TRUE;
219 if (io->need_content_sniffed) {
220 if (io->sniff_data->length < priv->bytes_for_sniffing &&
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, ¶ms);
228 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
229 soup_message_content_sniffed (msg, sniffed_mime_type, params);
230 g_free (sniffed_mime_type);
232 g_hash_table_destroy (params);
234 soup_buffer_free (sniffed_buffer);
235 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
238 if (io->need_got_chunk) {
239 io->need_got_chunk = FALSE;
240 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
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);
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.
255 * This function is used to read metadata, and read_body_chunk() is
256 * used to read the message body contents.
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.
269 read_metadata (SoupMessage *msg, gboolean to_blank)
271 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
272 SoupMessageIOData *io = priv->io_data;
273 SoupSocketIOStatus status;
274 guchar read_buf[RESPONSE_BLOCK_SIZE];
277 GError *error = NULL;
280 status = soup_socket_read_until (io->sock, read_buf,
282 "\n", 1, &nread, &got_lf,
283 io->cancellable, &error);
286 g_byte_array_append (io->read_meta_buf, read_buf, nread);
289 case SOUP_SOCKET_EOF:
290 /* More lame server handling... deal with
291 * servers that don't send the final chunk.
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);
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);
306 /* else fall through */
308 case SOUP_SOCKET_ERROR:
309 io_error (io->sock, msg, error);
312 case SOUP_SOCKET_WOULD_BLOCK:
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,
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,
336 content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
338 gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
340 GConverterResult result;
341 gboolean dummy_zlib_header_used = FALSE;
343 outbuf_length = MAX (buf->length * 2, 1024);
344 outbuf = g_malloc (outbuf_length);
345 outbuf_cur = input_cur = 0;
348 result = g_converter_convert (
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;
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);
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)) {
366 GZlibCompressorFormat format;
367 g_object_get (G_OBJECT (converter), "format", &format, NULL);
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.
377 static char dummy_zlib_header[2] = { 0x78, 0x9C };
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);
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
405 } while (input_cur < buf->length && result != G_CONVERTER_FINISHED);
408 return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
416 content_decode (SoupMessage *msg, SoupBuffer *buf)
418 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
421 GError *error = NULL;
424 for (d = priv->decoders; d; d = d->next) {
427 decoded = content_decode_one (buf, decoder, &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);
433 soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED);
437 soup_buffer_free (buf);
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.
453 * See the note at read_metadata() for an explanation of the return
457 read_body_chunk (SoupMessage *msg)
459 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
460 SoupMessageIOData *io = priv->io_data;
461 SoupSocketIOStatus status;
462 guchar *stack_buf = NULL;
464 gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
466 GError *error = NULL;
469 if (!io_handle_sniffing (msg, FALSE))
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);
476 soup_message_io_pause (msg);
481 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
482 buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
484 RESPONSE_BLOCK_SIZE);
488 len = buffer->length;
490 len = MIN (buffer->length, io->read_length);
492 status = soup_socket_read (io->sock,
493 (guchar *)buffer->data, len,
494 &nread, io->cancellable, &error);
496 if (status == SOUP_SOCKET_OK && nread) {
497 buffer->length = nread;
498 io->read_length -= nread;
500 buffer = content_decode (msg, buffer);
504 soup_message_body_got_chunk (io->read_body, buffer);
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))
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);
522 soup_buffer_free (buffer);
527 case SOUP_SOCKET_EOF:
528 if (io->read_eof_ok) {
532 /* else fall through */
534 case SOUP_SOCKET_ERROR:
535 io_error (io->sock, msg, error);
538 case SOUP_SOCKET_WOULD_BLOCK:
546 /* Attempts to write @len bytes from @data. See the note at
547 * read_metadata() for an explanation of the return value.
550 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
552 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
553 SoupMessageIOData *io = priv->io_data;
554 SoupSocketIOStatus status;
556 GError *error = NULL;
560 while (len > io->written) {
561 status = soup_socket_write (io->sock,
565 io->cancellable, &error);
567 case SOUP_SOCKET_EOF:
568 case SOUP_SOCKET_ERROR:
569 io_error (io->sock, msg, error);
572 case SOUP_SOCKET_WOULD_BLOCK:
576 start = data + io->written;
577 io->written += nwrote;
580 if (io->write_length)
581 io->write_length -= nwrote;
583 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
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);
598 static inline SoupMessageIOState
599 io_body_state (SoupEncoding encoding)
601 if (encoding == SOUP_ENCODING_CHUNKED)
602 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
604 return SOUP_MESSAGE_IO_STATE_BODY;
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):
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
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:
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
634 io_write (SoupSocket *sock, SoupMessage *msg)
636 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
637 SoupMessageIOData *io = priv->io_data;
640 switch (io->write_state) {
641 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
645 case SOUP_MESSAGE_IO_STATE_HEADERS:
646 if (!io->write_buf->len) {
647 io->get_headers_cb (msg, io->write_buf,
650 if (!io->write_buf->len) {
651 soup_message_io_pause (msg);
656 if (!write_data (msg, io->write_buf->str,
657 io->write_buf->len, FALSE))
660 g_string_truncate (io->write_buf, 0);
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);
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 */
674 SOUP_MESSAGE_IO_STATE_BLOCKING;
675 io->read_state = io_body_state (io->read_encoding);
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
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;
691 io->write_state = io_body_state (io->write_encoding);
693 /* If the client was waiting for a Continue
694 * but we sent something else, then they're
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;
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);
707 soup_message_wrote_headers (msg);
708 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
712 case SOUP_MESSAGE_IO_STATE_BLOCKING:
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
724 case SOUP_MESSAGE_IO_STATE_BODY:
725 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
727 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
729 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
730 soup_message_wrote_body (msg);
731 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
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);
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.
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)
756 if (!write_data (msg, io->write_chunk->data,
757 io->write_chunk->length, TRUE))
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;
767 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
768 soup_message_wrote_chunk (msg);
769 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
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);
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;
784 if (!write_data (msg, io->write_buf->str,
785 io->write_buf->len, FALSE))
788 g_string_truncate (io->write_buf, 0);
790 if (io->write_chunk->length == 0) {
791 /* The last chunk has no CHUNK_END... */
792 io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
796 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
800 case SOUP_MESSAGE_IO_STATE_CHUNK:
801 if (!write_data (msg, io->write_chunk->data,
802 io->write_chunk->length, TRUE))
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;
811 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
813 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
814 soup_message_wrote_chunk (msg);
815 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
820 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
821 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
822 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
825 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
829 case SOUP_MESSAGE_IO_STATE_TRAILERS:
830 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
831 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
834 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
836 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
837 soup_message_wrote_body (msg);
838 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
842 case SOUP_MESSAGE_IO_STATE_FINISHING:
844 g_signal_handler_disconnect (io->sock, io->write_tag);
847 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
849 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
850 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
853 soup_message_io_finished (msg);
857 case SOUP_MESSAGE_IO_STATE_DONE:
859 g_return_if_reached ();
866 io_read (SoupSocket *sock, SoupMessage *msg)
868 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
869 SoupMessageIOData *io = priv->io_data;
873 switch (io->read_state) {
874 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
878 case SOUP_MESSAGE_IO_STATE_HEADERS:
879 if (!read_metadata (msg, TRUE))
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.
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--;
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,
896 g_byte_array_set_size (io->read_meta_buf, 0);
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.
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;
913 if (io->read_encoding == SOUP_ENCODING_EOF)
914 io->read_eof_ok = TRUE;
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);
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.
929 io->read_eof_ok = TRUE;
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 */
939 SOUP_MESSAGE_IO_STATE_BLOCKING;
941 io_body_state (io->write_encoding);
943 /* Just stay in HEADERS */
944 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
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
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;
956 io->read_state = io_body_state (io->read_encoding);
958 /* If the client was waiting for a Continue
959 * but got something else, then it's done
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;
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;
974 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
975 soup_message_got_headers (msg);
976 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
981 case SOUP_MESSAGE_IO_STATE_BLOCKING:
982 io_write (sock, msg);
984 /* As in the io_write case, we *must* return here. */
988 case SOUP_MESSAGE_IO_STATE_BODY:
989 if (!read_body_chunk (msg))
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
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;
1008 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
1010 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
1011 soup_message_got_body (msg);
1012 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
1016 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
1017 if (!read_metadata (msg, FALSE))
1020 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
1021 g_byte_array_set_size (io->read_meta_buf, 0);
1023 if (io->read_length > 0)
1024 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
1026 io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
1030 case SOUP_MESSAGE_IO_STATE_CHUNK:
1031 if (!read_body_chunk (msg))
1034 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
1038 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
1039 if (!read_metadata (msg, FALSE))
1042 g_byte_array_set_size (io->read_meta_buf, 0);
1043 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
1047 case SOUP_MESSAGE_IO_STATE_TRAILERS:
1048 if (!read_metadata (msg, FALSE))
1051 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
1054 /* FIXME: process trailers */
1055 g_byte_array_set_size (io->read_meta_buf, 0);
1059 case SOUP_MESSAGE_IO_STATE_FINISHING:
1061 g_signal_handler_disconnect (io->sock, io->read_tag);
1064 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
1066 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
1067 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1068 io_write (sock, msg);
1070 soup_message_io_finished (msg);
1074 case SOUP_MESSAGE_IO_STATE_DONE:
1076 g_return_if_reached ();
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)
1090 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1091 SoupMessageIOData *io;
1093 io = g_slice_new0 (SoupMessageIOData);
1094 io->sock = g_object_ref (sock);
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;
1102 io->read_meta_buf = g_byte_array_new ();
1103 io->write_buf = g_string_new (NULL);
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);
1110 io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1111 io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1114 soup_message_io_cleanup (msg);
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)
1127 SoupMessageIOData *io;
1128 SoupSocket *sock = soup_connection_get_socket (item->conn);
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);
1135 soup_message_queue_item_ref (item);
1136 io->cancellable = item->cancellable;
1138 io->read_body = item->msg->response_body;
1139 io->write_body = item->msg->request_body;
1141 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1142 io_write (sock, item->msg);
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)
1153 SoupMessageIOData *io;
1155 io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
1156 get_headers_cb, parse_headers_cb, header_data,
1157 completion_cb, completion_data);
1159 io->read_body = msg->request_body;
1160 io->write_body = msg->response_body;
1162 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1163 io_read (sock, msg);
1167 soup_message_io_pause (SoupMessage *msg)
1169 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1170 SoupMessageIOData *io = priv->io_data;
1172 g_return_if_fail (io != NULL);
1174 if (io->write_tag) {
1175 g_signal_handler_disconnect (io->sock, io->write_tag);
1179 g_signal_handler_disconnect (io->sock, io->read_tag);
1183 if (io->unpause_source) {
1184 g_source_destroy (io->unpause_source);
1185 io->unpause_source = NULL;
1190 io_unpause_internal (gpointer msg)
1192 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1193 SoupMessageIOData *io = priv->io_data;
1195 g_return_val_if_fail (io != NULL, FALSE);
1196 io->unpause_source = NULL;
1198 if (io->write_tag || io->read_tag)
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);
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);
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);
1220 soup_message_io_unpause (SoupMessage *msg)
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;
1227 g_return_if_fail (io != NULL);
1229 g_object_get (io->sock,
1230 SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
1231 SOUP_SOCKET_USE_THREAD_CONTEXT, &use_thread_context,
1233 if (use_thread_context)
1234 async_context = g_main_context_ref_thread_default ();
1236 g_object_get (io->sock,
1237 SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1242 if (!io->unpause_source) {
1243 io->unpause_source = soup_add_completion (
1244 async_context, io_unpause_internal, msg);
1247 io_unpause_internal (msg);
1249 g_main_context_unref (async_context);
1253 * soup_message_io_in_progress:
1254 * @msg: a #SoupMessage
1256 * Tests whether or not I/O is currently in progress on @msg.
1258 * Return value: whether or not I/O is currently in progress.
1261 soup_message_io_in_progress (SoupMessage *msg)
1263 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1265 return priv->io_data != NULL;