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-coding.h"
16 #include "soup-connection.h"
17 #include "soup-message.h"
18 #include "soup-message-private.h"
19 #include "soup-message-queue.h"
20 #include "soup-misc.h"
21 #include "soup-socket.h"
25 SOUP_MESSAGE_IO_CLIENT,
26 SOUP_MESSAGE_IO_SERVER
30 SOUP_MESSAGE_IO_STATE_NOT_STARTED,
31 SOUP_MESSAGE_IO_STATE_HEADERS,
32 SOUP_MESSAGE_IO_STATE_BLOCKING,
33 SOUP_MESSAGE_IO_STATE_BODY,
34 SOUP_MESSAGE_IO_STATE_CHUNK_SIZE,
35 SOUP_MESSAGE_IO_STATE_CHUNK,
36 SOUP_MESSAGE_IO_STATE_CHUNK_END,
37 SOUP_MESSAGE_IO_STATE_TRAILERS,
38 SOUP_MESSAGE_IO_STATE_FINISHING,
39 SOUP_MESSAGE_IO_STATE_DONE
42 #define SOUP_MESSAGE_IO_STATE_ACTIVE(state) \
43 (state != SOUP_MESSAGE_IO_STATE_NOT_STARTED && \
44 state != SOUP_MESSAGE_IO_STATE_BLOCKING && \
45 state != SOUP_MESSAGE_IO_STATE_DONE)
49 SoupMessageQueueItem *item;
50 SoupMessageIOMode mode;
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, err_tag;
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;
106 g_object_unref (io->sock);
108 soup_message_queue_item_unref (io->item);
110 g_byte_array_free (io->read_meta_buf, TRUE);
112 g_string_free (io->write_buf, TRUE);
114 soup_buffer_free (io->write_chunk);
117 soup_message_body_free (io->sniff_data);
119 g_slice_free (SoupMessageIOData, io);
123 soup_message_io_stop (SoupMessage *msg)
125 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
126 SoupMessageIOData *io = priv->io_data;
132 g_signal_handler_disconnect (io->sock, io->read_tag);
136 g_signal_handler_disconnect (io->sock, io->write_tag);
140 g_signal_handler_disconnect (io->sock, io->err_tag);
144 if (io->unpause_source) {
145 g_source_destroy (io->unpause_source);
146 io->unpause_source = NULL;
149 if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
150 soup_socket_disconnect (io->sock);
151 else if (io->item && io->item->conn)
152 soup_connection_set_state (io->item->conn, SOUP_CONNECTION_IDLE);
155 #define SOUP_MESSAGE_IO_EOL "\r\n"
156 #define SOUP_MESSAGE_IO_EOL_LEN 2
159 soup_message_io_finished (SoupMessage *msg)
161 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
162 SoupMessageIOData *io = priv->io_data;
163 SoupMessageCompletionFn completion_cb = io->completion_cb;
164 gpointer completion_data = io->completion_data;
167 soup_message_io_cleanup (msg);
169 completion_cb (msg, completion_data);
170 g_object_unref (msg);
173 static void io_read (SoupSocket *sock, SoupMessage *msg);
176 request_is_idempotent (SoupMessage *msg)
179 return (msg->method == SOUP_METHOD_GET);
183 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
185 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
186 SoupMessageIOData *io = priv->io_data;
188 if (error && error->domain == G_TLS_ERROR) {
189 soup_message_set_status_full (msg,
190 SOUP_STATUS_SSL_FAILED,
192 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
193 io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS &&
194 io->read_meta_buf->len == 0 &&
195 soup_connection_get_ever_used (io->item->conn) &&
196 !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) &&
197 request_is_idempotent (msg)) {
198 /* Connection got closed, but we can safely try again */
199 io->item->state = SOUP_MESSAGE_RESTARTING;
200 } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code))
201 soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
204 g_error_free (error);
206 soup_message_io_finished (msg);
210 io_disconnected (SoupSocket *sock, SoupMessage *msg)
212 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
213 SoupMessageIOData *io = priv->io_data;
215 /* Closing the connection to signify EOF is sometimes ok */
216 if (io->read_state == SOUP_MESSAGE_IO_STATE_BODY && io->read_eof_ok) {
217 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
222 io_error (sock, msg, NULL);
226 io_handle_sniffing (SoupMessage *msg, gboolean done_reading)
228 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
229 SoupMessageIOData *io = priv->io_data;
230 SoupBuffer *sniffed_buffer;
231 char *sniffed_mime_type;
232 GHashTable *params = NULL;
237 if (!io->sniff_data) {
238 io->sniff_data = soup_message_body_new ();
239 io->need_content_sniffed = TRUE;
242 if (io->need_content_sniffed) {
243 if (io->sniff_data->length < priv->bytes_for_sniffing &&
247 io->need_content_sniffed = FALSE;
248 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
249 sniffed_mime_type = soup_content_sniffer_sniff (priv->sniffer, msg, sniffed_buffer, ¶ms);
251 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
252 soup_message_content_sniffed (msg, sniffed_mime_type, params);
253 g_free (sniffed_mime_type);
255 g_hash_table_destroy (params);
257 soup_buffer_free (sniffed_buffer);
258 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
261 if (io->need_got_chunk) {
262 io->need_got_chunk = FALSE;
263 sniffed_buffer = soup_message_body_flatten (io->sniff_data);
265 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
266 soup_message_got_chunk (msg, sniffed_buffer);
267 soup_buffer_free (sniffed_buffer);
268 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
274 /* Reads data from io->sock into io->read_meta_buf. If @to_blank is
275 * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF").
276 * Otherwise, it reads up until a single CRLF or LF.
278 * This function is used to read metadata, and read_body_chunk() is
279 * used to read the message body contents.
281 * read_metadata, read_body_chunk, and write_data all use the same
282 * convention for return values: if they return %TRUE, it means
283 * they've completely finished the requested read/write, and the
284 * caller should move on to the next step. If they return %FALSE, it
285 * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
286 * so the caller should give up for now and wait for the socket to
287 * emit a signal, or (b) the socket returned an error, and io_error()
288 * was called to process it and cancel the I/O. So either way, if the
289 * function returns %FALSE, the caller should return immediately.
292 read_metadata (SoupMessage *msg, gboolean to_blank)
294 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
295 SoupMessageIOData *io = priv->io_data;
296 SoupSocketIOStatus status;
297 guchar read_buf[RESPONSE_BLOCK_SIZE];
300 GError *error = NULL;
303 status = soup_socket_read_until (io->sock, read_buf,
305 "\n", 1, &nread, &got_lf,
309 g_byte_array_append (io->read_meta_buf, read_buf, nread);
312 case SOUP_SOCKET_EOF:
313 /* More lame server handling... deal with
314 * servers that don't send the final chunk.
316 if (io->read_state == SOUP_MESSAGE_IO_STATE_CHUNK_SIZE &&
317 io->read_meta_buf->len == 0) {
318 g_byte_array_append (io->read_meta_buf,
319 (guchar *)"0\r\n", 3);
322 } else if (io->read_state == SOUP_MESSAGE_IO_STATE_TRAILERS &&
323 io->read_meta_buf->len == 0) {
324 g_byte_array_append (io->read_meta_buf,
325 (guchar *)"\r\n", 2);
329 /* else fall through */
331 case SOUP_SOCKET_ERROR:
332 io_error (io->sock, msg, error);
335 case SOUP_SOCKET_WOULD_BLOCK:
343 !strncmp ((char *)io->read_meta_buf->data +
344 io->read_meta_buf->len - 2,
347 else if (nread == 2 &&
348 !strncmp ((char *)io->read_meta_buf->data +
349 io->read_meta_buf->len - 3,
359 content_decode (SoupMessage *msg, SoupBuffer *buf)
361 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
364 GError *error = NULL;
367 for (d = priv->decoders; d; d = d->next) {
370 decoded = soup_coding_apply (decoder, buf->data, buf->length,
373 if (g_error_matches (error, SOUP_CODING_ERROR, SOUP_CODING_ERROR_INTERNAL_ERROR))
374 g_warning ("Content-Decoding error: %s\n", error->message);
375 g_error_free (error);
377 soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED);
381 soup_buffer_free (buf);
392 /* Reads as much message body data as is available on io->sock (but no
393 * further than the end of the current message body or chunk). On a
394 * successful read, emits "got_chunk" (possibly multiple times), and
395 * (unless told not to) appends the chunk to io->read_body.
397 * See the note at read_metadata() for an explanation of the return
401 read_body_chunk (SoupMessage *msg)
403 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
404 SoupMessageIOData *io = priv->io_data;
405 SoupSocketIOStatus status;
406 guchar *stack_buf = NULL;
408 gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
410 GError *error = NULL;
413 if (!io_handle_sniffing (msg, FALSE))
416 while (read_to_eof || io->read_length > 0) {
417 if (priv->chunk_allocator) {
418 buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
420 soup_message_io_pause (msg);
425 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
426 buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
428 RESPONSE_BLOCK_SIZE);
432 len = buffer->length;
434 len = MIN (buffer->length, io->read_length);
436 status = soup_socket_read (io->sock,
437 (guchar *)buffer->data, len,
438 &nread, NULL, &error);
440 if (status == SOUP_SOCKET_OK && nread) {
441 buffer->length = nread;
442 io->read_length -= nread;
444 buffer = content_decode (msg, buffer);
448 soup_message_body_got_chunk (io->read_body, buffer);
450 if (io->need_content_sniffed) {
451 soup_message_body_append_buffer (io->sniff_data, buffer);
452 soup_buffer_free (buffer);
453 io->need_got_chunk = TRUE;
454 if (!io_handle_sniffing (msg, FALSE))
459 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
460 soup_message_got_chunk (msg, buffer);
461 soup_buffer_free (buffer);
462 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
466 soup_buffer_free (buffer);
471 case SOUP_SOCKET_EOF:
472 if (io->read_eof_ok) {
476 /* else fall through */
478 case SOUP_SOCKET_ERROR:
479 io_error (io->sock, msg, error);
482 case SOUP_SOCKET_WOULD_BLOCK:
490 /* Attempts to write @len bytes from @data. See the note at
491 * read_metadata() for an explanation of the return value.
494 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
496 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
497 SoupMessageIOData *io = priv->io_data;
498 SoupSocketIOStatus status;
500 GError *error = NULL;
504 while (len > io->written) {
505 status = soup_socket_write (io->sock,
508 &nwrote, NULL, &error);
510 case SOUP_SOCKET_EOF:
511 case SOUP_SOCKET_ERROR:
512 io_error (io->sock, msg, error);
515 case SOUP_SOCKET_WOULD_BLOCK:
519 start = data + io->written;
520 io->written += nwrote;
523 if (io->write_length)
524 io->write_length -= nwrote;
526 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
528 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
529 soup_message_wrote_body_data (msg, chunk);
530 soup_buffer_free (chunk);
531 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
541 static inline SoupMessageIOState
542 io_body_state (SoupEncoding encoding)
544 if (encoding == SOUP_ENCODING_CHUNKED)
545 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
547 return SOUP_MESSAGE_IO_STATE_BODY;
551 * There are two request/response formats: the basic request/response,
552 * possibly with one or more unsolicited informational responses (such
553 * as the WebDAV "102 Processing" response):
556 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
557 * W:BODY / R:NOT_STARTED -> R:BODY / W:NOT_STARTED
558 * [W:DONE / R:HEADERS (1xx) <- R:DONE / W:HEADERS (1xx) ...]
559 * W:DONE / R:HEADERS <- R:DONE / W:HEADERS
560 * W:DONE / R:BODY <- R:DONE / W:BODY
561 * W:DONE / R:DONE R:DONE / W:DONE
563 * and the "Expect: 100-continue" request/response, with the client
564 * blocking halfway through its request, and then either continuing or
565 * aborting, depending on the server response:
568 * W:HEADERS / R:NOT_STARTED -> R:HEADERS / W:NOT_STARTED
569 * W:BLOCKING / R:HEADERS <- R:BLOCKING / W:HEADERS
570 * [W:BODY / R:BLOCKING -> R:BODY / W:BLOCKING]
571 * [W:DONE / R:HEADERS <- R:DONE / W:HEADERS]
572 * W:DONE / R:BODY <- R:DONE / W:BODY
573 * W:DONE / R:DONE R:DONE / W:DONE
577 io_write (SoupSocket *sock, SoupMessage *msg)
579 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
580 SoupMessageIOData *io = priv->io_data;
583 switch (io->write_state) {
584 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
588 case SOUP_MESSAGE_IO_STATE_HEADERS:
589 if (!io->write_buf->len) {
590 io->get_headers_cb (msg, io->write_buf,
593 if (!io->write_buf->len) {
594 soup_message_io_pause (msg);
599 if (!write_data (msg, io->write_buf->str,
600 io->write_buf->len, FALSE))
603 g_string_truncate (io->write_buf, 0);
605 if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
606 SoupMessageHeaders *hdrs =
607 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
608 msg->request_headers : msg->response_headers;
609 io->write_length = soup_message_headers_get_content_length (hdrs);
612 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
613 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
614 if (msg->status_code == SOUP_STATUS_CONTINUE) {
615 /* Stop and wait for the body now */
617 SOUP_MESSAGE_IO_STATE_BLOCKING;
618 io->read_state = io_body_state (io->read_encoding);
620 /* We just wrote a 1xx response
621 * header, so stay in STATE_HEADERS.
622 * (The caller will pause us from the
623 * wrote_informational callback if he
624 * is not ready to send the final
628 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
629 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
630 /* Need to wait for the Continue response */
631 io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
632 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
634 io->write_state = io_body_state (io->write_encoding);
636 /* If the client was waiting for a Continue
637 * but we sent something else, then they're
640 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
641 io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
642 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
645 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
646 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
647 soup_message_wrote_informational (msg);
648 soup_message_cleanup_response (msg);
650 soup_message_wrote_headers (msg);
651 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
655 case SOUP_MESSAGE_IO_STATE_BLOCKING:
658 /* If io_read reached a point where we could write
659 * again, it would have recursively called io_write.
660 * So (a) we don't need to try to keep writing, and
661 * (b) we can't anyway, because msg may have been
667 case SOUP_MESSAGE_IO_STATE_BODY:
668 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
670 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
672 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
673 soup_message_wrote_body (msg);
674 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
678 if (!io->write_chunk) {
679 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
680 if (!io->write_chunk) {
681 soup_message_io_pause (msg);
684 if (io->write_chunk->length > io->write_length &&
685 io->write_encoding != SOUP_ENCODING_EOF) {
686 /* App is trying to write more than it
687 * claimed it would; we have to truncate.
689 SoupBuffer *truncated =
690 soup_buffer_new_subbuffer (io->write_chunk,
691 0, io->write_length);
692 soup_buffer_free (io->write_chunk);
693 io->write_chunk = truncated;
694 } else if (io->write_encoding == SOUP_ENCODING_EOF &&
695 !io->write_chunk->length)
699 if (!write_data (msg, io->write_chunk->data,
700 io->write_chunk->length, TRUE))
703 if (io->mode == SOUP_MESSAGE_IO_SERVER)
704 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
705 io->write_body_offset += io->write_chunk->length;
706 soup_buffer_free (io->write_chunk);
707 io->write_chunk = NULL;
709 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
710 soup_message_wrote_chunk (msg);
711 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
714 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
715 if (!io->write_chunk) {
716 io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
717 if (!io->write_chunk) {
718 soup_message_io_pause (msg);
721 g_string_append_printf (io->write_buf, "%lx\r\n",
722 (unsigned long) io->write_chunk->length);
723 io->write_body_offset += io->write_chunk->length;
726 if (!write_data (msg, io->write_buf->str,
727 io->write_buf->len, FALSE))
730 g_string_truncate (io->write_buf, 0);
732 if (io->write_chunk->length == 0) {
733 /* The last chunk has no CHUNK_END... */
734 io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
738 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
742 case SOUP_MESSAGE_IO_STATE_CHUNK:
743 if (!write_data (msg, io->write_chunk->data,
744 io->write_chunk->length, TRUE))
747 if (io->mode == SOUP_MESSAGE_IO_SERVER)
748 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
749 soup_buffer_free (io->write_chunk);
750 io->write_chunk = NULL;
752 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
754 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
755 soup_message_wrote_chunk (msg);
756 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
761 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
762 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
763 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
766 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
770 case SOUP_MESSAGE_IO_STATE_TRAILERS:
771 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
772 SOUP_MESSAGE_IO_EOL_LEN, FALSE))
775 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
777 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
778 soup_message_wrote_body (msg);
779 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
783 case SOUP_MESSAGE_IO_STATE_FINISHING:
785 g_signal_handler_disconnect (io->sock, io->write_tag);
788 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
790 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
791 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
794 soup_message_io_finished (msg);
798 case SOUP_MESSAGE_IO_STATE_DONE:
800 g_return_if_reached ();
807 io_read (SoupSocket *sock, SoupMessage *msg)
809 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
810 SoupMessageIOData *io = priv->io_data;
814 switch (io->read_state) {
815 case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
819 case SOUP_MESSAGE_IO_STATE_HEADERS:
820 if (!read_metadata (msg, TRUE))
823 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
824 soup_socket_is_ssl (io->sock)) {
825 GTlsCertificate *certificate;
826 GTlsCertificateFlags errors;
828 g_object_get (io->sock,
829 SOUP_SOCKET_TLS_CERTIFICATE, &certificate,
830 SOUP_SOCKET_TLS_ERRORS, &errors,
834 SOUP_MESSAGE_TLS_CERTIFICATE, certificate,
835 SOUP_MESSAGE_TLS_ERRORS, errors,
837 g_object_unref (certificate);
841 /* We need to "rewind" io->read_meta_buf back one line.
842 * That SHOULD be two characters (CR LF), but if the
843 * web server was stupid, it might only be one.
845 if (io->read_meta_buf->len < 3 ||
846 io->read_meta_buf->data[io->read_meta_buf->len - 2] == '\n')
847 io->read_meta_buf->len--;
849 io->read_meta_buf->len -= 2;
850 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
851 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
852 io->read_meta_buf->len,
855 g_byte_array_set_size (io->read_meta_buf, 0);
857 if (status != SOUP_STATUS_OK) {
858 /* Either we couldn't parse the headers, or they
859 * indicated something that would mean we wouldn't
860 * be able to parse the body. (Eg, unknown
861 * Transfer-Encoding.). Skip the rest of the
862 * reading, and make sure the connection gets
863 * closed when we're done.
865 soup_message_set_status (msg, status);
866 soup_message_headers_append (msg->request_headers,
867 "Connection", "close");
868 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
872 if (io->read_encoding == SOUP_ENCODING_EOF)
873 io->read_eof_ok = TRUE;
875 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
876 SoupMessageHeaders *hdrs =
877 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
878 msg->response_headers : msg->request_headers;
879 io->read_length = soup_message_headers_get_content_length (hdrs);
881 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
882 !soup_message_is_keepalive (msg)) {
883 /* Some servers suck and send
884 * incorrect Content-Length values, so
885 * allow EOF termination in this case
886 * (iff the message is too short) too.
888 io->read_eof_ok = TRUE;
892 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
893 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
894 if (msg->status_code == SOUP_STATUS_CONTINUE &&
895 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
896 /* Pause the reader, unpause the writer */
898 SOUP_MESSAGE_IO_STATE_BLOCKING;
900 io_body_state (io->write_encoding);
902 /* Just stay in HEADERS */
903 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
905 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
906 soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
907 /* The client requested a Continue response. The
908 * got_headers handler may change this to something
911 soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
912 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
913 io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
915 io->read_state = io_body_state (io->read_encoding);
917 /* If the client was waiting for a Continue
918 * but got something else, then it's done
921 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
922 io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
923 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
926 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
927 SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
928 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
929 soup_message_got_informational (msg);
930 soup_message_cleanup_response (msg);
931 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
933 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
934 soup_message_got_headers (msg);
935 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
940 case SOUP_MESSAGE_IO_STATE_BLOCKING:
941 io_write (sock, msg);
943 /* As in the io_write case, we *must* return here. */
947 case SOUP_MESSAGE_IO_STATE_BODY:
948 if (!read_body_chunk (msg))
952 if (!io_handle_sniffing (msg, TRUE)) {
953 /* If the message was paused (as opposed to
954 * cancelled), we need to make sure we wind up
955 * back here when it's unpaused, even if it
956 * was doing a chunked or EOF-terminated read
959 if (io == priv->io_data) {
960 io->read_state = SOUP_MESSAGE_IO_STATE_BODY;
961 io->read_encoding = SOUP_ENCODING_CONTENT_LENGTH;
967 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
969 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
970 soup_message_got_body (msg);
971 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
975 case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
976 if (!read_metadata (msg, FALSE))
979 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
980 g_byte_array_set_size (io->read_meta_buf, 0);
982 if (io->read_length > 0)
983 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
985 io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
989 case SOUP_MESSAGE_IO_STATE_CHUNK:
990 if (!read_body_chunk (msg))
993 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
997 case SOUP_MESSAGE_IO_STATE_CHUNK_END:
998 if (!read_metadata (msg, FALSE))
1001 g_byte_array_set_size (io->read_meta_buf, 0);
1002 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
1006 case SOUP_MESSAGE_IO_STATE_TRAILERS:
1007 if (!read_metadata (msg, FALSE))
1010 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
1013 /* FIXME: process trailers */
1014 g_byte_array_set_size (io->read_meta_buf, 0);
1018 case SOUP_MESSAGE_IO_STATE_FINISHING:
1020 g_signal_handler_disconnect (io->sock, io->read_tag);
1023 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
1025 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
1026 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1027 io_write (sock, msg);
1029 soup_message_io_finished (msg);
1033 case SOUP_MESSAGE_IO_STATE_DONE:
1035 g_return_if_reached ();
1041 static SoupMessageIOData *
1042 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
1043 SoupMessageGetHeadersFn get_headers_cb,
1044 SoupMessageParseHeadersFn parse_headers_cb,
1045 gpointer header_data,
1046 SoupMessageCompletionFn completion_cb,
1047 gpointer completion_data)
1049 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1050 SoupMessageIOData *io;
1052 io = g_slice_new0 (SoupMessageIOData);
1053 io->sock = g_object_ref (sock);
1055 io->get_headers_cb = get_headers_cb;
1056 io->parse_headers_cb = parse_headers_cb;
1057 io->header_data = header_data;
1058 io->completion_cb = completion_cb;
1059 io->completion_data = completion_data;
1061 io->read_meta_buf = g_byte_array_new ();
1062 io->write_buf = g_string_new (NULL);
1064 io->read_tag = g_signal_connect (io->sock, "readable",
1065 G_CALLBACK (io_read), msg);
1066 io->write_tag = g_signal_connect (io->sock, "writable",
1067 G_CALLBACK (io_write), msg);
1068 io->err_tag = g_signal_connect (io->sock, "disconnected",
1069 G_CALLBACK (io_disconnected), msg);
1071 io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1072 io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
1075 soup_message_io_cleanup (msg);
1081 soup_message_io_client (SoupMessageQueueItem *item,
1082 SoupMessageGetHeadersFn get_headers_cb,
1083 SoupMessageParseHeadersFn parse_headers_cb,
1084 gpointer header_data,
1085 SoupMessageCompletionFn completion_cb,
1086 gpointer completion_data)
1088 SoupMessageIOData *io;
1089 SoupSocket *sock = soup_connection_get_socket (item->conn);
1091 io = new_iostate (item->msg, sock, SOUP_MESSAGE_IO_CLIENT,
1092 get_headers_cb, parse_headers_cb, header_data,
1093 completion_cb, completion_data);
1096 soup_message_queue_item_ref (item);
1098 io->read_body = item->msg->response_body;
1099 io->write_body = item->msg->request_body;
1101 io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1102 io_write (sock, item->msg);
1106 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
1107 SoupMessageGetHeadersFn get_headers_cb,
1108 SoupMessageParseHeadersFn parse_headers_cb,
1109 gpointer header_data,
1110 SoupMessageCompletionFn completion_cb,
1111 gpointer completion_data)
1113 SoupMessageIOData *io;
1115 io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
1116 get_headers_cb, parse_headers_cb, header_data,
1117 completion_cb, completion_data);
1119 io->read_body = msg->request_body;
1120 io->write_body = msg->response_body;
1122 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
1123 io_read (sock, msg);
1127 soup_message_io_pause (SoupMessage *msg)
1129 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1130 SoupMessageIOData *io = priv->io_data;
1132 g_return_if_fail (io != NULL);
1134 if (io->write_tag) {
1135 g_signal_handler_disconnect (io->sock, io->write_tag);
1139 g_signal_handler_disconnect (io->sock, io->read_tag);
1143 if (io->unpause_source) {
1144 g_source_destroy (io->unpause_source);
1145 io->unpause_source = NULL;
1150 io_unpause_internal (gpointer msg)
1152 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1153 SoupMessageIOData *io = priv->io_data;
1155 g_return_val_if_fail (io != NULL, FALSE);
1156 io->unpause_source = NULL;
1158 if (io->write_tag || io->read_tag)
1161 if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
1162 io->write_tag = g_signal_connect (io->sock, "writable",
1163 G_CALLBACK (io_write), msg);
1166 if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
1167 io->read_tag = g_signal_connect (io->sock, "readable",
1168 G_CALLBACK (io_read), msg);
1171 if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
1172 io_write (io->sock, msg);
1173 else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
1174 io_read (io->sock, msg);
1180 soup_message_io_unpause (SoupMessage *msg)
1182 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1183 SoupMessageIOData *io = priv->io_data;
1184 gboolean non_blocking;
1185 GMainContext *async_context;
1187 g_return_if_fail (io != NULL);
1189 g_object_get (io->sock,
1190 SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
1191 SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1194 if (!io->unpause_source) {
1195 io->unpause_source = soup_add_completion (
1196 async_context, io_unpause_internal, msg);
1199 io_unpause_internal (msg);
1201 g_main_context_unref (async_context);
1205 * soup_message_io_in_progress:
1206 * @msg: a #SoupMessage
1208 * Tests whether or not I/O is currently in progress on @msg.
1210 * Return value: whether or not I/O is currently in progress.
1213 soup_message_io_in_progress (SoupMessage *msg)
1215 SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1217 return priv->io_data != NULL;