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