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 goffset 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);
151 g_object_unref (io->item->conn);
152 io->item->conn = NULL;
156 #define SOUP_MESSAGE_IO_EOL "\r\n"
157 #define SOUP_MESSAGE_IO_EOL_LEN 2
160 soup_message_io_finished (SoupMessage *msg)
162 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
163 SoupMessageIOData *io = priv->io_data;
164 SoupMessageCompletionFn completion_cb = io->completion_cb;
165 gpointer completion_data = io->completion_data;
168 soup_message_io_cleanup (msg);
170 completion_cb (msg, completion_data);
171 g_object_unref (msg);
174 static void io_read (SoupSocket *sock, SoupMessage *msg);
177 request_is_idempotent (SoupMessage *msg)
180 return (msg->method == SOUP_METHOD_GET);
184 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
186 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
187 SoupMessageIOData *io = priv->io_data;
189 if (error && error->domain == G_TLS_ERROR) {
190 soup_message_set_status_full (msg,
191 SOUP_STATUS_SSL_FAILED,
193 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
194 io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
195 io->read_meta_buf->len == 0 &&
196 soup_connection_get_ever_used (io->item->conn) &&
197 !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) &&
198 request_is_idempotent (msg)) {
199 /* Connection got closed, but we can safely try again */
200 io->item->state = SOUP_MESSAGE_RESTARTING;
201 } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
202 soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
205 g_error_free (error);
207 soup_message_io_finished (msg);
211 io_handle_sniffing (SoupMessage *msg, gboolean done_reading)
213 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
214 SoupMessageIOData *io = priv->io_data;
215 SoupBuffer *sniffed_buffer;
216 char *sniffed_mime_type;
217 GHashTable *params = NULL;
222 if (!io->sniff_data) {
223 io->sniff_data = soup_message_body_new ();
224 io->need_content_sniffed = TRUE;
227 if (io->need_content_sniffed) {
228 if (io->sniff_data->length < priv->bytes_for_sniffing &&
232 io->need_content_sniffed = FALSE;
233 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
234 sniffed_mime_type = soup_content_sniffer_sniff (priv->sniffer, msg, sniffed_buffer, ¶ms);
236 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
237 soup_message_content_sniffed (msg, sniffed_mime_type, params);
238 g_free (sniffed_mime_type);
240 g_hash_table_destroy (params);
242 soup_buffer_free (sniffed_buffer);
243 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
246 if (io->need_got_chunk) {
247 io->need_got_chunk = FALSE;
248 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
250 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
251 soup_message_got_chunk (msg, sniffed_buffer);
252 soup_buffer_free (sniffed_buffer);
253 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
259 /* Reads data from io->sock into io->read_meta_buf. If @to_blank is
260 * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF").
261 * Otherwise, it reads up until a single CRLF or LF.
263 * This function is used to read metadata, and read_body_chunk() is
264 * used to read the message body contents.
266 * read_metadata, read_body_chunk, and write_data all use the same
267 * convention for return values: if they return %TRUE, it means
268 * they've completely finished the requested read/write, and the
269 * caller should move on to the next step. If they return %FALSE, it
270 * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
271 * so the caller should give up for now and wait for the socket to
272 * emit a signal, or (b) the socket returned an error, and io_error()
273 * was called to process it and cancel the I/O. So either way, if the
274 * function returns %FALSE, the caller should return immediately.
277 read_metadata (SoupMessage *msg, gboolean to_blank)
279 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
280 SoupMessageIOData *io = priv->io_data;
281 SoupSocketIOStatus status;
282 guchar read_buf[RESPONSE_BLOCK_SIZE];
285 GError *error = NULL;
288 status = soup_socket_read_until (io->sock, read_buf,
290 "\n", 1, &nread, &got_lf,
291 io->cancellable, &error);
294 g_byte_array_append (io->read_meta_buf, read_buf, nread);
297 case SOUP_SOCKET_EOF:
298 /* More lame server handling... deal with
299 * servers that don't send the final chunk.
301 if (io->read_state == SOUP_MESSAGE_IO_STATE_CHUNK_SIZE &&
302 io->read_meta_buf->len == 0) {
303 g_byte_array_append (io->read_meta_buf,
304 (guchar *)"0\r\n", 3);
307 } else if (io->read_state == SOUP_MESSAGE_IO_STATE_TRAILERS &&
308 io->read_meta_buf->len == 0) {
309 g_byte_array_append (io->read_meta_buf,
310 (guchar *)"\r\n", 2);
314 /* else fall through */
316 case SOUP_SOCKET_ERROR:
317 io_error (io->sock, msg, error);
320 case SOUP_SOCKET_WOULD_BLOCK:
328 !strncmp ((char *)io->read_meta_buf->data +
329 io->read_meta_buf->len - 2,
332 else if (nread == 2 &&
333 !strncmp ((char *)io->read_meta_buf->data +
334 io->read_meta_buf->len - 3,
344 content_decode_one (SoupBuffer *buf, GConverter *converter, GError **error)
346 gsize outbuf_length, outbuf_used, outbuf_cur, input_used, input_cur;
348 GConverterResult result;
350 outbuf_length = MAX (buf->length * 2, 1024);
351 outbuf = g_malloc (outbuf_length);
352 outbuf_cur = input_cur = 0;
355 result = g_converter_convert (
357 buf->data + input_cur, buf->length - input_cur,
358 outbuf + outbuf_cur, outbuf_length - outbuf_cur,
359 0, &input_used, &outbuf_used, error);
360 input_cur += input_used;
361 outbuf_cur += outbuf_used;
363 if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_NO_SPACE) ||
364 (!*error && outbuf_cur == outbuf_length)) {
365 g_clear_error (error);
367 outbuf = g_realloc (outbuf, outbuf_length);
369 /* GZlibDecompressor can't ever return
370 * G_IO_ERROR_PARTIAL_INPUT unless we pass it
371 * input_length = 0, which we don't. Other
372 * converters might of course, so eventually
373 * this code needs to be rewritten to deal
379 } while (input_cur < buf->length && result != G_CONVERTER_FINISHED);
382 return soup_buffer_new (SOUP_MEMORY_TAKE, outbuf, outbuf_cur);
390 content_decode (SoupMessage *msg, SoupBuffer *buf)
392 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
395 GError *error = NULL;
398 for (d = priv->decoders; d; d = d->next) {
401 decoded = content_decode_one (buf, decoder, &error);
403 if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_FAILED))
404 g_warning ("Content-Decoding error: %s\n", error->message);
405 g_error_free (error);
407 soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED);
411 soup_buffer_free (buf);
422 /* Reads as much message body data as is available on io->sock (but no
423 * further than the end of the current message body or chunk). On a
424 * successful read, emits "got_chunk" (possibly multiple times), and
425 * (unless told not to) appends the chunk to io->read_body.
427 * See the note at read_metadata() for an explanation of the return
431 read_body_chunk (SoupMessage *msg)
433 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
434 SoupMessageIOData *io = priv->io_data;
435 SoupSocketIOStatus status;
436 guchar *stack_buf = NULL;
438 gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
440 GError *error = NULL;
443 if (!io_handle_sniffing (msg, FALSE))
446 while (read_to_eof || io->read_length > 0) {
447 if (priv->chunk_allocator) {
448 buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
450 soup_message_io_pause (msg);
455 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
456 buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
458 RESPONSE_BLOCK_SIZE);
462 len = buffer->length;
464 len = MIN (buffer->length, io->read_length);
466 status = soup_socket_read (io->sock,
467 (guchar *)buffer->data, len,
468 &nread, io->cancellable, &error);
470 if (status == SOUP_SOCKET_OK && nread) {
471 buffer->length = nread;
472 io->read_length -= nread;
474 buffer = content_decode (msg, buffer);
478 soup_message_body_got_chunk (io->read_body, buffer);
480 if (io->need_content_sniffed) {
481 soup_message_body_append_buffer (io->sniff_data, buffer);
482 soup_buffer_free (buffer);
483 io->need_got_chunk = TRUE;
484 if (!io_handle_sniffing (msg, FALSE))
489 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
490 soup_message_got_chunk (msg, buffer);
491 soup_buffer_free (buffer);
492 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
496 soup_buffer_free (buffer);
501 case SOUP_SOCKET_EOF:
502 if (io->read_eof_ok) {
506 /* else fall through */
508 case SOUP_SOCKET_ERROR:
509 io_error (io->sock, msg, error);
512 case SOUP_SOCKET_WOULD_BLOCK:
520 /* Attempts to write @len bytes from @data. See the note at
521 * read_metadata() for an explanation of the return value.
524 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
526 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
527 SoupMessageIOData *io = priv->io_data;
528 SoupSocketIOStatus status;
530 GError *error = NULL;
534 while (len > io->written) {
535 status = soup_socket_write (io->sock,
539 io->cancellable, &error);
541 case SOUP_SOCKET_EOF:
542 case SOUP_SOCKET_ERROR:
543 io_error (io->sock, msg, error);
546 case SOUP_SOCKET_WOULD_BLOCK:
550 start = data + io->written;
551 io->written += nwrote;
554 if (io->write_length)
555 io->write_length -= nwrote;
557 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
559 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
560 soup_message_wrote_body_data (msg, chunk);
561 soup_buffer_free (chunk);
562 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
572 static inline SoupMessageIOState
573 io_body_state (SoupEncoding encoding)
575 if (encoding == SOUP_ENCODING_CHUNKED)
576 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
578 return SOUP_MESSAGE_IO_STATE_BODY;
582 * There are two request/response formats: the basic request/response,
583 * possibly with one or more unsolicited informational responses (such
584 * as the WebDAV "102 Processing" response):
587 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
588 * W:BODY / R:NOT_STARTED -> R:BODY / W:NOT_STARTED
589 * [W:DONE / R:HEADERS (1xx) <- R:DONE / W:HEADERS (1xx) ...]
590 * W:DONE / R:HEADERS <- R:DONE / W:HEADERS
591 * W:DONE / R:BODY <- R:DONE / W:BODY
592 * W:DONE / R:DONE R:DONE / W:DONE
594 * and the "Expect: 100-continue" request/response, with the client
595 * blocking halfway through its request, and then either continuing or
596 * aborting, depending on the server response:
599 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
600 * W:BLOCKING / R:HEADERS <- R:BLOCKING / W:HEADERS
601 * [W:BODY / R:BLOCKING -> R:BODY / W:BLOCKING]
602 * [W:DONE / R:HEADERS <- R:DONE / W:HEADERS]
603 * W:DONE / R:BODY <- R:DONE / W:BODY
604 * W:DONE / R:DONE R:DONE / W:DONE
608 io_write (SoupSocket *sock, SoupMessage *msg)
610 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
611 SoupMessageIOData *io = priv->io_data;
614 switch (io->write_state) {
615 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
619 case SOUP_MESSAGE_IO_STATE_HEADERS:
620 if (!io->write_buf->len) {
621 io->get_headers_cb (msg, io->write_buf,
624 if (!io->write_buf->len) {
625 soup_message_io_pause (msg);
630 if (!write_data (msg, io->write_buf->str,
631 io->write_buf->len, FALSE))
634 g_string_truncate (io->write_buf, 0);
636 if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
637 SoupMessageHeaders *hdrs =
638 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
639 msg->request_headers : msg->response_headers;
640 io->write_length = soup_message_headers_get_content_length (hdrs);
643 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
644 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
645 if (msg->status_code == SOUP_STATUS_CONTINUE) {
646 /* Stop and wait for the body now */
648 SOUP_MESSAGE_IO_STATE_BLOCKING;
649 io->read_state = io_body_state (io->read_encoding);
651 /* We just wrote a 1xx response
652 * header, so stay in STATE_HEADERS.
653 * (The caller will pause us from the
654 * wrote_informational callback if he
655 * is not ready to send the final
659 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
660 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
661 /* Need to wait for the Continue response */
662 io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
663 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
665 io->write_state = io_body_state (io->write_encoding);
667 /* If the client was waiting for a Continue
668 * but we sent something else, then they're
671 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
672 io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
673 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
676 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
677 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
678 soup_message_wrote_informational (msg);
679 soup_message_cleanup_response (msg);
681 soup_message_wrote_headers (msg);
682 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
686 case SOUP_MESSAGE_IO_STATE_BLOCKING:
689 /* If io_read reached a point where we could write
690 * again, it would have recursively called io_write.
691 * So (a) we don't need to try to keep writing, and
692 * (b) we can't anyway, because msg may have been
698 case SOUP_MESSAGE_IO_STATE_BODY:
699 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
701 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
703 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
704 soup_message_wrote_body (msg);
705 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
709 if (!io->write_chunk) {
710 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
711 if (!io->write_chunk) {
712 soup_message_io_pause (msg);
715 if (io->write_chunk->length > io->write_length &&
716 io->write_encoding != SOUP_ENCODING_EOF) {
717 /* App is trying to write more than it
718 * claimed it would; we have to truncate.
720 SoupBuffer *truncated =
721 soup_buffer_new_subbuffer (io->write_chunk,
722 0, io->write_length);
723 soup_buffer_free (io->write_chunk);
724 io->write_chunk = truncated;
725 } else if (io->write_encoding == SOUP_ENCODING_EOF &&
726 !io->write_chunk->length)
730 if (!write_data (msg, io->write_chunk->data,
731 io->write_chunk->length, TRUE))
734 if (io->mode == SOUP_MESSAGE_IO_SERVER)
735 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
736 io->write_body_offset += io->write_chunk->length;
737 soup_buffer_free (io->write_chunk);
738 io->write_chunk = NULL;
740 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
741 soup_message_wrote_chunk (msg);
742 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
745 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
746 if (!io->write_chunk) {
747 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
748 if (!io->write_chunk) {
749 soup_message_io_pause (msg);
752 g_string_append_printf (io->write_buf, "%lx\r\n",
753 (unsigned long) io->write_chunk->length);
754 io->write_body_offset += io->write_chunk->length;
757 if (!write_data (msg, io->write_buf->str,
758 io->write_buf->len, FALSE))
761 g_string_truncate (io->write_buf, 0);
763 if (io->write_chunk->length == 0) {
764 /* The last chunk has no CHUNK_END... */
765 io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
769 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
773 case SOUP_MESSAGE_IO_STATE_CHUNK:
774 if (!write_data (msg, io->write_chunk->data,
775 io->write_chunk->length, TRUE))
778 if (io->mode == SOUP_MESSAGE_IO_SERVER)
779 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
780 soup_buffer_free (io->write_chunk);
781 io->write_chunk = NULL;
783 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
785 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
786 soup_message_wrote_chunk (msg);
787 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
792 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
793 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
794 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
797 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
801 case SOUP_MESSAGE_IO_STATE_TRAILERS:
802 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
803 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
806 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
808 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
809 soup_message_wrote_body (msg);
810 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
814 case SOUP_MESSAGE_IO_STATE_FINISHING:
816 g_signal_handler_disconnect (io->sock, io->write_tag);
819 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
821 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
822 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
825 soup_message_io_finished (msg);
829 case SOUP_MESSAGE_IO_STATE_DONE:
831 g_return_if_reached ();
838 io_read (SoupSocket *sock, SoupMessage *msg)
840 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
841 SoupMessageIOData *io = priv->io_data;
845 switch (io->read_state) {
846 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
850 case SOUP_MESSAGE_IO_STATE_HEADERS:
851 if (!read_metadata (msg, TRUE))
854 /* We need to "rewind" io->read_meta_buf back one line.
855 * That SHOULD be two characters (CR LF), but if the
856 * web server was stupid, it might only be one.
858 if (io->read_meta_buf->len < 3 ||
859 io->read_meta_buf->data[io->read_meta_buf->len - 2] == '\n')
860 io->read_meta_buf->len--;
862 io->read_meta_buf->len -= 2;
863 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
864 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
865 io->read_meta_buf->len,
868 g_byte_array_set_size (io->read_meta_buf, 0);
870 if (status != SOUP_STATUS_OK) {
871 /* Either we couldn't parse the headers, or they
872 * indicated something that would mean we wouldn't
873 * be able to parse the body. (Eg, unknown
874 * Transfer-Encoding.). Skip the rest of the
875 * reading, and make sure the connection gets
876 * closed when we're done.
878 soup_message_set_status (msg, status);
879 soup_message_headers_append (msg->request_headers,
880 "Connection", "close");
881 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
885 if (io->read_encoding == SOUP_ENCODING_EOF)
886 io->read_eof_ok = TRUE;
888 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
889 SoupMessageHeaders *hdrs =
890 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
891 msg->response_headers : msg->request_headers;
892 io->read_length = soup_message_headers_get_content_length (hdrs);
894 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
895 !soup_message_is_keepalive (msg)) {
896 /* Some servers suck and send
897 * incorrect Content-Length values, so
898 * allow EOF termination in this case
899 * (iff the message is too short) too.
901 io->read_eof_ok = TRUE;
905 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
906 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
907 if (msg->status_code == SOUP_STATUS_CONTINUE &&
908 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
909 /* Pause the reader, unpause the writer */
911 SOUP_MESSAGE_IO_STATE_BLOCKING;
913 io_body_state (io->write_encoding);
915 /* Just stay in HEADERS */
916 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
918 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
919 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
920 /* The client requested a Continue response. The
921 * got_headers handler may change this to something
924 soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
925 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
926 io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
928 io->read_state = io_body_state (io->read_encoding);
930 /* If the client was waiting for a Continue
931 * but got something else, then it's done
934 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
935 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
936 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
939 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
940 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
941 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
942 soup_message_got_informational (msg);
943 soup_message_cleanup_response (msg);
944 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
946 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
947 soup_message_got_headers (msg);
948 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
953 case SOUP_MESSAGE_IO_STATE_BLOCKING:
954 io_write (sock, msg);
956 /* As in the io_write case, we *must* return here. */
960 case SOUP_MESSAGE_IO_STATE_BODY:
961 if (!read_body_chunk (msg))
965 if (!io_handle_sniffing (msg, TRUE)) {
966 /* If the message was paused (as opposed to
967 * cancelled), we need to make sure we wind up
968 * back here when it's unpaused, even if it
969 * was doing a chunked or EOF-terminated read
972 if (io == priv->io_data) {
973 io->read_state = SOUP_MESSAGE_IO_STATE_BODY;
974 io->read_encoding = SOUP_ENCODING_CONTENT_LENGTH;
980 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
982 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
983 soup_message_got_body (msg);
984 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
988 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
989 if (!read_metadata (msg, FALSE))
992 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
993 g_byte_array_set_size (io->read_meta_buf, 0);
995 if (io->read_length > 0)
996 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
998 io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
1002 case SOUP_MESSAGE_IO_STATE_CHUNK:
1003 if (!read_body_chunk (msg))
1006 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
1010 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
1011 if (!read_metadata (msg, FALSE))
1014 g_byte_array_set_size (io->read_meta_buf, 0);
1015 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
1019 case SOUP_MESSAGE_IO_STATE_TRAILERS:
1020 if (!read_metadata (msg, FALSE))
1023 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
1026 /* FIXME: process trailers */
1027 g_byte_array_set_size (io->read_meta_buf, 0);
1031 case SOUP_MESSAGE_IO_STATE_FINISHING:
1033 g_signal_handler_disconnect (io->sock, io->read_tag);
1036 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
1038 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
1039 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1040 io_write (sock, msg);
1042 soup_message_io_finished (msg);
1046 case SOUP_MESSAGE_IO_STATE_DONE:
1048 g_return_if_reached ();
1055 socket_tls_certificate_changed (GObject *sock, GParamSpec *pspec,
1058 GTlsCertificate *certificate;
1059 GTlsCertificateFlags errors;
1062 SOUP_SOCKET_TLS_CERTIFICATE, &certificate,
1063 SOUP_SOCKET_TLS_ERRORS, &errors,
1066 SOUP_MESSAGE_TLS_CERTIFICATE, certificate,
1067 SOUP_MESSAGE_TLS_ERRORS, errors,
1070 g_object_unref (certificate);
1073 static SoupMessageIOData *
1074 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
1075 SoupMessageGetHeadersFn get_headers_cb,
1076 SoupMessageParseHeadersFn parse_headers_cb,
1077 gpointer header_data,
1078 SoupMessageCompletionFn completion_cb,
1079 gpointer completion_data)
1081 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1082 SoupMessageIOData *io;
1084 io = g_slice_new0 (SoupMessageIOData);
1085 io->sock = g_object_ref (sock);
1087 io->get_headers_cb = get_headers_cb;
1088 io->parse_headers_cb = parse_headers_cb;
1089 io->header_data = header_data;
1090 io->completion_cb = completion_cb;
1091 io->completion_data = completion_data;
1093 io->read_meta_buf = g_byte_array_new ();
1094 io->write_buf = g_string_new (NULL);
1096 io->read_tag = g_signal_connect (io->sock, "readable",
1097 G_CALLBACK (io_read), msg);
1098 io->write_tag = g_signal_connect (io->sock, "writable",
1099 G_CALLBACK (io_write), msg);
1101 io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1102 io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1104 if (soup_socket_is_ssl (io->sock)) {
1105 io->tls_signal_id = g_signal_connect (io->sock, "notify::tls-certificate",
1106 G_CALLBACK (socket_tls_certificate_changed), msg);
1110 soup_message_io_cleanup (msg);
1116 soup_message_io_client (SoupMessageQueueItem *item,
1117 SoupMessageGetHeadersFn get_headers_cb,
1118 SoupMessageParseHeadersFn parse_headers_cb,
1119 gpointer header_data,
1120 SoupMessageCompletionFn completion_cb,
1121 gpointer completion_data)
1123 SoupMessageIOData *io;
1124 SoupSocket *sock = soup_connection_get_socket (item->conn);
1126 io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
1127 get_headers_cb, parse_headers_cb, header_data,
1128 completion_cb, completion_data);
1131 soup_message_queue_item_ref (item);
1132 io->cancellable = item->cancellable;
1134 io->read_body = item->msg->response_body;
1135 io->write_body = item->msg->request_body;
1137 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1138 io_write (sock, item->msg);
1142 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
1143 SoupMessageGetHeadersFn get_headers_cb,
1144 SoupMessageParseHeadersFn parse_headers_cb,
1145 gpointer header_data,
1146 SoupMessageCompletionFn completion_cb,
1147 gpointer completion_data)
1149 SoupMessageIOData *io;
1151 io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
1152 get_headers_cb, parse_headers_cb, header_data,
1153 completion_cb, completion_data);
1155 io->read_body = msg->request_body;
1156 io->write_body = msg->response_body;
1158 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1159 io_read (sock, msg);
1163 soup_message_io_pause (SoupMessage *msg)
1165 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1166 SoupMessageIOData *io = priv->io_data;
1168 g_return_if_fail (io != NULL);
1170 if (io->write_tag) {
1171 g_signal_handler_disconnect (io->sock, io->write_tag);
1175 g_signal_handler_disconnect (io->sock, io->read_tag);
1179 if (io->unpause_source) {
1180 g_source_destroy (io->unpause_source);
1181 io->unpause_source = NULL;
1186 io_unpause_internal (gpointer msg)
1188 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1189 SoupMessageIOData *io = priv->io_data;
1191 g_return_val_if_fail (io != NULL, FALSE);
1192 io->unpause_source = NULL;
1194 if (io->write_tag || io->read_tag)
1197 if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
1198 io->write_tag = g_signal_connect (io->sock, "writable",
1199 G_CALLBACK (io_write), msg);
1202 if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
1203 io->read_tag = g_signal_connect (io->sock, "readable",
1204 G_CALLBACK (io_read), msg);
1207 if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
1208 io_write (io->sock, msg);
1209 else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
1210 io_read (io->sock, msg);
1216 soup_message_io_unpause (SoupMessage *msg)
1218 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1219 SoupMessageIOData *io = priv->io_data;
1220 gboolean non_blocking;
1221 GMainContext *async_context;
1223 g_return_if_fail (io != NULL);
1225 g_object_get (io->sock,
1226 SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
1227 SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1230 if (!io->unpause_source) {
1231 io->unpause_source = soup_add_completion (
1232 async_context, io_unpause_internal, msg);
1235 io_unpause_internal (msg);
1237 g_main_context_unref (async_context);
1241 * soup_message_io_in_progress:
1242 * @msg: a #SoupMessage
1244 * Tests whether or not I/O is currently in progress on @msg.
1246 * Return value: whether or not I/O is currently in progress.
1249 soup_message_io_in_progress (SoupMessage *msg)
1251 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1253 return priv->io_data != NULL;