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