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