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