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