Git init
[profile/ivi/libsoup2.4.git] / libsoup / soup-server.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-server.c: Asynchronous HTTP server
4  *
5  * Copyright (C) 2001-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <unistd.h>
16
17 #include "soup-server.h"
18 #include "soup-address.h"
19 #include "soup-auth-domain.h"
20 #include "soup-date.h"
21 #include "soup-form.h"
22 #include "soup-headers.h"
23 #include "soup-message-private.h"
24 #include "soup-marshal.h"
25 #include "soup-path-map.h" 
26 #include "soup-socket.h"
27 #include "soup-ssl.h"
28
29 /**
30  * SECTION:soup-server
31  * @short_description: HTTP server
32  * @see_also: #SoupAuthDomain
33  *
34  * #SoupServer implements a simple HTTP server.
35  * 
36  * To begin, create a server using soup_server_new(). Add at least one
37  * handler by calling soup_server_add_handler(); the handler will be
38  * called to process any requests underneath the path passed to
39  * soup_server_add_handler(). (If you want all requests to go to the
40  * same handler, just pass "/" (or %NULL) for the path.) Any request
41  * that does not match any handler will automatically be returned to
42  * the client with a 404 (Not Found) status.
43  *
44  * If you want to handle the special "*" URI (eg, "OPTIONS *"), you
45  * must explicitly register a handler for "*"; the default handler
46  * will not be used for that case.
47  * 
48  * To add authentication to some or all paths, create an appropriate
49  * #SoupAuthDomain (qv), and add it to the server via
50  * soup_server_add_auth_domain(). (As with handlers, you must
51  * explicitly add "*" to an auth domain if you want it to be covered.)
52  * 
53  * Additional processing options are available via #SoupServer's
54  * signals; Connect to #SoupServer::request-started to be notified
55  * every time a new request is being processed. (This gives you a
56  * chance to connect to the #SoupMessage "got-" signals in case you
57  * want to do processing before the body has been fully read.)
58  * 
59  * Once the server is set up, start it processing connections by
60  * calling soup_server_run_async() or soup_server_run(). #SoupServer
61  * runs via the glib main loop; if you need to have a server that runs
62  * in another thread (or merely isn't bound to the default main loop),
63  * create a #GMainContext for it to use, and set that via the
64  * #SOUP_SERVER_ASYNC_CONTEXT property.
65  **/
66
67 G_DEFINE_TYPE (SoupServer, soup_server, G_TYPE_OBJECT)
68
69 enum {
70         REQUEST_STARTED,
71         REQUEST_READ,
72         REQUEST_FINISHED,
73         REQUEST_ABORTED,
74         LAST_SIGNAL
75 };
76
77 static guint signals[LAST_SIGNAL] = { 0 };
78
79 struct SoupClientContext {
80         SoupServer     *server;
81         SoupSocket     *sock;
82         SoupMessage    *msg;
83         SoupAuthDomain *auth_domain;
84         char           *auth_user;
85
86         int             ref_count;
87 };
88
89 typedef struct {
90         char                   *path;
91
92         SoupServerCallback      callback;
93         GDestroyNotify          destroy;
94         gpointer                user_data;
95 } SoupServerHandler;
96
97 typedef struct {
98         SoupAddress       *iface;
99         guint              port;
100
101         char              *ssl_cert_file, *ssl_key_file;
102         SoupSSLCredentials *ssl_creds;
103
104         char              *server_header;
105
106         GMainLoop         *loop;
107
108         SoupSocket        *listen_sock;
109         GSList            *clients;
110
111         gboolean           raw_paths;
112         SoupPathMap       *handlers;
113         SoupServerHandler *default_handler;
114         
115         GSList            *auth_domains;
116
117         GMainContext      *async_context;
118 } SoupServerPrivate;
119 #define SOUP_SERVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SERVER, SoupServerPrivate))
120
121 #define SOUP_SERVER_SERVER_HEADER_BASE "libsoup/" PACKAGE_VERSION
122
123 enum {
124         PROP_0,
125
126         PROP_PORT,
127         PROP_INTERFACE,
128         PROP_SSL_CERT_FILE,
129         PROP_SSL_KEY_FILE,
130         PROP_ASYNC_CONTEXT,
131         PROP_RAW_PATHS,
132         PROP_SERVER_HEADER,
133
134         LAST_PROP
135 };
136
137 static GObject *constructor (GType                  type,
138                              guint                  n_construct_properties,
139                              GObjectConstructParam *construct_properties);
140 static void set_property (GObject *object, guint prop_id,
141                           const GValue *value, GParamSpec *pspec);
142 static void get_property (GObject *object, guint prop_id,
143                           GValue *value, GParamSpec *pspec);
144
145 static void
146 free_handler (SoupServerHandler *hand)
147 {
148         g_free (hand->path);
149         g_slice_free (SoupServerHandler, hand);
150 }
151
152 static void
153 soup_server_init (SoupServer *server)
154 {
155         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
156
157         priv->handlers = soup_path_map_new ((GDestroyNotify)free_handler);
158 }
159
160 static void
161 finalize (GObject *object)
162 {
163         SoupServer *server = SOUP_SERVER (object);
164         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
165         GSList *iter;
166
167         if (priv->iface)
168                 g_object_unref (priv->iface);
169
170         g_free (priv->ssl_cert_file);
171         g_free (priv->ssl_key_file);
172         if (priv->ssl_creds)
173                 soup_ssl_free_server_credentials (priv->ssl_creds);
174
175         g_free (priv->server_header);
176
177         if (priv->listen_sock)
178                 g_object_unref (priv->listen_sock);
179
180         while (priv->clients) {
181                 SoupClientContext *client = priv->clients->data;
182                 SoupSocket *sock = g_object_ref (client->sock);
183
184                 priv->clients = g_slist_remove (priv->clients, client);
185
186                 if (client->msg) {
187                         soup_message_set_status (client->msg, SOUP_STATUS_IO_ERROR);
188                         soup_message_io_finished (client->msg);
189                 }
190
191                 soup_socket_disconnect (sock);
192                 g_object_unref (sock);
193         }
194
195         if (priv->default_handler)
196                 free_handler (priv->default_handler);
197         soup_path_map_free (priv->handlers);
198
199         for (iter = priv->auth_domains; iter; iter = iter->next)
200                 g_object_unref (iter->data);
201         g_slist_free (priv->auth_domains);
202
203         if (priv->loop)
204                 g_main_loop_unref (priv->loop);
205         if (priv->async_context)
206                 g_main_context_unref (priv->async_context);
207
208         G_OBJECT_CLASS (soup_server_parent_class)->finalize (object);
209 }
210
211 static void
212 soup_server_class_init (SoupServerClass *server_class)
213 {
214         GObjectClass *object_class = G_OBJECT_CLASS (server_class);
215
216         g_type_class_add_private (server_class, sizeof (SoupServerPrivate));
217
218         /* virtual method override */
219         object_class->constructor = constructor;
220         object_class->finalize = finalize;
221         object_class->set_property = set_property;
222         object_class->get_property = get_property;
223
224         /* signals */
225
226         /**
227          * SoupServer::request-started
228          * @server: the server
229          * @message: the new message
230          * @client: the client context
231          *
232          * Emitted when the server has started reading a new request.
233          * @message will be completely blank; not even the
234          * Request-Line will have been read yet. About the only thing
235          * you can usefully do with it is connect to its signals.
236          *
237          * If the request is read successfully, this will eventually
238          * be followed by a #SoupServer::request_read signal. If a
239          * response is then sent, the request processing will end with
240          * a #SoupServer::request_finished signal. If a network error
241          * occurs, the processing will instead end with
242          * #SoupServer::request_aborted.
243          **/
244         signals[REQUEST_STARTED] =
245                 g_signal_new ("request-started",
246                               G_OBJECT_CLASS_TYPE (object_class),
247                               G_SIGNAL_RUN_FIRST,
248                               G_STRUCT_OFFSET (SoupServerClass, request_started),
249                               NULL, NULL,
250                               soup_marshal_NONE__OBJECT_POINTER,
251                               G_TYPE_NONE, 2, 
252                               SOUP_TYPE_MESSAGE,
253                               SOUP_TYPE_CLIENT_CONTEXT);
254
255         /**
256          * SoupServer::request-read
257          * @server: the server
258          * @message: the message
259          * @client: the client context
260          *
261          * Emitted when the server has successfully read a request.
262          * @message will have all of its request-side information
263          * filled in, and if the message was authenticated, @client
264          * will have information about that. This signal is emitted
265          * before any handlers are called for the message, and if it
266          * sets the message's #status_code, then normal handler
267          * processing will be skipped.
268          **/
269         signals[REQUEST_READ] =
270                 g_signal_new ("request-read",
271                               G_OBJECT_CLASS_TYPE (object_class),
272                               G_SIGNAL_RUN_FIRST,
273                               G_STRUCT_OFFSET (SoupServerClass, request_read),
274                               NULL, NULL,
275                               soup_marshal_NONE__OBJECT_POINTER,
276                               G_TYPE_NONE, 2,
277                               SOUP_TYPE_MESSAGE,
278                               SOUP_TYPE_CLIENT_CONTEXT);
279
280         /**
281          * SoupServer::request-finished
282          * @server: the server
283          * @message: the message
284          * @client: the client context
285          *
286          * Emitted when the server has finished writing a response to
287          * a request.
288          **/
289         signals[REQUEST_FINISHED] =
290                 g_signal_new ("request-finished",
291                               G_OBJECT_CLASS_TYPE (object_class),
292                               G_SIGNAL_RUN_FIRST,
293                               G_STRUCT_OFFSET (SoupServerClass, request_finished),
294                               NULL, NULL,
295                               soup_marshal_NONE__OBJECT_POINTER,
296                               G_TYPE_NONE, 2,
297                               SOUP_TYPE_MESSAGE,
298                               SOUP_TYPE_CLIENT_CONTEXT);
299
300         /**
301          * SoupServer::request-aborted
302          * @server: the server
303          * @message: the message
304          * @client: the client context
305          *
306          * Emitted when processing has failed for a message; this
307          * could mean either that it could not be read (if
308          * #SoupServer::request_read has not been emitted for it yet),
309          * or that the response could not be written back (if
310          * #SoupServer::request_read has been emitted but
311          * #SoupServer::request_finished has not been).
312          *
313          * @message is in an undefined state when this signal is
314          * emitted; the signal exists primarily to allow the server to
315          * free any state that it may have allocated in
316          * #SoupServer::request_started.
317          **/
318         signals[REQUEST_ABORTED] =
319                 g_signal_new ("request-aborted",
320                               G_OBJECT_CLASS_TYPE (object_class),
321                               G_SIGNAL_RUN_FIRST,
322                               G_STRUCT_OFFSET (SoupServerClass, request_aborted),
323                               NULL, NULL,
324                               soup_marshal_NONE__OBJECT_POINTER,
325                               G_TYPE_NONE, 2,
326                               SOUP_TYPE_MESSAGE,
327                               SOUP_TYPE_CLIENT_CONTEXT);
328
329         /* properties */
330         /**
331          * SOUP_SERVER_PORT:
332          *
333          * Alias for the #SoupServer:port property. (The port the
334          * server listens on.)
335          **/
336         g_object_class_install_property (
337                 object_class, PROP_PORT,
338                 g_param_spec_uint (SOUP_SERVER_PORT,
339                                    "Port",
340                                    "Port to listen on",
341                                    0, 65536, 0,
342                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
343         /**
344          * SOUP_SERVER_INTERFACE:
345          *
346          * Alias for the #SoupServer:interface property. (The address
347          * of the network interface the server listens on.)
348          **/
349         g_object_class_install_property (
350                 object_class, PROP_INTERFACE,
351                 g_param_spec_object (SOUP_SERVER_INTERFACE,
352                                      "Interface",
353                                      "Address of interface to listen on",
354                                      SOUP_TYPE_ADDRESS,
355                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
356         /**
357          * SOUP_SERVER_SSL_CERT_FILE:
358          *
359          * Alias for the #SoupServer:ssl-cert-file property. (The file
360          * containing the SSL certificate for the server.)
361          **/
362         g_object_class_install_property (
363                 object_class, PROP_SSL_CERT_FILE,
364                 g_param_spec_string (SOUP_SERVER_SSL_CERT_FILE,
365                                      "SSL certificate file",
366                                      "File containing server SSL certificate",
367                                      NULL,
368                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
369         /**
370          * SOUP_SERVER_SSL_KEY_FILE:
371          *
372          * Alias for the #SoupServer:ssl-key-file property. (The file
373          * containing the SSL certificate key for the server.)
374          **/
375         g_object_class_install_property (
376                 object_class, PROP_SSL_KEY_FILE,
377                 g_param_spec_string (SOUP_SERVER_SSL_KEY_FILE,
378                                      "SSL key file",
379                                      "File containing server SSL key",
380                                      NULL,
381                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
382         /**
383          * SOUP_SERVER_ASYNC_CONTEXT:
384          *
385          * Alias for the #SoupServer:async-context property. (The
386          * server's #GMainContext.)
387          **/
388         g_object_class_install_property (
389                 object_class, PROP_ASYNC_CONTEXT,
390                 g_param_spec_pointer (SOUP_SERVER_ASYNC_CONTEXT,
391                                       "Async GMainContext",
392                                       "The GMainContext to dispatch async I/O in",
393                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
394         /**
395          * SOUP_SERVER_RAW_PATHS:
396          *
397          * Alias for the #SoupServer:raw-paths property. (If %TRUE,
398          * percent-encoding in the Request-URI path will not be
399          * automatically decoded.)
400          **/
401         g_object_class_install_property (
402                 object_class, PROP_RAW_PATHS,
403                 g_param_spec_boolean (SOUP_SERVER_RAW_PATHS,
404                                       "Raw paths",
405                                       "If %TRUE, percent-encoding in the Request-URI path will not be automatically decoded.",
406                                       FALSE,
407                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
408
409         /**
410          * SoupServer:server-header:
411          *
412          * If non-%NULL, the value to use for the "Server" header on
413          * #SoupMessage<!-- -->s processed by this server.
414          *
415          * The Server header is the server equivalent of the
416          * User-Agent header, and provides information about the
417          * server and its components. It contains a list of one or
418          * more product tokens, separated by whitespace, with the most
419          * significant product token coming first. The tokens must be
420          * brief, ASCII, and mostly alphanumeric (although "-", "_",
421          * and "." are also allowed), and may optionally include a "/"
422          * followed by a version string. You may also put comments,
423          * enclosed in parentheses, between or after the tokens.
424          *
425          * Some HTTP server implementations intentionally do not use
426          * version numbers in their Server header, so that
427          * installations running older versions of the server don't
428          * end up advertising their vulnerability to specific security
429          * holes.
430          *
431          * As with #SoupSession:user_agent, if you set a
432          * %server_header property that has trailing whitespace,
433          * #SoupServer will append its own product token (eg,
434          * "<literal>libsoup/2.3.2</literal>") to the end of the
435          * header for you.
436          **/
437         /**
438          * SOUP_SERVER_SERVER_HEADER:
439          *
440          * Alias for the #SoupServer:server-header property, qv.
441          **/
442         g_object_class_install_property (
443                 object_class, PROP_SERVER_HEADER,
444                 g_param_spec_string (SOUP_SERVER_SERVER_HEADER,
445                                      "Server header",
446                                      "Server header",
447                                      NULL,
448                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
449 }
450
451 static GObject *
452 constructor (GType                  type,
453              guint                  n_construct_properties,
454              GObjectConstructParam *construct_properties)
455 {
456         GObject *server;
457         SoupServerPrivate *priv;
458
459         server = G_OBJECT_CLASS (soup_server_parent_class)->constructor (
460                 type, n_construct_properties, construct_properties);
461         if (!server)
462                 return NULL;
463         priv = SOUP_SERVER_GET_PRIVATE (server);
464
465         if (!priv->iface) {
466                 priv->iface =
467                         soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4,
468                                               priv->port);
469         }
470
471         if (priv->ssl_cert_file && priv->ssl_key_file) {
472                 priv->ssl_creds = soup_ssl_get_server_credentials (
473                         priv->ssl_cert_file,
474                         priv->ssl_key_file);
475                 if (!priv->ssl_creds) {
476                         g_object_unref (server);
477                         return NULL;
478                 }
479         }
480
481         priv->listen_sock =
482                 soup_socket_new (SOUP_SOCKET_LOCAL_ADDRESS, priv->iface,
483                                  SOUP_SOCKET_SSL_CREDENTIALS, priv->ssl_creds,
484                                  SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
485                                  NULL);
486         if (!soup_socket_listen (priv->listen_sock)) {
487                 g_object_unref (server);
488                 return NULL;
489         }
490
491         /* Re-resolve the interface address, in particular in case
492          * the passed-in address had SOUP_ADDRESS_ANY_PORT.
493          */
494         g_object_unref (priv->iface);
495         priv->iface = soup_socket_get_local_address (priv->listen_sock);
496         g_object_ref (priv->iface);
497         priv->port = soup_address_get_port (priv->iface);
498
499         return server;
500 }
501
502 static void
503 set_property (GObject *object, guint prop_id,
504               const GValue *value, GParamSpec *pspec)
505 {
506         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
507         const char *header;
508
509         switch (prop_id) {
510         case PROP_PORT:
511                 priv->port = g_value_get_uint (value);
512                 break;
513         case PROP_INTERFACE:
514                 if (priv->iface)
515                         g_object_unref (priv->iface);
516                 priv->iface = g_value_get_object (value);
517                 if (priv->iface)
518                         g_object_ref (priv->iface);
519                 break;
520         case PROP_SSL_CERT_FILE:
521                 priv->ssl_cert_file =
522                         g_strdup (g_value_get_string (value));
523                 break;
524         case PROP_SSL_KEY_FILE:
525                 priv->ssl_key_file =
526                         g_strdup (g_value_get_string (value));
527                 break;
528         case PROP_ASYNC_CONTEXT:
529                 priv->async_context = g_value_get_pointer (value);
530                 if (priv->async_context)
531                         g_main_context_ref (priv->async_context);
532                 break;
533         case PROP_RAW_PATHS:
534                 priv->raw_paths = g_value_get_boolean (value);
535                 break;
536         case PROP_SERVER_HEADER:
537                 g_free (priv->server_header);
538                 header = g_value_get_string (value);
539                 if (!header)
540                         priv->server_header = NULL;
541                 else if (!*header) {
542                         priv->server_header =
543                                 g_strdup (SOUP_SERVER_SERVER_HEADER_BASE);
544                 } else if (g_str_has_suffix (header, " ")) {
545                         priv->server_header =
546                                 g_strdup_printf ("%s%s", header,
547                                                  SOUP_SERVER_SERVER_HEADER_BASE);
548                 } else
549                         priv->server_header = g_strdup (header);
550                 break;
551         default:
552                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
553                 break;
554         }
555 }
556
557 static void
558 get_property (GObject *object, guint prop_id,
559               GValue *value, GParamSpec *pspec)
560 {
561         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (object);
562
563         switch (prop_id) {
564         case PROP_PORT:
565                 g_value_set_uint (value, priv->port);
566                 break;
567         case PROP_INTERFACE:
568                 g_value_set_object (value, priv->iface);
569                 break;
570         case PROP_SSL_CERT_FILE:
571                 g_value_set_string (value, priv->ssl_cert_file);
572                 break;
573         case PROP_SSL_KEY_FILE:
574                 g_value_set_string (value, priv->ssl_key_file);
575                 break;
576         case PROP_ASYNC_CONTEXT:
577                 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
578                 break;
579         case PROP_RAW_PATHS:
580                 g_value_set_boolean (value, priv->raw_paths);
581                 break;
582         case PROP_SERVER_HEADER:
583                 g_value_set_string (value, priv->server_header);
584                 break;
585         default:
586                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
587                 break;
588         }
589 }
590
591 /**
592  * soup_server_new:
593  * @optname1: name of first property to set
594  * @...: value of @optname1, followed by additional property/value pairs
595  *
596  * Creates a new #SoupServer.
597  *
598  * Return value: a new #SoupServer
599  **/
600 SoupServer *
601 soup_server_new (const char *optname1, ...)
602 {
603         SoupServer *server;
604         va_list ap;
605
606         va_start (ap, optname1);
607         server = (SoupServer *)g_object_new_valist (SOUP_TYPE_SERVER,
608                                                     optname1, ap);
609         va_end (ap);
610
611         return server;
612 }
613
614 /**
615  * soup_server_get_port:
616  * @server: a #SoupServer
617  *
618  * Gets the TCP port that @server is listening on. This is most useful
619  * when you did not request a specific port (or explicitly requested
620  * %SOUP_ADDRESS_ANY_PORT).
621  *
622  * Return value: the port @server is listening on.
623  **/
624 guint
625 soup_server_get_port (SoupServer *server)
626 {
627         g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
628
629         return SOUP_SERVER_GET_PRIVATE (server)->port;
630 }
631
632 /**
633  * soup_server_is_https:
634  * @server: a #SoupServer
635  *
636  * Checks whether @server is running plain http or https.
637  *
638  * In order for a server to run https, you must set the
639  * %SOUP_SERVER_SSL_CERT_FILE and %SOUP_SERVER_SSL_KEY_FILE properties
640  * to provide it with an SSL certificate to use.
641  *
642  * Return value: %TRUE if @server is serving https.
643  **/
644 gboolean
645 soup_server_is_https (SoupServer *server)
646 {
647         SoupServerPrivate *priv;
648
649         g_return_val_if_fail (SOUP_IS_SERVER (server), 0);
650         priv = SOUP_SERVER_GET_PRIVATE (server);
651
652         return (priv->ssl_cert_file && priv->ssl_key_file);
653 }
654
655 /**
656  * soup_server_get_listener:
657  * @server: a #SoupServer
658  *
659  * Gets @server's listening socket. You should treat this as
660  * read-only; writing to it or modifiying it may cause @server to
661  * malfunction.
662  *
663  * Return value: (transfer none): the listening socket.
664  **/
665 SoupSocket *
666 soup_server_get_listener (SoupServer *server)
667 {
668         SoupServerPrivate *priv;
669
670         g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
671         priv = SOUP_SERVER_GET_PRIVATE (server);
672
673         return priv->listen_sock;
674 }
675
676 static void start_request (SoupServer *, SoupClientContext *);
677
678 static SoupClientContext *
679 soup_client_context_new (SoupServer *server, SoupSocket *sock)
680 {
681         SoupClientContext *client = g_slice_new0 (SoupClientContext);
682
683         client->server = server;
684         client->sock = sock;
685         client->ref_count = 1;
686
687         return client;
688 }
689
690 static void
691 soup_client_context_cleanup (SoupClientContext *client)
692 {
693         if (client->auth_domain) {
694                 g_object_unref (client->auth_domain);
695                 client->auth_domain = NULL;
696         }
697         if (client->auth_user) {
698                 g_free (client->auth_user);
699                 client->auth_user = NULL;
700         }
701         client->msg = NULL;
702 }
703
704 static SoupClientContext *
705 soup_client_context_ref (SoupClientContext *client)
706 {
707         client->ref_count++;
708         return client;
709 }
710
711 static void
712 soup_client_context_unref (SoupClientContext *client)
713 {
714         if (--client->ref_count == 0) {
715                 soup_client_context_cleanup (client);
716                 g_slice_free (SoupClientContext, client);
717         }
718 }
719
720 static void
721 request_finished (SoupMessage *msg, gpointer user_data)
722 {
723         SoupClientContext *client = user_data;
724         SoupServer *server = client->server;
725         SoupSocket *sock = client->sock;
726
727         soup_message_finished (msg);
728         g_signal_emit (server,
729                        msg->status_code == SOUP_STATUS_IO_ERROR ?
730                        signals[REQUEST_ABORTED] : signals[REQUEST_FINISHED],
731                        0, msg, client);
732
733         soup_client_context_cleanup (client);
734         if (soup_socket_is_connected (sock) && soup_message_is_keepalive (msg)) {
735                 /* Start a new request */
736                 start_request (server, client);
737         } else {
738                 soup_socket_disconnect (sock);
739                 soup_client_context_unref (client);
740         }
741         g_object_unref (msg);
742         g_object_unref (sock);
743 }
744
745 static SoupServerHandler *
746 soup_server_get_handler (SoupServer *server, const char *path)
747 {
748         SoupServerPrivate *priv;
749         SoupServerHandler *hand;
750
751         g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
752         priv = SOUP_SERVER_GET_PRIVATE (server);
753
754         if (path) {
755                 hand = soup_path_map_lookup (priv->handlers, path);
756                 if (hand)
757                         return hand;
758                 if (!strcmp (path, "*"))
759                         return NULL;
760         }
761         return priv->default_handler;
762 }
763
764 static void
765 got_headers (SoupMessage *req, SoupClientContext *client)
766 {
767         SoupServer *server = client->server;
768         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
769         SoupURI *uri;
770         SoupDate *date;
771         char *date_string;
772         SoupAuthDomain *domain;
773         GSList *iter;
774         gboolean rejected = FALSE;
775         char *auth_user;
776
777         if (!priv->raw_paths) {
778                 char *decoded_path;
779
780                 uri = soup_message_get_uri (req);
781                 decoded_path = soup_uri_decode (uri->path);
782
783                 if (strstr (decoded_path, "/../") ||
784                     g_str_has_suffix (decoded_path, "/..")) {
785                         /* Introducing new ".." segments is not allowed */
786                         g_free (decoded_path);
787                         soup_message_set_status (req, SOUP_STATUS_BAD_REQUEST);
788                         return;
789                 }
790
791                 soup_uri_set_path (uri, decoded_path);
792                 g_free (decoded_path);
793         }
794
795         /* Add required response headers */
796         date = soup_date_new_from_now (0);
797         date_string = soup_date_to_string (date, SOUP_DATE_HTTP);
798         soup_message_headers_replace (req->response_headers, "Date",
799                                       date_string);
800         g_free (date_string);
801         soup_date_free (date);
802         
803         /* Now handle authentication. (We do this here so that if
804          * the request uses "Expect: 100-continue", we can reject it
805          * immediately rather than waiting for the request body to
806          * be sent.
807          */
808         for (iter = priv->auth_domains; iter; iter = iter->next) {
809                 domain = iter->data;
810
811                 if (soup_auth_domain_covers (domain, req)) {
812                         auth_user = soup_auth_domain_accepts (domain, req);
813                         if (auth_user) {
814                                 client->auth_domain = g_object_ref (domain);
815                                 client->auth_user = auth_user;
816                                 return;
817                         }
818
819                         rejected = TRUE;
820                 }
821         }
822
823         /* If no auth domain rejected it, then it's ok. */
824         if (!rejected)
825                 return;
826
827         for (iter = priv->auth_domains; iter; iter = iter->next) {
828                 domain = iter->data;
829
830                 if (soup_auth_domain_covers (domain, req))
831                         soup_auth_domain_challenge (domain, req);
832         }
833 }
834
835 static void
836 call_handler (SoupMessage *req, SoupClientContext *client)
837 {
838         SoupServer *server = client->server;
839         SoupServerHandler *hand;
840         SoupURI *uri;
841
842         g_signal_emit (server, signals[REQUEST_READ], 0, req, client);
843
844         if (req->status_code != 0)
845                 return;
846
847         uri = soup_message_get_uri (req);
848         hand = soup_server_get_handler (server, uri->path);
849         if (!hand) {
850                 soup_message_set_status (req, SOUP_STATUS_NOT_FOUND);
851                 return;
852         }
853
854         if (hand->callback) {
855                 GHashTable *form_data_set;
856
857                 if (uri->query)
858                         form_data_set = soup_form_decode (uri->query);
859                 else
860                         form_data_set = NULL;
861
862                 /* Call method handler */
863                 (*hand->callback) (server, req,
864                                    uri->path, form_data_set,
865                                    client, hand->user_data);
866
867                 if (form_data_set)
868                         g_hash_table_destroy (form_data_set);
869         }
870 }
871
872 static void
873 start_request (SoupServer *server, SoupClientContext *client)
874 {
875         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
876         SoupMessage *msg;
877
878         soup_client_context_cleanup (client);
879
880         /* Listen for another request on this connection */
881         msg = g_object_new (SOUP_TYPE_MESSAGE,
882                             SOUP_MESSAGE_SERVER_SIDE, TRUE,
883                             NULL);
884         client->msg = msg;
885
886         if (priv->server_header) {
887                 soup_message_headers_append (msg->response_headers, "Server",
888                                              priv->server_header);
889         }
890
891         g_signal_connect (msg, "got_headers", G_CALLBACK (got_headers), client);
892         g_signal_connect (msg, "got_body", G_CALLBACK (call_handler), client);
893
894         g_signal_emit (server, signals[REQUEST_STARTED], 0,
895                        msg, client);
896
897         g_object_ref (client->sock);
898         soup_message_read_request (msg, client->sock,
899                                    request_finished, client);
900 }
901
902 static void
903 socket_disconnected (SoupSocket *sock, SoupClientContext *client)
904 {
905         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (client->server);
906
907         priv->clients = g_slist_remove (priv->clients, client);
908         g_signal_handlers_disconnect_by_func (sock, socket_disconnected, client);
909         g_object_unref (sock);
910 }
911
912 static void
913 new_connection (SoupSocket *listner, SoupSocket *sock, gpointer user_data)
914 {
915         SoupServer *server = user_data;
916         SoupServerPrivate *priv = SOUP_SERVER_GET_PRIVATE (server);
917         SoupClientContext *client;
918
919         client = soup_client_context_new (server, g_object_ref (sock));
920         priv->clients = g_slist_prepend (priv->clients, client);
921         g_signal_connect (sock, "disconnected",
922                           G_CALLBACK (socket_disconnected), client);
923         start_request (server, client);
924 }
925
926 /**
927  * soup_server_run_async:
928  * @server: a #SoupServer
929  *
930  * Starts @server, causing it to listen for and process incoming
931  * connections.
932  *
933  * The server actually runs in @server's #GMainContext. It will not
934  * actually perform any processing unless the appropriate main loop is
935  * running. In the simple case where you did not set the server's
936  * %SOUP_SERVER_ASYNC_CONTEXT property, this means the server will run
937  * whenever the glib main loop is running.
938  **/
939 void
940 soup_server_run_async (SoupServer *server)
941 {
942         SoupServerPrivate *priv;
943
944         g_return_if_fail (SOUP_IS_SERVER (server));
945         priv = SOUP_SERVER_GET_PRIVATE (server);
946
947         if (!priv->listen_sock) {
948                 if (priv->loop) {
949                         g_main_loop_unref (priv->loop);
950                         priv->loop = NULL;
951                 }
952                 return;
953         }
954
955         g_signal_connect (priv->listen_sock, "new_connection",
956                           G_CALLBACK (new_connection), server);
957
958         return;
959
960 }
961
962 /**
963  * soup_server_run:
964  * @server: a #SoupServer
965  *
966  * Starts @server, causing it to listen for and process incoming
967  * connections. Unlike soup_server_run_async(), this creates a
968  * #GMainLoop and runs it, and it will not return until someone calls
969  * soup_server_quit() to stop the server.
970  **/
971 void
972 soup_server_run (SoupServer *server)
973 {
974         SoupServerPrivate *priv;
975
976         g_return_if_fail (SOUP_IS_SERVER (server));
977         priv = SOUP_SERVER_GET_PRIVATE (server);
978
979         if (!priv->loop) {
980                 priv->loop = g_main_loop_new (priv->async_context, TRUE);
981                 soup_server_run_async (server);
982         }
983
984         if (priv->loop)
985                 g_main_loop_run (priv->loop);
986 }
987
988 /**
989  * soup_server_quit:
990  * @server: a #SoupServer
991  *
992  * Stops processing for @server. Call this to clean up after
993  * soup_server_run_async(), or to terminate a call to soup_server_run().
994  *
995  * @server is still in a working state after this call; you can start
996  * and stop a server as many times as you want.
997  **/
998 void
999 soup_server_quit (SoupServer *server)
1000 {
1001         SoupServerPrivate *priv;
1002
1003         g_return_if_fail (SOUP_IS_SERVER (server));
1004         priv = SOUP_SERVER_GET_PRIVATE (server);
1005
1006         g_signal_handlers_disconnect_by_func (priv->listen_sock,
1007                                               G_CALLBACK (new_connection),
1008                                               server);
1009         if (priv->loop)
1010                 g_main_loop_quit (priv->loop);
1011 }
1012
1013 /**
1014  * soup_server_disconnect:
1015  * @server: a #SoupServer
1016  *
1017  * Stops processing for @server and closes its socket. This implies
1018  * the effects of soup_server_quit(), but additionally closes the
1019  * listening socket.  Note that messages currently in progress will
1020  * continue to be handled, if the main loop associated with the
1021  * server is resumed or kept running.
1022  *
1023  * After calling this function, @server is no longer functional, so it
1024  * has nearly the same effect as destroying @server entirely. The
1025  * function is thus useful mainly for language bindings without
1026  * explicit control over object lifetime.
1027  **/
1028 void
1029 soup_server_disconnect (SoupServer *server)
1030 {
1031         SoupServerPrivate *priv;
1032
1033         g_return_if_fail (SOUP_IS_SERVER (server));
1034         priv = SOUP_SERVER_GET_PRIVATE (server);
1035
1036         soup_server_quit (server);
1037
1038         if (priv->listen_sock) {
1039                 soup_socket_disconnect (priv->listen_sock);
1040                 g_object_unref (priv->listen_sock);
1041                 priv->listen_sock = NULL;
1042         }
1043 }
1044
1045 /**
1046  * soup_server_get_async_context:
1047  * @server: a #SoupServer
1048  *
1049  * Gets @server's async_context. This does not add a ref to the
1050  * context, so you will need to ref it yourself if you want it to
1051  * outlive its server.
1052  *
1053  * Return value: (transfer none): @server's #GMainContext, which may be %NULL
1054  **/
1055 GMainContext *
1056 soup_server_get_async_context (SoupServer *server)
1057 {
1058         SoupServerPrivate *priv;
1059
1060         g_return_val_if_fail (SOUP_IS_SERVER (server), NULL);
1061         priv = SOUP_SERVER_GET_PRIVATE (server);
1062
1063         return priv->async_context;
1064 }
1065
1066 /**
1067  * SoupClientContext:
1068  *
1069  * A #SoupClientContext provides additional information about the
1070  * client making a particular request. In particular, you can use
1071  * soup_client_context_get_auth_domain() and
1072  * soup_client_context_get_auth_user() to determine if HTTP
1073  * authentication was used successfully.
1074  *
1075  * soup_client_context_get_address() and/or
1076  * soup_client_context_get_host() can be used to get information for
1077  * logging or debugging purposes. soup_client_context_get_socket() may
1078  * also be of use in some situations (eg, tracking when multiple
1079  * requests are made on the same connection).
1080  **/
1081 GType
1082 soup_client_context_get_type (void)
1083 {
1084         static volatile gsize type_volatile = 0;
1085
1086         if (g_once_init_enter (&type_volatile)) {
1087                 GType type = g_boxed_type_register_static (
1088                         g_intern_static_string ("SoupClientContext"),
1089                         (GBoxedCopyFunc) soup_client_context_ref,
1090                         (GBoxedFreeFunc) soup_client_context_unref);
1091                 g_once_init_leave (&type_volatile, type);
1092         }
1093         return type_volatile;
1094 }
1095
1096 /**
1097  * soup_client_context_get_socket:
1098  * @client: a #SoupClientContext
1099  *
1100  * Retrieves the #SoupSocket that @client is associated with.
1101  *
1102  * If you are using this method to observe when multiple requests are
1103  * made on the same persistent HTTP connection (eg, as the ntlm-test
1104  * test program does), you will need to pay attention to socket
1105  * destruction as well (either by using weak references, or by
1106  * connecting to the #SoupSocket::disconnected signal), so that you do
1107  * not get fooled when the allocator reuses the memory address of a
1108  * previously-destroyed socket to represent a new socket.
1109  *
1110  * Return value: (transfer none): the #SoupSocket that @client is
1111  * associated with.
1112  **/
1113 SoupSocket *
1114 soup_client_context_get_socket (SoupClientContext *client)
1115 {
1116         g_return_val_if_fail (client != NULL, NULL);
1117
1118         return client->sock;
1119 }
1120
1121 /**
1122  * soup_client_context_get_address:
1123  * @client: a #SoupClientContext
1124  *
1125  * Retrieves the #SoupAddress associated with the remote end
1126  * of a connection.
1127  *
1128  * Return value: (transfer none): the #SoupAddress associated with the
1129  * remote end of a connection.
1130  **/
1131 SoupAddress *
1132 soup_client_context_get_address (SoupClientContext *client)
1133 {
1134         g_return_val_if_fail (client != NULL, NULL);
1135
1136         return soup_socket_get_remote_address (client->sock);
1137 }
1138
1139 /**
1140  * soup_client_context_get_host:
1141  * @client: a #SoupClientContext
1142  *
1143  * Retrieves the IP address associated with the remote end of a
1144  * connection. (If you want the actual hostname, you'll have to call
1145  * soup_client_context_get_address() and then call the appropriate
1146  * #SoupAddress method to resolve it.)
1147  *
1148  * Return value: the IP address associated with the remote end of a
1149  * connection.
1150  **/
1151 const char *
1152 soup_client_context_get_host (SoupClientContext *client)
1153 {
1154         SoupAddress *address;
1155
1156         address = soup_client_context_get_address (client);
1157         return soup_address_get_physical (address);
1158 }
1159
1160 /**
1161  * soup_client_context_get_auth_domain:
1162  * @client: a #SoupClientContext
1163  *
1164  * Checks whether the request associated with @client has been
1165  * authenticated, and if so returns the #SoupAuthDomain that
1166  * authenticated it.
1167  *
1168  * Return value: (transfer none) (allow-none): a #SoupAuthDomain, or
1169  * %NULL if the request was not authenticated.
1170  **/
1171 SoupAuthDomain *
1172 soup_client_context_get_auth_domain (SoupClientContext *client)
1173 {
1174         g_return_val_if_fail (client != NULL, NULL);
1175
1176         return client->auth_domain;
1177 }
1178
1179 /**
1180  * soup_client_context_get_auth_user:
1181  * @client: a #SoupClientContext
1182  *
1183  * Checks whether the request associated with @client has been
1184  * authenticated, and if so returns the username that the client
1185  * authenticated as.
1186  *
1187  * Return value: the authenticated-as user, or %NULL if the request
1188  * was not authenticated.
1189  **/
1190 const char *
1191 soup_client_context_get_auth_user (SoupClientContext *client)
1192 {
1193         g_return_val_if_fail (client != NULL, NULL);
1194
1195         return client->auth_user;
1196 }
1197
1198 /**
1199  * SoupServerCallback:
1200  * @server: the #SoupServer
1201  * @msg: the message being processed
1202  * @path: the path component of @msg's Request-URI
1203  * @query: (element-type utf8 utf8) (allow-none): the parsed query
1204  *         component of @msg's Request-URI
1205  * @client: additional contextual information about the client
1206  * @user_data: the data passed to @soup_server_add_handler
1207  *
1208  * A callback used to handle requests to a #SoupServer. The callback
1209  * will be invoked after receiving the request body; @msg's %method,
1210  * %request_headers, and %request_body fields will be filled in.
1211  *
1212  * @path and @query contain the likewise-named components of the
1213  * Request-URI, subject to certain assumptions. By default,
1214  * #SoupServer decodes all percent-encoding in the URI path, such that
1215  * "/foo%<!-- -->2Fbar" is treated the same as "/foo/bar". If your
1216  * server is serving resources in some non-POSIX-filesystem namespace,
1217  * you may want to distinguish those as two distinct paths. In that
1218  * case, you can set the %SOUP_SERVER_RAW_PATHS property when creating
1219  * the #SoupServer, and it will leave those characters undecoded. (You
1220  * may want to call soup_uri_normalize() to decode any percent-encoded
1221  * characters that you aren't handling specially.)
1222  *
1223  * @query contains the query component of the Request-URI parsed
1224  * according to the rules for HTML form handling. Although this is the
1225  * only commonly-used query string format in HTTP, there is nothing
1226  * that actually requires that HTTP URIs use that format; if your
1227  * server needs to use some other format, you can just ignore @query,
1228  * and call soup_message_get_uri() and parse the URI's query field
1229  * yourself.
1230  *
1231  * After determining what to do with the request, the callback must at
1232  * a minimum call soup_message_set_status() (or
1233  * soup_message_set_status_full()) on @msg to set the response status
1234  * code. Additionally, it may set response headers and/or fill in the
1235  * response body.
1236  *
1237  * If the callback cannot fully fill in the response before returning
1238  * (eg, if it needs to wait for information from a database, or
1239  * another network server), it should call soup_server_pause_message()
1240  * to tell #SoupServer to not send the response right away. When the
1241  * response is ready, call soup_server_unpause_message() to cause it
1242  * to be sent.
1243  *
1244  * To send the response body a bit at a time using "chunked" encoding,
1245  * first call soup_message_headers_set_encoding() to set
1246  * %SOUP_ENCODING_CHUNKED on the %response_headers. Then call
1247  * soup_message_body_append() (or soup_message_body_append_buffer())
1248  * to append each chunk as it becomes ready, and
1249  * soup_server_unpause_message() to make sure it's running. (The
1250  * server will automatically pause the message if it is using chunked
1251  * encoding but no more chunks are available.) When you are done, call
1252  * soup_message_body_complete() to indicate that no more chunks are
1253  * coming.
1254  **/
1255
1256 /**
1257  * soup_server_add_handler:
1258  * @server: a #SoupServer
1259  * @path: (allow-none): the toplevel path for the handler
1260  * @callback: callback to invoke for requests under @path
1261  * @user_data: data for @callback
1262  * @destroy: destroy notifier to free @user_data
1263  *
1264  * Adds a handler to @server for requests under @path. See the
1265  * documentation for #SoupServerCallback for information about
1266  * how callbacks should behave.
1267  *
1268  * If @path is %NULL or "/", then this will be the default handler for
1269  * all requests that don't have a more specific handler. Note though
1270  * that if you want to handle requests to the special "*" URI, you
1271  * must explicitly register a handler for "*"; the default handler
1272  * will not be used for that case.
1273  **/
1274 void
1275 soup_server_add_handler (SoupServer            *server,
1276                          const char            *path,
1277                          SoupServerCallback     callback,
1278                          gpointer               user_data,
1279                          GDestroyNotify         destroy)
1280 {
1281         SoupServerPrivate *priv;
1282         SoupServerHandler *hand;
1283
1284         g_return_if_fail (SOUP_IS_SERVER (server));
1285         g_return_if_fail (callback != NULL);
1286         priv = SOUP_SERVER_GET_PRIVATE (server);
1287
1288         /* "" was never documented as meaning the same this as "/",
1289          * but it effectively was. We have to special case it now or
1290          * otherwise it would match "*" too.
1291          */
1292         if (path && (!*path || !strcmp (path, "/")))
1293                 path = NULL;
1294
1295         hand = g_slice_new0 (SoupServerHandler);
1296         hand->path       = g_strdup (path);
1297         hand->callback   = callback;
1298         hand->destroy    = destroy;
1299         hand->user_data  = user_data;
1300
1301         soup_server_remove_handler (server, path);
1302         if (path)
1303                 soup_path_map_add (priv->handlers, path, hand);
1304         else
1305                 priv->default_handler = hand;
1306 }
1307
1308 static void
1309 unregister_handler (SoupServerHandler *handler)
1310 {
1311         if (handler->destroy)
1312                 handler->destroy (handler->user_data);
1313 }
1314
1315 /**
1316  * soup_server_remove_handler:
1317  * @server: a #SoupServer
1318  * @path: the toplevel path for the handler
1319  *
1320  * Removes the handler registered at @path.
1321  **/
1322 void
1323 soup_server_remove_handler (SoupServer *server, const char *path)
1324 {
1325         SoupServerPrivate *priv;
1326         SoupServerHandler *hand;
1327
1328         g_return_if_fail (SOUP_IS_SERVER (server));
1329         priv = SOUP_SERVER_GET_PRIVATE (server);
1330
1331         if (!path || !*path || !strcmp (path, "/")) {
1332                 if (priv->default_handler) {
1333                         unregister_handler (priv->default_handler);
1334                         free_handler (priv->default_handler);
1335                         priv->default_handler = NULL;
1336                 }
1337                 return;
1338         }
1339
1340         hand = soup_path_map_lookup (priv->handlers, path);
1341         if (hand && !strcmp (path, hand->path)) {
1342                 unregister_handler (hand);
1343                 soup_path_map_remove (priv->handlers, path);
1344         }
1345 }
1346
1347 /**
1348  * soup_server_add_auth_domain:
1349  * @server: a #SoupServer
1350  * @auth_domain: a #SoupAuthDomain
1351  *
1352  * Adds an authentication domain to @server. Each auth domain will
1353  * have the chance to require authentication for each request that
1354  * comes in; normally auth domains will require authentication for
1355  * requests on certain paths that they have been set up to watch, or
1356  * that meet other criteria set by the caller. If an auth domain
1357  * determines that a request requires authentication (and the request
1358  * doesn't contain authentication), @server will automatically reject
1359  * the request with an appropriate status (401 Unauthorized or 407
1360  * Proxy Authentication Required). If the request used the
1361  * "100-continue" Expectation, @server will reject it before the
1362  * request body is sent.
1363  **/
1364 void
1365 soup_server_add_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1366 {
1367         SoupServerPrivate *priv;
1368
1369         g_return_if_fail (SOUP_IS_SERVER (server));
1370         priv = SOUP_SERVER_GET_PRIVATE (server);
1371
1372         priv->auth_domains = g_slist_append (priv->auth_domains, auth_domain);
1373         g_object_ref (auth_domain);
1374 }
1375
1376 /**
1377  * soup_server_remove_auth_domain:
1378  * @server: a #SoupServer
1379  * @auth_domain: a #SoupAuthDomain
1380  *
1381  * Removes @auth_domain from @server.
1382  **/
1383 void
1384 soup_server_remove_auth_domain (SoupServer *server, SoupAuthDomain *auth_domain)
1385 {
1386         SoupServerPrivate *priv;
1387
1388         g_return_if_fail (SOUP_IS_SERVER (server));
1389         priv = SOUP_SERVER_GET_PRIVATE (server);
1390
1391         priv->auth_domains = g_slist_remove (priv->auth_domains, auth_domain);
1392         g_object_unref (auth_domain);
1393 }
1394
1395 /**
1396  * soup_server_pause_message:
1397  * @server: a #SoupServer
1398  * @msg: a #SoupMessage associated with @server.
1399  *
1400  * Pauses I/O on @msg. This can be used when you need to return from
1401  * the server handler without having the full response ready yet. Use
1402  * soup_server_unpause_message() to resume I/O.
1403  **/
1404 void
1405 soup_server_pause_message (SoupServer *server,
1406                            SoupMessage *msg)
1407 {
1408         g_return_if_fail (SOUP_IS_SERVER (server));
1409         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1410
1411         soup_message_io_pause (msg);
1412 }
1413
1414 /**
1415  * soup_server_unpause_message:
1416  * @server: a #SoupServer
1417  * @msg: a #SoupMessage associated with @server.
1418  *
1419  * Resumes I/O on @msg. Use this to resume after calling
1420  * soup_server_pause_message(), or after adding a new chunk to a
1421  * chunked response.
1422  *
1423  * I/O won't actually resume until you return to the main loop.
1424  **/
1425 void
1426 soup_server_unpause_message (SoupServer *server,
1427                              SoupMessage *msg)
1428 {
1429         g_return_if_fail (SOUP_IS_SERVER (server));
1430         g_return_if_fail (SOUP_IS_MESSAGE (msg));
1431
1432         soup_message_io_unpause (msg);
1433 }
1434