Fix the header/body boundary detection logic
[platform/upstream/libsoup.git] / libsoup / soup-message-io.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-message-io.c: HTTP message I/O
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <stdlib.h>
13 #include <string.h>
14
15 #include "soup-connection.h"
16 #include "soup-message.h"
17 #include "soup-message-private.h"
18 #include "soup-misc.h"
19 #include "soup-socket.h"
20 #include "soup-ssl.h"
21
22 typedef enum {
23         SOUP_MESSAGE_IO_CLIENT,
24         SOUP_MESSAGE_IO_SERVER
25 } SoupMessageIOMode;
26
27 typedef enum {
28         SOUP_MESSAGE_IO_STATE_NOT_STARTED,
29         SOUP_MESSAGE_IO_STATE_HEADERS,
30         SOUP_MESSAGE_IO_STATE_BLOCKING,
31         SOUP_MESSAGE_IO_STATE_BODY,
32         SOUP_MESSAGE_IO_STATE_CHUNK_SIZE,
33         SOUP_MESSAGE_IO_STATE_CHUNK,
34         SOUP_MESSAGE_IO_STATE_CHUNK_END,
35         SOUP_MESSAGE_IO_STATE_TRAILERS,
36         SOUP_MESSAGE_IO_STATE_FINISHING,
37         SOUP_MESSAGE_IO_STATE_DONE
38 } SoupMessageIOState;
39
40 #define SOUP_MESSAGE_IO_STATE_ACTIVE(state) \
41         (state != SOUP_MESSAGE_IO_STATE_NOT_STARTED && \
42          state != SOUP_MESSAGE_IO_STATE_BLOCKING && \
43          state != SOUP_MESSAGE_IO_STATE_DONE)
44
45 typedef struct {
46         SoupSocket           *sock;
47         SoupConnection       *conn;
48         SoupMessageIOMode     mode;
49
50         SoupMessageIOState    read_state;
51         SoupEncoding          read_encoding;
52         GByteArray           *read_meta_buf;
53         SoupMessageBody      *read_body;
54         goffset               read_length;
55
56         SoupMessageIOState    write_state;
57         SoupEncoding          write_encoding;
58         GString              *write_buf;
59         SoupMessageBody      *write_body;
60         SoupBuffer           *write_chunk;
61         gsize                 write_body_offset;
62         goffset               write_length;
63         goffset               written;
64
65         guint read_tag, write_tag, err_tag;
66         GSource *unpause_source;
67
68         SoupMessageGetHeadersFn   get_headers_cb;
69         SoupMessageParseHeadersFn parse_headers_cb;
70         gpointer                  user_data;
71 } SoupMessageIOData;
72         
73
74 /* Put these around callback invocation if there is code afterward
75  * that depends on the IO having not been cancelled.
76  */
77 #define dummy_to_make_emacs_happy {
78 #define SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK { gboolean cancelled; g_object_ref (msg);
79 #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; }
80 #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; }
81
82 #define RESPONSE_BLOCK_SIZE 8192
83
84 void
85 soup_message_io_cleanup (SoupMessage *msg)
86 {
87         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
88         SoupMessageIOData *io;
89
90         soup_message_io_stop (msg);
91
92         io = priv->io_data;
93         if (!io)
94                 return;
95         priv->io_data = NULL;
96
97         if (io->sock)
98                 g_object_unref (io->sock);
99         if (io->conn)
100                 g_object_unref (io->conn);
101
102         g_byte_array_free (io->read_meta_buf, TRUE);
103
104         g_string_free (io->write_buf, TRUE);
105         if (io->write_chunk)
106                 soup_buffer_free (io->write_chunk);
107
108         g_slice_free (SoupMessageIOData, io);
109 }
110
111 /**
112  * soup_message_io_stop:
113  * @msg: a #SoupMessage
114  *
115  * Immediately stops I/O on msg; if the connection would be left in an
116  * inconsistent state, it will be closed.
117  *
118  * Note: this is a low-level function that does not cause any signals
119  * to be emitted on @msg; it is up to the caller to make sure that
120  * @msg doesn't get "stranded".
121  **/
122 void
123 soup_message_io_stop (SoupMessage *msg)
124 {
125         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
126         SoupMessageIOData *io = priv->io_data;
127
128         if (!io)
129                 return;
130
131         if (io->read_tag) {
132                 g_signal_handler_disconnect (io->sock, io->read_tag);
133                 io->read_tag = 0;
134         }
135         if (io->write_tag) {
136                 g_signal_handler_disconnect (io->sock, io->write_tag);
137                 io->write_tag = 0;
138         }
139         if (io->err_tag) {
140                 g_signal_handler_disconnect (io->sock, io->err_tag);
141                 io->err_tag = 0;
142         }
143
144         if (io->unpause_source) {
145                 g_source_destroy (io->unpause_source);
146                 io->unpause_source = NULL;
147         }
148
149         if (io->read_state < SOUP_MESSAGE_IO_STATE_FINISHING)
150                 soup_socket_disconnect (io->sock);
151         else if (io->conn) {
152                 SoupConnection *conn = io->conn;
153                 io->conn = NULL;
154                 soup_connection_release (conn);
155                 g_object_unref (conn);
156         }
157 }
158
159 #define SOUP_MESSAGE_IO_EOL            "\r\n"
160 #define SOUP_MESSAGE_IO_EOL_LEN        2
161
162 static void
163 soup_message_io_finished (SoupMessage *msg)
164 {
165         g_object_ref (msg);
166         soup_message_io_cleanup (msg);
167         if (SOUP_MESSAGE_IS_STARTING (msg))
168                 soup_message_restarted (msg);
169         else
170                 soup_message_finished (msg);
171         g_object_unref (msg);
172 }
173
174 static void io_read (SoupSocket *sock, SoupMessage *msg);
175
176 static void
177 io_error (SoupSocket *sock, SoupMessage *msg, GError *error)
178 {
179         if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) {
180                 if (error && error->domain == SOUP_SSL_ERROR) {
181                         soup_message_set_status_full (msg,
182                                                       SOUP_STATUS_SSL_FAILED,
183                                                       error->message);
184                 } else
185                         soup_message_set_status (msg, SOUP_STATUS_IO_ERROR);
186         }
187         if (error)
188                 g_error_free (error);
189
190         soup_message_io_finished (msg);
191 }
192
193 static void
194 io_disconnected (SoupSocket *sock, SoupMessage *msg)
195 {
196         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
197         SoupMessageIOData *io = priv->io_data;
198
199         /* Closing the connection to signify EOF is sometimes ok */
200         if (io->read_state == SOUP_MESSAGE_IO_STATE_BODY &&
201             io->read_encoding == SOUP_ENCODING_EOF) {
202                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
203                 io_read (sock, msg);
204                 return;
205         }
206
207         io_error (sock, msg, NULL);
208 }
209
210 /* Reads data from io->sock into io->read_meta_buf. If @to_blank is
211  * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF").
212  * Otherwise, it reads up until a single CRLF or LF.
213  *
214  * This function is used to read metadata, and read_body_chunk() is
215  * used to read the message body contents.
216  *
217  * read_metadata, read_body_chunk, and write_data all use the same
218  * convention for return values: if they return %TRUE, it means
219  * they've completely finished the requested read/write, and the
220  * caller should move on to the next step. If they return %FALSE, it
221  * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK,
222  * so the caller should give up for now and wait for the socket to
223  * emit a signal, or (b) the socket returned an error, and io_error()
224  * was called to process it and cancel the I/O. So either way, if the
225  * function returns %FALSE, the caller should return immediately.
226  */
227 static gboolean
228 read_metadata (SoupMessage *msg, gboolean to_blank)
229 {
230         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
231         SoupMessageIOData *io = priv->io_data;
232         SoupSocketIOStatus status;
233         guchar read_buf[RESPONSE_BLOCK_SIZE];
234         gsize nread;
235         gboolean got_lf;
236         GError *error = NULL;
237
238         while (1) {
239                 status = soup_socket_read_until (io->sock, read_buf,
240                                                  sizeof (read_buf),
241                                                  "\n", 1, &nread, &got_lf,
242                                                  NULL, &error);
243                 switch (status) {
244                 case SOUP_SOCKET_OK:
245                         g_byte_array_append (io->read_meta_buf, read_buf, nread);
246                         break;
247
248                 case SOUP_SOCKET_ERROR:
249                 case SOUP_SOCKET_EOF:
250                         io_error (io->sock, msg, error);
251                         return FALSE;
252
253                 case SOUP_SOCKET_WOULD_BLOCK:
254                         return FALSE;
255                 }
256
257                 if (got_lf) {
258                         if (!to_blank)
259                                 break;
260                         if (nread == 1 &&
261                             !strncmp (io->read_meta_buf->data +
262                                       io->read_meta_buf->len - 2,
263                                       "\n\n", 2))
264                                 break;
265                         else if (nread == 2 &&
266                                  !strncmp (io->read_meta_buf->data +
267                                            io->read_meta_buf->len - 3,
268                                            "\n\r\n", 3))
269                                 break;
270                 }
271         }
272
273         return TRUE;
274 }
275
276 /* Reads as much message body data as is available on io->sock (but no
277  * further than the end of the current message body or chunk). On a
278  * successful read, emits "got_chunk" (possibly multiple times), and
279  * (unless told not to) appends the chunk to io->read_body.
280  *
281  * See the note at read_metadata() for an explanation of the return
282  * value.
283  */
284 static gboolean
285 read_body_chunk (SoupMessage *msg)
286 {
287         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
288         SoupMessageIOData *io = priv->io_data;
289         SoupSocketIOStatus status;
290         guchar *stack_buf = NULL;
291         gsize len;
292         gboolean read_to_eof = (io->read_encoding == SOUP_ENCODING_EOF);
293         gsize nread;
294         GError *error = NULL;
295         SoupBuffer *buffer;
296
297         while (read_to_eof || io->read_length > 0) {
298                 if (priv->chunk_allocator) {
299                         buffer = priv->chunk_allocator (msg, io->read_length, priv->chunk_allocator_data);
300                         if (!buffer) {
301                                 soup_message_io_pause (msg);
302                                 return FALSE;
303                         }
304                 } else {
305                         if (!stack_buf)
306                                 stack_buf = alloca (RESPONSE_BLOCK_SIZE);
307                         buffer = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
308                                                   stack_buf,
309                                                   RESPONSE_BLOCK_SIZE);
310                 }
311
312                 if (read_to_eof)
313                         len = buffer->length;
314                 else
315                         len = MIN (buffer->length, io->read_length);
316
317                 status = soup_socket_read (io->sock,
318                                            (guchar *)buffer->data, len,
319                                            &nread, NULL, &error);
320
321                 if (status == SOUP_SOCKET_OK && nread) {
322                         buffer->length = nread;
323                         soup_message_body_got_chunk (io->read_body, buffer);
324
325                         io->read_length -= nread;
326
327                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
328                         soup_message_got_chunk (msg, buffer);
329                         soup_buffer_free (buffer);
330                         SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
331                         continue;
332                 }
333
334                 soup_buffer_free (buffer);
335                 switch (status) {
336                 case SOUP_SOCKET_OK:
337                         break;
338
339                 case SOUP_SOCKET_EOF:
340                         if (read_to_eof)
341                                 return TRUE;
342                         /* else fall through */
343
344                 case SOUP_SOCKET_ERROR:
345                         io_error (io->sock, msg, error);
346                         return FALSE;
347
348                 case SOUP_SOCKET_WOULD_BLOCK:
349                         return FALSE;
350                 }
351         }
352
353         return TRUE;
354 }
355
356 /* Attempts to write @len bytes from @data. See the note at
357  * read_metadata() for an explanation of the return value.
358  */
359 static gboolean
360 write_data (SoupMessage *msg, const char *data, guint len, gboolean body)
361 {
362         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
363         SoupMessageIOData *io = priv->io_data;
364         SoupSocketIOStatus status;
365         gsize nwrote;
366         GError *error = NULL;
367         SoupBuffer *chunk;
368         const char *start;
369
370         while (len > io->written) {
371                 status = soup_socket_write (io->sock,
372                                             data + io->written,
373                                             len - io->written,
374                                             &nwrote, NULL, &error);
375                 switch (status) {
376                 case SOUP_SOCKET_EOF:
377                 case SOUP_SOCKET_ERROR:
378                         io_error (io->sock, msg, error);
379                         return FALSE;
380
381                 case SOUP_SOCKET_WOULD_BLOCK:
382                         return FALSE;
383
384                 case SOUP_SOCKET_OK:
385                         start = data + io->written;
386                         io->written += nwrote;
387
388                         if (body) {
389                                 if (io->write_length)
390                                         io->write_length -= nwrote;
391
392                                 chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY,
393                                                          start, nwrote);
394                                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
395                                 soup_message_wrote_body_data (msg, chunk);
396                                 soup_buffer_free (chunk);
397                                 SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE);
398                         }
399                         break;
400                 }
401         }
402
403         io->written = 0;
404         return TRUE;
405 }
406
407 static inline SoupMessageIOState
408 io_body_state (SoupEncoding encoding)
409 {
410         if (encoding == SOUP_ENCODING_CHUNKED)
411                 return SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
412         else
413                 return SOUP_MESSAGE_IO_STATE_BODY;
414 }
415
416 /*
417  * There are two request/response formats: the basic request/response,
418  * possibly with one or more unsolicited informational responses (such
419  * as the WebDAV "102 Processing" response):
420  *
421  *     Client                            Server
422  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
423  *      W:BODY     / R:NOT_STARTED    ->  R:BODY     / W:NOT_STARTED
424  *     [W:DONE     / R:HEADERS (1xx)  <-  R:DONE     / W:HEADERS (1xx) ...]
425  *      W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS
426  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
427  *      W:DONE     / R:DONE               R:DONE     / W:DONE
428  *     
429  * and the "Expect: 100-continue" request/response, with the client
430  * blocking halfway through its request, and then either continuing or
431  * aborting, depending on the server response:
432  *
433  *     Client                            Server
434  *      W:HEADERS  / R:NOT_STARTED    ->  R:HEADERS  / W:NOT_STARTED
435  *      W:BLOCKING / R:HEADERS        <-  R:BLOCKING / W:HEADERS
436  *     [W:BODY     / R:BLOCKING       ->  R:BODY     / W:BLOCKING]
437  *     [W:DONE     / R:HEADERS        <-  R:DONE     / W:HEADERS]
438  *      W:DONE     / R:BODY           <-  R:DONE     / W:BODY
439  *      W:DONE     / R:DONE               R:DONE     / W:DONE
440  */
441
442 static void
443 io_write (SoupSocket *sock, SoupMessage *msg)
444 {
445         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
446         SoupMessageIOData *io = priv->io_data;
447
448  write_more:
449         switch (io->write_state) {
450         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
451                 return;
452
453
454         case SOUP_MESSAGE_IO_STATE_HEADERS:
455                 if (!io->write_buf->len) {
456                         io->get_headers_cb (msg, io->write_buf,
457                                             &io->write_encoding,
458                                             io->user_data);
459                         if (!io->write_buf->len) {
460                                 soup_message_io_pause (msg);
461                                 return;
462                         }
463                 }
464
465                 if (!write_data (msg, io->write_buf->str,
466                                  io->write_buf->len, FALSE))
467                         return;
468
469                 g_string_truncate (io->write_buf, 0);
470
471                 if (io->write_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
472                         SoupMessageHeaders *hdrs =
473                                 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
474                                 msg->request_headers : msg->response_headers;
475                         io->write_length = soup_message_headers_get_content_length (hdrs);
476                 }
477
478                 if (io->mode == SOUP_MESSAGE_IO_SERVER &&
479                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
480                         if (msg->status_code == SOUP_STATUS_CONTINUE) {
481                                 /* Stop and wait for the body now */
482                                 io->write_state =
483                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
484                                 io->read_state = io_body_state (io->read_encoding);
485                         } else {
486                                 /* We just wrote a 1xx response
487                                  * header, so stay in STATE_HEADERS.
488                                  * (The caller will pause us from the
489                                  * wrote_informational callback if he
490                                  * is not ready to send the final
491                                  * response.)
492                                  */
493                         }
494                 } else if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
495                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
496                         /* Need to wait for the Continue response */
497                         io->write_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
498                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
499                 } else {
500                         io->write_state = io_body_state (io->write_encoding);
501
502                         /* If the client was waiting for a Continue
503                          * but we sent something else, then they're
504                          * now done writing.
505                          */
506                         if (io->mode == SOUP_MESSAGE_IO_SERVER &&
507                             io->read_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
508                                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
509                 }
510
511                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
512                 if (SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
513                         soup_message_wrote_informational (msg);
514                         soup_message_cleanup_response (msg);
515                 } else
516                         soup_message_wrote_headers (msg);
517                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
518                 break;
519
520
521         case SOUP_MESSAGE_IO_STATE_BLOCKING:
522                 io_read (sock, msg);
523
524                 /* If io_read reached a point where we could write
525                  * again, it would have recursively called io_write.
526                  * So (a) we don't need to try to keep writing, and
527                  * (b) we can't anyway, because msg may have been
528                  * destroyed.
529                  */
530                 return;
531
532
533         case SOUP_MESSAGE_IO_STATE_BODY:
534                 if (!io->write_length && io->write_encoding != SOUP_ENCODING_EOF) {
535                 wrote_body:
536                         io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
537
538                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
539                         soup_message_wrote_body (msg);
540                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
541                         break;
542                 }
543
544                 if (!io->write_chunk) {
545                         io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
546                         if (!io->write_chunk) {
547                                 soup_message_io_pause (msg);
548                                 return;
549                         }
550                         if (io->write_chunk->length > io->write_length &&
551                             io->write_encoding != SOUP_ENCODING_EOF) {
552                                 /* App is trying to write more than it
553                                  * claimed it would; we have to truncate.
554                                  */
555                                 SoupBuffer *truncated =
556                                         soup_buffer_new_subbuffer (io->write_chunk,
557                                                                    0, io->write_length);
558                                 soup_buffer_free (io->write_chunk);
559                                 io->write_chunk = truncated;
560                         } else if (io->write_encoding == SOUP_ENCODING_EOF &&
561                                    !io->write_chunk->length)
562                                 goto wrote_body;
563                 }
564
565                 if (!write_data (msg, io->write_chunk->data,
566                                  io->write_chunk->length, TRUE))
567                         return;
568
569                 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
570                 io->write_body_offset += io->write_chunk->length;
571                 soup_buffer_free (io->write_chunk);
572                 io->write_chunk = NULL;
573
574                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
575                 soup_message_wrote_chunk (msg);
576                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
577                 break;
578
579         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
580                 if (!io->write_chunk) {
581                         io->write_chunk = soup_message_body_get_chunk (io->write_body, io->write_body_offset);
582                         if (!io->write_chunk) {
583                                 soup_message_io_pause (msg);
584                                 return;
585                         }
586                         g_string_append_printf (io->write_buf, "%lx\r\n",
587                                                 (unsigned long) io->write_chunk->length);
588                         io->write_body_offset += io->write_chunk->length;
589                 }
590
591                 if (!write_data (msg, io->write_buf->str,
592                                  io->write_buf->len, FALSE))
593                         return;
594
595                 g_string_truncate (io->write_buf, 0);
596
597                 if (io->write_chunk->length == 0) {
598                         /* The last chunk has no CHUNK_END... */
599                         io->write_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
600                         break;
601                 }
602
603                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK;
604                 /* fall through */
605
606
607         case SOUP_MESSAGE_IO_STATE_CHUNK:
608                 if (!write_data (msg, io->write_chunk->data,
609                                  io->write_chunk->length, TRUE))
610                         return;
611
612                 soup_message_body_wrote_chunk (io->write_body, io->write_chunk);
613                 soup_buffer_free (io->write_chunk);
614                 io->write_chunk = NULL;
615
616                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
617
618                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
619                 soup_message_wrote_chunk (msg);
620                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
621
622                 /* fall through */
623
624
625         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
626                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
627                                  SOUP_MESSAGE_IO_EOL_LEN, FALSE))
628                         return;
629
630                 io->write_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
631                 break;
632
633
634         case SOUP_MESSAGE_IO_STATE_TRAILERS:
635                 if (!write_data (msg, SOUP_MESSAGE_IO_EOL,
636                                  SOUP_MESSAGE_IO_EOL_LEN, FALSE))
637                         return;
638
639                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
640
641                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
642                 soup_message_wrote_body (msg);
643                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
644                 /* fall through */
645
646
647         case SOUP_MESSAGE_IO_STATE_FINISHING:
648                 if (io->write_tag) {
649                         g_signal_handler_disconnect (io->sock, io->write_tag);
650                         io->write_tag = 0;
651                 }
652                 io->write_state = SOUP_MESSAGE_IO_STATE_DONE;
653
654                 if (io->mode == SOUP_MESSAGE_IO_CLIENT) {
655                         io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
656                         io_read (sock, msg);
657                 } else
658                         soup_message_io_finished (msg);
659                 return;
660
661
662         case SOUP_MESSAGE_IO_STATE_DONE:
663         default:
664                 g_return_if_reached ();
665         }
666
667         goto write_more;
668 }
669
670 static void
671 io_read (SoupSocket *sock, SoupMessage *msg)
672 {
673         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
674         SoupMessageIOData *io = priv->io_data;
675         guint status;
676
677  read_more:
678         switch (io->read_state) {
679         case SOUP_MESSAGE_IO_STATE_NOT_STARTED:
680                 return;
681
682
683         case SOUP_MESSAGE_IO_STATE_HEADERS:
684                 if (!read_metadata (msg, TRUE))
685                         return;
686
687                 /* We need to "rewind" io->read_meta_buf back one line.
688                  * That SHOULD be two characters (CR LF), but if the
689                  * web server was stupid, it might only be one.
690                  */
691                 if (io->read_meta_buf->len < 3 ||
692                     io->read_meta_buf->data[io->read_meta_buf->len - 2] == '\n')
693                         io->read_meta_buf->len--;
694                 else
695                         io->read_meta_buf->len -= 2;
696                 io->read_meta_buf->data[io->read_meta_buf->len] = '\0';
697                 status = io->parse_headers_cb (msg, (char *)io->read_meta_buf->data,
698                                                io->read_meta_buf->len,
699                                                &io->read_encoding,
700                                                io->user_data);
701                 g_byte_array_set_size (io->read_meta_buf, 0);
702
703                 if (status != SOUP_STATUS_OK) {
704                         /* Either we couldn't parse the headers, or they
705                          * indicated something that would mean we wouldn't
706                          * be able to parse the body. (Eg, unknown
707                          * Transfer-Encoding.). Skip the rest of the
708                          * reading, and make sure the connection gets
709                          * closed when we're done.
710                          */
711                         soup_message_set_status (msg, status);
712                         soup_message_headers_append (msg->request_headers,
713                                                      "Connection", "close");
714                         io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
715                         break;
716                 }
717
718                 if (io->read_encoding == SOUP_ENCODING_CONTENT_LENGTH) {
719                         SoupMessageHeaders *hdrs =
720                                 (io->mode == SOUP_MESSAGE_IO_CLIENT) ?
721                                 msg->response_headers : msg->request_headers;
722                         io->read_length = soup_message_headers_get_content_length (hdrs);
723                 }
724
725                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
726                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
727                         if (msg->status_code == SOUP_STATUS_CONTINUE &&
728                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING) {
729                                 /* Pause the reader, unpause the writer */
730                                 io->read_state =
731                                         SOUP_MESSAGE_IO_STATE_BLOCKING;
732                                 io->write_state =
733                                         io_body_state (io->write_encoding);
734                         } else {
735                                 /* Just stay in HEADERS */
736                                 io->read_state = SOUP_MESSAGE_IO_STATE_HEADERS;
737                         }
738                 } else if (io->mode == SOUP_MESSAGE_IO_SERVER &&
739                            soup_message_headers_get_expectations (msg->request_headers) & SOUP_EXPECTATION_CONTINUE) {
740                         /* The client requested a Continue response. The
741                          * got_headers handler may change this to something
742                          * else though.
743                          */
744                         soup_message_set_status (msg, SOUP_STATUS_CONTINUE);
745                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
746                         io->read_state = SOUP_MESSAGE_IO_STATE_BLOCKING;
747                 } else {
748                         io->read_state = io_body_state (io->read_encoding);
749
750                         /* If the client was waiting for a Continue
751                          * but got something else, then it's done
752                          * writing.
753                          */
754                         if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
755                             io->write_state == SOUP_MESSAGE_IO_STATE_BLOCKING)
756                                 io->write_state = SOUP_MESSAGE_IO_STATE_FINISHING;
757                 }
758
759                 if (io->mode == SOUP_MESSAGE_IO_CLIENT &&
760                     SOUP_STATUS_IS_INFORMATIONAL (msg->status_code)) {
761                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
762                         soup_message_got_informational (msg);
763                         soup_message_cleanup_response (msg);
764                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
765                 } else {
766                         SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
767                         soup_message_got_headers (msg);
768                         SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
769                 }
770                 break;
771
772
773         case SOUP_MESSAGE_IO_STATE_BLOCKING:
774                 io_write (sock, msg);
775
776                 /* As in the io_write case, we *must* return here. */
777                 return;
778
779
780         case SOUP_MESSAGE_IO_STATE_BODY:
781                 if (!read_body_chunk (msg))
782                         return;
783
784         got_body:
785                 io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING;
786
787                 SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK;
788                 soup_message_got_body (msg);
789                 SOUP_MESSAGE_IO_RETURN_IF_CANCELLED_OR_PAUSED;
790                 break;
791
792
793         case SOUP_MESSAGE_IO_STATE_CHUNK_SIZE:
794                 if (!read_metadata (msg, FALSE))
795                         return;
796
797                 io->read_length = strtoul ((char *)io->read_meta_buf->data, NULL, 16);
798                 g_byte_array_set_size (io->read_meta_buf, 0);
799
800                 if (io->read_length > 0)
801                         io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK;
802                 else
803                         io->read_state = SOUP_MESSAGE_IO_STATE_TRAILERS;
804                 break;
805
806
807         case SOUP_MESSAGE_IO_STATE_CHUNK:
808                 if (!read_body_chunk (msg))
809                         return;
810
811                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_END;
812                 break;
813
814
815         case SOUP_MESSAGE_IO_STATE_CHUNK_END:
816                 if (!read_metadata (msg, FALSE))
817                         return;
818
819                 g_byte_array_set_size (io->read_meta_buf, 0);
820                 io->read_state = SOUP_MESSAGE_IO_STATE_CHUNK_SIZE;
821                 break;
822
823
824         case SOUP_MESSAGE_IO_STATE_TRAILERS:
825                 if (!read_metadata (msg, FALSE))
826                         return;
827
828                 if (io->read_meta_buf->len <= SOUP_MESSAGE_IO_EOL_LEN)
829                         goto got_body;
830
831                 /* FIXME: process trailers */
832                 g_byte_array_set_size (io->read_meta_buf, 0);
833                 break;
834
835
836         case SOUP_MESSAGE_IO_STATE_FINISHING:
837                 if (io->read_tag) {
838                         g_signal_handler_disconnect (io->sock, io->read_tag);
839                         io->read_tag = 0;
840                 }
841                 io->read_state = SOUP_MESSAGE_IO_STATE_DONE;
842
843                 if (io->mode == SOUP_MESSAGE_IO_SERVER) {
844                         io->write_state = SOUP_MESSAGE_IO_STATE_HEADERS;
845                         io_write (sock, msg);
846                 } else
847                         soup_message_io_finished (msg);
848                 return;
849
850
851         case SOUP_MESSAGE_IO_STATE_DONE:
852         default:
853                 g_return_if_reached ();
854         }
855
856         goto read_more;
857 }
858
859 static SoupMessageIOData *
860 new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode,
861              SoupMessageGetHeadersFn get_headers_cb,
862              SoupMessageParseHeadersFn parse_headers_cb,
863              gpointer user_data)
864 {
865         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
866         SoupMessageIOData *io;
867
868         io = g_slice_new0 (SoupMessageIOData);
869         io->sock = g_object_ref (sock);
870         io->mode = mode;
871         io->get_headers_cb   = get_headers_cb;
872         io->parse_headers_cb = parse_headers_cb;
873         io->user_data        = user_data;
874
875         io->read_meta_buf    = g_byte_array_new ();
876         io->write_buf        = g_string_new (NULL);
877
878         io->read_tag  = g_signal_connect (io->sock, "readable",
879                                           G_CALLBACK (io_read), msg);
880         io->write_tag = g_signal_connect (io->sock, "writable",
881                                           G_CALLBACK (io_write), msg);
882         io->err_tag   = g_signal_connect (io->sock, "disconnected",
883                                           G_CALLBACK (io_disconnected), msg);
884
885         io->read_state  = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
886         io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED;
887
888         if (priv->io_data)
889                 soup_message_io_cleanup (msg);
890         priv->io_data = io;
891         return io;
892 }
893
894 void
895 soup_message_io_client (SoupMessage *msg, SoupSocket *sock,
896                         SoupConnection *conn,
897                         SoupMessageGetHeadersFn get_headers_cb,
898                         SoupMessageParseHeadersFn parse_headers_cb,
899                         gpointer user_data)
900 {
901         SoupMessageIOData *io;
902
903         io = new_iostate (msg, sock, SOUP_MESSAGE_IO_CLIENT,
904                           get_headers_cb, parse_headers_cb, user_data);
905
906         if (conn)
907                 io->conn = g_object_ref (conn);
908
909         io->read_body       = msg->response_body;
910         io->write_body      = msg->request_body;
911
912         io->write_state     = SOUP_MESSAGE_IO_STATE_HEADERS;
913         io_write (sock, msg);
914 }
915
916 void
917 soup_message_io_server (SoupMessage *msg, SoupSocket *sock,
918                         SoupMessageGetHeadersFn get_headers_cb,
919                         SoupMessageParseHeadersFn parse_headers_cb,
920                         gpointer user_data)
921 {
922         SoupMessageIOData *io;
923
924         io = new_iostate (msg, sock, SOUP_MESSAGE_IO_SERVER,
925                           get_headers_cb, parse_headers_cb, user_data);
926
927         io->read_body       = msg->request_body;
928         io->write_body      = msg->response_body;
929
930         io->read_state      = SOUP_MESSAGE_IO_STATE_HEADERS;
931         io_read (sock, msg);
932 }
933
934 void  
935 soup_message_io_pause (SoupMessage *msg)
936 {
937         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
938         SoupMessageIOData *io = priv->io_data;
939
940         g_return_if_fail (io != NULL);
941
942         if (io->write_tag) {
943                 g_signal_handler_disconnect (io->sock, io->write_tag);
944                 io->write_tag = 0;
945         }
946         if (io->read_tag) {
947                 g_signal_handler_disconnect (io->sock, io->read_tag);
948                 io->read_tag = 0;
949         }
950
951         if (io->unpause_source) {
952                 g_source_destroy (io->unpause_source);
953                 io->unpause_source = NULL;
954         }
955 }
956
957 static gboolean
958 io_unpause_internal (gpointer msg)
959 {
960         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
961         SoupMessageIOData *io = priv->io_data;
962
963         g_return_val_if_fail (io != NULL, FALSE);
964         io->unpause_source = NULL;
965
966         if (io->write_tag || io->read_tag)
967                 return FALSE;
968
969         if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) {
970                 io->write_tag = g_signal_connect (io->sock, "writable",
971                                                   G_CALLBACK (io_write), msg);
972         }
973
974         if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) {
975                 io->read_tag = g_signal_connect (io->sock, "readable",
976                                                  G_CALLBACK (io_read), msg);
977         }
978
979         if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state))
980                 io_write (io->sock, msg);
981         else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state))
982                 io_read (io->sock, msg);
983
984         return FALSE;
985 }
986
987 void
988 soup_message_io_unpause (SoupMessage *msg)
989 {
990         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
991         SoupMessageIOData *io = priv->io_data;
992         gboolean non_blocking;
993         GMainContext *async_context;
994
995         g_return_if_fail (io != NULL);
996
997         g_object_get (io->sock,
998                       SOUP_SOCKET_FLAG_NONBLOCKING, &non_blocking,
999                       SOUP_SOCKET_ASYNC_CONTEXT, &async_context,
1000                       NULL);
1001         if (non_blocking) {
1002                 if (!io->unpause_source) {
1003                         io->unpause_source = soup_add_completion (
1004                                 async_context, io_unpause_internal, msg);
1005                 }
1006         } else
1007                 io_unpause_internal (msg);
1008         if (async_context)
1009                 g_main_context_unref (async_context);
1010 }
1011
1012 /**
1013  * soup_message_io_in_progress:
1014  * @msg: a #SoupMessage
1015  *
1016  * Tests whether or not I/O is currently in progress on @msg.
1017  *
1018  * Return value: whether or not I/O is currently in progress.
1019  **/
1020 gboolean
1021 soup_message_io_in_progress (SoupMessage *msg)
1022 {
1023         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1024
1025         return priv->io_data != NULL;
1026 }