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