belatedly pull up changes from gnome-2-10 branch
[platform/upstream/libsoup.git] / libsoup / soup-socket.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-socket.c: Socket networking code.
4  *
5  * Copyright (C) 2000-2003, Ximian, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <string.h>
16 #include <unistd.h>
17
18 #include "soup-address.h"
19 #include "soup-socket.h"
20 #include "soup-marshal.h"
21 #include "soup-misc.h"
22 #include "soup-ssl.h"
23
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #include <netinet/tcp.h>
28
29 #define PARENT_TYPE G_TYPE_OBJECT
30 static GObjectClass *parent_class;
31
32 enum {
33         CONNECT_RESULT,
34         READABLE,
35         WRITABLE,
36         DISCONNECTED,
37         NEW_CONNECTION,
38         LAST_SIGNAL
39 };
40
41 static guint signals[LAST_SIGNAL] = { 0 };
42
43 enum {
44         PROP_0,
45
46         PROP_NON_BLOCKING,
47         PROP_NODELAY,
48         PROP_REUSEADDR,
49         PROP_IS_SERVER,
50         PROP_SSL_CREDENTIALS,
51
52         LAST_PROP
53 };
54
55 struct SoupSocketPrivate {
56         int sockfd;
57         SoupAddress *local_addr, *remote_addr;
58         GIOChannel *iochannel;
59
60         guint non_blocking:1;
61         guint nodelay:1;
62         guint reuseaddr:1;
63         guint is_server:1;
64         gpointer ssl_creds;
65
66         guint           watch;
67         guint           read_tag, write_tag, error_tag;
68         GByteArray     *read_buf;
69
70         GMutex *iolock, *addrlock;
71 };
72
73 #ifdef HAVE_IPV6
74 #define soup_sockaddr_max sockaddr_in6
75 #else
76 #define soup_sockaddr_max sockaddr_in
77 #endif
78
79 static void set_property (GObject *object, guint prop_id,
80                           const GValue *value, GParamSpec *pspec);
81 static void get_property (GObject *object, guint prop_id,
82                           GValue *value, GParamSpec *pspec);
83
84 static void
85 init (GObject *object)
86 {
87         SoupSocket *sock = SOUP_SOCKET (object);
88
89         sock->priv = g_new0 (SoupSocketPrivate, 1);
90         sock->priv->sockfd = -1;
91         sock->priv->non_blocking = sock->priv->nodelay = TRUE;
92         sock->priv->reuseaddr = TRUE;
93         sock->priv->addrlock = g_mutex_new ();
94         sock->priv->iolock = g_mutex_new ();
95 }
96
97 static void
98 disconnect_internal (SoupSocket *sock)
99 {
100         g_io_channel_unref (sock->priv->iochannel);
101         sock->priv->iochannel = NULL;
102         sock->priv->sockfd = -1;
103
104         if (sock->priv->read_tag) {
105                 g_source_remove (sock->priv->read_tag);
106                 sock->priv->read_tag = 0;
107         }
108         if (sock->priv->write_tag) {
109                 g_source_remove (sock->priv->write_tag);
110                 sock->priv->write_tag = 0;
111         }
112         if (sock->priv->error_tag) {
113                 g_source_remove (sock->priv->error_tag);
114                 sock->priv->error_tag = 0;
115         }
116 }
117
118 static void
119 finalize (GObject *object)
120 {
121         SoupSocket *sock = SOUP_SOCKET (object);
122
123         if (sock->priv->iochannel)
124                 disconnect_internal (sock);
125
126         if (sock->priv->local_addr)
127                 g_object_unref (sock->priv->local_addr);
128         if (sock->priv->remote_addr)
129                 g_object_unref (sock->priv->remote_addr);
130
131         if (sock->priv->watch)
132                 g_source_remove (sock->priv->watch);
133
134         g_mutex_free (sock->priv->addrlock);
135         g_mutex_free (sock->priv->iolock);
136
137         g_free (sock->priv);
138
139         G_OBJECT_CLASS (parent_class)->finalize (object);
140 }
141
142 static void
143 class_init (GObjectClass *object_class)
144 {
145         parent_class = g_type_class_ref (PARENT_TYPE);
146
147         /* virtual method override */
148         object_class->finalize = finalize;
149         object_class->set_property = set_property;
150         object_class->get_property = get_property;
151
152         /* signals */
153         signals[CONNECT_RESULT] =
154                 g_signal_new ("connect_result",
155                               G_OBJECT_CLASS_TYPE (object_class),
156                               G_SIGNAL_RUN_FIRST,
157                               G_STRUCT_OFFSET (SoupSocketClass, connect_result),
158                               NULL, NULL,
159                               soup_marshal_NONE__INT,
160                               G_TYPE_NONE, 1,
161                               G_TYPE_INT);
162         signals[READABLE] =
163                 g_signal_new ("readable",
164                               G_OBJECT_CLASS_TYPE (object_class),
165                               G_SIGNAL_RUN_LAST,
166                               G_STRUCT_OFFSET (SoupSocketClass, readable),
167                               NULL, NULL,
168                               soup_marshal_NONE__NONE,
169                               G_TYPE_NONE, 0);
170         signals[WRITABLE] =
171                 g_signal_new ("writable",
172                               G_OBJECT_CLASS_TYPE (object_class),
173                               G_SIGNAL_RUN_LAST,
174                               G_STRUCT_OFFSET (SoupSocketClass, writable),
175                               NULL, NULL,
176                               soup_marshal_NONE__NONE,
177                               G_TYPE_NONE, 0);
178         signals[DISCONNECTED] =
179                 g_signal_new ("disconnected",
180                               G_OBJECT_CLASS_TYPE (object_class),
181                               G_SIGNAL_RUN_LAST,
182                               G_STRUCT_OFFSET (SoupSocketClass, disconnected),
183                               NULL, NULL,
184                               soup_marshal_NONE__NONE,
185                               G_TYPE_NONE, 0);
186         signals[NEW_CONNECTION] =
187                 g_signal_new ("new_connection",
188                               G_OBJECT_CLASS_TYPE (object_class),
189                               G_SIGNAL_RUN_FIRST,
190                               G_STRUCT_OFFSET (SoupSocketClass, new_connection),
191                               NULL, NULL,
192                               soup_marshal_NONE__OBJECT,
193                               G_TYPE_NONE, 1,
194                               SOUP_TYPE_SOCKET);
195
196         /* properties */
197         g_object_class_install_property (
198                 object_class, PROP_NON_BLOCKING,
199                 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
200                                       "Non-blocking",
201                                       "Whether or not the socket uses non-blocking I/O",
202                                       TRUE,
203                                       G_PARAM_READWRITE));
204         g_object_class_install_property (
205                 object_class, PROP_NODELAY,
206                 g_param_spec_boolean (SOUP_SOCKET_FLAG_NODELAY,
207                                       "NODELAY",
208                                       "Whether or not the socket uses TCP NODELAY",
209                                       TRUE,
210                                       G_PARAM_READWRITE));
211         g_object_class_install_property (
212                 object_class, PROP_REUSEADDR,
213                 g_param_spec_boolean (SOUP_SOCKET_FLAG_REUSEADDR,
214                                       "REUSEADDR",
215                                       "Whether or not the socket uses the TCP REUSEADDR flag",
216                                       TRUE,
217                                       G_PARAM_READWRITE));
218         g_object_class_install_property (
219                 object_class, PROP_IS_SERVER,
220                 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
221                                       "Server",
222                                       "Whether or not the socket is a server socket",
223                                       FALSE,
224                                       G_PARAM_READABLE));
225         g_object_class_install_property (
226                 object_class, PROP_SSL_CREDENTIALS,
227                 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
228                                       "SSL credentials",
229                                       "SSL credential information, passed from the session to the SSL implementation",
230                                       G_PARAM_READWRITE));
231 }
232
233 SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
234
235
236 static void
237 update_fdflags (SoupSocket *sock)
238 {
239         int flags, opt;
240
241         if (sock->priv->sockfd == -1)
242                 return;
243
244         flags = fcntl (sock->priv->sockfd, F_GETFL, 0);
245         if (flags != -1) {
246                 if (sock->priv->non_blocking)
247                         flags |= O_NONBLOCK;
248                 else
249                         flags &= ~O_NONBLOCK;
250                 fcntl (sock->priv->sockfd, F_SETFL, flags);
251         }
252
253         opt = (sock->priv->nodelay != 0);
254         setsockopt (sock->priv->sockfd, IPPROTO_TCP,
255                     TCP_NODELAY, &opt, sizeof (opt));
256
257         opt = (sock->priv->reuseaddr != 0);
258         setsockopt (sock->priv->sockfd, SOL_SOCKET,
259                     SO_REUSEADDR, &opt, sizeof (opt));
260 }
261
262 static void
263 set_property (GObject *object, guint prop_id,
264               const GValue *value, GParamSpec *pspec)
265 {
266         SoupSocket *sock = SOUP_SOCKET (object);
267
268         switch (prop_id) {
269         case PROP_NON_BLOCKING:
270                 sock->priv->non_blocking = g_value_get_boolean (value);
271                 update_fdflags (sock);
272                 break;
273         case PROP_NODELAY:
274                 sock->priv->nodelay = g_value_get_boolean (value);
275                 update_fdflags (sock);
276                 break;
277         case PROP_REUSEADDR:
278                 sock->priv->reuseaddr = g_value_get_boolean (value);
279                 update_fdflags (sock);
280                 break;
281         case PROP_SSL_CREDENTIALS:
282                 sock->priv->ssl_creds = g_value_get_pointer (value);
283                 break;
284         default:
285                 break;
286         }
287 }
288
289 static void
290 get_property (GObject *object, guint prop_id,
291               GValue *value, GParamSpec *pspec)
292 {
293         SoupSocket *sock = SOUP_SOCKET (object);
294
295         switch (prop_id) {
296         case PROP_NON_BLOCKING:
297                 g_value_set_boolean (value, sock->priv->non_blocking);
298                 break;
299         case PROP_NODELAY:
300                 g_value_set_boolean (value, sock->priv->nodelay);
301                 break;
302         case PROP_REUSEADDR:
303                 g_value_set_boolean (value, sock->priv->reuseaddr);
304                 break;
305         case PROP_IS_SERVER:
306                 g_value_set_boolean (value, sock->priv->is_server);
307                 break;
308         case PROP_SSL_CREDENTIALS:
309                 g_value_set_pointer (value, sock->priv->ssl_creds);
310                 break;
311         default:
312                 break;
313         }
314 }
315
316
317 /**
318  * soup_socket_new:
319  * @optname1: name of first property to set (or %NULL)
320  * @...: value of @optname1, followed by additional property/value pairs
321  *
322  * Creates a new (disconnected) socket
323  *
324  * Return value: the new socket
325  **/
326 SoupSocket *
327 soup_socket_new (const char *optname1, ...)
328 {
329         SoupSocket *sock;
330         va_list ap;
331
332         va_start (ap, optname1);
333         sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
334                                                   optname1, ap);
335         va_end (ap);
336
337         return sock;
338 }
339
340 static GIOChannel *
341 get_iochannel (SoupSocket *sock)
342 {
343         g_mutex_lock (sock->priv->iolock);
344         if (!sock->priv->iochannel) {
345                 sock->priv->iochannel =
346                         g_io_channel_unix_new (sock->priv->sockfd);
347                 g_io_channel_set_close_on_unref (sock->priv->iochannel, TRUE);
348                 g_io_channel_set_encoding (sock->priv->iochannel, NULL, NULL);
349                 g_io_channel_set_buffered (sock->priv->iochannel, FALSE);
350         }
351         g_mutex_unlock (sock->priv->iolock);
352         return sock->priv->iochannel;
353 }
354
355 static gboolean
356 idle_connect_result (gpointer user_data)
357 {
358         SoupSocket *sock = user_data;
359
360         sock->priv->watch = 0;
361
362         g_signal_emit (sock, signals[CONNECT_RESULT], 0,
363                        sock->priv->sockfd != -1 ? SOUP_STATUS_OK : SOUP_STATUS_CANT_CONNECT);
364         return FALSE;
365 }
366
367 static gboolean
368 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
369 {
370         SoupSocket *sock = data;
371         int error = 0;
372         int len = sizeof (error);
373
374         /* Remove the watch now in case we don't return immediately */
375         g_source_remove (sock->priv->watch);
376         sock->priv->watch = 0;
377
378         if (condition & ~(G_IO_IN | G_IO_OUT))
379                 goto cant_connect;
380
381         if (getsockopt (sock->priv->sockfd, SOL_SOCKET, SO_ERROR,
382                         &error, &len) != 0)
383                 goto cant_connect;
384         if (error)
385                 goto cant_connect;
386
387         return idle_connect_result (sock);
388
389  cant_connect:
390         g_signal_emit (sock, signals[CONNECT_RESULT], 0, SOUP_STATUS_CANT_CONNECT);
391         return FALSE;
392 }
393
394 static void
395 got_address (SoupAddress *addr, guint status, gpointer user_data)
396 {
397         SoupSocket *sock = user_data;
398
399         if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
400                 g_signal_emit (sock, signals[CONNECT_RESULT], 0, status);
401                 g_object_unref (sock);
402                 return;
403         }
404
405         soup_socket_connect (sock, sock->priv->remote_addr);
406         /* soup_socket_connect re-reffed addr */
407         g_object_unref (addr);
408
409         g_object_unref (sock);
410 }
411
412 /**
413  * soup_socket_connect:
414  * @sock: a client #SoupSocket (which must not already be connected)
415  * @remote_addr: address to connect to
416  *
417  * If %SOUP_SOCKET_FLAG_NONBLOCKING has been set on the socket, this
418  * begins asynchronously connecting to the given address. The socket
419  * will emit %connect_result when it succeeds or fails (but not before
420  * returning from this function).
421  *
422  * If %SOUP_SOCKET_FLAG_NONBLOCKING has not been set, this will
423  * attempt to synchronously connect.
424  *
425  * Return value: %SOUP_STATUS_CONTINUE if connecting asynchronously,
426  * otherwise a success or failure code.
427  **/
428 guint
429 soup_socket_connect (SoupSocket *sock, SoupAddress *remote_addr)
430 {
431         struct sockaddr *sa;
432         int len, status;
433
434         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
435         g_return_val_if_fail (!sock->priv->is_server, SOUP_STATUS_MALFORMED);
436         g_return_val_if_fail (sock->priv->sockfd == -1, SOUP_STATUS_MALFORMED);
437         g_return_val_if_fail (SOUP_IS_ADDRESS (remote_addr), SOUP_STATUS_MALFORMED);
438
439         sock->priv->remote_addr = g_object_ref (remote_addr);
440         if (!sock->priv->non_blocking) {
441                 status = soup_address_resolve_sync (remote_addr);
442                 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
443                         return status;
444         }
445
446         sa = soup_address_get_sockaddr (sock->priv->remote_addr, &len);
447         if (!sa) {
448                 if (!sock->priv->non_blocking)
449                         return SOUP_STATUS_CANT_RESOLVE;
450
451                 g_object_ref (sock);
452                 soup_address_resolve_async (remote_addr, got_address, sock);
453                 return SOUP_STATUS_CONTINUE;
454         }
455
456         sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
457         if (sock->priv->sockfd == -1) {
458                 goto done;
459         }
460         update_fdflags (sock);
461
462         status = connect (sock->priv->sockfd, sa, len);
463
464         if (status == -1) {
465                 if (errno == EINPROGRESS) {
466                         /* Wait for connect to succeed or fail */
467                         sock->priv->watch =
468                                 g_io_add_watch (get_iochannel (sock),
469                                                 G_IO_IN | G_IO_OUT |
470                                                 G_IO_PRI | G_IO_ERR |
471                                                 G_IO_HUP | G_IO_NVAL,
472                                                 connect_watch, sock);
473                         return SOUP_STATUS_CONTINUE;
474                 } else {
475                         close (sock->priv->sockfd);
476                         sock->priv->sockfd = -1;
477                 }
478         }
479
480  done:
481         if (sock->priv->non_blocking) {
482                 sock->priv->watch = g_idle_add (idle_connect_result, sock);
483                 return SOUP_STATUS_CONTINUE;
484         } else if (sock->priv->sockfd == -1)
485                 return SOUP_STATUS_CANT_CONNECT;
486         else {
487                 get_iochannel (sock);
488                 return SOUP_STATUS_OK;
489         }
490 }
491
492 static gboolean
493 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
494 {
495         SoupSocket *sock = data, *new;
496         struct soup_sockaddr_max sa;
497         int sa_len, sockfd;
498
499         if (condition & (G_IO_HUP | G_IO_ERR)) {
500                 g_source_remove (sock->priv->watch);
501                 sock->priv->watch = 0;
502                 return FALSE;
503         }
504
505         sa_len = sizeof (sa);
506         sockfd = accept (sock->priv->sockfd, (struct sockaddr *)&sa, &sa_len);
507         if (sockfd == -1)
508                 return TRUE;
509
510         new = g_object_new (SOUP_TYPE_SOCKET, NULL);
511         new->priv->sockfd = sockfd;
512         new->priv->non_blocking = sock->priv->non_blocking;
513         new->priv->nodelay = sock->priv->nodelay;
514         new->priv->is_server = TRUE;
515         new->priv->ssl_creds = sock->priv->ssl_creds;
516         update_fdflags (new);
517
518         new->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
519
520         if (new->priv->ssl_creds) {
521                 if (!soup_socket_start_ssl (new)) {
522                         g_object_unref (new);
523                         return TRUE;
524                 }
525         } else
526                 get_iochannel (new);
527
528         g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
529         g_object_unref (new);
530
531         return TRUE;
532 }
533
534 /**
535  * soup_socket_listen:
536  * @sock: a server #SoupSocket (which must not already be connected or
537  * listening)
538  * @local_addr: Local address to bind to.
539  *
540  * Makes @sock start listening on the given interface and port. When
541  * connections come in, @sock will emit %new_connection.
542  *
543  * Return value: whether or not @sock is now listening.
544  **/
545 gboolean
546 soup_socket_listen (SoupSocket *sock, SoupAddress *local_addr)
547 {
548         struct sockaddr *sa;
549         int sa_len;
550
551         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
552         g_return_val_if_fail (sock->priv->is_server, FALSE);
553         g_return_val_if_fail (sock->priv->sockfd == -1, FALSE);
554         g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), FALSE);
555
556         /* @local_addr may have its port set to 0. So we intentionally
557          * don't store it in sock->priv->local_addr, so that if the
558          * caller calls soup_socket_get_local_address() later, we'll
559          * have to make a new addr by calling getsockname(), which
560          * will have the right port number.
561          */
562         sa = soup_address_get_sockaddr (local_addr, &sa_len);
563         g_return_val_if_fail (sa != NULL, FALSE);
564
565         sock->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
566         if (sock->priv->sockfd < 0)
567                 goto cant_listen;
568         update_fdflags (sock);
569
570         /* Bind */
571         if (bind (sock->priv->sockfd, sa, sa_len) != 0)
572                 goto cant_listen;
573
574         /* Listen */
575         if (listen (sock->priv->sockfd, 10) != 0)
576                 goto cant_listen;
577
578         sock->priv->watch = g_io_add_watch (get_iochannel (sock),
579                                             G_IO_IN | G_IO_ERR | G_IO_HUP,
580                                             listen_watch, sock);
581         return TRUE;
582
583  cant_listen:
584         if (sock->priv->sockfd != -1) {
585                 close (sock->priv->sockfd);
586                 sock->priv->sockfd = -1;
587         }
588
589         return FALSE;
590 }
591
592 /**
593  * soup_socket_start_ssl:
594  * @sock: the socket
595  *
596  * Starts using SSL on @socket.
597  *
598  * Return value: success or failure
599  **/
600 gboolean
601 soup_socket_start_ssl (SoupSocket *sock)
602 {
603         return soup_socket_start_proxy_ssl (sock, soup_address_get_name (sock->priv->remote_addr));
604 }
605         
606 /**
607  * soup_socket_start_proxy_ssl:
608  * @sock: the socket
609  * @ssl_host: hostname of the SSL server
610  *
611  * Starts using SSL on @socket, expecting to find a host named
612  * @ssl_host.
613  *
614  * Return value: success or failure
615  **/
616 gboolean
617 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host)
618 {
619         GIOChannel *ssl_chan;
620
621         get_iochannel (sock);
622         ssl_chan = soup_ssl_wrap_iochannel (
623                 sock->priv->iochannel, sock->priv->is_server ?
624                 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
625                 ssl_host, sock->priv->ssl_creds);
626
627         if (!ssl_chan)
628                 return FALSE;
629
630         sock->priv->iochannel = ssl_chan;
631         return TRUE;
632 }
633         
634
635 /**
636  * soup_socket_client_new_async:
637  * @hostname: remote machine to connect to
638  * @port: remote port to connect to
639  * @ssl_creds: SSL credentials structure, or %NULL if not SSL
640  * @callback: callback to call when the socket is connected
641  * @user_data: data for @callback
642  *
643  * Creates a connection to @hostname and @port. @callback will be
644  * called when the connection completes (or fails).
645  *
646  * Return value: the new socket (not yet ready for use).
647  **/
648 SoupSocket *
649 soup_socket_client_new_async (const char *hostname, guint port,
650                               gpointer ssl_creds,
651                               SoupSocketCallback callback, gpointer user_data)
652 {
653         SoupSocket *sock;
654
655         g_return_val_if_fail (hostname != NULL, NULL);
656
657         sock = g_object_new (SOUP_TYPE_SOCKET,
658                              SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
659                              NULL);
660         soup_socket_connect (sock, soup_address_new (hostname, port));
661
662         if (callback) {
663                 soup_signal_connect_once (sock, "connect_result",
664                                           G_CALLBACK (callback), user_data);
665         }
666         return sock;
667 }
668
669 /**
670  * soup_socket_client_new_sync:
671  * @hostname: remote machine to connect to
672  * @port: remote port to connect to
673  * @ssl_creds: SSL credentials structure, or %NULL if not SSL
674  * @status_ret: pointer to return the soup status in
675  *
676  * Creates a connection to @hostname and @port. If @status_ret is not
677  * %NULL, it will contain a status code on return.
678  *
679  * Return value: the new socket, or %NULL if it could not connect.
680  **/
681 SoupSocket *
682 soup_socket_client_new_sync (const char *hostname, guint port,
683                              gpointer ssl_creds, guint *status_ret)
684 {
685         SoupSocket *sock;
686         guint status;
687
688         g_return_val_if_fail (hostname != NULL, NULL);
689
690         sock = g_object_new (SOUP_TYPE_SOCKET,
691                              SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
692                              NULL);
693         sock->priv->non_blocking = FALSE;
694         status = soup_socket_connect (sock, soup_address_new (hostname, port));
695
696         if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
697                 g_object_unref (sock);
698                 sock = NULL;
699         }
700
701         if (status_ret)
702                 *status_ret = status;
703         return sock;
704 }
705
706 /**
707  * soup_socket_server_new:
708  * @local_addr: Local address to bind to. (Use soup_address_any_new() to
709  * accept connections on any local address)
710  * @ssl_creds: SSL credentials, or %NULL if this is not an SSL server
711  * @callback: Callback to call when a client connects
712  * @user_data: data to pass to @callback.
713  *
714  * Create and open a new #SoupSocket listening on the specified
715  * address. @callback will be called each time a client connects,
716  * with a new #SoupSocket.
717  *
718  * Returns: a new #SoupSocket, or NULL if there was a failure.
719  **/
720 SoupSocket *
721 soup_socket_server_new (SoupAddress *local_addr, gpointer ssl_creds,
722                         SoupSocketListenerCallback callback,
723                         gpointer user_data)
724 {
725         SoupSocket *sock;
726
727         g_return_val_if_fail (SOUP_IS_ADDRESS (local_addr), NULL);
728
729         sock = g_object_new (SOUP_TYPE_SOCKET,
730                              SOUP_SOCKET_SSL_CREDENTIALS, ssl_creds,
731                              NULL);
732         sock->priv->is_server = TRUE;
733         if (!soup_socket_listen (sock, local_addr)) {
734                 g_object_unref (sock);
735                 return NULL;
736         }
737
738         if (callback) {
739                 g_signal_connect (sock, "new_connection",
740                                   G_CALLBACK (callback), user_data);
741         }
742
743         return sock;
744 }
745
746
747 /**
748  * soup_socket_disconnect:
749  * @sock: a #SoupSocket
750  *
751  * Disconnects @sock. Any further read or write attempts on it will
752  * fail.
753  **/
754 void
755 soup_socket_disconnect (SoupSocket *sock)
756 {
757         gboolean already_disconnected = FALSE;
758
759         g_return_if_fail (SOUP_IS_SOCKET (sock));
760
761         if (g_mutex_trylock (sock->priv->iolock)) {
762                 if (sock->priv->iochannel)
763                         disconnect_internal (sock);
764                 else
765                         already_disconnected = TRUE;
766                 g_mutex_unlock (sock->priv->iolock);
767         } else {
768                 int sockfd;
769
770                 /* Another thread is currently doing IO, so
771                  * we can't close the iochannel. So just kick
772                  * the file descriptor out from under it.
773                  */
774
775                 sockfd = sock->priv->sockfd;
776                 sock->priv->sockfd = -1;
777                 if (sockfd == -1)
778                         already_disconnected = TRUE;
779                 else {
780                         g_io_channel_set_close_on_unref (sock->priv->iochannel,
781                                                          FALSE);
782                         close (sockfd);
783                 }
784         }
785
786         if (already_disconnected)
787                 return;
788
789         /* Give all readers a chance to notice the connection close */
790         g_signal_emit (sock, signals[READABLE], 0);
791
792         /* FIXME: can't disconnect until all data is read */
793
794         /* Then let everyone know we're disconnected */
795         g_signal_emit (sock, signals[DISCONNECTED], 0);
796 }
797
798 /**
799  * soup_socket_is_connected:
800  * @sock: a #SoupSocket
801  *
802  * Tests if @sock is connected to another host
803  *
804  * Return value: %TRUE or %FALSE.
805  **/
806 gboolean
807 soup_socket_is_connected (SoupSocket *sock)
808 {
809         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
810
811         return sock->priv->iochannel != NULL;
812 }
813
814 /**
815  * soup_socket_get_local_address:
816  * @sock: a #SoupSocket
817  *
818  * Returns the #SoupAddress corresponding to the local end of @sock.
819  *
820  * Return value: the #SoupAddress
821  **/
822 SoupAddress *
823 soup_socket_get_local_address (SoupSocket *sock)
824 {
825         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
826
827         g_mutex_lock (sock->priv->addrlock);
828         if (!sock->priv->local_addr) {
829                 struct soup_sockaddr_max bound_sa;
830                 int sa_len;
831
832                 sa_len = sizeof (bound_sa);
833                 getsockname (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
834                 sock->priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
835         }
836         g_mutex_unlock (sock->priv->addrlock);
837
838         return sock->priv->local_addr;
839 }
840
841 /**
842  * soup_socket_get_remote_address:
843  * @sock: a #SoupSocket
844  *
845  * Returns the #SoupAddress corresponding to the remote end of @sock.
846  *
847  * Return value: the #SoupAddress
848  **/
849 SoupAddress *
850 soup_socket_get_remote_address (SoupSocket *sock)
851 {
852         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
853
854         g_mutex_lock (sock->priv->addrlock);
855         if (!sock->priv->remote_addr) {
856                 struct soup_sockaddr_max bound_sa;
857                 int sa_len;
858
859                 sa_len = sizeof (bound_sa);
860                 getpeername (sock->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len);
861                 sock->priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
862         }
863         g_mutex_unlock (sock->priv->addrlock);
864
865         return sock->priv->remote_addr;
866 }
867
868
869
870
871 static gboolean
872 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
873 {
874         SoupSocket *sock = user_data;
875
876         sock->priv->read_tag = 0;
877         g_signal_emit (sock, signals[READABLE], 0);
878
879         return FALSE;
880 }
881
882 static SoupSocketIOStatus
883 read_from_network (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
884 {
885         GIOStatus status;
886         GIOCondition cond = G_IO_IN;
887         GError *err = NULL;
888
889         if (!sock->priv->iochannel) 
890                 return SOUP_SOCKET_EOF;
891
892         status = g_io_channel_read_chars (sock->priv->iochannel,
893                                           buffer, len, nread, &err);
894         if (err) {
895                 if (err->domain == SOUP_SSL_ERROR &&
896                     err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
897                         cond = G_IO_OUT;
898                 g_object_set_data_full (G_OBJECT (sock),
899                                         "SoupSocket-last_error",
900                                         err, (GDestroyNotify)g_error_free);
901         } else {
902                 g_object_set_data (G_OBJECT (sock),
903                                    "SoupSocket-last_error",
904                                    NULL);
905         }
906
907         switch (status) {
908         case G_IO_STATUS_NORMAL:
909         case G_IO_STATUS_AGAIN:
910                 if (*nread > 0)
911                         return SOUP_SOCKET_OK;
912
913                 if (!sock->priv->read_tag) {
914                         sock->priv->read_tag =
915                                 g_io_add_watch (sock->priv->iochannel, cond,
916                                                 socket_read_watch, sock);
917                 }
918                 return SOUP_SOCKET_WOULD_BLOCK;
919
920         case G_IO_STATUS_EOF:
921                 return SOUP_SOCKET_EOF;
922
923         default:
924                 return SOUP_SOCKET_ERROR;
925         }
926 }
927
928 static SoupSocketIOStatus
929 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
930 {
931         GByteArray *read_buf = sock->priv->read_buf;
932
933         *nread = MIN (read_buf->len, len);
934         memcpy (buffer, read_buf->data, *nread);
935
936         if (*nread == read_buf->len) {
937                 g_byte_array_free (read_buf, TRUE);
938                 sock->priv->read_buf = NULL;
939         } else {
940                 memmove (read_buf->data, read_buf->data + *nread, 
941                          read_buf->len - *nread);
942                 g_byte_array_set_size (read_buf, read_buf->len - *nread);
943         }
944
945         return SOUP_SOCKET_OK;
946 }
947
948 /**
949  * soup_socket_read:
950  * @sock: the socket
951  * @buffer: buffer to read into
952  * @len: size of @buffer in bytes
953  * @nread: on return, the number of bytes read into @buffer
954  *
955  * Attempts to read up to @len bytes from @sock into @buffer. If some
956  * data is successfully read, soup_socket_read() will return
957  * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
958  * actually read.
959  *
960  * If @sock is non-blocking, and no data is available, the return
961  * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
962  * can connect to the %readable signal to know when there is more data
963  * to read. (NB: You MUST read all available data off the socket
964  * first. The %readable signal will only be emitted after
965  * soup_socket_read() has returned %SOUP_SOCKET_WOULD_BLOCK.)
966  *
967  * Return value: a #SoupSocketIOStatus, as described above (or
968  * %SOUP_SOCKET_EOF if the socket is no longer connected, or
969  * %SOUP_SOCKET_ERROR on any other error).
970  **/
971 SoupSocketIOStatus
972 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
973 {
974         SoupSocketIOStatus status;
975
976         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
977
978         g_mutex_lock (sock->priv->iolock);
979         if (sock->priv->read_buf)
980                 status = read_from_buf (sock, buffer, len, nread);
981         else
982                 status = read_from_network (sock, buffer, len, nread);
983         g_mutex_unlock (sock->priv->iolock);
984
985         return status;
986 }
987
988 /**
989  * soup_socket_read_until:
990  * @sock: the socket
991  * @buffer: buffer to read into
992  * @len: size of @buffer in bytes
993  * @boundary: boundary to read until
994  * @boundary_len: length of @boundary in bytes
995  * @nread: on return, the number of bytes read into @buffer
996  * @got_boundary: on return, whether or not the data in @buffer
997  * ends with the boundary string
998  *
999  * Like soup_socket_read(), but reads no further than the first
1000  * occurrence of @boundary. (If the boundary is found, it will be
1001  * included in the returned data, and *@got_boundary will be set to
1002  * %TRUE.) Any data after the boundary will returned in future reads.
1003  *
1004  * Return value: as for soup_socket_read()
1005  **/
1006 SoupSocketIOStatus
1007 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1008                         gconstpointer boundary, gsize boundary_len,
1009                         gsize *nread, gboolean *got_boundary)
1010 {
1011         SoupSocketIOStatus status;
1012         GByteArray *read_buf;
1013         guint match_len, prev_len;
1014         guint8 *p, *end;
1015
1016         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1017         g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1018
1019         g_mutex_lock (sock->priv->iolock);
1020
1021         *got_boundary = FALSE;
1022
1023         if (!sock->priv->read_buf)
1024                 sock->priv->read_buf = g_byte_array_new ();
1025         read_buf = sock->priv->read_buf;
1026
1027         if (read_buf->len < boundary_len) {
1028                 prev_len = read_buf->len;
1029                 g_byte_array_set_size (read_buf, len);
1030                 status = read_from_network (sock,
1031                                             read_buf->data + prev_len,
1032                                             len - prev_len, nread);
1033                 read_buf->len = prev_len + *nread;
1034
1035                 if (status != SOUP_SOCKET_OK) {
1036                         g_mutex_unlock (sock->priv->iolock);
1037                         return status;
1038                 }
1039         }
1040
1041         /* Scan for the boundary */
1042         end = read_buf->data + read_buf->len;
1043         for (p = read_buf->data; p <= end - boundary_len; p++) {
1044                 if (!memcmp (p, boundary, boundary_len)) {
1045                         p += boundary_len;
1046                         *got_boundary = TRUE;
1047                         break;
1048                 }
1049         }
1050
1051         /* Return everything up to 'p' (which is either just after the
1052          * boundary, or @boundary_len - 1 bytes before the end of the
1053          * buffer).
1054          */
1055         match_len = p - read_buf->data;
1056         status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1057
1058         g_mutex_unlock (sock->priv->iolock);
1059         return status;
1060 }
1061
1062 static gboolean
1063 socket_write_watch (GIOChannel *chan, GIOCondition condition, gpointer user_data)
1064 {
1065         SoupSocket *sock = user_data;
1066
1067         sock->priv->write_tag = 0;
1068         g_signal_emit (sock, signals[WRITABLE], 0);
1069
1070         return FALSE;
1071 }
1072
1073 /**
1074  * soup_socket_write:
1075  * @sock: the socket
1076  * @buffer: data to write
1077  * @len: size of @buffer, in bytes
1078  * @nwrote: on return, number of bytes written
1079  *
1080  * Attempts to write @len bytes from @buffer to @sock. If some data is
1081  * successfully written, the resturn status will be
1082  * %SOUP_SOCKET_SUCCESS, and *@nwrote will contain the number of bytes
1083  * actually written.
1084  *
1085  * If @sock is non-blocking, and no data could be written right away,
1086  * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1087  * the caller can connect to the %writable signal to know when more
1088  * data can be written. (NB: %writable is only emitted after a
1089  * %SOUP_SOCKET_WOULD_BLOCK.)
1090  *
1091  * Return value: a #SoupSocketIOStatus, as described above (or
1092  * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR).
1093  **/
1094 SoupSocketIOStatus
1095 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1096                    gsize len, gsize *nwrote)
1097 {
1098         GIOStatus status;
1099         gpointer pipe_handler;
1100         GIOCondition cond = G_IO_OUT;
1101         GError *err = NULL;
1102
1103         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1104
1105         g_mutex_lock (sock->priv->iolock);
1106
1107         if (!sock->priv->iochannel) {
1108                 g_mutex_unlock (sock->priv->iolock);
1109                 return SOUP_SOCKET_EOF;
1110         }
1111         if (sock->priv->write_tag) {
1112                 g_mutex_unlock (sock->priv->iolock);
1113                 return SOUP_SOCKET_WOULD_BLOCK;
1114         }
1115
1116         pipe_handler = signal (SIGPIPE, SIG_IGN);
1117         status = g_io_channel_write_chars (sock->priv->iochannel,
1118                                            buffer, len, nwrote, &err);
1119         signal (SIGPIPE, pipe_handler);
1120         if (err) {
1121                 if (err->domain == SOUP_SSL_ERROR &&
1122                     err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1123                         cond = G_IO_IN;
1124                 g_object_set_data_full (G_OBJECT (sock),
1125                                         "SoupSocket-last_error",
1126                                         err, (GDestroyNotify)g_error_free);
1127         } else {
1128                 g_object_set_data (G_OBJECT (sock),
1129                                    "SoupSocket-last_error",
1130                                    NULL);
1131         }
1132
1133         if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1134                 g_mutex_unlock (sock->priv->iolock);
1135                 return SOUP_SOCKET_ERROR;
1136         }
1137
1138         if (*nwrote) {
1139                 g_mutex_unlock (sock->priv->iolock);
1140                 return SOUP_SOCKET_OK;
1141         }
1142
1143         sock->priv->write_tag =
1144                 g_io_add_watch (sock->priv->iochannel, cond, 
1145                                 socket_write_watch, sock);
1146         g_mutex_unlock (sock->priv->iolock);
1147         return SOUP_SOCKET_WOULD_BLOCK;
1148 }