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"
24 SOUP_MESSAGE_IO_CLIENT,
25 SOUP_MESSAGE_IO_SERVER
29 SOUP_MESSAGE_IO_STATE_NOT_STARTED,
30 SOUP_MESSAGE_IO_STATE_HEADERS,
31 SOUP_MESSAGE_IO_STATE_BLOCKING,
32 SOUP_MESSAGE_IO_STATE_BODY,
33 SOUP_MESSAGE_IO_STATE_CHUNK_SIZE,
34 SOUP_MESSAGE_IO_STATE_CHUNK,
35 SOUP_MESSAGE_IO_STATE_CHUNK_END,
36 SOUP_MESSAGE_IO_STATE_TRAILERS,
37 SOUP_MESSAGE_IO_STATE_FINISHING,
38 SOUP_MESSAGE_IO_STATE_DONE
41 #define SOUP_MESSAGE_IO_STATE_ACTIVE(state) \
42 (state != SOUP_MESSAGE_IO_STATE_NOT_STARTED && \
43 state != SOUP_MESSAGE_IO_STATE_BLOCKING && \
44 state != SOUP_MESSAGE_IO_STATE_DONE)
48 SoupMessageQueueItem *item;
49 SoupMessageIOMode mode;
50 GCancellable *cancellable;
52 SoupMessageIOState read_state;
53 SoupEncoding read_encoding;
54 GByteArray *read_meta_buf;
55 SoupMessageBody *read_body;
59 gboolean need_content_sniffed, need_got_chunk;
60 SoupMessageBody *sniff_data;
62 SoupMessageIOState write_state;
63 SoupEncoding write_encoding;
65 SoupMessageBody *write_body;
66 SoupBuffer *write_chunk;
67 gsize write_body_offset;
71 guint read_tag, write_tag, tls_signal_id;
72 GSource *unpause_source;
74 SoupMessageGetHeadersFn get_headers_cb;
75 SoupMessageParseHeadersFn parse_headers_cb;
77 SoupMessageCompletionFn completion_cb;
78 gpointer completion_data;
82 /* Put these around callback invocation if there is code afterward
83 * that depends on the IO having not been cancelled.
85 #define dummy_to_make_emacs_happy {
86 #define SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK { gboolean cancelled; g_object_ref (msg);
87 #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; }
88 #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; }
90 #define RESPONSE_BLOCK_SIZE 8192
93 soup_message_io_cleanup (SoupMessage *msg)
95 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
96 SoupMessageIOData *io;
98 soup_message_io_stop (msg);
103 priv->io_data = NULL;
105 if (io->tls_signal_id)
106 g_signal_handler_disconnect (io->sock, io->tls_signal_id);
108 g_object_unref (io->sock);
110 soup_message_queue_item_unref (io->item);
112 g_byte_array_free (io->read_meta_buf, TRUE);
114 g_string_free (io->write_buf, TRUE);
116 soup_buffer_free (io->write_chunk);
119 soup_message_body_free (io->sniff_data);
121 g_slice_free (SoupMessageIOData, io);
125 soup_message_io_stop (SoupMessage *msg)
127 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
128 SoupMessageIOData *io = priv->io_data;
134 g_signal_handler_disconnect (io->sock, io->read_tag);
138 g_signal_handler_disconnect (io->sock, io->write_tag);
142 if (io->unpause_source) {
143 g_source_destroy (io->unpause_source);
144 io->unpause_source = NULL;
147 if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
148 soup_socket_disconnect (io->sock);
149 else if (io->item && io->item->conn)
150 soup_connection_set_state (io->item->conn, SOUP_CONNECTION_IDLE);
153 #define SOUP_MESSAGE_IO_EOL "\r\n"
154 #define SOUP_MESSAGE_IO_EOL_LEN 2
157 soup_message_io_finished (SoupMessage *msg)
159 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
160 SoupMessageIOData *io = priv->io_data;
161 SoupMessageCompletionFn completion_cb = io->completion_cb;
162 gpointer completion_data = io->completion_data;
165 soup_message_io_cleanup (msg);
167 completion_cb (msg, completion_data);
168 g_object_unref (msg);
171 static void io_read (SoupSocket *sock, SoupMessage *msg);
174 request_is_idempotent (SoupMessage *msg)
177 return (msg->method == SOUP_METHOD_GET);
181 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
183 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
184 SoupMessageIOData *io = priv->io_data;
186 if (error && error->domain == G_TLS_ERROR) {
187 soup_message_set_status_full (msg,
188 SOUP_STATUS_SSL_FAILED,
190 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
191 io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
192 io->read_meta_buf->len == 0 &&
193 soup_connection_get_ever_used (io->item->conn) &&
194 !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) &&
195 request_is_idempotent (msg)) {
196 /* Connection got closed, but we can safely try again */
197 io->item->state = SOUP_MESSAGE_RESTARTING;
198 } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
199 soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
202 g_error_free (error);
204 soup_message_io_finished (msg);
208 io_handle_sniffing (SoupMessage *msg, gboolean done_reading)
210 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
211 SoupMessageIOData *io = priv->io_data;
212 SoupBuffer *sniffed_buffer;
213 char *sniffed_mime_type;
214 GHashTable *params = NULL;
219 if (!io->sniff_data) {
220 io->sniff_data = soup_message_body_new ();
221 io->need_content_sniffed = TRUE;
224 if (io->need_content_sniffed) {
225 if (io->sniff_data->length < priv->bytes_for_sniffing &&
229 io->need_content_sniffed = FALSE;
230 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
231 sniffed_mime_type = soup_content_sniffer_sniff (priv->sniffer, msg, sniffed_buffer, ¶ms);
233 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
234 soup_message_content_sniffed (msg, sniffed_mime_type, params);
235 g_free (sniffed_mime_type);
237 g_hash_table_destroy (params);
239 soup_buffer_free (sniffed_buffer);
240 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
243 if (io->need_got_chunk) {
244 io->need_got_chunk = FALSE;
245 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
247 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
248 soup_message_got_chunk (msg, sniffed_buffer);
249 soup_buffer_free (sniffed_buffer);
250 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
256 /* Reads data from io->sock into io->read_meta_buf. If @to_blank is
257 * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF").
258 * Otherwise, it reads up until a single CRLF or LF.
260 * This function is used to read metadata, and read_body_chunk() is
261 * used to read the message body contents.
263 * read_metadata, read_body_chunk, and write_data all use the same
264 * convention for return values: if they return %TRUE, it means
265 * they've completely finished the requested read/write, and the
266 * caller should move on to the next step. If they return %FALSE, it
267 * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
268 * so the caller should give up for now and wait for the socket to
269 * emit a signal, or (b) the socket returned an error, and io_error()
270 * was called to process it and cancel the I/O. So either way, if the
271 * function returns %FALSE, the caller should return immediately.
274 read_metadata (SoupMessage *msg, gboolean to_blank)
276 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
277 SoupMessageIOData *io = priv->io_data;
278 SoupSocketIOStatus status;
279 guchar read_buf[RESPONSE_BLOCK_SIZE];
282 GError *error = NULL;
285 status = soup_socket_read_until (io->sock, read_buf,
287 "\n", 1, &nread, &got_lf,
288 io->cancellable, &error);
291 g_byte_array_append (io->read_meta_buf, read_buf, nread);
294 case SOUP_SOCKET_EOF:
295 /* More lame server handling... deal with
296 * servers that don't send the final chunk.
298 if (io->read_state == SOUP_MESSAGE_IO_STATE_CHUNK_SIZE &&
299 io->read_meta_buf->len == 0) {
300 g_byte_array_append (io->read_meta_buf,
301 (guchar *)"0\r\n", 3);
304 } else if (io->read_state == SOUP_MESSAGE_IO_STATE_TRAILERS &&
305 io->read_meta_buf->len == 0) {
306 g_byte_array_append (io->read_meta_buf,
307 (guchar *)"\r\n", 2);
311 /* else fall through */
313 case SOUP_SOCKET_ERROR:
314 io_error (io->sock, msg, error);
317 case SOUP_SOCKET_WOULD_BLOCK:
325 !strncmp ((char *)io->read_meta_buf->data +
326 io->read_meta_buf->len - 2,
329 else if (nread == 2 &&
330 !strncmp ((char *)io->read_meta_buf->data +
331 io->read_meta_buf->len - 3,
341 content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
343 gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
345 GConverterResult result;
347 outbuf_length = MAX (buf->length * 2, 1024);
348 outbuf = g_malloc (outbuf_length);
349 outbuf_cur = input_cur = 0;
352 result = g_converter_convert (
354 buf->data + input_cur, buf->length - input_cur,
355 outbuf + outbuf_cur, outbuf_length - outbuf_cur,
356 0, &input_used, &outbuf_used, error);
357 input_cur += input_used;
358 outbuf_cur += outbuf_used;
360 if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NO_SPACE) ||
361 (!*error && outbuf_cur == outbuf_length)) {
362 g_clear_error (error);
364 outbuf = g_realloc (outbuf, outbuf_length);
366 /* GZlibDecompressor can't ever return
367 * G_IO_ERROR_PARTIAL_INPUT unless we pass it
368 * input_length = 0, which we don't. Other
369 * converters might of course, so eventually
370 * this code needs to be rewritten to deal
376 } while (input_cur < buf->length && result != G_CONVERTER_FINISHED);
379 return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
387 content_decode (SoupMessage *msg, SoupBuffer *buf)
389 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
392 GError *error = NULL;
395 for (d = priv->decoders; d; d = d->next) {
398 decoded = content_decode_one (buf, decoder, &error);
400 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED))
401 g_warning ("Content-Decoding error: %s\n", error->message);
402 g_error_free (error);
404 soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED);
408 soup_buffer_free (buf);
419 /* Reads as much message body data as is available on io->sock (but no
420 * further than the end of the current message body or chunk). On a
421 * successful read, emits "got_chunk" (possibly multiple times), and
422 * (unless told not to) appends the chunk to io->read_body.
424 * See the note at read_metadata() for an explanation of the return
428 read_body_chunk (SoupMessage *msg)
430 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
431 SoupMessageIOData *io = priv->io_data;
432 SoupSocketIOStatus status;
433 guchar *stack_buf = NULL;
435 gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
437 GError *error = NULL;
440 if (!io_handle_sniffing (msg, FALSE))
443 while (read_to_eof || io->read_length > 0) {
444 if (priv->chunk_allocator) {
445 buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
447 soup_message_io_pause (msg);
452 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
453 buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
455 RESPONSE_BLOCK_SIZE);
459 len = buffer->length;
461 len = MIN (buffer->length, io->read_length);
463 status = soup_socket_read (io->sock,
464 (guchar *)buffer->data, len,
465 &nread, io->cancellable, &error);
467 if (status == SOUP_SOCKET_OK && nread) {
468 buffer->length = nread;
469 io->read_length -= nread;
471 buffer = content_decode (msg, buffer);
475 soup_message_body_got_chunk (io->read_body, buffer);
477 if (io->need_content_sniffed) {
478 soup_message_body_append_buffer (io->sniff_data, buffer);
479 soup_buffer_free (buffer);
480 io->need_got_chunk = TRUE;
481 if (!io_handle_sniffing (msg, FALSE))
486 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
487 soup_message_got_chunk (msg, buffer);
488 soup_buffer_free (buffer);
489 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
493 soup_buffer_free (buffer);
498 case SOUP_SOCKET_EOF:
499 if (io->read_eof_ok) {
503 /* else fall through */
505 case SOUP_SOCKET_ERROR:
506 io_error (io->sock, msg, error);
509 case SOUP_SOCKET_WOULD_BLOCK:
517 /* Attempts to write @len bytes from @data. See the note at
518 * read_metadata() for an explanation of the return value.
521 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
523 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
524 SoupMessageIOData *io = priv->io_data;
525 SoupSocketIOStatus status;
527 GError *error = NULL;
531 while (len > io->written) {
532 status = soup_socket_write (io->sock,
536 io->cancellable, &error);
538 case SOUP_SOCKET_EOF:
539 case SOUP_SOCKET_ERROR:
540 io_error (io->sock, msg, error);
543 case SOUP_SOCKET_WOULD_BLOCK:
547 start = data + io->written;
548 io->written += nwrote;
551 if (io->write_length)
552 io->write_length -= nwrote;
554 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
556 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
557 soup_message_wrote_body_data (msg, chunk);
558 soup_buffer_free (chunk);
559 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
569 static inline SoupMessageIOState
570 io_body_state (SoupEncoding encoding)
572 if (encoding == SOUP_ENCODING_CHUNKED)
573 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
575 return SOUP_MESSAGE_IO_STATE_BODY;
579 * There are two request/response formats: the basic request/response,
580 * possibly with one or more unsolicited informational responses (such
581 * as the WebDAV "102 Processing" response):
584 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
585 * W:BODY / R:NOT_STARTED -> R:BODY / W:NOT_STARTED
586 * [W:DONE / R:HEADERS (1xx) <- R:DONE / W:HEADERS (1xx) ...]
587 * W:DONE / R:HEADERS <- R:DONE / W:HEADERS
588 * W:DONE / R:BODY <- R:DONE / W:BODY
589 * W:DONE / R:DONE R:DONE / W:DONE
591 * and the "Expect: 100-continue" request/response, with the client
592 * blocking halfway through its request, and then either continuing or
593 * aborting, depending on the server response:
596 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
597 * W:BLOCKING / R:HEADERS <- R:BLOCKING / W:HEADERS
598 * [W:BODY / R:BLOCKING -> R:BODY / W:BLOCKING]
599 * [W:DONE / R:HEADERS <- R:DONE / W:HEADERS]
600 * W:DONE / R:BODY <- R:DONE / W:BODY
601 * W:DONE / R:DONE R:DONE / W:DONE
605 io_write (SoupSocket *sock, SoupMessage *msg)
607 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
608 SoupMessageIOData *io = priv->io_data;
611 switch (io->write_state) {
612 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
616 case SOUP_MESSAGE_IO_STATE_HEADERS:
617 if (!io->write_buf->len) {
618 io->get_headers_cb (msg, io->write_buf,
621 if (!io->write_buf->len) {
622 soup_message_io_pause (msg);
627 if (!write_data (msg, io->write_buf->str,
628 io->write_buf->len, FALSE))
631 g_string_truncate (io->write_buf, 0);
633 if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
634 SoupMessageHeaders *hdrs =
635 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
636 msg->request_headers : msg->response_headers;
637 io->write_length = soup_message_headers_get_content_length (hdrs);
640 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
641 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
642 if (msg->status_code == SOUP_STATUS_CONTINUE) {
643 /* Stop and wait for the body now */
645 SOUP_MESSAGE_IO_STATE_BLOCKING;
646 io->read_state = io_body_state (io->read_encoding);
648 /* We just wrote a 1xx response
649 * header, so stay in STATE_HEADERS.
650 * (The caller will pause us from the
651 * wrote_informational callback if he
652 * is not ready to send the final
656 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
657 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
658 /* Need to wait for the Continue response */
659 io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
660 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
662 io->write_state = io_body_state (io->write_encoding);
664 /* If the client was waiting for a Continue
665 * but we sent something else, then they're
668 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
669 io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
670 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
673 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
674 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
675 soup_message_wrote_informational (msg);
676 soup_message_cleanup_response (msg);
678 soup_message_wrote_headers (msg);
679 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
683 case SOUP_MESSAGE_IO_STATE_BLOCKING:
686 /* If io_read reached a point where we could write
687 * again, it would have recursively called io_write.
688 * So (a) we don't need to try to keep writing, and
689 * (b) we can't anyway, because msg may have been
695 case SOUP_MESSAGE_IO_STATE_BODY:
696 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
698 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
700 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
701 soup_message_wrote_body (msg);
702 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
706 if (!io->write_chunk) {
707 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
708 if (!io->write_chunk) {
709 soup_message_io_pause (msg);
712 if (io->write_chunk->length > io->write_length &&
713 io->write_encoding != SOUP_ENCODING_EOF) {
714 /* App is trying to write more than it
715 * claimed it would; we have to truncate.
717 SoupBuffer *truncated =
718 soup_buffer_new_subbuffer (io->write_chunk,
719 0, io->write_length);
720 soup_buffer_free (io->write_chunk);
721 io->write_chunk = truncated;
722 } else if (io->write_encoding == SOUP_ENCODING_EOF &&
723 !io->write_chunk->length)
727 if (!write_data (msg, io->write_chunk->data,
728 io->write_chunk->length, TRUE))
731 if (io->mode == SOUP_MESSAGE_IO_SERVER)
732 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
733 io->write_body_offset += io->write_chunk->length;
734 soup_buffer_free (io->write_chunk);
735 io->write_chunk = NULL;
737 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
738 soup_message_wrote_chunk (msg);
739 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
742 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
743 if (!io->write_chunk) {
744 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
745 if (!io->write_chunk) {
746 soup_message_io_pause (msg);
749 g_string_append_printf (io->write_buf, "%lx\r\n",
750 (unsigned long) io->write_chunk->length);
751 io->write_body_offset += io->write_chunk->length;
754 if (!write_data (msg, io->write_buf->str,
755 io->write_buf->len, FALSE))
758 g_string_truncate (io->write_buf, 0);
760 if (io->write_chunk->length == 0) {
761 /* The last chunk has no CHUNK_END... */
762 io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
766 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
770 case SOUP_MESSAGE_IO_STATE_CHUNK:
771 if (!write_data (msg, io->write_chunk->data,
772 io->write_chunk->length, TRUE))
775 if (io->mode == SOUP_MESSAGE_IO_SERVER)
776 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
777 soup_buffer_free (io->write_chunk);
778 io->write_chunk = NULL;
780 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
782 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
783 soup_message_wrote_chunk (msg);
784 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
789 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
790 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
791 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
794 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
798 case SOUP_MESSAGE_IO_STATE_TRAILERS:
799 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
800 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
803 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
805 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
806 soup_message_wrote_body (msg);
807 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
811 case SOUP_MESSAGE_IO_STATE_FINISHING:
813 g_signal_handler_disconnect (io->sock, io->write_tag);
816 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
818 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
819 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
822 soup_message_io_finished (msg);
826 case SOUP_MESSAGE_IO_STATE_DONE:
828 g_return_if_reached ();
835 io_read (SoupSocket *sock, SoupMessage *msg)
837 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
838 SoupMessageIOData *io = priv->io_data;
842 switch (io->read_state) {
843 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
847 case SOUP_MESSAGE_IO_STATE_HEADERS:
848 if (!read_metadata (msg, TRUE))
851 /* We need to "rewind" io->read_meta_buf back one line.
852 * That SHOULD be two characters (CR LF), but if the
853 * web server was stupid, it might only be one.
855 if (io->read_meta_buf->len < 3 ||
856 io->read_meta_buf->data[io->read_meta_buf->len - 2] == '\n')
857 io->read_meta_buf->len--;
859 io->read_meta_buf->len -= 2;
860 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
861 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
862 io->read_meta_buf->len,
865 g_byte_array_set_size (io->read_meta_buf, 0);
867 if (status != SOUP_STATUS_OK) {
868 /* Either we couldn't parse the headers, or they
869 * indicated something that would mean we wouldn't
870 * be able to parse the body. (Eg, unknown
871 * Transfer-Encoding.). Skip the rest of the
872 * reading, and make sure the connection gets
873 * closed when we're done.
875 soup_message_set_status (msg, status);
876 soup_message_headers_append (msg->request_headers,
877 "Connection", "close");
878 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
882 if (io->read_encoding == SOUP_ENCODING_EOF)
883 io->read_eof_ok = TRUE;
885 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
886 SoupMessageHeaders *hdrs =
887 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
888 msg->response_headers : msg->request_headers;
889 io->read_length = soup_message_headers_get_content_length (hdrs);
891 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
892 !soup_message_is_keepalive (msg)) {
893 /* Some servers suck and send
894 * incorrect Content-Length values, so
895 * allow EOF termination in this case
896 * (iff the message is too short) too.
898 io->read_eof_ok = TRUE;
902 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
903 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
904 if (msg->status_code == SOUP_STATUS_CONTINUE &&
905 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
906 /* Pause the reader, unpause the writer */
908 SOUP_MESSAGE_IO_STATE_BLOCKING;
910 io_body_state (io->write_encoding);
912 /* Just stay in HEADERS */
913 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
915 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
916 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
917 /* The client requested a Continue response. The
918 * got_headers handler may change this to something
921 soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
922 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
923 io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
925 io->read_state = io_body_state (io->read_encoding);
927 /* If the client was waiting for a Continue
928 * but got something else, then it's done
931 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
932 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
933 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
936 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
937 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
938 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
939 soup_message_got_informational (msg);
940 soup_message_cleanup_response (msg);
941 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
943 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
944 soup_message_got_headers (msg);
945 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
950 case SOUP_MESSAGE_IO_STATE_BLOCKING:
951 io_write (sock, msg);
953 /* As in the io_write case, we *must* return here. */
957 case SOUP_MESSAGE_IO_STATE_BODY:
958 if (!read_body_chunk (msg))
962 if (!io_handle_sniffing (msg, TRUE)) {
963 /* If the message was paused (as opposed to
964 * cancelled), we need to make sure we wind up
965 * back here when it's unpaused, even if it
966 * was doing a chunked or EOF-terminated read
969 if (io == priv->io_data) {
970 io->read_state = SOUP_MESSAGE_IO_STATE_BODY;
971 io->read_encoding = SOUP_ENCODING_CONTENT_LENGTH;
977 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
979 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
980 soup_message_got_body (msg);
981 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
985 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
986 if (!read_metadata (msg, FALSE))
989 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
990 g_byte_array_set_size (io->read_meta_buf, 0);
992 if (io->read_length > 0)
993 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
995 io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
999 case SOUP_MESSAGE_IO_STATE_CHUNK:
1000 if (!read_body_chunk (msg))
1003 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
1007 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
1008 if (!read_metadata (msg, FALSE))
1011 g_byte_array_set_size (io->read_meta_buf, 0);
1012 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
1016 case SOUP_MESSAGE_IO_STATE_TRAILERS:
1017 if (!read_metadata (msg, FALSE))
1020 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
1023 /* FIXME: process trailers */
1024 g_byte_array_set_size (io->read_meta_buf, 0);
1028 case SOUP_MESSAGE_IO_STATE_FINISHING:
1030 g_signal_handler_disconnect (io->sock, io->read_tag);
1033 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
1035 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
1036 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1037 io_write (sock, msg);
1039 soup_message_io_finished (msg);
1043 case SOUP_MESSAGE_IO_STATE_DONE:
1045 g_return_if_reached ();
1052 socket_tls_certificate_changed (GObject *sock, GParamSpec *pspec,
1055 GTlsCertificate *certificate;
1056 GTlsCertificateFlags errors;
1059 SOUP_SOCKET_TLS_CERTIFICATE, &certificate,
1060 SOUP_SOCKET_TLS_ERRORS, &errors,
1063 SOUP_MESSAGE_TLS_CERTIFICATE, certificate,
1064 SOUP_MESSAGE_TLS_ERRORS, errors,
1067 g_object_unref (certificate);
1070 static SoupMessageIOData *
1071 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
1072 SoupMessageGetHeadersFn get_headers_cb,
1073 SoupMessageParseHeadersFn parse_headers_cb,
1074 gpointer header_data,
1075 SoupMessageCompletionFn completion_cb,
1076 gpointer completion_data)
1078 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1079 SoupMessageIOData *io;
1081 io = g_slice_new0 (SoupMessageIOData);
1082 io->sock = g_object_ref (sock);
1084 io->get_headers_cb = get_headers_cb;
1085 io->parse_headers_cb = parse_headers_cb;
1086 io->header_data = header_data;
1087 io->completion_cb = completion_cb;
1088 io->completion_data = completion_data;
1090 io->read_meta_buf = g_byte_array_new ();
1091 io->write_buf = g_string_new (NULL);
1093 io->read_tag = g_signal_connect (io->sock, "readable",
1094 G_CALLBACK (io_read), msg);
1095 io->write_tag = g_signal_connect (io->sock, "writable",
1096 G_CALLBACK (io_write), msg);
1098 io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1099 io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1101 if (soup_socket_is_ssl (io->sock)) {
1102 io->tls_signal_id = g_signal_connect (io->sock, "notify::tls-certificate",
1103 G_CALLBACK (socket_tls_certificate_changed), msg);
1107 soup_message_io_cleanup (msg);
1113 soup_message_io_client (SoupMessageQueueItem *item,
1114 SoupMessageGetHeadersFn get_headers_cb,
1115 SoupMessageParseHeadersFn parse_headers_cb,
1116 gpointer header_data,
1117 SoupMessageCompletionFn completion_cb,
1118 gpointer completion_data)
1120 SoupMessageIOData *io;
1121 SoupSocket *sock = soup_connection_get_socket (item->conn);
1123 io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
1124 get_headers_cb, parse_headers_cb, header_data,
1125 completion_cb, completion_data);
1128 soup_message_queue_item_ref (item);
1129 io->cancellable = item->cancellable;
1131 io->read_body = item->msg->response_body;
1132 io->write_body = item->msg->request_body;
1134 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1135 io_write (sock, item->msg);
1139 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
1140 SoupMessageGetHeadersFn get_headers_cb,
1141 SoupMessageParseHeadersFn parse_headers_cb,
1142 gpointer header_data,
1143 SoupMessageCompletionFn completion_cb,
1144 gpointer completion_data)
1146 SoupMessageIOData *io;
1148 io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
1149 get_headers_cb, parse_headers_cb, header_data,
1150 completion_cb, completion_data);
1152 io->read_body = msg->request_body;
1153 io->write_body = msg->response_body;
1155 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1156 io_read (sock, msg);
1160 soup_message_io_pause (SoupMessage *msg)
1162 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1163 SoupMessageIOData *io = priv->io_data;
1165 g_return_if_fail (io != NULL);
1167 if (io->write_tag) {
1168 g_signal_handler_disconnect (io->sock, io->write_tag);
1172 g_signal_handler_disconnect (io->sock, io->read_tag);
1176 if (io->unpause_source) {
1177 g_source_destroy (io->unpause_source);
1178 io->unpause_source = NULL;
1183 io_unpause_internal (gpointer msg)
1185 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1186 SoupMessageIOData *io = priv->io_data;
1188 g_return_val_if_fail (io != NULL, FALSE);
1189 io->unpause_source = NULL;
1191 if (io->write_tag || io->read_tag)
1194 if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
1195 io->write_tag = g_signal_connect (io->sock, "writable",
1196 G_CALLBACK (io_write), msg);
1199 if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
1200 io->read_tag = g_signal_connect (io->sock, "readable",
1201 G_CALLBACK (io_read), msg);
1204 if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
1205 io_write (io->sock, msg);
1206 else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
1207 io_read (io->sock, msg);
1213 soup_message_io_unpause (SoupMessage *msg)
1215 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1216 SoupMessageIOData *io = priv->io_data;
1217 gboolean non_blocking;
1218 GMainContext *async_context;
1220 g_return_if_fail (io != NULL);
1222 g_object_get (io->sock,
1223 SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
1224 SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1227 if (!io->unpause_source) {
1228 io->unpause_source = soup_add_completion (
1229 async_context, io_unpause_internal, msg);
1232 io_unpause_internal (msg);
1234 g_main_context_unref (async_context);
1238 * soup_message_io_in_progress:
1239 * @msg: a #SoupMessage
1241 * Tests whether or not I/O is currently in progress on @msg.
1243 * Return value: whether or not I/O is currently in progress.
1246 soup_message_io_in_progress (SoupMessage *msg)
1248 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1250 return priv->io_data != NULL;