2.24.0.1
[platform/upstream/libsoup.git] / libsoup / soup-message.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-message.c: HTTP request/response
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "soup-auth.h"
12 #include "soup-enum-types.h"
13 #include "soup-marshal.h"
14 #include "soup-message.h"
15 #include "soup-message-private.h"
16 #include "soup-misc.h"
17 #include "soup-uri.h"
18
19 /**
20  * SECTION:soup-message
21  * @short_description: An HTTP request and response.
22  * @see_also: #SoupMessageHeaders, #SoupMessageBody
23  *
24  * A #SoupMessage represents an HTTP message that is being sent or
25  * received.
26  *
27  * For client-side usage, you would create a #SoupMessage with
28  * soup_message_new() or soup_message_new_from_uri(), set up its
29  * fields appropriate, and send it via a #SoupSession.
30  *
31  * For server-side usage, #SoupServer will create #SoupMessage<!--
32  * -->s automatically for incoming requests, which your application
33  * will receive via handlers.
34  *
35  * Note that libsoup's terminology here does not quite match the HTTP
36  * specification: in RFC 2616, an "HTTP-message" is
37  * <emphasis>either</emphasis> a Request, <emphasis>or</emphasis> a
38  * Response. In libsoup, a #SoupMessage combines both the request and
39  * the response.
40  **/
41
42 /**
43  * SoupMessage:
44  * @method: the HTTP method
45  * @status_code: the HTTP status code
46  * @reason_phrase: the status phrase associated with @status_code
47  * @request_body: the request body
48  * @request_headers: the request headers
49  * @response_body: the response body
50  * @response_headers: the response headers
51  *
52  * Represents an HTTP message being sent or received.
53  *
54  * As described in the #SoupMessageBody documentation, the
55  * @request_body and @response_body %data fields will not necessarily
56  * be filled in at all times. When they are filled in, they will be
57  * terminated with a '\0' byte (which is not included in the %length),
58  * so you can use them as ordinary C strings (assuming that you know
59  * that the body doesn't have any other '\0' bytes).
60  *
61  * For a client-side #SoupMessage, @request_body's %data is usually
62  * filled in right before libsoup writes the request to the network,
63  * but you should not count on this; use soup_message_body_flatten()
64  * if you want to ensure that %data is filled in. @response_body's
65  * %data will be filled in before #SoupMessage::finished is emitted.
66  *
67  * For a server-side #SoupMessage, @request_body's %data will be
68  * filled in before #SoupMessage::got_body is emitted.
69  *
70  * To prevent the %data field from being filled in at all (eg, if you
71  * are handling the data from a #SoupMessage::got_chunk, and so don't
72  * need to see it all at the end), call
73  * soup_message_body_set_accumulate() on @response_body or
74  * @request_body as appropriate, passing %FALSE.
75  **/
76
77 G_DEFINE_TYPE (SoupMessage, soup_message, G_TYPE_OBJECT)
78
79 enum {
80         WROTE_INFORMATIONAL,
81         WROTE_HEADERS,
82         WROTE_CHUNK,
83         WROTE_BODY_DATA,
84         WROTE_BODY,
85
86         GOT_INFORMATIONAL,
87         GOT_HEADERS,
88         GOT_CHUNK,
89         GOT_BODY,
90
91         RESTARTED,
92         FINISHED,
93
94         LAST_SIGNAL
95 };
96
97 static guint signals[LAST_SIGNAL] = { 0 };
98
99 enum {
100         PROP_0,
101
102         PROP_METHOD,
103         PROP_URI,
104         PROP_HTTP_VERSION,
105         PROP_FLAGS,
106         PROP_SERVER_SIDE,
107         PROP_STATUS_CODE,
108         PROP_REASON_PHRASE,
109
110         LAST_PROP
111 };
112
113 static void got_body (SoupMessage *req);
114 static void restarted (SoupMessage *req);
115 static void finished (SoupMessage *req);
116
117 static void set_property (GObject *object, guint prop_id,
118                           const GValue *value, GParamSpec *pspec);
119 static void get_property (GObject *object, guint prop_id,
120                           GValue *value, GParamSpec *pspec);
121
122 static void
123 soup_message_init (SoupMessage *msg)
124 {
125         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
126
127         priv->io_status = SOUP_MESSAGE_IO_STATUS_IDLE;
128         priv->http_version = priv->orig_http_version = SOUP_HTTP_1_1;
129
130         msg->request_body = soup_message_body_new ();
131         msg->request_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_REQUEST);
132         msg->response_body = soup_message_body_new ();
133         msg->response_headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
134 }
135
136 static void
137 finalize (GObject *object)
138 {
139         SoupMessage *msg = SOUP_MESSAGE (object);
140         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
141
142         soup_message_io_cleanup (msg);
143         if (priv->chunk_allocator_dnotify)
144                 priv->chunk_allocator_dnotify (priv->chunk_allocator_data);
145
146         if (priv->uri)
147                 soup_uri_free (priv->uri);
148
149         if (priv->auth)
150                 g_object_unref (priv->auth);
151         if (priv->proxy_auth)
152                 g_object_unref (priv->proxy_auth);
153
154         soup_message_body_free (msg->request_body);
155         soup_message_headers_free (msg->request_headers);
156         soup_message_body_free (msg->response_body);
157         soup_message_headers_free (msg->response_headers);
158
159         g_free (msg->reason_phrase);
160
161         G_OBJECT_CLASS (soup_message_parent_class)->finalize (object);
162 }
163
164 static void
165 soup_message_class_init (SoupMessageClass *message_class)
166 {
167         GObjectClass *object_class = G_OBJECT_CLASS (message_class);
168
169         g_type_class_add_private (message_class, sizeof (SoupMessagePrivate));
170
171         /* virtual method definition */
172         message_class->got_body     = got_body;
173         message_class->restarted    = restarted;
174         message_class->finished     = finished;
175
176         /* virtual method override */
177         object_class->finalize = finalize;
178         object_class->set_property = set_property;
179         object_class->get_property = get_property;
180
181         /* signals */
182
183         /**
184          * SoupMessage::wrote-informational:
185          * @msg: the message
186          *
187          * Emitted immediately after writing a 1xx (Informational)
188          * response for a (server-side) message.
189          **/
190         signals[WROTE_INFORMATIONAL] =
191                 g_signal_new ("wrote_informational",
192                               G_OBJECT_CLASS_TYPE (object_class),
193                               G_SIGNAL_RUN_FIRST,
194                               G_STRUCT_OFFSET (SoupMessageClass, wrote_informational),
195                               NULL, NULL,
196                               soup_marshal_NONE__NONE,
197                               G_TYPE_NONE, 0);
198
199         /**
200          * SoupMessage::wrote-headers:
201          * @msg: the message
202          *
203          * Emitted immediately after writing the headers for a
204          * message. (For a client-side message, this is after writing
205          * the request headers; for a server-side message, it is after
206          * writing the response headers.)
207          **/
208         signals[WROTE_HEADERS] =
209                 g_signal_new ("wrote_headers",
210                               G_OBJECT_CLASS_TYPE (object_class),
211                               G_SIGNAL_RUN_FIRST,
212                               G_STRUCT_OFFSET (SoupMessageClass, wrote_headers),
213                               NULL, NULL,
214                               soup_marshal_NONE__NONE,
215                               G_TYPE_NONE, 0);
216
217         /**
218          * SoupMessage::wrote-chunk:
219          * @msg: the message
220          *
221          * Emitted immediately after writing a body chunk for a message.
222          *
223          * Note that this signal is not parallel to
224          * #SoupMessage::got_chunk; it is emitted only when a complete
225          * chunk (added with soup_message_body_append() or
226          * soup_message_body_append_buffer()) has been written. To get
227          * more useful continuous progress information, use
228          * #SoupMessage::wrote_body_data.
229          **/
230         signals[WROTE_CHUNK] =
231                 g_signal_new ("wrote_chunk",
232                               G_OBJECT_CLASS_TYPE (object_class),
233                               G_SIGNAL_RUN_FIRST,
234                               G_STRUCT_OFFSET (SoupMessageClass, wrote_chunk),
235                               NULL, NULL,
236                               soup_marshal_NONE__NONE,
237                               G_TYPE_NONE, 0);
238
239         /**
240          * SoupMessage::wrote-body-data:
241          * @msg: the message
242          * @chunk: the data written
243          *
244          * Emitted immediately after writing a portion of the message
245          * body to the network.
246          *
247          * Unlike #SoupMessage::wrote_chunk, this is emitted after
248          * every successful write() call, not only after finishing a
249          * complete "chunk".
250          **/
251         signals[WROTE_BODY_DATA] =
252                 g_signal_new ("wrote_body_data",
253                               G_OBJECT_CLASS_TYPE (object_class),
254                               G_SIGNAL_RUN_FIRST,
255                               0, /* FIXME after next ABI break */
256                               NULL, NULL,
257                               soup_marshal_NONE__BOXED,
258                               G_TYPE_NONE, 1,
259                               SOUP_TYPE_BUFFER);
260
261         /**
262          * SoupMessage::wrote-body:
263          * @msg: the message
264          *
265          * Emitted immediately after writing the complete body for a
266          * message. (For a client-side message, this means that
267          * libsoup is done writing and is now waiting for the response
268          * from the server. For a server-side message, this means that
269          * libsoup has finished writing the response and is nearly
270          * done with the message.)
271          **/
272         signals[WROTE_BODY] =
273                 g_signal_new ("wrote_body",
274                               G_OBJECT_CLASS_TYPE (object_class),
275                               G_SIGNAL_RUN_FIRST,
276                               G_STRUCT_OFFSET (SoupMessageClass, wrote_body),
277                               NULL, NULL,
278                               soup_marshal_NONE__NONE,
279                               G_TYPE_NONE, 0);
280
281         /**
282          * SoupMessage::got-informational:
283          * @msg: the message
284          *
285          * Emitted after receiving a 1xx (Informational) response for
286          * a (client-side) message. The response_headers will be
287          * filled in with the headers associated with the
288          * informational response; however, those header values will
289          * be erased after this signal is done.
290          *
291          * If you cancel or requeue @msg while processing this signal,
292          * then the current HTTP I/O will be stopped after this signal
293          * emission finished, and @msg's connection will be closed.
294          **/
295         signals[GOT_INFORMATIONAL] =
296                 g_signal_new ("got_informational",
297                               G_OBJECT_CLASS_TYPE (object_class),
298                               G_SIGNAL_RUN_FIRST,
299                               G_STRUCT_OFFSET (SoupMessageClass, got_informational),
300                               NULL, NULL,
301                               soup_marshal_NONE__NONE,
302                               G_TYPE_NONE, 0);
303
304         /**
305          * SoupMessage::got-headers:
306          * @msg: the message
307          *
308          * Emitted after receiving all message headers for a message.
309          * (For a client-side message, this is after receiving the
310          * Status-Line and response headers; for a server-side
311          * message, it is after receiving the Request-Line and request
312          * headers.)
313          *
314          * See also soup_message_add_header_handler() and
315          * soup_message_add_status_code_handler(), which can be used
316          * to connect to a subset of emissions of this signal.
317          *
318          * If you cancel or requeue @msg while processing this signal,
319          * then the current HTTP I/O will be stopped after this signal
320          * emission finished, and @msg's connection will be closed.
321          * (If you need to requeue a message--eg, after handling
322          * authentication or redirection--it is usually better to
323          * requeue it from a #SoupMessage::got_body handler rather
324          * than a #SoupMessage::got_header handler, so that the
325          * existing HTTP connection can be reused.)
326          **/
327         signals[GOT_HEADERS] =
328                 g_signal_new ("got_headers",
329                               G_OBJECT_CLASS_TYPE (object_class),
330                               G_SIGNAL_RUN_FIRST,
331                               G_STRUCT_OFFSET (SoupMessageClass, got_headers),
332                               NULL, NULL,
333                               soup_marshal_NONE__NONE,
334                               G_TYPE_NONE, 0);
335
336         /**
337          * SoupMessage::got-chunk:
338          * @msg: the message
339          * @chunk: the just-read chunk
340          *
341          * Emitted after receiving a chunk of a message body. Note
342          * that "chunk" in this context means any subpiece of the
343          * body, not necessarily the specific HTTP 1.1 chunks sent by
344          * the other side.
345          *
346          * If you cancel or requeue @msg while processing this signal,
347          * then the current HTTP I/O will be stopped after this signal
348          * emission finished, and @msg's connection will be closed.
349          **/
350         signals[GOT_CHUNK] =
351                 g_signal_new ("got_chunk",
352                               G_OBJECT_CLASS_TYPE (object_class),
353                               G_SIGNAL_RUN_FIRST,
354                               G_STRUCT_OFFSET (SoupMessageClass, got_chunk),
355                               NULL, NULL,
356                               soup_marshal_NONE__BOXED,
357                               G_TYPE_NONE, 1,
358                               /* Use %G_SIGNAL_TYPE_STATIC_SCOPE so that
359                                * the %SOUP_MEMORY_TEMPORARY buffers used
360                                * by soup-message-io.c when emitting this
361                                * signal don't get forcibly copied by
362                                * g_signal_emit().
363                                */
364                               SOUP_TYPE_BUFFER | G_SIGNAL_TYPE_STATIC_SCOPE);
365
366         /**
367          * SoupMessage::got-body:
368          * @msg: the message
369          *
370          * Emitted after receiving the complete message body. (For a
371          * server-side message, this means it has received the request
372          * body. For a client-side message, this means it has received
373          * the response body and is nearly done with the message.)
374          *
375          * See also soup_message_add_header_handler() and
376          * soup_message_add_status_code_handler(), which can be used
377          * to connect to a subset of emissions of this signal.
378          **/
379         signals[GOT_BODY] =
380                 g_signal_new ("got_body",
381                               G_OBJECT_CLASS_TYPE (object_class),
382                               G_SIGNAL_RUN_FIRST,
383                               G_STRUCT_OFFSET (SoupMessageClass, got_body),
384                               NULL, NULL,
385                               soup_marshal_NONE__NONE,
386                               G_TYPE_NONE, 0);
387
388         /**
389          * SoupMessage::restarted:
390          * @msg: the message
391          *
392          * Emitted when a request that was already sent once is now
393          * being sent again (eg, because the first attempt received a
394          * redirection response, or because we needed to use
395          * authentication).
396          **/
397         signals[RESTARTED] =
398                 g_signal_new ("restarted",
399                               G_OBJECT_CLASS_TYPE (object_class),
400                               G_SIGNAL_RUN_FIRST,
401                               G_STRUCT_OFFSET (SoupMessageClass, restarted),
402                               NULL, NULL,
403                               soup_marshal_NONE__NONE,
404                               G_TYPE_NONE, 0);
405
406         /**
407          * SoupMessage::finished:
408          * @msg: the message
409          *
410          * Emitted when all HTTP processing is finished for a message.
411          * (After #SoupMessage::got_body for client-side messages, or
412          * after #SoupMessage::wrote_body for server-side messages.)
413          **/
414         signals[FINISHED] =
415                 g_signal_new ("finished",
416                               G_OBJECT_CLASS_TYPE (object_class),
417                               G_SIGNAL_RUN_FIRST,
418                               G_STRUCT_OFFSET (SoupMessageClass, finished),
419                               NULL, NULL,
420                               soup_marshal_NONE__NONE,
421                               G_TYPE_NONE, 0);
422
423         /* properties */
424         g_object_class_install_property (
425                 object_class, PROP_METHOD,
426                 g_param_spec_string (SOUP_MESSAGE_METHOD,
427                                      "Method",
428                                      "The message's HTTP method",
429                                      SOUP_METHOD_GET,
430                                      G_PARAM_READWRITE));
431         g_object_class_install_property (
432                 object_class, PROP_URI,
433                 g_param_spec_boxed (SOUP_MESSAGE_URI,
434                                     "URI",
435                                     "The message's Request-URI",
436                                     SOUP_TYPE_URI,
437                                     G_PARAM_READWRITE));
438         g_object_class_install_property (
439                 object_class, PROP_HTTP_VERSION,
440                 g_param_spec_enum (SOUP_MESSAGE_HTTP_VERSION,
441                                    "HTTP Version",
442                                    "The HTTP protocol version to use",
443                                    SOUP_TYPE_HTTP_VERSION,
444                                    SOUP_HTTP_1_1,
445                                    G_PARAM_READWRITE));
446         g_object_class_install_property (
447                 object_class, PROP_FLAGS,
448                 g_param_spec_flags (SOUP_MESSAGE_FLAGS,
449                                     "Flags",
450                                     "Various message options",
451                                     SOUP_TYPE_MESSAGE_FLAGS,
452                                     0,
453                                     G_PARAM_READWRITE));
454         g_object_class_install_property (
455                 object_class, PROP_SERVER_SIDE,
456                 g_param_spec_boolean (SOUP_MESSAGE_SERVER_SIDE,
457                                       "Server-side",
458                                       "Whether or not the message is server-side rather than client-side",
459                                       FALSE,
460                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
461         g_object_class_install_property (
462                 object_class, PROP_STATUS_CODE,
463                 g_param_spec_uint (SOUP_MESSAGE_STATUS_CODE,
464                                    "Status code",
465                                    "The HTTP response status code",
466                                    0, 599, 0,
467                                    G_PARAM_READWRITE));
468         g_object_class_install_property (
469                 object_class, PROP_REASON_PHRASE,
470                 g_param_spec_string (SOUP_MESSAGE_REASON_PHRASE,
471                                      "Reason phrase",
472                                      "The HTTP response reason phrase",
473                                      NULL,
474                                      G_PARAM_READWRITE));
475 }
476
477 static void
478 set_property (GObject *object, guint prop_id,
479               const GValue *value, GParamSpec *pspec)
480 {
481         SoupMessage *msg = SOUP_MESSAGE (object);
482         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
483
484         switch (prop_id) {
485         case PROP_METHOD:
486                 msg->method = g_intern_string (g_value_get_string (value));
487                 break;
488         case PROP_URI:
489                 soup_message_set_uri (msg, g_value_get_boxed (value));
490                 break;
491         case PROP_HTTP_VERSION:
492                 soup_message_set_http_version (msg, g_value_get_enum (value));
493                 break;
494         case PROP_FLAGS:
495                 soup_message_set_flags (msg, g_value_get_flags (value));
496                 break;
497         case PROP_SERVER_SIDE:
498                 priv->server_side = g_value_get_boolean (value);
499                 break;
500         case PROP_STATUS_CODE:
501                 soup_message_set_status (msg, g_value_get_uint (value));
502                 break;
503         case PROP_REASON_PHRASE:
504                 soup_message_set_status_full (msg, msg->status_code,
505                                               g_value_get_string (value));
506                 break;
507         default:
508                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
509                 break;
510         }
511 }
512
513 static void
514 get_property (GObject *object, guint prop_id,
515               GValue *value, GParamSpec *pspec)
516 {
517         SoupMessage *msg = SOUP_MESSAGE (object);
518         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
519
520         switch (prop_id) {
521         case PROP_METHOD:
522                 g_value_set_string (value, msg->method);
523                 break;
524         case PROP_URI:
525                 g_value_set_boxed (value, priv->uri);
526                 break;
527         case PROP_HTTP_VERSION:
528                 g_value_set_enum (value, priv->http_version);
529                 break;
530         case PROP_FLAGS:
531                 g_value_set_flags (value, priv->msg_flags);
532                 break;
533         case PROP_SERVER_SIDE:
534                 g_value_set_boolean (value, priv->server_side);
535                 break;
536         case PROP_STATUS_CODE:
537                 g_value_set_uint (value, msg->status_code);
538                 break;
539         case PROP_REASON_PHRASE:
540                 g_value_set_string (value, msg->reason_phrase);
541                 break;
542         default:
543                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
544                 break;
545         }
546 }
547
548
549 /**
550  * soup_message_new:
551  * @method: the HTTP method for the created request
552  * @uri_string: the destination endpoint (as a string)
553  * 
554  * Creates a new empty #SoupMessage, which will connect to @uri
555  *
556  * Return value: the new #SoupMessage (or %NULL if @uri could not
557  * be parsed).
558  */
559 SoupMessage *
560 soup_message_new (const char *method, const char *uri_string)
561 {
562         SoupMessage *msg;
563         SoupURI *uri;
564
565         g_return_val_if_fail (method != NULL, NULL);
566         g_return_val_if_fail (uri_string != NULL, NULL);
567
568         uri = soup_uri_new (uri_string);
569         if (!uri)
570                 return NULL;
571         if (!uri->host) {
572                 soup_uri_free (uri);
573                 return NULL;
574         }
575
576         msg = soup_message_new_from_uri (method, uri);
577         soup_uri_free (uri);
578         return msg;
579 }
580
581 /**
582  * soup_message_new_from_uri:
583  * @method: the HTTP method for the created request
584  * @uri: the destination endpoint (as a #SoupURI)
585  * 
586  * Creates a new empty #SoupMessage, which will connect to @uri
587  *
588  * Return value: the new #SoupMessage
589  */
590 SoupMessage *
591 soup_message_new_from_uri (const char *method, SoupURI *uri)
592 {
593         return g_object_new (SOUP_TYPE_MESSAGE,
594                              SOUP_MESSAGE_METHOD, method,
595                              SOUP_MESSAGE_URI, uri,
596                              NULL);
597 }
598
599 /**
600  * soup_message_set_request:
601  * @msg: the message
602  * @content_type: MIME Content-Type of the body
603  * @req_use: a #SoupMemoryUse describing how to handle @req_body
604  * @req_body: a data buffer containing the body of the message request.
605  * @req_length: the byte length of @req_body.
606  * 
607  * Convenience function to set the request body of a #SoupMessage. If
608  * @content_type is %NULL, the request body must be empty as well.
609  */
610 void
611 soup_message_set_request (SoupMessage    *msg,
612                           const char     *content_type,
613                           SoupMemoryUse   req_use,
614                           const char     *req_body,
615                           gsize           req_length)
616 {
617         g_return_if_fail (SOUP_IS_MESSAGE (msg));
618         g_return_if_fail (content_type != NULL || req_length == 0);
619
620         if (content_type) {
621                 soup_message_headers_replace (msg->request_headers,
622                                               "Content-Type", content_type);
623                 soup_message_body_append (msg->request_body, req_use,
624                                           req_body, req_length);
625         } else {
626                 soup_message_headers_remove (msg->request_headers,
627                                              "Content-Type");
628                 soup_message_body_truncate (msg->request_body);
629         }
630 }
631
632 /**
633  * soup_message_set_response:
634  * @msg: the message
635  * @content_type: MIME Content-Type of the body
636  * @resp_use: a #SoupMemoryUse describing how to handle @resp_body
637  * @resp_body: a data buffer containing the body of the message response.
638  * @resp_length: the byte length of @resp_body.
639  * 
640  * Convenience function to set the response body of a #SoupMessage. If
641  * @content_type is %NULL, the response body must be empty as well.
642  */
643 void
644 soup_message_set_response (SoupMessage    *msg,
645                            const char     *content_type,
646                            SoupMemoryUse   resp_use,
647                            const char     *resp_body,
648                            gsize           resp_length)
649 {
650         g_return_if_fail (SOUP_IS_MESSAGE (msg));
651         g_return_if_fail (content_type != NULL || resp_length == 0);
652
653         if (content_type) {
654                 soup_message_headers_replace (msg->response_headers,
655                                               "Content-Type", content_type);
656                 soup_message_body_append (msg->response_body, resp_use,
657                                           resp_body, resp_length);
658         } else {
659                 soup_message_headers_remove (msg->response_headers,
660                                              "Content-Type");
661                 soup_message_body_truncate (msg->response_body);
662         }
663 }
664
665 /**
666  * soup_message_wrote_informational:
667  * @msg: a #SoupMessage
668  *
669  * Emits the %wrote_informational signal, indicating that the IO layer
670  * finished writing an informational (1xx) response for @msg.
671  **/
672 void
673 soup_message_wrote_informational (SoupMessage *msg)
674 {
675         g_signal_emit (msg, signals[WROTE_INFORMATIONAL], 0);
676 }
677
678 /**
679  * soup_message_wrote_headers:
680  * @msg: a #SoupMessage
681  *
682  * Emits the %wrote_headers signal, indicating that the IO layer
683  * finished writing the (non-informational) headers for @msg.
684  **/
685 void
686 soup_message_wrote_headers (SoupMessage *msg)
687 {
688         g_signal_emit (msg, signals[WROTE_HEADERS], 0);
689 }
690
691 /**
692  * soup_message_wrote_chunk:
693  * @msg: a #SoupMessage
694  *
695  * Emits the %wrote_chunk signal, indicating that the IO layer
696  * finished writing a chunk of @msg's body.
697  **/
698 void
699 soup_message_wrote_chunk (SoupMessage *msg)
700 {
701         g_signal_emit (msg, signals[WROTE_CHUNK], 0);
702 }
703
704 /**
705  * soup_message_wrote_body_data:
706  * @msg: a #SoupMessage
707  * @chunk: the data written
708  *
709  * Emits the %wrote_body_data signal, indicating that the IO layer
710  * finished writing a portion of @msg's body.
711  **/
712 void
713 soup_message_wrote_body_data (SoupMessage *msg, SoupBuffer *chunk)
714 {
715         g_signal_emit (msg, signals[WROTE_BODY_DATA], 0, chunk);
716 }
717
718 /**
719  * soup_message_wrote_body:
720  * @msg: a #SoupMessage
721  *
722  * Emits the %wrote_body signal, indicating that the IO layer finished
723  * writing the body for @msg.
724  **/
725 void
726 soup_message_wrote_body (SoupMessage *msg)
727 {
728         g_signal_emit (msg, signals[WROTE_BODY], 0);
729 }
730
731 /**
732  * soup_message_got_informational:
733  * @msg: a #SoupMessage
734  *
735  * Emits the %got_informational signal, indicating that the IO layer
736  * read a complete informational (1xx) response for @msg.
737  **/
738 void
739 soup_message_got_informational (SoupMessage *msg)
740 {
741         g_signal_emit (msg, signals[GOT_INFORMATIONAL], 0);
742 }
743
744 /**
745  * soup_message_got_headers:
746  * @msg: a #SoupMessage
747  *
748  * Emits the %got_headers signal, indicating that the IO layer
749  * finished reading the (non-informational) headers for @msg.
750  **/
751 void
752 soup_message_got_headers (SoupMessage *msg)
753 {
754         g_signal_emit (msg, signals[GOT_HEADERS], 0);
755 }
756
757 /**
758  * soup_message_got_chunk:
759  * @msg: a #SoupMessage
760  * @chunk: the newly-read chunk
761  *
762  * Emits the %got_chunk signal, indicating that the IO layer finished
763  * reading a chunk of @msg's body.
764  **/
765 void
766 soup_message_got_chunk (SoupMessage *msg, SoupBuffer *chunk)
767 {
768         g_signal_emit (msg, signals[GOT_CHUNK], 0, chunk);
769 }
770
771 static void
772 got_body (SoupMessage *req)
773 {
774         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
775         SoupMessageBody *body;
776
777         body = priv->server_side ? req->request_body : req->response_body;
778         if (soup_message_body_get_accumulate (body)) {
779                 SoupBuffer *buffer;
780
781                 buffer = soup_message_body_flatten (body);
782                 soup_buffer_free (buffer);
783         }
784 }
785
786 /**
787  * soup_message_got_body:
788  * @msg: a #SoupMessage
789  *
790  * Emits the %got_body signal, indicating that the IO layer finished
791  * reading the body for @msg.
792  **/
793 void
794 soup_message_got_body (SoupMessage *msg)
795 {
796         g_signal_emit (msg, signals[GOT_BODY], 0);
797 }
798
799 static void
800 restarted (SoupMessage *req)
801 {
802         soup_message_io_stop (req);
803 }
804
805 /**
806  * soup_message_restarted:
807  * @msg: a #SoupMessage
808  *
809  * Emits the %restarted signal, indicating that @msg should be
810  * requeued.
811  **/
812 void
813 soup_message_restarted (SoupMessage *msg)
814 {
815         g_signal_emit (msg, signals[RESTARTED], 0);
816 }
817
818 static void
819 finished (SoupMessage *req)
820 {
821         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
822
823         soup_message_io_stop (req);
824         priv->io_status = SOUP_MESSAGE_IO_STATUS_FINISHED;
825 }
826
827 /**
828  * soup_message_finished:
829  * @msg: a #SoupMessage
830  *
831  * Emits the %finished signal, indicating that @msg has been completely
832  * processed.
833  **/
834 void
835 soup_message_finished (SoupMessage *msg)
836 {
837         g_signal_emit (msg, signals[FINISHED], 0);
838 }
839
840 static void
841 header_handler_free (gpointer header_name, GClosure *closure)
842 {
843         g_free (header_name);
844 }
845
846 static void
847 header_handler_metamarshal (GClosure *closure, GValue *return_value,
848                             guint n_param_values, const GValue *param_values,
849                             gpointer invocation_hint, gpointer marshal_data)
850 {
851         SoupMessage *msg = g_value_get_object (&param_values[0]);
852         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
853         const char *header_name = marshal_data;
854         SoupMessageHeaders *hdrs;
855
856         if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING)
857                 return;
858
859         hdrs = priv->server_side ? msg->request_headers : msg->response_headers;
860         if (soup_message_headers_get (hdrs, header_name)) {
861                 closure->marshal (closure, return_value, n_param_values,
862                                   param_values, invocation_hint,
863                                   ((GCClosure *)closure)->callback);
864         }
865 }
866
867 /**
868  * soup_message_add_header_handler:
869  * @msg: a #SoupMessage
870  * @signal: signal to connect the handler to.
871  * @header: HTTP response header to match against
872  * @callback: the header handler
873  * @user_data: data to pass to @handler_cb
874  *
875  * Adds a signal handler to @msg for @signal, as with
876  * g_signal_connect(), but with two differences: the @callback will
877  * only be run if @msg has a header named @header, and it will only be
878  * run if no earlier handler cancelled or requeued the message.
879  *
880  * If @signal is one of the "got" signals (eg, "got_headers"), or
881  * "finished" or "restarted", then @header is matched against the
882  * incoming message headers (that is, the #request_headers for a
883  * client #SoupMessage, or the #response_headers for a server
884  * #SoupMessage). If @signal is one of the "wrote" signals, then
885  * @header is matched against the outgoing message headers.
886  *
887  * Return value: the handler ID from g_signal_connect()
888  **/
889 guint
890 soup_message_add_header_handler (SoupMessage *msg,
891                                  const char  *signal,
892                                  const char  *header,
893                                  GCallback    callback,
894                                  gpointer     user_data)
895 {
896         SoupMessagePrivate *priv;
897         GClosure *closure;
898         char *header_name;
899
900         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
901         g_return_val_if_fail (signal != NULL, 0);
902         g_return_val_if_fail (header != NULL, 0);
903         g_return_val_if_fail (callback != NULL, 0);
904
905         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
906
907         closure = g_cclosure_new (callback, user_data, NULL);
908
909         header_name = g_strdup (header);
910         g_closure_set_meta_marshal (closure, header_name,
911                                     header_handler_metamarshal);
912         g_closure_add_finalize_notifier (closure, header_name,
913                                          header_handler_free);
914
915         return g_signal_connect_closure (msg, signal, closure, FALSE);
916 }
917
918 static void
919 status_handler_metamarshal (GClosure *closure, GValue *return_value,
920                             guint n_param_values, const GValue *param_values,
921                             gpointer invocation_hint, gpointer marshal_data)
922 {
923         SoupMessage *msg = g_value_get_object (&param_values[0]);
924         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
925         guint status = GPOINTER_TO_UINT (marshal_data);
926
927         if (priv->io_status != SOUP_MESSAGE_IO_STATUS_RUNNING)
928                 return;
929
930         if (msg->status_code == status) {
931                 closure->marshal (closure, return_value, n_param_values,
932                                   param_values, invocation_hint,
933                                   ((GCClosure *)closure)->callback);
934         }
935 }
936
937 /**
938  * soup_message_add_status_code_handler:
939  * @msg: a #SoupMessage
940  * @signal: signal to connect the handler to.
941  * @status_code: status code to match against
942  * @callback: the header handler
943  * @user_data: data to pass to @handler_cb
944  *
945  * Adds a signal handler to @msg for @signal, as with
946  * g_signal_connect() but with two differences: the @callback will
947  * only be run if @msg has the status @status_code, and it will only
948  * be run if no earlier handler cancelled or requeued the message.
949  *
950  * @signal must be a signal that will be emitted after @msg's status
951  * is set. For a client #SoupMessage, this means it can't be a "wrote"
952  * signal. For a server #SoupMessage, this means it can't be a "got"
953  * signal.
954  *
955  * Return value: the handler ID from g_signal_connect()
956  **/
957 guint
958 soup_message_add_status_code_handler (SoupMessage *msg,
959                                       const char  *signal,
960                                       guint        status_code,
961                                       GCallback    callback,
962                                       gpointer     user_data)
963 {
964         GClosure *closure;
965
966         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
967         g_return_val_if_fail (signal != NULL, 0);
968         g_return_val_if_fail (callback != NULL, 0);
969
970         closure = g_cclosure_new (callback, user_data, NULL);
971         g_closure_set_meta_marshal (closure, GUINT_TO_POINTER (status_code),
972                                     status_handler_metamarshal);
973
974         return g_signal_connect_closure (msg, signal, closure, FALSE);
975 }
976
977
978 /**
979  * soup_message_set_auth:
980  * @msg: a #SoupMessage
981  * @auth: a #SoupAuth, or %NULL
982  *
983  * Sets @msg to authenticate to its destination using @auth, which
984  * must have already been fully authenticated. If @auth is %NULL, @msg
985  * will not authenticate to its destination.
986  **/
987 void
988 soup_message_set_auth (SoupMessage *msg, SoupAuth *auth)
989 {
990         SoupMessagePrivate *priv;
991         char *token;
992
993         g_return_if_fail (SOUP_IS_MESSAGE (msg));
994         g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
995         g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
996
997         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
998
999         if (priv->auth) {
1000                 g_object_unref (priv->auth);
1001                 soup_message_headers_remove (msg->request_headers,
1002                                              "Authorization");
1003         }
1004         priv->auth = auth;
1005         if (!priv->auth)
1006                 return;
1007
1008         g_object_ref (priv->auth);
1009         token = soup_auth_get_authorization (auth, msg);
1010         soup_message_headers_replace (msg->request_headers,
1011                                       "Authorization", token);
1012         g_free (token);
1013 }
1014
1015 /**
1016  * soup_message_get_auth:
1017  * @msg: a #SoupMessage
1018  *
1019  * Gets the #SoupAuth used by @msg for authentication.
1020  *
1021  * Return value: the #SoupAuth used by @msg for authentication, or
1022  * %NULL if @msg is unauthenticated.
1023  **/
1024 SoupAuth *
1025 soup_message_get_auth (SoupMessage *msg)
1026 {
1027         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1028
1029         return SOUP_MESSAGE_GET_PRIVATE (msg)->auth;
1030 }
1031
1032 /**
1033  * soup_message_set_proxy_auth:
1034  * @msg: a #SoupMessage
1035  * @auth: a #SoupAuth, or %NULL
1036  *
1037  * Sets @msg to authenticate to its proxy using @auth, which must have
1038  * already been fully authenticated. If @auth is %NULL, @msg will not
1039  * authenticate to its proxy.
1040  **/
1041 void
1042 soup_message_set_proxy_auth (SoupMessage *msg, SoupAuth *auth)
1043 {
1044         SoupMessagePrivate *priv;
1045         char *token;
1046
1047         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1048         g_return_if_fail (auth == NULL || SOUP_IS_AUTH (auth));
1049         g_return_if_fail (auth == NULL || soup_auth_is_authenticated (auth));
1050
1051         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1052
1053         if (priv->proxy_auth) {
1054                 g_object_unref (priv->proxy_auth);
1055                 soup_message_headers_remove (msg->request_headers,
1056                                              "Proxy-Authorization");
1057         }
1058         priv->proxy_auth = auth;
1059         if (!priv->proxy_auth)
1060                 return;
1061
1062         g_object_ref (priv->proxy_auth);
1063         token = soup_auth_get_authorization (auth, msg);
1064         soup_message_headers_replace (msg->request_headers,
1065                                       "Proxy-Authorization", token);
1066         g_free (token);
1067 }
1068
1069 /**
1070  * soup_message_get_proxy_auth:
1071  * @msg: a #SoupMessage
1072  *
1073  * Gets the #SoupAuth used by @msg for authentication to its proxy..
1074  *
1075  * Return value: the #SoupAuth used by @msg for authentication to its
1076  * proxy, or %NULL if @msg isn't authenticated to its proxy.
1077  **/
1078 SoupAuth *
1079 soup_message_get_proxy_auth (SoupMessage *msg)
1080 {
1081         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1082
1083         return SOUP_MESSAGE_GET_PRIVATE (msg)->proxy_auth;
1084 }
1085
1086 /**
1087  * soup_message_cleanup_response:
1088  * @req: a #SoupMessage
1089  *
1090  * Cleans up all response data on @req, so that the request can be sent
1091  * again and receive a new response. (Eg, as a result of a redirect or
1092  * authorization request.)
1093  **/
1094 void
1095 soup_message_cleanup_response (SoupMessage *req)
1096 {
1097         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req);
1098
1099         soup_message_body_truncate (req->response_body);
1100         soup_message_headers_clear (req->response_headers);
1101
1102         req->status_code = SOUP_STATUS_NONE;
1103         if (req->reason_phrase) {
1104                 g_free (req->reason_phrase);
1105                 req->reason_phrase = NULL;
1106         }
1107         priv->http_version = priv->orig_http_version;
1108
1109         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE);
1110         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE);
1111         g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION);
1112 }
1113
1114 /**
1115  * SoupMessageFlags:
1116  * @SOUP_MESSAGE_NO_REDIRECT: The session should not follow redirect
1117  * (3xx) responses received by this message.
1118  * @SOUP_MESSAGE_OVERWRITE_CHUNKS: Deprecated: equivalent to calling
1119  * soup_message_body_set_accumulate() on the incoming message body
1120  * (ie, %response_body for a client-side request), passing %FALSE.
1121  *
1122  * Various flags that can be set on a #SoupMessage to alter its
1123  * behavior.
1124  **/
1125
1126 /**
1127  * soup_message_set_flags:
1128  * @msg: a #SoupMessage
1129  * @flags: a set of #SoupMessageFlags values
1130  *
1131  * Sets the specified flags on @msg.
1132  **/
1133 void
1134 soup_message_set_flags (SoupMessage *msg, SoupMessageFlags flags)
1135 {
1136         SoupMessagePrivate *priv;
1137
1138         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1139         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1140
1141         if ((priv->msg_flags ^ flags) & SOUP_MESSAGE_OVERWRITE_CHUNKS) {
1142                 soup_message_body_set_accumulate (
1143                         priv->server_side ? msg->request_body : msg->response_body,
1144                         !(flags & SOUP_MESSAGE_OVERWRITE_CHUNKS));
1145         }
1146
1147         priv->msg_flags = flags;
1148         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_FLAGS);
1149 }
1150
1151 /**
1152  * soup_message_get_flags:
1153  * @msg: a #SoupMessage
1154  *
1155  * Gets the flags on @msg
1156  *
1157  * Return value: the flags
1158  **/
1159 SoupMessageFlags
1160 soup_message_get_flags (SoupMessage *msg)
1161 {
1162         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), 0);
1163
1164         return SOUP_MESSAGE_GET_PRIVATE (msg)->msg_flags;
1165 }
1166
1167 /**
1168  * SoupHTTPVersion:
1169  * @SOUP_HTTP_1_0: HTTP 1.0 (RFC 1945)
1170  * @SOUP_HTTP_1_1: HTTP 1.1 (RFC 2616)
1171  *
1172  * Indicates the HTTP protocol version being used.
1173  **/
1174
1175 /**
1176  * soup_message_set_http_version:
1177  * @msg: a #SoupMessage
1178  * @version: the HTTP version
1179  *
1180  * Sets the HTTP version on @msg. The default version is
1181  * %SOUP_HTTP_1_1. Setting it to %SOUP_HTTP_1_0 will prevent certain
1182  * functionality from being used.
1183  **/
1184 void
1185 soup_message_set_http_version (SoupMessage *msg, SoupHTTPVersion version)
1186 {
1187         SoupMessagePrivate *priv;
1188
1189         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1190         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1191
1192         priv->http_version = version;
1193         if (msg->status_code == SOUP_STATUS_NONE)
1194                 priv->orig_http_version = version;
1195         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_HTTP_VERSION);
1196 }
1197
1198 /**
1199  * soup_message_get_http_version:
1200  * @msg: a #SoupMessage
1201  *
1202  * Gets the HTTP version of @msg. This is the minimum of the
1203  * version from the request and the version from the response.
1204  *
1205  * Return value: the HTTP version
1206  **/
1207 SoupHTTPVersion
1208 soup_message_get_http_version (SoupMessage *msg)
1209 {
1210         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), SOUP_HTTP_1_0);
1211
1212         return SOUP_MESSAGE_GET_PRIVATE (msg)->http_version;
1213 }
1214
1215 /**
1216  * soup_message_is_keepalive:
1217  * @msg: a #SoupMessage
1218  *
1219  * Determines whether or not @msg's connection can be kept alive for
1220  * further requests after processing @msg, based on the HTTP version,
1221  * Connection header, etc.
1222  *
1223  * Return value: %TRUE or %FALSE.
1224  **/
1225 gboolean
1226 soup_message_is_keepalive (SoupMessage *msg)
1227 {
1228         const char *c_conn, *s_conn;
1229
1230         c_conn = soup_message_headers_get (msg->request_headers, "Connection");
1231         s_conn = soup_message_headers_get (msg->response_headers, "Connection");
1232
1233         if (msg->status_code == SOUP_STATUS_OK &&
1234             msg->method == SOUP_METHOD_CONNECT)
1235                 return TRUE;
1236
1237         if (SOUP_MESSAGE_GET_PRIVATE (msg)->http_version == SOUP_HTTP_1_0) {
1238                 /* Only persistent if the client requested keepalive
1239                  * and the server agreed.
1240                  */
1241
1242                 if (!c_conn || !s_conn)
1243                         return FALSE;
1244                 if (soup_header_contains (c_conn, "Keep-Alive") ||
1245                     soup_header_contains (s_conn, "Keep-Alive"))
1246                         return FALSE;
1247
1248                 return TRUE;
1249         } else {
1250                 /* Normally persistent unless either side requested otherwise */
1251                 if (c_conn && soup_header_contains (c_conn, "close"))
1252                         return FALSE;
1253                 if (s_conn && soup_header_contains (s_conn, "close"))
1254                         return FALSE;
1255
1256                 /* But not if the server sent a terminate-by-EOF response */
1257                 if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_EOF)
1258                         return FALSE;
1259
1260                 return TRUE;
1261         }
1262 }
1263
1264 /**
1265  * soup_message_set_uri:
1266  * @msg: a #SoupMessage
1267  * @uri: the new #SoupURI
1268  *
1269  * Sets @msg's URI to @uri. If @msg has already been sent and you want
1270  * to re-send it with the new URI, you need to call
1271  * soup_session_requeue_message().
1272  **/
1273 void
1274 soup_message_set_uri (SoupMessage *msg, SoupURI *uri)
1275 {
1276         SoupMessagePrivate *priv;
1277
1278         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1279         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1280
1281         if (priv->uri)
1282                 soup_uri_free (priv->uri);
1283         priv->uri = soup_uri_copy (uri);
1284
1285         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_URI);
1286 }
1287
1288 /**
1289  * soup_message_get_uri:
1290  * @msg: a #SoupMessage
1291  *
1292  * Gets @msg's URI
1293  *
1294  * Return value: the URI @msg is targeted for.
1295  **/
1296 SoupURI *
1297 soup_message_get_uri (SoupMessage *msg)
1298 {
1299         g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
1300
1301         return SOUP_MESSAGE_GET_PRIVATE (msg)->uri;
1302 }
1303
1304 /**
1305  * soup_message_set_status:
1306  * @msg: a #SoupMessage
1307  * @status_code: an HTTP status code
1308  *
1309  * Sets @msg's status code to @status_code. If @status_code is a
1310  * known value, it will also set @msg's reason_phrase.
1311  **/
1312 void
1313 soup_message_set_status (SoupMessage *msg, guint status_code)
1314 {
1315         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1316         g_return_if_fail (status_code != 0);
1317
1318         g_free (msg->reason_phrase);
1319
1320         msg->status_code = status_code;
1321         msg->reason_phrase = g_strdup (soup_status_get_phrase (status_code));
1322         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
1323         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
1324 }
1325
1326 /**
1327  * soup_message_set_status_full:
1328  * @msg: a #SoupMessage
1329  * @status_code: an HTTP status code
1330  * @reason_phrase: a description of the status
1331  *
1332  * Sets @msg's status code and reason phrase.
1333  **/
1334 void
1335 soup_message_set_status_full (SoupMessage *msg,
1336                               guint        status_code,
1337                               const char  *reason_phrase)
1338 {
1339         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1340         g_return_if_fail (status_code != 0);
1341         g_return_if_fail (reason_phrase != NULL);
1342
1343         g_free (msg->reason_phrase);
1344
1345         msg->status_code = status_code;
1346         msg->reason_phrase = g_strdup (reason_phrase);
1347         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_STATUS_CODE);
1348         g_object_notify (G_OBJECT (msg), SOUP_MESSAGE_REASON_PHRASE);
1349 }
1350
1351 void
1352 soup_message_set_io_status (SoupMessage          *msg,
1353                             SoupMessageIOStatus   status)
1354 {
1355         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1356
1357         priv->io_status = status;
1358 }
1359
1360 SoupMessageIOStatus
1361 soup_message_get_io_status (SoupMessage *msg)
1362 {
1363         SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1364
1365         return priv->io_status;
1366 }
1367
1368 /**
1369  * SoupChunkAllocator:
1370  * @msg: the #SoupMessage the chunk is being allocated for
1371  * @max_len: the maximum length that will be read, or 0.
1372  * @user_data: the data passed to soup_message_set_chunk_allocator()
1373  *
1374  * The prototype for a chunk allocation callback. This should allocate
1375  * a new #SoupBuffer and return it for the I/O layer to read message
1376  * body data off the network into.
1377  *
1378  * If @max_len is non-0, it indicates the maximum number of bytes that
1379  * could be read, based on what is known about the message size. Note
1380  * that this might be a very large number, and you should not simply
1381  * try to allocate that many bytes blindly. If @max_len is 0, that
1382  * means that libsoup does not know how many bytes remain to be read,
1383  * and the allocator should return a buffer of a size that it finds
1384  * convenient.
1385  *
1386  * If the allocator returns %NULL, the message will be paused. It is
1387  * up to the application to make sure that it gets unpaused when it
1388  * becomes possible to allocate a new buffer.
1389  *
1390  * Return value: the new buffer (or %NULL)
1391  **/
1392
1393 /**
1394  * soup_message_set_chunk_allocator:
1395  * @msg: a #SoupMessage
1396  * @allocator: the chunk allocator callback
1397  * @user_data: data to pass to @allocator
1398  * @destroy_notify: destroy notifier to free @user_data when @msg is
1399  * destroyed
1400  *
1401  * Sets an alternate chunk-allocation function to use when reading
1402  * @msg's body. Every time data is available to read, libsoup will
1403  * call @allocator, which should return a #SoupBuffer. (See
1404  * #SoupChunkAllocator for additional details.) Libsoup will then read
1405  * data from the network into that buffer, and update the buffer's
1406  * %length to indicate how much data it read.
1407  *
1408  * Generally, a custom chunk allocator would be used in conjunction
1409  * with soup_message_body_set_accumulate() %FALSE and
1410  * #SoupMessage::got_chunk, as part of a strategy to avoid unnecessary
1411  * copying of data. However, you cannot assume that every call to the
1412  * allocator will be followed by a call to your %got_chunk handler; if
1413  * an I/O error occurs, then the buffer will be unreffed without ever
1414  * having been used. If your buffer-allocation strategy requires
1415  * special cleanup, use soup_buffer_new_with_owner() rather than doing
1416  * the cleanup from the %got_chunk handler.
1417  *
1418  * The other thing to remember when using non-accumulating message
1419  * bodies is that the buffer passed to the %got_chunk handler will be
1420  * unreffed after the handler returns, just as it would be in the
1421  * non-custom-allocated case. If you want to hand the chunk data off
1422  * to some other part of your program to use later, you'll need to ref
1423  * the #SoupBuffer (or its owner, in the soup_buffer_new_with_owner()
1424  * case) to ensure that the data remains valid.
1425  **/
1426 void
1427 soup_message_set_chunk_allocator (SoupMessage *msg,
1428                                   SoupChunkAllocator allocator,
1429                                   gpointer user_data,
1430                                   GDestroyNotify destroy_notify)
1431 {
1432         SoupMessagePrivate *priv;
1433
1434         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1435
1436         priv = SOUP_MESSAGE_GET_PRIVATE (msg);
1437
1438         if (priv->chunk_allocator_dnotify)
1439                 priv->chunk_allocator_dnotify (priv->chunk_allocator_data);
1440
1441         priv->chunk_allocator         = allocator;
1442         priv->chunk_allocator_data    = user_data;
1443         priv->chunk_allocator_dnotify = destroy_notify;
1444 }