Notice closed connections sooner
[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 <stdio.h>
13 #include <errno.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #include "soup-address.h"
20 #include "soup-socket.h"
21 #include "soup-marshal.h"
22 #include "soup-misc.h"
23 #include "soup-ssl.h"
24
25 #include <sys/time.h>
26 #include <sys/types.h>
27
28 /**
29  * SECTION:soup-socket
30  * @short_description: A network socket
31  *
32  * #SoupSocket is libsoup's TCP socket type. While it is primarily
33  * intended for internal use, #SoupSocket<!-- -->s are exposed in the
34  * API in various places, and some of their methods (eg,
35  * soup_socket_get_remote_address()) may be useful to applications.
36  **/
37
38 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
39
40 enum {
41         READABLE,
42         WRITABLE,
43         DISCONNECTED,
44         NEW_CONNECTION,
45         LAST_SIGNAL
46 };
47
48 static guint signals[LAST_SIGNAL] = { 0 };
49
50 enum {
51         PROP_0,
52
53         PROP_LOCAL_ADDRESS,
54         PROP_REMOTE_ADDRESS,
55         PROP_NON_BLOCKING,
56         PROP_IS_SERVER,
57         PROP_SSL_CREDENTIALS,
58         PROP_ASYNC_CONTEXT,
59         PROP_TIMEOUT,
60
61         LAST_PROP
62 };
63
64 typedef struct {
65         int sockfd;
66         SoupAddress *local_addr, *remote_addr;
67         GIOChannel *iochannel;
68
69         guint non_blocking:1;
70         guint is_server:1;
71         guint timed_out:1;
72         gpointer ssl_creds;
73
74         GMainContext   *async_context;
75         GSource        *watch_src;
76         GSource        *read_src, *write_src;
77         GSource        *read_timeout, *write_timeout;
78         GSource        *connect_timeout;
79         GByteArray     *read_buf;
80
81         GMutex *iolock, *addrlock;
82         guint timeout;
83 } SoupSocketPrivate;
84 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
85
86 #ifdef HAVE_IPV6
87 #define soup_sockaddr_max sockaddr_in6
88 #else
89 #define soup_sockaddr_max sockaddr_in
90 #endif
91
92 static void set_property (GObject *object, guint prop_id,
93                           const GValue *value, GParamSpec *pspec);
94 static void get_property (GObject *object, guint prop_id,
95                           GValue *value, GParamSpec *pspec);
96
97 #ifdef G_OS_WIN32
98 #define SOUP_IS_SOCKET_ERROR(status) ((status) == SOCKET_ERROR)
99 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) == INVALID_SOCKET)
100 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (WSAGetLastError () == WSAEWOULDBLOCK)
101 #define SHUT_RDWR SD_BOTH
102 #else
103 #define SOUP_IS_SOCKET_ERROR(status) ((status) == -1)
104 #define SOUP_IS_INVALID_SOCKET(socket) ((socket) < 0)
105 #define SOUP_IS_CONNECT_STATUS_INPROGRESS() (errno == EINPROGRESS)
106 #endif
107
108 static void
109 soup_socket_init (SoupSocket *sock)
110 {
111         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
112
113         priv->sockfd = -1;
114         priv->non_blocking = TRUE;
115         priv->addrlock = g_mutex_new ();
116         priv->iolock = g_mutex_new ();
117         priv->timeout = 0;
118 }
119
120 static void
121 disconnect_internal (SoupSocketPrivate *priv)
122 {
123         g_io_channel_unref (priv->iochannel);
124         priv->iochannel = NULL;
125         priv->sockfd = -1;
126
127         if (priv->read_src) {
128                 g_source_destroy (priv->read_src);
129                 priv->read_src = NULL;
130         }
131         if (priv->write_src) {
132                 g_source_destroy (priv->write_src);
133                 priv->write_src = NULL;
134         }
135         if (priv->read_timeout) {
136                 g_source_destroy (priv->read_timeout);
137                 priv->read_timeout = NULL;
138         }
139         if (priv->write_timeout) {
140                 g_source_destroy (priv->write_timeout);
141                 priv->write_timeout = NULL;
142         }
143 }
144
145 static void
146 finalize (GObject *object)
147 {
148         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
149
150         if (priv->iochannel)
151                 disconnect_internal (priv);
152
153         if (priv->local_addr)
154                 g_object_unref (priv->local_addr);
155         if (priv->remote_addr)
156                 g_object_unref (priv->remote_addr);
157
158         if (priv->watch_src)
159                 g_source_destroy (priv->watch_src);
160         if (priv->connect_timeout)
161                 g_source_destroy (priv->connect_timeout);
162         if (priv->async_context)
163                 g_main_context_unref (priv->async_context);
164
165         if (priv->read_buf)
166                 g_byte_array_free (priv->read_buf, TRUE);
167
168         g_mutex_free (priv->addrlock);
169         g_mutex_free (priv->iolock);
170
171         G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
172 }
173
174 static void
175 soup_socket_class_init (SoupSocketClass *socket_class)
176 {
177         GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
178
179 #ifdef SIGPIPE
180         signal (SIGPIPE, SIG_IGN);
181 #endif
182
183         g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
184
185         /* virtual method override */
186         object_class->finalize = finalize;
187         object_class->set_property = set_property;
188         object_class->get_property = get_property;
189
190         /* signals */
191
192         /**
193          * SoupSocket::readable:
194          * @sock: the socket
195          *
196          * Emitted when an async socket is readable. See
197          * soup_socket_read(), soup_socket_read_until() and
198          * #SoupSocket:non-blocking.
199          **/
200         signals[READABLE] =
201                 g_signal_new ("readable",
202                               G_OBJECT_CLASS_TYPE (object_class),
203                               G_SIGNAL_RUN_LAST,
204                               G_STRUCT_OFFSET (SoupSocketClass, readable),
205                               NULL, NULL,
206                               soup_marshal_NONE__NONE,
207                               G_TYPE_NONE, 0);
208
209         /**
210          * SoupSocket::writable:
211          * @sock: the socket
212          *
213          * Emitted when an async socket is writable. See
214          * soup_socket_write() and #SoupSocket:non-blocking.
215          **/
216         signals[WRITABLE] =
217                 g_signal_new ("writable",
218                               G_OBJECT_CLASS_TYPE (object_class),
219                               G_SIGNAL_RUN_LAST,
220                               G_STRUCT_OFFSET (SoupSocketClass, writable),
221                               NULL, NULL,
222                               soup_marshal_NONE__NONE,
223                               G_TYPE_NONE, 0);
224
225         /**
226          * SoupSocket::disconnected:
227          * @sock: the socket
228          *
229          * Emitted when the socket is disconnected, for whatever
230          * reason.
231          **/
232         signals[DISCONNECTED] =
233                 g_signal_new ("disconnected",
234                               G_OBJECT_CLASS_TYPE (object_class),
235                               G_SIGNAL_RUN_LAST,
236                               G_STRUCT_OFFSET (SoupSocketClass, disconnected),
237                               NULL, NULL,
238                               soup_marshal_NONE__NONE,
239                               G_TYPE_NONE, 0);
240
241         /**
242          * SoupSocket::new-connection:
243          * @sock: the socket
244          * @new: the new socket
245          *
246          * Emitted when a listening socket (set up with
247          * soup_socket_listen()) receives a new connection.
248          *
249          * You must ref the @new if you want to keep it; otherwise it
250          * will be destroyed after the signal is emitted.
251          **/
252         signals[NEW_CONNECTION] =
253                 g_signal_new ("new_connection",
254                               G_OBJECT_CLASS_TYPE (object_class),
255                               G_SIGNAL_RUN_FIRST,
256                               G_STRUCT_OFFSET (SoupSocketClass, new_connection),
257                               NULL, NULL,
258                               soup_marshal_NONE__OBJECT,
259                               G_TYPE_NONE, 1,
260                               SOUP_TYPE_SOCKET);
261
262         /* properties */
263         /**
264          * SOUP_SOCKET_LOCAL_ADDRESS:
265          *
266          * Alias for the #SoupSocket:local-address property. (Address
267          * of local end of socket.)
268          **/
269         g_object_class_install_property (
270                 object_class, PROP_LOCAL_ADDRESS,
271                 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
272                                      "Local address",
273                                      "Address of local end of socket",
274                                      SOUP_TYPE_ADDRESS,
275                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
276         /**
277          * SOUP_SOCKET_REMOTE_ADDRESS:
278          *
279          * Alias for the #SoupSocket:remote-address property. (Address
280          * of remote end of socket.)
281          **/
282         g_object_class_install_property (
283                 object_class, PROP_REMOTE_ADDRESS,
284                 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
285                                      "Remote address",
286                                      "Address of remote end of socket",
287                                      SOUP_TYPE_ADDRESS,
288                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
289         /**
290          * SoupSocket:non-blocking:
291          *
292          * Whether or not the socket uses non-blocking I/O.
293          *
294          * #SoupSocket's I/O methods are designed around the idea of
295          * using a single codepath for both synchronous and
296          * asynchronous I/O. If you want to read off a #SoupSocket,
297          * the "correct" way to do it is to call soup_socket_read() or
298          * soup_socket_read_until() repeatedly until you have read
299          * everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK
300          * at any point, stop reading and wait for it to emit the
301          * #SoupSocket::readable signal. Then go back to the
302          * reading-as-much-as-you-can loop. Likewise, for writing to a
303          * #SoupSocket, you should call soup_socket_write() either
304          * until you have written everything, or it returns
305          * %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for
306          * #SoupSocket::writable and then go back into the loop).
307          *
308          * Code written this way will work correctly with both
309          * blocking and non-blocking sockets; blocking sockets will
310          * simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the
311          * code that handles that case just won't get used for them.
312          **/
313         /**
314          * SOUP_SOCKET_FLAG_NONBLOCKING:
315          *
316          * Alias for the #SoupSocket:non-blocking property. (Whether
317          * or not the socket uses non-blocking I/O.)
318          **/
319         g_object_class_install_property (
320                 object_class, PROP_NON_BLOCKING,
321                 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
322                                       "Non-blocking",
323                                       "Whether or not the socket uses non-blocking I/O",
324                                       TRUE,
325                                       G_PARAM_READWRITE));
326         /**
327          * SOUP_SOCKET_IS_SERVER:
328          *
329          * Alias for the #SoupSocket:is-server property. (Whether or
330          * not the socket is a server socket.)
331          **/
332         g_object_class_install_property (
333                 object_class, PROP_IS_SERVER,
334                 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
335                                       "Server",
336                                       "Whether or not the socket is a server socket",
337                                       FALSE,
338                                       G_PARAM_READABLE));
339         /**
340          * SOUP_SOCKET_SSL_CREDENTIALS:
341          *
342          * Alias for the #SoupSocket:ssl-credentials property.
343          * (SSL credential information.)
344          **/
345         g_object_class_install_property (
346                 object_class, PROP_SSL_CREDENTIALS,
347                 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
348                                       "SSL credentials",
349                                       "SSL credential information, passed from the session to the SSL implementation",
350                                       G_PARAM_READWRITE));
351         /**
352          * SOUP_SOCKET_ASYNC_CONTEXT:
353          *
354          * Alias for the #SoupSocket:async-context property. (The
355          * socket's #GMainContext.)
356          **/
357         g_object_class_install_property (
358                 object_class, PROP_ASYNC_CONTEXT,
359                 g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
360                                       "Async GMainContext",
361                                       "The GMainContext to dispatch this socket's async I/O in",
362                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
363
364         /**
365          * SOUP_SOCKET_TIMEOUT:
366          *
367          * Alias for the #SoupSocket:timeout property. (The timeout
368          * in seconds for blocking socket I/O operations.)
369          **/
370         g_object_class_install_property (
371                 object_class, PROP_TIMEOUT,
372                 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
373                                    "Timeout value",
374                                    "Value in seconds to timeout a blocking I/O",
375                                    0, G_MAXUINT, 0,
376                                    G_PARAM_READWRITE));
377
378 #ifdef G_OS_WIN32
379         /* Make sure WSAStartup() gets called. */
380         soup_address_get_type ();
381 #endif
382 }
383
384
385 static void
386 set_nonblocking (SoupSocketPrivate *priv)
387 {
388 #ifndef G_OS_WIN32
389         int flags;
390 #else
391         u_long val;
392 #endif
393
394         if (priv->sockfd == -1)
395                 return;
396
397 #ifndef G_OS_WIN32
398         flags = fcntl (priv->sockfd, F_GETFL, 0);
399         if (flags != -1) {
400                 if (priv->non_blocking)
401                         flags |= O_NONBLOCK;
402                 else
403                         flags &= ~O_NONBLOCK;
404                 fcntl (priv->sockfd, F_SETFL, flags);
405         }
406 #else
407         val = priv->non_blocking ? 1 : 0;
408         ioctlsocket (priv->sockfd, FIONBIO, &val);
409 #endif
410 }
411
412 static void
413 set_fdflags (SoupSocketPrivate *priv)
414 {
415         int opt;
416 #ifndef G_OS_WIN32
417         struct timeval timeout;
418         int flags;
419 #endif
420
421         if (priv->sockfd == -1)
422                 return;
423
424         set_nonblocking (priv);
425
426 #ifndef G_OS_WIN32
427         flags = fcntl (priv->sockfd, F_GETFD, 0);
428         if (flags != -1) {
429                 flags |= FD_CLOEXEC;
430                 fcntl (priv->sockfd, F_SETFD, flags);
431         }
432 #endif
433
434         opt = 1;
435         setsockopt (priv->sockfd, IPPROTO_TCP,
436                     TCP_NODELAY, (void *) &opt, sizeof (opt));
437         setsockopt (priv->sockfd, SOL_SOCKET,
438                     SO_REUSEADDR, (void *) &opt, sizeof (opt));
439
440 #ifndef G_OS_WIN32
441         timeout.tv_sec = priv->timeout;
442         timeout.tv_usec = 0;
443         setsockopt (priv->sockfd, SOL_SOCKET,
444                     SO_RCVTIMEO, (void *) &timeout, sizeof (timeout));
445
446         timeout.tv_sec = priv->timeout;
447         timeout.tv_usec = 0;
448         setsockopt (priv->sockfd, SOL_SOCKET,
449                     SO_SNDTIMEO, (void *) &timeout, sizeof (timeout));
450 #else
451         if (priv->timeout < G_MAXINT / 1000)
452                 opt = priv->timeout * 1000;
453         else
454                 opt = 0;
455
456         setsockopt (priv->sockfd, SOL_SOCKET,
457                     SO_RCVTIMEO, (void *) &opt, sizeof (opt));
458         
459         setsockopt (priv->sockfd, SOL_SOCKET,
460                     SO_SNDTIMEO, (void *) &opt, sizeof (opt));
461 #endif
462
463 #ifndef G_OS_WIN32
464         priv->iochannel =
465                 g_io_channel_unix_new (priv->sockfd);
466 #else
467         priv->iochannel =
468                 g_io_channel_win32_new_socket (priv->sockfd);
469 #endif
470         g_io_channel_set_close_on_unref (priv->iochannel, TRUE);
471         g_io_channel_set_encoding (priv->iochannel, NULL, NULL);
472         g_io_channel_set_buffered (priv->iochannel, FALSE);
473 }
474
475 static void
476 set_property (GObject *object, guint prop_id,
477               const GValue *value, GParamSpec *pspec)
478 {
479         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
480
481         switch (prop_id) {
482         case PROP_LOCAL_ADDRESS:
483                 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
484                 break;
485         case PROP_REMOTE_ADDRESS:
486                 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
487                 break;
488         case PROP_NON_BLOCKING:
489                 priv->non_blocking = g_value_get_boolean (value);
490                 set_nonblocking (priv);
491                 break;
492         case PROP_SSL_CREDENTIALS:
493                 priv->ssl_creds = g_value_get_pointer (value);
494                 break;
495         case PROP_ASYNC_CONTEXT:
496                 priv->async_context = g_value_get_pointer (value);
497                 if (priv->async_context)
498                         g_main_context_ref (priv->async_context);
499                 break;
500         case PROP_TIMEOUT:
501                 priv->timeout = g_value_get_uint (value);
502                 break;
503         default:
504                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
505                 break;
506         }
507 }
508
509 static void
510 get_property (GObject *object, guint prop_id,
511               GValue *value, GParamSpec *pspec)
512 {
513         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
514
515         switch (prop_id) {
516         case PROP_LOCAL_ADDRESS:
517                 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
518                 break;
519         case PROP_REMOTE_ADDRESS:
520                 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
521                 break;
522         case PROP_NON_BLOCKING:
523                 g_value_set_boolean (value, priv->non_blocking);
524                 break;
525         case PROP_IS_SERVER:
526                 g_value_set_boolean (value, priv->is_server);
527                 break;
528         case PROP_SSL_CREDENTIALS:
529                 g_value_set_pointer (value, priv->ssl_creds);
530                 break;
531         case PROP_ASYNC_CONTEXT:
532                 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
533                 break;
534         case PROP_TIMEOUT:
535                 g_value_set_uint (value, priv->timeout);
536                 break;
537         default:
538                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
539                 break;
540         }
541 }
542
543
544 /**
545  * soup_socket_new:
546  * @optname1: name of first property to set (or %NULL)
547  * @...: value of @optname1, followed by additional property/value pairs
548  *
549  * Creates a new (disconnected) socket
550  *
551  * Return value: the new socket
552  **/
553 SoupSocket *
554 soup_socket_new (const char *optname1, ...)
555 {
556         SoupSocket *sock;
557         va_list ap;
558
559         va_start (ap, optname1);
560         sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
561                                                   optname1, ap);
562         va_end (ap);
563
564         return sock;
565 }
566
567 typedef struct {
568         SoupSocket *sock;
569         GCancellable *cancellable;
570         guint cancel_id;
571         SoupSocketCallback callback;
572         gpointer user_data;
573 } SoupSocketAsyncConnectData;
574
575 static gboolean
576 idle_connect_result (gpointer user_data)
577 {
578         SoupSocketAsyncConnectData *sacd = user_data;
579         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
580         guint status;
581
582         priv->watch_src = NULL;
583         if (sacd->cancel_id)
584                 g_signal_handler_disconnect (sacd->cancellable, sacd->cancel_id);
585
586         if (priv->sockfd == -1) {
587                 if (g_cancellable_is_cancelled (sacd->cancellable))
588                         status = SOUP_STATUS_CANCELLED;
589                 else
590                         status = SOUP_STATUS_CANT_CONNECT;
591         } else
592                 status = SOUP_STATUS_OK;
593
594         sacd->callback (sacd->sock, status, sacd->user_data);
595         g_slice_free (SoupSocketAsyncConnectData, sacd);
596         return FALSE;
597 }
598
599 static gboolean
600 connect_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
601 {
602         SoupSocketAsyncConnectData *sacd = data;
603         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
604         int error = 0;
605         int len = sizeof (error);
606
607         /* Remove the watch now in case we don't return immediately */
608         g_source_destroy (priv->watch_src);
609         priv->watch_src = NULL;
610         if (priv->connect_timeout) {
611                 g_source_destroy (priv->connect_timeout);
612                 priv->connect_timeout = NULL;
613         }
614
615         if ((condition & ~(G_IO_IN | G_IO_OUT)) ||
616             (getsockopt (priv->sockfd, SOL_SOCKET, SO_ERROR,
617                          (void *)&error, (void *)&len) != 0) ||
618             error)
619                 disconnect_internal (priv);
620
621         return idle_connect_result (sacd);
622 }
623
624 static gboolean
625 connect_timeout (gpointer data)
626 {
627         SoupSocketAsyncConnectData *sacd = data;
628         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
629
630         /* Remove the watch now in case we don't return immediately */
631         g_source_destroy (priv->watch_src);
632         priv->watch_src = NULL;
633         g_source_destroy (priv->connect_timeout);
634         priv->connect_timeout = NULL;
635
636         disconnect_internal (priv);
637         return idle_connect_result (sacd);
638 }
639
640 static void
641 got_address (SoupAddress *addr, guint status, gpointer user_data)
642 {
643         SoupSocketAsyncConnectData *sacd = user_data;
644
645         if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
646                 sacd->callback (sacd->sock, status, sacd->user_data);
647                 g_slice_free (SoupSocketAsyncConnectData, sacd);
648                 return;
649         }
650
651         soup_socket_connect_async (sacd->sock, sacd->cancellable,
652                                    sacd->callback, sacd->user_data);
653         g_slice_free (SoupSocketAsyncConnectData, sacd);
654 }
655
656 static void
657 async_cancel (GCancellable *cancellable, gpointer user_data)
658 {
659         SoupSocketAsyncConnectData *sacd = user_data;
660         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sacd->sock);
661
662         if (priv->watch_src)
663                 g_source_destroy (priv->watch_src);
664         disconnect_internal (priv);
665         priv->watch_src = soup_add_completion (priv->async_context,
666                                                idle_connect_result, sacd);
667 }
668
669 static guint
670 socket_connect_internal (SoupSocket *sock)
671 {
672         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
673         struct sockaddr *sa;
674         int len, status;
675
676         sa = soup_address_get_sockaddr (priv->remote_addr, &len);
677         if (!sa)
678                 return SOUP_STATUS_CANT_RESOLVE;
679
680         priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
681         if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
682                 return SOUP_STATUS_CANT_CONNECT;
683         set_fdflags (priv);
684
685         status = connect (priv->sockfd, sa, len);
686
687         if (SOUP_IS_SOCKET_ERROR (status)) {
688                 if (SOUP_IS_CONNECT_STATUS_INPROGRESS ())
689                         return SOUP_STATUS_CONTINUE;
690
691                 disconnect_internal (priv);
692                 return SOUP_STATUS_CANT_CONNECT;
693         } else
694                 return SOUP_STATUS_OK;
695 }
696
697 /**
698  * SoupSocketCallback:
699  * @sock: the #SoupSocket
700  * @status: an HTTP status code indicating success or failure
701  * @user_data: the data passed to soup_socket_connect_async()
702  *
703  * The callback function passed to soup_socket_connect_async().
704  **/
705
706 /**
707  * soup_socket_connect_async:
708  * @sock: a client #SoupSocket (which must not already be connected)
709  * @cancellable: a #GCancellable, or %NULL
710  * @callback: callback to call after connecting
711  * @user_data: data to pass to @callback
712  *
713  * Begins asynchronously connecting to @sock's remote address. The
714  * socket will call @callback when it succeeds or fails (but not
715  * before returning from this function).
716  *
717  * If @cancellable is non-%NULL, it can be used to cancel the
718  * connection. @callback will still be invoked in this case, with a
719  * status of %SOUP_STATUS_CANCELLED.
720  **/
721 void
722 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
723                            SoupSocketCallback callback, gpointer user_data)
724 {
725         SoupSocketPrivate *priv;
726         SoupSocketAsyncConnectData *sacd;
727         guint status;
728
729         g_return_if_fail (SOUP_IS_SOCKET (sock));
730         priv = SOUP_SOCKET_GET_PRIVATE (sock);
731         g_return_if_fail (priv->remote_addr != NULL);
732
733         sacd = g_slice_new0 (SoupSocketAsyncConnectData);
734         sacd->sock = sock;
735         sacd->cancellable = cancellable;
736         sacd->callback = callback;
737         sacd->user_data = user_data;
738
739         if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
740                 soup_address_resolve_async (priv->remote_addr,
741                                             priv->async_context,
742                                             cancellable,
743                                             got_address, sacd);
744                 return;
745         }
746
747         status = socket_connect_internal (sock);
748         if (status == SOUP_STATUS_CONTINUE) {
749                 /* Wait for connect to succeed or fail */
750                 priv->watch_src =
751                         soup_add_io_watch (priv->async_context,
752                                            priv->iochannel,
753                                            G_IO_IN | G_IO_OUT |
754                                            G_IO_PRI | G_IO_ERR |
755                                            G_IO_HUP | G_IO_NVAL,
756                                            connect_watch, sacd);
757                 if (priv->timeout) {
758                         priv->connect_timeout =
759                                 soup_add_timeout (priv->async_context,
760                                                   priv->timeout * 1000,
761                                                   connect_timeout, sacd);
762                 }
763                 if (cancellable) {
764                         sacd->cancel_id =
765                                 g_signal_connect (cancellable, "cancelled",
766                                                   G_CALLBACK (async_cancel),
767                                                   sacd);
768                 }
769         } else {
770                 priv->watch_src = soup_add_completion (priv->async_context,
771                                                        idle_connect_result, sacd);
772         }
773 }
774
775 static void
776 sync_cancel (GCancellable *cancellable, gpointer sock)
777 {
778         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
779
780         shutdown (priv->sockfd, SHUT_RDWR);
781 }
782
783 /**
784  * soup_socket_connect_sync:
785  * @sock: a client #SoupSocket (which must not already be connected)
786  * @cancellable: a #GCancellable, or %NULL
787  *
788  * Attempt to synchronously connect @sock to its remote address.
789  *
790  * If @cancellable is non-%NULL, it can be used to cancel the
791  * connection, in which case soup_socket_connect_sync() will return
792  * %SOUP_STATUS_CANCELLED.
793  *
794  * Return value: a success or failure code.
795  **/
796 guint
797 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
798 {
799         SoupSocketPrivate *priv;
800         guint status, cancel_id;
801
802         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
803         priv = SOUP_SOCKET_GET_PRIVATE (sock);
804         g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
805         g_return_val_if_fail (priv->sockfd == -1, SOUP_STATUS_MALFORMED);
806         g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
807
808         if (!soup_address_get_sockaddr (priv->remote_addr, NULL)) {
809                 status = soup_address_resolve_sync (priv->remote_addr,
810                                                     cancellable);
811                 if (!SOUP_STATUS_IS_SUCCESSFUL (status))
812                         return status;
813         }
814
815         if (cancellable) {
816                 cancel_id = g_signal_connect (cancellable, "cancelled",
817                                               G_CALLBACK (sync_cancel), sock);
818         }
819
820         status = socket_connect_internal (sock);
821
822         if (cancellable) {
823                 if (status != SOUP_STATUS_OK &&
824                     g_cancellable_is_cancelled (cancellable)) {
825                         status = SOUP_STATUS_CANCELLED;
826                         disconnect_internal (priv);
827                 }
828                 g_signal_handler_disconnect (cancellable, cancel_id);
829         }
830
831         return status;
832 }
833
834 int
835 soup_socket_get_fd (SoupSocket *sock)
836 {
837         g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
838
839         return SOUP_SOCKET_GET_PRIVATE (sock)->sockfd;
840 }
841
842 static gboolean
843 listen_watch (GIOChannel* iochannel, GIOCondition condition, gpointer data)
844 {
845         SoupSocket *sock = data, *new;
846         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
847         struct soup_sockaddr_max sa;
848         int sa_len, sockfd;
849
850         if (condition & (G_IO_HUP | G_IO_ERR)) {
851                 g_source_destroy (priv->watch_src);
852                 priv->watch_src = NULL;
853                 return FALSE;
854         }
855
856         sa_len = sizeof (sa);
857         sockfd = accept (priv->sockfd, (struct sockaddr *)&sa, (void *)&sa_len);
858         if (SOUP_IS_INVALID_SOCKET (sockfd))
859                 return TRUE;
860
861         new = g_object_new (SOUP_TYPE_SOCKET, NULL);
862         new_priv = SOUP_SOCKET_GET_PRIVATE (new);
863         new_priv->sockfd = sockfd;
864         if (priv->async_context)
865                 new_priv->async_context = g_main_context_ref (priv->async_context);
866         new_priv->non_blocking = priv->non_blocking;
867         new_priv->is_server = TRUE;
868         new_priv->ssl_creds = priv->ssl_creds;
869         set_fdflags (new_priv);
870
871         new_priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
872
873         if (new_priv->ssl_creds) {
874                 if (!soup_socket_start_ssl (new, NULL)) {
875                         g_object_unref (new);
876                         return TRUE;
877                 }
878         }
879
880         g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
881         g_object_unref (new);
882
883         return TRUE;
884 }
885
886 /**
887  * soup_socket_listen:
888  * @sock: a server #SoupSocket (which must not already be connected or
889  * listening)
890  *
891  * Makes @sock start listening on its local address. When connections
892  * come in, @sock will emit %new_connection.
893  *
894  * Return value: whether or not @sock is now listening.
895  **/
896 gboolean
897 soup_socket_listen (SoupSocket *sock)
898
899 {
900         SoupSocketPrivate *priv;
901         struct sockaddr *sa;
902         int sa_len;
903
904         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
905         priv = SOUP_SOCKET_GET_PRIVATE (sock);
906         g_return_val_if_fail (priv->sockfd == -1, FALSE);
907         g_return_val_if_fail (priv->local_addr != NULL, FALSE);
908
909         priv->is_server = TRUE;
910
911         /* @local_addr may have its port set to 0. So we intentionally
912          * don't store it in priv->local_addr, so that if the
913          * caller calls soup_socket_get_local_address() later, we'll
914          * have to make a new addr by calling getsockname(), which
915          * will have the right port number.
916          */
917         sa = soup_address_get_sockaddr (priv->local_addr, &sa_len);
918         g_return_val_if_fail (sa != NULL, FALSE);
919
920         priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0);
921         if (SOUP_IS_INVALID_SOCKET (priv->sockfd))
922                 goto cant_listen;
923         set_fdflags (priv);
924
925         /* Bind */
926         if (bind (priv->sockfd, sa, sa_len) != 0)
927                 goto cant_listen;
928         /* Force local_addr to be re-resolved now */
929         g_object_unref (priv->local_addr);
930         priv->local_addr = NULL;
931
932         /* Listen */
933         if (listen (priv->sockfd, 10) != 0)
934                 goto cant_listen;
935
936         priv->watch_src = soup_add_io_watch (priv->async_context,
937                                              priv->iochannel,
938                                              G_IO_IN | G_IO_ERR | G_IO_HUP,
939                                              listen_watch, sock);
940         return TRUE;
941
942  cant_listen:
943         if (priv->iochannel)
944                 disconnect_internal (priv);
945
946         return FALSE;
947 }
948
949 /**
950  * soup_socket_start_ssl:
951  * @sock: the socket
952  * @cancellable: a #GCancellable
953  *
954  * Starts using SSL on @socket.
955  *
956  * Return value: success or failure
957  **/
958 gboolean
959 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
960 {
961         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
962
963         return soup_socket_start_proxy_ssl (sock, soup_address_get_name (priv->remote_addr), cancellable);
964 }
965         
966 /**
967  * soup_socket_start_proxy_ssl:
968  * @sock: the socket
969  * @ssl_host: hostname of the SSL server
970  * @cancellable: a #GCancellable
971  *
972  * Starts using SSL on @socket, expecting to find a host named
973  * @ssl_host.
974  *
975  * Return value: success or failure
976  **/
977 gboolean
978 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
979                              GCancellable *cancellable)
980 {
981         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
982         GIOChannel *ssl_chan;
983         GIOChannel *real_chan;
984
985         real_chan = priv->iochannel;
986         ssl_chan = soup_ssl_wrap_iochannel (
987                 real_chan, priv->non_blocking, priv->is_server ?
988                 SOUP_SSL_TYPE_SERVER : SOUP_SSL_TYPE_CLIENT,
989                 ssl_host, priv->ssl_creds);
990
991         if (!ssl_chan)
992                 return FALSE;
993
994         priv->iochannel = ssl_chan;
995         g_io_channel_unref (real_chan);
996
997         return TRUE;
998 }
999         
1000 /**
1001  * soup_socket_is_ssl:
1002  * @sock: a #SoupSocket
1003  *
1004  * Tests if @sock is set up to do SSL. Note that this simply means
1005  * that the %SOUP_SOCKET_SSL_CREDENTIALS property has been set; it
1006  * does not mean that soup_socket_start_ssl() has been called.
1007  *
1008  * Return value: %TRUE if @sock has SSL credentials set
1009  **/
1010 gboolean
1011 soup_socket_is_ssl (SoupSocket *sock)
1012 {
1013         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1014
1015         return priv->ssl_creds != NULL;
1016 }
1017
1018 /**
1019  * soup_socket_disconnect:
1020  * @sock: a #SoupSocket
1021  *
1022  * Disconnects @sock. Any further read or write attempts on it will
1023  * fail.
1024  **/
1025 void
1026 soup_socket_disconnect (SoupSocket *sock)
1027 {
1028         SoupSocketPrivate *priv;
1029         gboolean already_disconnected = FALSE;
1030
1031         g_return_if_fail (SOUP_IS_SOCKET (sock));
1032         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1033
1034         if (g_mutex_trylock (priv->iolock)) {
1035                 if (priv->iochannel)
1036                         disconnect_internal (priv);
1037                 else
1038                         already_disconnected = TRUE;
1039                 g_mutex_unlock (priv->iolock);
1040         } else {
1041                 int sockfd;
1042
1043                 /* Another thread is currently doing IO, so
1044                  * we can't close the iochannel. So just shutdown
1045                  * the file descriptor to force the I/O to fail.
1046                  * (It will actually be closed when the socket is
1047                  * destroyed.)
1048                  */
1049                 sockfd = priv->sockfd;
1050                 priv->sockfd = -1;
1051
1052                 if (sockfd == -1)
1053                         already_disconnected = TRUE;
1054                 else
1055                         shutdown (sockfd, SHUT_RDWR);
1056         }
1057
1058         if (already_disconnected)
1059                 return;
1060
1061         /* Give all readers a chance to notice the connection close */
1062         g_signal_emit (sock, signals[READABLE], 0);
1063
1064         /* FIXME: can't disconnect until all data is read */
1065
1066         /* Then let everyone know we're disconnected */
1067         g_signal_emit (sock, signals[DISCONNECTED], 0);
1068 }
1069
1070 /**
1071  * soup_socket_is_connected:
1072  * @sock: a #SoupSocket
1073  *
1074  * Tests if @sock is connected to another host
1075  *
1076  * Return value: %TRUE or %FALSE.
1077  **/
1078 gboolean
1079 soup_socket_is_connected (SoupSocket *sock)
1080 {
1081         SoupSocketPrivate *priv;
1082
1083         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1084         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1085
1086         return priv->iochannel != NULL;
1087 }
1088
1089 /**
1090  * soup_socket_get_local_address:
1091  * @sock: a #SoupSocket
1092  *
1093  * Returns the #SoupAddress corresponding to the local end of @sock.
1094  *
1095  * Return value: the #SoupAddress
1096  **/
1097 SoupAddress *
1098 soup_socket_get_local_address (SoupSocket *sock)
1099 {
1100         SoupSocketPrivate *priv;
1101
1102         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1103         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1104
1105         g_mutex_lock (priv->addrlock);
1106         if (!priv->local_addr) {
1107                 struct soup_sockaddr_max bound_sa;
1108                 int sa_len;
1109
1110                 sa_len = sizeof (bound_sa);
1111                 getsockname (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
1112                 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1113         }
1114         g_mutex_unlock (priv->addrlock);
1115
1116         return priv->local_addr;
1117 }
1118
1119 /**
1120  * soup_socket_get_remote_address:
1121  * @sock: a #SoupSocket
1122  *
1123  * Returns the #SoupAddress corresponding to the remote end of @sock.
1124  *
1125  * Return value: the #SoupAddress
1126  **/
1127 SoupAddress *
1128 soup_socket_get_remote_address (SoupSocket *sock)
1129 {
1130         SoupSocketPrivate *priv;
1131
1132         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1133         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1134
1135         g_mutex_lock (priv->addrlock);
1136         if (!priv->remote_addr) {
1137                 struct soup_sockaddr_max bound_sa;
1138                 int sa_len;
1139
1140                 sa_len = sizeof (bound_sa);
1141                 getpeername (priv->sockfd, (struct sockaddr *)&bound_sa, (void *)&sa_len);
1142                 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa, sa_len);
1143         }
1144         g_mutex_unlock (priv->addrlock);
1145
1146         return priv->remote_addr;
1147 }
1148
1149
1150 static gboolean
1151 socket_timeout (gpointer sock)
1152 {
1153         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1154         gboolean readable = FALSE, writable = FALSE;
1155
1156         priv->timed_out = TRUE;
1157         if (priv->read_timeout) {
1158                 priv->read_timeout = NULL;
1159                 readable = TRUE;
1160         }
1161         if (priv->write_timeout) {
1162                 priv->write_timeout = NULL;
1163                 writable = TRUE;
1164         }
1165
1166         if (readable)
1167                 g_signal_emit (sock, signals[READABLE], 0);
1168         if (writable)
1169                 g_signal_emit (sock, signals[WRITABLE], 0);
1170
1171         return FALSE;
1172 }
1173
1174 static gboolean
1175 socket_read_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1176 {
1177         SoupSocket *sock = user_data;
1178         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1179
1180         priv->read_src = NULL;
1181         if (priv->read_timeout) {
1182                 g_source_destroy (priv->read_timeout);
1183                 priv->read_timeout = NULL;
1184         }
1185
1186         if (cond & (G_IO_ERR | G_IO_HUP))
1187                 soup_socket_disconnect (sock);
1188         else
1189                 g_signal_emit (sock, signals[READABLE], 0);
1190
1191         return FALSE;
1192 }
1193
1194 static SoupSocketIOStatus
1195 read_from_network (SoupSocket *sock, gpointer buffer, gsize len,
1196                    gsize *nread, GError **error)
1197 {
1198         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1199         GIOStatus status;
1200         GIOCondition cond = G_IO_IN;
1201         GError *my_err = NULL;
1202
1203         *nread = 0;
1204
1205         if (!priv->iochannel)
1206                 return SOUP_SOCKET_EOF;
1207
1208         if (priv->timed_out)
1209                 return SOUP_SOCKET_ERROR;
1210
1211         status = g_io_channel_read_chars (priv->iochannel,
1212                                           buffer, len, nread, &my_err);
1213         if (my_err) {
1214                 if (my_err->domain == SOUP_SSL_ERROR &&
1215                     my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_WRITE)
1216                         cond = G_IO_OUT;
1217                 g_propagate_error (error, my_err);
1218         }
1219
1220         switch (status) {
1221         case G_IO_STATUS_NORMAL:
1222         case G_IO_STATUS_AGAIN:
1223                 if (*nread > 0) {
1224                         g_clear_error (error);
1225                         return SOUP_SOCKET_OK;
1226                 }
1227
1228                 /* If the socket is sync and we get EAGAIN, then it is
1229                  * a socket timeout and should be treated as an error
1230                  * condition.
1231                  */
1232                 if (!priv->non_blocking)
1233                         return SOUP_SOCKET_ERROR;
1234
1235                 if (!priv->read_src) {
1236                         priv->read_src =
1237                                 soup_add_io_watch (priv->async_context,
1238                                                    priv->iochannel,
1239                                                    cond | G_IO_HUP | G_IO_ERR,
1240                                                    socket_read_watch, sock);
1241                         if (priv->timeout) {
1242                                 priv->read_timeout =
1243                                         soup_add_timeout (priv->async_context,
1244                                                           priv->timeout * 1000,
1245                                                           socket_timeout, sock);
1246                         }
1247                 }
1248                 g_clear_error (error);
1249                 return SOUP_SOCKET_WOULD_BLOCK;
1250
1251         case G_IO_STATUS_EOF:
1252                 g_clear_error (error);
1253                 return SOUP_SOCKET_EOF;
1254
1255         default:
1256                 return SOUP_SOCKET_ERROR;
1257         }
1258 }
1259
1260 static SoupSocketIOStatus
1261 read_from_buf (SoupSocket *sock, gpointer buffer, gsize len, gsize *nread)
1262 {
1263         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1264         GByteArray *read_buf = priv->read_buf;
1265
1266         *nread = MIN (read_buf->len, len);
1267         memcpy (buffer, read_buf->data, *nread);
1268
1269         if (*nread == read_buf->len) {
1270                 g_byte_array_free (read_buf, TRUE);
1271                 priv->read_buf = NULL;
1272         } else {
1273                 memmove (read_buf->data, read_buf->data + *nread, 
1274                          read_buf->len - *nread);
1275                 g_byte_array_set_size (read_buf, read_buf->len - *nread);
1276         }
1277
1278         return SOUP_SOCKET_OK;
1279 }
1280
1281 /**
1282  * SoupSocketIOStatus:
1283  * @SOUP_SOCKET_OK: Success
1284  * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1285  * @SOUP_SOCKET_EOF: End of file
1286  * @SOUP_SOCKET_ERROR: Other error
1287  *
1288  * Return value from the #SoupSocket IO methods.
1289  **/
1290
1291 /**
1292  * soup_socket_read:
1293  * @sock: the socket
1294  * @buffer: buffer to read into
1295  * @len: size of @buffer in bytes
1296  * @nread: on return, the number of bytes read into @buffer
1297  * @cancellable: a #GCancellable, or %NULL
1298  * @error: error pointer
1299  *
1300  * Attempts to read up to @len bytes from @sock into @buffer. If some
1301  * data is successfully read, soup_socket_read() will return
1302  * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1303  * actually read (which may be less than @len).
1304  *
1305  * If @sock is non-blocking, and no data is available, the return
1306  * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1307  * can connect to the #SoupSocket::readable signal to know when there
1308  * is more data to read. (NB: You MUST read all available data off the
1309  * socket first. #SoupSocket::readable is only emitted after
1310  * soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only
1311  * emitted once. See the documentation for #SoupSocket:non-blocking.)
1312  *
1313  * Return value: a #SoupSocketIOStatus, as described above (or
1314  * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1315  * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1316  * also be set).
1317  **/
1318 SoupSocketIOStatus
1319 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1320                   gsize *nread, GCancellable *cancellable, GError **error)
1321 {
1322         SoupSocketPrivate *priv;
1323         SoupSocketIOStatus status;
1324
1325         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1326         g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1327
1328         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1329
1330         g_mutex_lock (priv->iolock);
1331         if (priv->read_buf)
1332                 status = read_from_buf (sock, buffer, len, nread);
1333         else
1334                 status = read_from_network (sock, buffer, len, nread, error);
1335         g_mutex_unlock (priv->iolock);
1336
1337         return status;
1338 }
1339
1340 /**
1341  * soup_socket_read_until:
1342  * @sock: the socket
1343  * @buffer: buffer to read into
1344  * @len: size of @buffer in bytes
1345  * @boundary: boundary to read until
1346  * @boundary_len: length of @boundary in bytes
1347  * @nread: on return, the number of bytes read into @buffer
1348  * @got_boundary: on return, whether or not the data in @buffer
1349  * ends with the boundary string
1350  * @cancellable: a #GCancellable, or %NULL
1351  * @error: error pointer
1352  *
1353  * Like soup_socket_read(), but reads no further than the first
1354  * occurrence of @boundary. (If the boundary is found, it will be
1355  * included in the returned data, and *@got_boundary will be set to
1356  * %TRUE.) Any data after the boundary will returned in future reads.
1357  *
1358  * soup_socket_read_until() will almost always return fewer than @len
1359  * bytes: if the boundary is found, then it will only return the bytes
1360  * up until the end of the boundary, and if the boundary is not found,
1361  * then it will leave the last <literal>(boundary_len - 1)</literal>
1362  * bytes in its internal buffer, in case they form the start of the
1363  * boundary string. Thus, @len normally needs to be at least 1 byte
1364  * longer than @boundary_len if you want to make any progress at all.
1365  *
1366  * Return value: as for soup_socket_read()
1367  **/
1368 SoupSocketIOStatus
1369 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1370                         gconstpointer boundary, gsize boundary_len,
1371                         gsize *nread, gboolean *got_boundary,
1372                         GCancellable *cancellable, GError **error)
1373 {
1374         SoupSocketPrivate *priv;
1375         SoupSocketIOStatus status;
1376         GByteArray *read_buf;
1377         guint match_len, prev_len;
1378         guint8 *p, *end;
1379
1380         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1381         g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1382         g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1383
1384         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1385
1386         g_mutex_lock (priv->iolock);
1387
1388         *got_boundary = FALSE;
1389
1390         if (!priv->read_buf)
1391                 priv->read_buf = g_byte_array_new ();
1392         read_buf = priv->read_buf;
1393
1394         if (read_buf->len < boundary_len) {
1395                 prev_len = read_buf->len;
1396                 g_byte_array_set_size (read_buf, len);
1397                 status = read_from_network (sock,
1398                                             read_buf->data + prev_len,
1399                                             len - prev_len, nread, error);
1400                 read_buf->len = prev_len + *nread;
1401
1402                 if (status != SOUP_SOCKET_OK) {
1403                         g_mutex_unlock (priv->iolock);
1404                         return status;
1405                 }
1406         }
1407
1408         /* Scan for the boundary */
1409         end = read_buf->data + read_buf->len;
1410         for (p = read_buf->data; p <= end - boundary_len; p++) {
1411                 if (!memcmp (p, boundary, boundary_len)) {
1412                         p += boundary_len;
1413                         *got_boundary = TRUE;
1414                         break;
1415                 }
1416         }
1417
1418         /* Return everything up to 'p' (which is either just after the
1419          * boundary, or @boundary_len - 1 bytes before the end of the
1420          * buffer).
1421          */
1422         match_len = p - read_buf->data;
1423         status = read_from_buf (sock, buffer, MIN (len, match_len), nread);
1424
1425         g_mutex_unlock (priv->iolock);
1426         return status;
1427 }
1428
1429 static gboolean
1430 socket_write_watch (GIOChannel *chan, GIOCondition cond, gpointer user_data)
1431 {
1432         SoupSocket *sock = user_data;
1433         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1434
1435         priv->write_src = NULL;
1436         if (priv->write_timeout) {
1437                 g_source_destroy (priv->write_timeout);
1438                 priv->write_timeout = NULL;
1439         }
1440
1441         if (cond & (G_IO_ERR | G_IO_HUP))
1442                 soup_socket_disconnect (sock);
1443         else
1444                 g_signal_emit (sock, signals[WRITABLE], 0);
1445
1446         return FALSE;
1447 }
1448
1449 /**
1450  * soup_socket_write:
1451  * @sock: the socket
1452  * @buffer: data to write
1453  * @len: size of @buffer, in bytes
1454  * @nwrote: on return, number of bytes written
1455  * @cancellable: a #GCancellable, or %NULL
1456  * @error: error pointer
1457  *
1458  * Attempts to write @len bytes from @buffer to @sock. If some data is
1459  * successfully written, the return status will be %SOUP_SOCKET_OK,
1460  * and *@nwrote will contain the number of bytes actually written
1461  * (which may be less than @len).
1462  *
1463  * If @sock is non-blocking, and no data could be written right away,
1464  * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1465  * the caller can connect to the #SoupSocket::writable signal to know
1466  * when more data can be written. (NB: #SoupSocket::writable is only
1467  * emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK,
1468  * and it is only emitted once. See the documentation for
1469  * #SoupSocket:non-blocking.)
1470  *
1471  * Return value: a #SoupSocketIOStatus, as described above (or
1472  * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1473  * return value is %SOUP_SOCKET_ERROR.)
1474  **/
1475 SoupSocketIOStatus
1476 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1477                    gsize len, gsize *nwrote,
1478                    GCancellable *cancellable, GError **error)
1479 {
1480         SoupSocketPrivate *priv;
1481         GIOStatus status;
1482         GIOCondition cond = G_IO_OUT;
1483         GError *my_err = NULL;
1484
1485         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1486         g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
1487
1488         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1489
1490         g_mutex_lock (priv->iolock);
1491
1492         if (!priv->iochannel) {
1493                 g_mutex_unlock (priv->iolock);
1494                 return SOUP_SOCKET_EOF;
1495         }
1496         if (priv->timed_out) {
1497                 g_mutex_unlock (priv->iolock);
1498                 return SOUP_SOCKET_ERROR;
1499         }
1500         if (priv->write_src) {
1501                 g_mutex_unlock (priv->iolock);
1502                 return SOUP_SOCKET_WOULD_BLOCK;
1503         }
1504
1505         status = g_io_channel_write_chars (priv->iochannel,
1506                                            buffer, len, nwrote, &my_err);
1507         if (my_err) {
1508                 if (my_err->domain == SOUP_SSL_ERROR &&
1509                     my_err->code == SOUP_SSL_ERROR_HANDSHAKE_NEEDS_READ)
1510                         cond = G_IO_IN;
1511                 g_propagate_error (error, my_err);
1512         }
1513
1514         /* If the socket is sync and we get EAGAIN, then it is a
1515          * socket timeout and should be treated as an error condition.
1516          */
1517         if (!priv->non_blocking && status == G_IO_STATUS_AGAIN) {
1518                 g_mutex_unlock (priv->iolock);
1519                 return SOUP_SOCKET_ERROR;
1520         }
1521
1522         if (status != G_IO_STATUS_NORMAL && status != G_IO_STATUS_AGAIN) {
1523                 g_mutex_unlock (priv->iolock);
1524                 return SOUP_SOCKET_ERROR;
1525         }
1526
1527         g_clear_error (error);
1528
1529         if (*nwrote) {
1530                 g_mutex_unlock (priv->iolock);
1531                 return SOUP_SOCKET_OK;
1532         }
1533
1534         priv->write_src =
1535                 soup_add_io_watch (priv->async_context,
1536                                    priv->iochannel,
1537                                    cond | G_IO_HUP | G_IO_ERR, 
1538                                    socket_write_watch, sock);
1539         if (priv->timeout) {
1540                 priv->write_timeout = soup_add_timeout (priv->async_context,
1541                                                         priv->timeout * 1000,
1542                                                         socket_timeout, sock);
1543         }
1544
1545         g_mutex_unlock (priv->iolock);
1546         return SOUP_SOCKET_WOULD_BLOCK;
1547 }