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