Remove build warning
[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 <string.h>
13
14 #include <gio/gnetworking.h>
15
16 #include "soup-socket.h"
17 #include "soup.h"
18 #include "soup-filter-input-stream.h"
19 #include "soup-io-stream.h"
20 #include "soup-misc-private.h"
21 #include "TIZEN.h"
22
23 #if ENABLE(TIZEN_PERFORMANCE_TEST_LOG)
24 #include <sys/prctl.h>
25 #ifndef PR_TASK_PERF_USER_TRACE
26 #define PR_TASK_PERF_USER_TRACE 666
27 #endif
28
29 #define MAX_STRING_LEN 256
30 #define HWCLOCK_LOG(s)  {const char *str=s; prctl(PR_TASK_PERF_USER_TRACE, str, strlen(str));}
31
32 static void prctl_with_url(const char *prestr, const char *url)
33 {
34         char s[MAX_STRING_LEN] = "";
35         int len_max = 120;
36         int len_pre = strlen(prestr);
37         int len_url = strlen(url);
38
39         strncpy(s, prestr, len_pre);
40         if(len_pre + len_url < len_max) {
41                 strncpy(s+len_pre, url, len_url);
42         }
43         else {
44                 int len_part = len_max - len_pre - 10;
45                 strncpy(s+len_pre, url, len_part);
46                 strncpy(s+len_pre+len_part, "...", MAX_STRING_LEN-len_pre-len_part-1);
47                 strncpy(s+len_pre+len_part+3, url+len_url-7, 7);
48         }
49         prctl(PR_TASK_PERF_USER_TRACE, s, strlen(s));
50 }
51 #endif
52
53 /**
54  * SECTION:soup-socket
55  * @short_description: A network socket
56  *
57  * #SoupSocket is libsoup's TCP socket type. While it is primarily
58  * intended for internal use, #SoupSocket<!-- -->s are exposed in the
59  * API in various places, and some of their methods (eg,
60  * soup_socket_get_remote_address()) may be useful to applications.
61  **/
62
63 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
64
65 enum {
66         READABLE,
67         WRITABLE,
68         DISCONNECTED,
69         NEW_CONNECTION,
70         EVENT,
71 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
72         DYNAMIC_CERTIFICATEPATH,
73 #endif
74 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
75         ACCEPT_CERTIFICATE,
76 #endif
77
78         LAST_SIGNAL
79 };
80
81 static guint signals[LAST_SIGNAL] = { 0 };
82
83 enum {
84         PROP_0,
85
86         PROP_LOCAL_ADDRESS,
87         PROP_REMOTE_ADDRESS,
88         PROP_NON_BLOCKING,
89         PROP_IS_SERVER,
90         PROP_SSL_CREDENTIALS,
91         PROP_SSL_STRICT,
92         PROP_SSL_FALLBACK,
93         PROP_ASYNC_CONTEXT,
94         PROP_USE_THREAD_CONTEXT,
95         PROP_TIMEOUT,
96         PROP_TRUSTED_CERTIFICATE,
97         PROP_CLEAN_DISPOSE,
98         PROP_TLS_CERTIFICATE,
99         PROP_TLS_ERRORS,
100         PROP_PROXY_RESOLVER,
101 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
102         PROP_WIDGET_ENGINE,
103 #endif
104
105         LAST_PROP
106 };
107
108 typedef struct {
109         SoupAddress *local_addr, *remote_addr;
110         GIOStream *conn, *iostream;
111         GSocket *gsock;
112         GInputStream *istream;
113         GOutputStream *ostream;
114         GTlsCertificateFlags tls_errors;
115         GProxyResolver *proxy_resolver;
116
117         guint non_blocking:1;
118         guint is_server:1;
119         guint ssl:1;
120         guint ssl_strict:1;
121         guint ssl_fallback:1;
122         guint clean_dispose:1;
123         guint use_thread_context:1;
124         gpointer ssl_creds;
125
126         GMainContext   *async_context;
127         GSource        *watch_src;
128         GSource        *read_src, *write_src;
129
130         GMutex iolock, addrlock;
131         guint timeout;
132
133         GCancellable *connect_cancel;
134 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
135         gboolean widget_engine;
136         gchar **cert_lists;
137         gchar **default_cert_lists;
138 #endif
139 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
140         gboolean acceptedCertificate;
141 #endif
142 } SoupSocketPrivate;
143
144 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
145 #define CERT_LIST_FILE "/usr/share/clientcert/ClientCertList"
146 #define DEFAULT_CERT_FILE "/usr/share/clientcert/DefaultClientCertList"
147 #endif
148
149 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
150
151 static void soup_socket_peer_certificate_changed (GObject *conn,
152                                                   GParamSpec *pspec,
153                                                   gpointer user_data);
154
155 static void
156 soup_socket_init (SoupSocket *sock)
157 {
158         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
159
160         priv->non_blocking = TRUE;
161 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
162         priv->cert_lists = NULL;
163         priv->default_cert_lists = NULL;
164 #endif
165 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
166         priv->acceptedCertificate = FALSE;
167 #endif
168         g_mutex_init (&priv->addrlock);
169         g_mutex_init (&priv->iolock);
170 }
171
172 static void
173 disconnect_internal (SoupSocket *sock, gboolean close)
174 {
175         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
176
177         g_clear_object (&priv->gsock);
178         if (priv->conn && close)
179                 g_io_stream_close (priv->conn, NULL, NULL);
180
181         if (priv->read_src) {
182                 g_source_destroy (priv->read_src);
183                 priv->read_src = NULL;
184         }
185         if (priv->write_src) {
186                 g_source_destroy (priv->write_src);
187                 priv->write_src = NULL;
188         }
189 }
190
191 static void
192 soup_socket_finalize (GObject *object)
193 {
194         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
195
196 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
197         if (priv->cert_lists)
198                 g_strfreev (priv->cert_lists);
199         if (priv->default_cert_lists)
200                 g_strfreev (priv->default_cert_lists);
201 #endif
202
203         if (priv->connect_cancel) {
204                 if (priv->clean_dispose)
205                         g_warning ("Disposing socket %p during connect", object);
206                 g_object_unref (priv->connect_cancel);
207         }
208         if (priv->gsock) {
209                 if (priv->clean_dispose)
210                         g_warning ("Disposing socket %p while still connected", object);
211                 disconnect_internal (SOUP_SOCKET (object), TRUE);
212         }
213
214         g_clear_object (&priv->conn);
215         g_clear_object (&priv->iostream);
216         g_clear_object (&priv->istream);
217         g_clear_object (&priv->ostream);
218
219         g_clear_object (&priv->local_addr);
220         g_clear_object (&priv->remote_addr);
221
222         g_clear_object (&priv->proxy_resolver);
223
224         if (priv->watch_src) {
225                 if (priv->clean_dispose && !priv->is_server)
226                         g_warning ("Disposing socket %p during async op", object);
227                 g_source_destroy (priv->watch_src);
228         }
229         g_clear_pointer (&priv->async_context, g_main_context_unref);
230
231         g_mutex_clear (&priv->addrlock);
232         g_mutex_clear (&priv->iolock);
233
234         G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
235 }
236
237
238 static void
239 finish_socket_setup (SoupSocketPrivate *priv)
240 {
241         if (!priv->gsock)
242                 return;
243
244         if (!priv->conn)
245                 priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock);
246         if (!priv->iostream)
247                 priv->iostream = soup_io_stream_new (priv->conn, FALSE);
248         if (!priv->istream)
249                 priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
250         if (!priv->ostream)
251                 priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
252
253         g_socket_set_timeout (priv->gsock, priv->timeout);
254         g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
255 }
256
257 static void
258 soup_socket_set_property (GObject *object, guint prop_id,
259                           const GValue *value, GParamSpec *pspec)
260 {
261         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
262
263         switch (prop_id) {
264         case PROP_LOCAL_ADDRESS:
265                 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
266                 break;
267         case PROP_REMOTE_ADDRESS:
268                 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
269                 break;
270         case PROP_NON_BLOCKING:
271                 priv->non_blocking = g_value_get_boolean (value);
272                 break;
273         case PROP_SSL_CREDENTIALS:
274                 priv->ssl_creds = g_value_get_pointer (value);
275                 break;
276         case PROP_SSL_STRICT:
277                 priv->ssl_strict = g_value_get_boolean (value);
278                 break;
279         case PROP_SSL_FALLBACK:
280                 priv->ssl_fallback = g_value_get_boolean (value);
281                 break;
282         case PROP_ASYNC_CONTEXT:
283                 priv->async_context = g_value_get_pointer (value);
284                 if (priv->async_context)
285                         g_main_context_ref (priv->async_context);
286                 break;
287         case PROP_USE_THREAD_CONTEXT:
288                 priv->use_thread_context = g_value_get_boolean (value);
289                 break;
290         case PROP_TIMEOUT:
291                 priv->timeout = g_value_get_uint (value);
292                 if (priv->conn)
293                         g_socket_set_timeout (priv->gsock, priv->timeout);
294                 break;
295         case PROP_PROXY_RESOLVER:
296                 priv->proxy_resolver = g_value_dup_object (value);
297                 break;
298         case PROP_CLEAN_DISPOSE:
299                 priv->clean_dispose = g_value_get_boolean (value);
300                 break;
301 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
302         case PROP_WIDGET_ENGINE:
303                 priv->widget_engine = g_value_get_boolean (value);
304                 break;
305 #endif
306         default:
307                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
308                 break;
309         }
310 }
311
312 static void
313 soup_socket_get_property (GObject *object, guint prop_id,
314                           GValue *value, GParamSpec *pspec)
315 {
316         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
317
318         switch (prop_id) {
319         case PROP_LOCAL_ADDRESS:
320                 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
321                 break;
322         case PROP_REMOTE_ADDRESS:
323                 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
324                 break;
325         case PROP_NON_BLOCKING:
326                 g_value_set_boolean (value, priv->non_blocking);
327                 break;
328         case PROP_IS_SERVER:
329                 g_value_set_boolean (value, priv->is_server);
330                 break;
331         case PROP_SSL_CREDENTIALS:
332                 g_value_set_pointer (value, priv->ssl_creds);
333                 break;
334         case PROP_SSL_STRICT:
335                 g_value_set_boolean (value, priv->ssl_strict);
336                 break;
337         case PROP_SSL_FALLBACK:
338                 g_value_set_boolean (value, priv->ssl_fallback);
339                 break;
340         case PROP_TRUSTED_CERTIFICATE:
341                 g_value_set_boolean (value, priv->tls_errors == 0);
342                 break;
343         case PROP_ASYNC_CONTEXT:
344                 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
345                 break;
346         case PROP_USE_THREAD_CONTEXT:
347                 g_value_set_boolean (value, priv->use_thread_context);
348                 break;
349         case PROP_TIMEOUT:
350                 g_value_set_uint (value, priv->timeout);
351                 break;
352         case PROP_TLS_CERTIFICATE:
353                 if (G_IS_TLS_CONNECTION (priv->conn))
354                         g_value_set_object (value, g_tls_connection_get_peer_certificate (G_TLS_CONNECTION (priv->conn)));
355                 else
356                         g_value_set_object (value, NULL);
357                 break;
358         case PROP_TLS_ERRORS:
359                 g_value_set_flags (value, priv->tls_errors);
360                 break;
361         case PROP_PROXY_RESOLVER:
362                 g_value_set_object (value, priv->proxy_resolver);
363                 break;
364 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
365         case PROP_WIDGET_ENGINE:
366                 g_value_set_boolean (value, priv->widget_engine);
367                 break;
368 #endif
369         default:
370                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
371                 break;
372         }
373 }
374
375 static void
376 soup_socket_class_init (SoupSocketClass *socket_class)
377 {
378         GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
379
380         g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
381
382         /* virtual method override */
383         object_class->finalize = soup_socket_finalize;
384         object_class->set_property = soup_socket_set_property;
385         object_class->get_property = soup_socket_get_property;
386
387         /* signals */
388
389         /**
390          * SoupSocket::readable:
391          * @sock: the socket
392          *
393          * Emitted when an async socket is readable. See
394          * soup_socket_read(), soup_socket_read_until() and
395          * #SoupSocket:non-blocking.
396          **/
397         signals[READABLE] =
398                 g_signal_new ("readable",
399                               G_OBJECT_CLASS_TYPE (object_class),
400                               G_SIGNAL_RUN_LAST,
401                               G_STRUCT_OFFSET (SoupSocketClass, readable),
402                               NULL, NULL,
403                               NULL,
404                               G_TYPE_NONE, 0);
405
406         /**
407          * SoupSocket::writable:
408          * @sock: the socket
409          *
410          * Emitted when an async socket is writable. See
411          * soup_socket_write() and #SoupSocket:non-blocking.
412          **/
413         signals[WRITABLE] =
414                 g_signal_new ("writable",
415                               G_OBJECT_CLASS_TYPE (object_class),
416                               G_SIGNAL_RUN_LAST,
417                               G_STRUCT_OFFSET (SoupSocketClass, writable),
418                               NULL, NULL,
419                               NULL,
420                               G_TYPE_NONE, 0);
421
422         /**
423          * SoupSocket::disconnected:
424          * @sock: the socket
425          *
426          * Emitted when the socket is disconnected, for whatever
427          * reason.
428          **/
429         signals[DISCONNECTED] =
430                 g_signal_new ("disconnected",
431                               G_OBJECT_CLASS_TYPE (object_class),
432                               G_SIGNAL_RUN_LAST,
433                               G_STRUCT_OFFSET (SoupSocketClass, disconnected),
434                               NULL, NULL,
435                               NULL,
436                               G_TYPE_NONE, 0);
437
438         /**
439          * SoupSocket::new-connection:
440          * @sock: the socket
441          * @new: the new socket
442          *
443          * Emitted when a listening socket (set up with
444          * soup_socket_listen()) receives a new connection.
445          *
446          * You must ref the @new if you want to keep it; otherwise it
447          * will be destroyed after the signal is emitted.
448          **/
449         signals[NEW_CONNECTION] =
450                 g_signal_new ("new_connection",
451                               G_OBJECT_CLASS_TYPE (object_class),
452                               G_SIGNAL_RUN_FIRST,
453                               G_STRUCT_OFFSET (SoupSocketClass, new_connection),
454                               NULL, NULL,
455                               NULL,
456                               G_TYPE_NONE, 1,
457                               SOUP_TYPE_SOCKET);
458         /**
459          * SoupSocket::event:
460          * @sock: the socket
461          * @event: the event that occurred
462          * @connection: the current connection state
463          *
464          * Emitted when a network-related event occurs. See
465          * #GSocketClient::event for more details.
466          *
467          * Since: 2.38
468          **/
469         signals[EVENT] =
470                 g_signal_new ("event",
471                               G_OBJECT_CLASS_TYPE (object_class),
472                               G_SIGNAL_RUN_LAST,
473                               0,
474                               NULL, NULL,
475                               NULL,
476                               G_TYPE_NONE, 2,
477                               G_TYPE_SOCKET_CLIENT_EVENT,
478                               G_TYPE_IO_STREAM);
479
480 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
481         signals[DYNAMIC_CERTIFICATEPATH] =
482                 g_signal_new ("dynamic-certificatePath",
483                               G_OBJECT_CLASS_TYPE (object_class),
484                               G_SIGNAL_RUN_LAST,
485                               0,
486                               NULL, NULL,
487                               NULL,
488                               G_TYPE_POINTER, 1,
489                               G_TYPE_POINTER);
490 #endif
491 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
492         signals[ACCEPT_CERTIFICATE] =
493                 g_signal_new ("accept-certificate",
494                               G_OBJECT_CLASS_TYPE (object_class),
495                               G_SIGNAL_RUN_LAST,
496                               0,
497                               NULL, NULL,
498                               NULL,
499                               G_TYPE_BOOLEAN, 2,
500                               G_TYPE_TLS_CERTIFICATE,
501                               G_TYPE_TLS_CERTIFICATE_FLAGS);
502 #endif
503
504         /* properties */
505         /**
506          * SOUP_SOCKET_LOCAL_ADDRESS:
507          *
508          * Alias for the #SoupSocket:local-address property. (Address
509          * of local end of socket.)
510          **/
511         g_object_class_install_property (
512                 object_class, PROP_LOCAL_ADDRESS,
513                 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
514                                      "Local address",
515                                      "Address of local end of socket",
516                                      SOUP_TYPE_ADDRESS,
517                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
518         /**
519          * SOUP_SOCKET_REMOTE_ADDRESS:
520          *
521          * Alias for the #SoupSocket:remote-address property. (Address
522          * of remote end of socket.)
523          **/
524         g_object_class_install_property (
525                 object_class, PROP_REMOTE_ADDRESS,
526                 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
527                                      "Remote address",
528                                      "Address of remote end of socket",
529                                      SOUP_TYPE_ADDRESS,
530                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
531         /**
532          * SoupSocket:non-blocking:
533          *
534          * Whether or not the socket uses non-blocking I/O.
535          *
536          * #SoupSocket's I/O methods are designed around the idea of
537          * using a single codepath for both synchronous and
538          * asynchronous I/O. If you want to read off a #SoupSocket,
539          * the "correct" way to do it is to call soup_socket_read() or
540          * soup_socket_read_until() repeatedly until you have read
541          * everything you want. If it returns %SOUP_SOCKET_WOULD_BLOCK
542          * at any point, stop reading and wait for it to emit the
543          * #SoupSocket::readable signal. Then go back to the
544          * reading-as-much-as-you-can loop. Likewise, for writing to a
545          * #SoupSocket, you should call soup_socket_write() either
546          * until you have written everything, or it returns
547          * %SOUP_SOCKET_WOULD_BLOCK (in which case you wait for
548          * #SoupSocket::writable and then go back into the loop).
549          *
550          * Code written this way will work correctly with both
551          * blocking and non-blocking sockets; blocking sockets will
552          * simply never return %SOUP_SOCKET_WOULD_BLOCK, and so the
553          * code that handles that case just won't get used for them.
554          **/
555         /**
556          * SOUP_SOCKET_FLAG_NONBLOCKING:
557          *
558          * Alias for the #SoupSocket:non-blocking property. (Whether
559          * or not the socket uses non-blocking I/O.)
560          **/
561         g_object_class_install_property (
562                 object_class, PROP_NON_BLOCKING,
563                 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
564                                       "Non-blocking",
565                                       "Whether or not the socket uses non-blocking I/O",
566                                       TRUE,
567                                       G_PARAM_READWRITE));
568         /**
569          * SOUP_SOCKET_IS_SERVER:
570          *
571          * Alias for the #SoupSocket:is-server property. (Whether or
572          * not the socket is a server socket.)
573          **/
574         g_object_class_install_property (
575                 object_class, PROP_IS_SERVER,
576                 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
577                                       "Server",
578                                       "Whether or not the socket is a server socket",
579                                       FALSE,
580                                       G_PARAM_READABLE));
581         /**
582          * SOUP_SOCKET_SSL_CREDENTIALS:
583          *
584          * Alias for the #SoupSocket:ssl-creds property.
585          * (SSL credential information.)
586          **/
587         /* For historical reasons, there's only a single property
588          * here, which is a GTlsDatabase for client sockets, and
589          * a GTlsCertificate for server sockets. Whee!
590          */
591         g_object_class_install_property (
592                 object_class, PROP_SSL_CREDENTIALS,
593                 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
594                                       "SSL credentials",
595                                       "SSL credential information, passed from the session to the SSL implementation",
596                                       G_PARAM_READWRITE));
597         /**
598          * SOUP_SOCKET_SSL_STRICT:
599          *
600          * Alias for the #SoupSocket:ssl-strict property.
601          **/
602         g_object_class_install_property (
603                 object_class, PROP_SSL_STRICT,
604                 g_param_spec_boolean (SOUP_SOCKET_SSL_STRICT,
605                                       "Strictly validate SSL certificates",
606                                       "Whether certificate errors should be considered a connection error",
607                                       TRUE,
608                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
609         /**
610          * SOUP_SOCKET_SSL_FALLBACK:
611          *
612          * Alias for the #SoupSocket:ssl-fallback property.
613          **/
614         g_object_class_install_property (
615                 object_class, PROP_SSL_FALLBACK,
616                 g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK,
617                                       "SSLv3 fallback",
618                                       "Use SSLv3 instead of TLS (client-side only)",
619                                       FALSE,
620                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
621         /**
622          * SOUP_SOCKET_TRUSTED_CERTIFICATE:
623          *
624          * Alias for the #SoupSocket:trusted-certificate
625          * property.
626          **/
627         g_object_class_install_property (
628                 object_class, PROP_TRUSTED_CERTIFICATE,
629                 g_param_spec_boolean (SOUP_SOCKET_TRUSTED_CERTIFICATE,
630                                      "Trusted Certificate",
631                                      "Whether the server certificate is trusted, if this is an SSL socket",
632                                      FALSE,
633                                      G_PARAM_READABLE));
634         /**
635          * SOUP_SOCKET_ASYNC_CONTEXT:
636          *
637          * Alias for the #SoupSocket:async-context property. (The
638          * socket's #GMainContext.)
639          **/
640         g_object_class_install_property (
641                 object_class, PROP_ASYNC_CONTEXT,
642                 g_param_spec_pointer (SOUP_SOCKET_ASYNC_CONTEXT,
643                                       "Async GMainContext",
644                                       "The GMainContext to dispatch this socket's async I/O in",
645                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
646
647         /**
648          * SOUP_SOCKET_USE_THREAD_CONTEXT:
649          *
650          * Alias for the #SoupSocket:use-thread-context property. (Use
651          * g_main_context_get_thread_default())
652          *
653          * Since: 2.38
654          */
655         /**
656          * SoupSocket:use-thread-context:
657          *
658          * Use g_main_context_get_thread_default().
659          *
660          * Since: 2.38
661          */
662         g_object_class_install_property (
663                 object_class, PROP_USE_THREAD_CONTEXT,
664                 g_param_spec_boolean (SOUP_SOCKET_USE_THREAD_CONTEXT,
665                                       "Use thread context",
666                                       "Use g_main_context_get_thread_default",
667                                       FALSE,
668                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
669
670         /**
671          * SOUP_SOCKET_TIMEOUT:
672          *
673          * Alias for the #SoupSocket:timeout property. (The timeout
674          * in seconds for blocking socket I/O operations.)
675          **/
676         g_object_class_install_property (
677                 object_class, PROP_TIMEOUT,
678                 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
679                                    "Timeout value",
680                                    "Value in seconds to timeout a blocking I/O",
681                                    0, G_MAXUINT, 0,
682                                    G_PARAM_READWRITE));
683
684         g_object_class_install_property (
685                 object_class, PROP_CLEAN_DISPOSE,
686                 g_param_spec_boolean ("clean-dispose",
687                                       "Clean dispose",
688                                       "Warn on unclean dispose",
689                                       FALSE,
690                                       G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
691         /**
692          * SOUP_SOCKET_TLS_CERTIFICATE:
693          *
694          * Alias for the #SoupSocket:tls-certificate
695          * property. Note that this property's value is only useful
696          * if the socket is for a TLS connection, and only reliable
697          * after some data has been transferred to or from it.
698          *
699          * Since: 2.34
700          **/
701         g_object_class_install_property (
702                 object_class, PROP_TLS_CERTIFICATE,
703                 g_param_spec_object (SOUP_SOCKET_TLS_CERTIFICATE,
704                                      "TLS certificate",
705                                      "The peer's TLS certificate",
706                                      G_TYPE_TLS_CERTIFICATE,
707                                      G_PARAM_READABLE));
708         /**
709          * SOUP_SOCKET_TLS_ERRORS:
710          *
711          * Alias for the #SoupSocket:tls-errors
712          * property. Note that this property's value is only useful
713          * if the socket is for a TLS connection, and only reliable
714          * after some data has been transferred to or from it.
715          *
716          * Since: 2.34
717          **/
718         g_object_class_install_property (
719                 object_class, PROP_TLS_ERRORS,
720                 g_param_spec_flags (SOUP_SOCKET_TLS_ERRORS,
721                                     "TLS errors",
722                                     "Errors with the peer's TLS certificate",
723                                     G_TYPE_TLS_CERTIFICATE_FLAGS, 0,
724                                     G_PARAM_READABLE));
725
726         g_object_class_install_property (
727                 object_class, PROP_PROXY_RESOLVER,
728                 g_param_spec_object (SOUP_SOCKET_PROXY_RESOLVER,
729                                      "Proxy resolver",
730                                      "GProxyResolver to use",
731                                      G_TYPE_PROXY_RESOLVER,
732                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
733
734 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
735         /**
736          * SOUP_SOCKET_WIDGET_ENGINE:
737          *
738          * Alias for the #SoupSocket:widget-engine property.
739          **/
740         g_object_class_install_property (
741                 object_class, PROP_WIDGET_ENGINE,
742                 g_param_spec_boolean (SOUP_SOCKET_WIDGET_ENGINE,
743                                       "widget engine",
744                                       "Whether or not to be running Widget Engine",
745                                       FALSE,
746                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
747 #endif
748 }
749
750 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE) || ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
751 static GTlsCertificate *
752 soup_make_client_certificate(const gchar* cert_file, const gchar* key_file)
753 {
754         GTlsCertificate* cert = NULL;
755         GError* pGError = NULL;
756
757         if (access (cert_file, 4) == 0 && access (key_file, 4) == 0) {
758                 cert = g_tls_certificate_new_from_files (cert_file, key_file, &pGError);
759                 if (!cert) {
760                         if (pGError) {
761                                 g_warning ("Could not read SSL certificate from : %s", pGError->message);
762                                 g_error_free (pGError);
763                         }
764                 }
765         } else
766                 g_warning ("Could not acess cert=%s, key=%s\n", cert_file, key_file);
767
768         return cert;
769 }
770 #endif
771
772 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
773 static GTlsCertificate *
774 soup_get_client_certificate(SoupSocket *sock, const char* ssl_host, gchar*** cert_list, const char* client_cert_list)
775 {
776         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
777         GTlsCertificate* cert = NULL;
778         GError* pGError = NULL;
779         gsize cert_list_len;
780         gchar* cert_file = NULL;
781         gchar* key_file = NULL;
782         int i;
783
784         if (!ssl_host || !ssl_host[0] || !priv)
785                 return NULL;
786         if (!*cert_list) {
787                 gchar *cert_list_file = NULL;
788                 if (!g_file_get_contents (client_cert_list, &cert_list_file, &cert_list_len, &pGError) || pGError) {
789                         g_warning ("Could not get certificate list of [%s] : %s", client_cert_list, pGError->message);
790                         g_error_free (pGError);
791                         return NULL;
792                 }
793
794                 if (!cert_list_file)
795                         return NULL;
796                 /* keep certficate list's infomation */
797                 *cert_list = g_strsplit (cert_list_file, ",", 0);
798                 g_free (cert_list_file);
799         }
800
801         for (i = 0; (*cert_list)[i]; i++) {
802                 gchar **path = g_strsplit ((*cert_list)[i], ":", 0);
803
804                 /* verify format (url:certpath:keypath) */
805                 if (path[0] && path[1] && path[2]) {
806                         /* remove white space */
807                         g_strstrip(path[0]);
808                         g_strstrip(path[1]);
809                         g_strstrip(path[2]);
810                         /* compare url pattern */
811                         if (strstr (ssl_host, path[0]) || !g_strcmp0(path[0], "*")) {
812                                 cert_file = g_strdup (path[1]);
813                                 key_file =g_strdup (path[2]);
814                                 g_strfreev (path);
815                                 break;
816                         }
817                 }
818                 g_strfreev (path);
819         }
820
821         if (!cert_file || !key_file)
822                 return NULL;
823
824         cert = soup_make_client_certificate(cert_file, key_file);
825
826         g_free (cert_file);
827         g_free (key_file);
828         return cert;
829 }
830 #endif
831
832 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
833 static GTlsCertificate *soup_get_dynamic_client_certificate(SoupSocket *sock, const char* ssl_host)
834 {
835         const char* get_certpath = NULL;
836
837         g_signal_emit (sock, signals[DYNAMIC_CERTIFICATEPATH], 0, ssl_host, &get_certpath);
838         TIZEN_LOGI("Get Certpath[%s] \n", get_certpath);
839
840         if (!get_certpath)
841                 return NULL;
842
843         return soup_make_client_certificate(get_certpath, get_certpath);
844 }
845 #endif
846
847 /**
848  * soup_socket_new:
849  * @optname1: name of first property to set (or %NULL)
850  * @...: value of @optname1, followed by additional property/value pairs
851  *
852  * Creates a new (disconnected) socket
853  *
854  * Return value: the new socket
855  **/
856 SoupSocket *
857 soup_socket_new (const char *optname1, ...)
858 {
859         SoupSocket *sock;
860         va_list ap;
861
862         va_start (ap, optname1);
863         sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
864                                                   optname1, ap);
865         va_end (ap);
866
867         return sock;
868 }
869
870 static void
871 re_emit_socket_client_event (GSocketClient       *client,
872                              GSocketClientEvent   event,
873                              GSocketConnectable  *connectable,
874                              GIOStream           *connection,
875                              gpointer             user_data)
876 {
877         SoupSocket *sock = user_data;
878
879         g_signal_emit (sock, signals[EVENT], 0,
880                        event, connection);
881 }
882
883 static gboolean
884 socket_connect_finish (SoupSocket *sock, GSocketConnection *conn)
885 {
886         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
887
888         g_clear_object (&priv->connect_cancel);
889
890         if (conn) {
891                 priv->conn = (GIOStream *)conn;
892                 priv->gsock = g_object_ref (g_socket_connection_get_socket (conn));
893                 finish_socket_setup (priv);
894                 return TRUE;
895         } else
896                 return FALSE;
897 }
898
899 static guint
900 socket_legacy_error (SoupSocket *sock, GError *error)
901 {
902         guint status;
903
904         if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
905                 status = SOUP_STATUS_CANCELLED;
906         else if (error->domain == G_RESOLVER_ERROR)
907                 status = SOUP_STATUS_CANT_RESOLVE;
908         else
909                 status = SOUP_STATUS_CANT_CONNECT;
910
911         g_error_free (error);
912         return status;
913 }
914
915 static GSocketClient *
916 new_socket_client (SoupSocket *sock)
917 {
918         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
919         GSocketClient *client = g_socket_client_new ();
920
921         g_signal_connect (client, "event",
922                           G_CALLBACK (re_emit_socket_client_event), sock);
923         if (priv->proxy_resolver) {
924                 g_socket_client_set_proxy_resolver (client, priv->proxy_resolver);
925                 g_socket_client_add_application_proxy (client, "http");
926         } else
927                 g_socket_client_set_enable_proxy (client, FALSE);
928         if (priv->timeout)
929                 g_socket_client_set_timeout (client, priv->timeout);
930
931         if (priv->local_addr) {
932                 GSocketAddress *addr;
933
934                 addr = soup_address_get_gsockaddr (priv->local_addr);
935                 g_socket_client_set_local_address (client, addr);
936                 g_object_unref (addr);
937         }
938
939         return client;
940 }
941
942 static void
943 async_connected (GObject *client, GAsyncResult *result, gpointer data)
944 {
945         GTask *task = data;
946         SoupSocket *sock = g_task_get_source_object (task);
947         GSocketConnection *conn;
948         GError *error = NULL;
949
950         conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client),
951                                                result, &error);
952         if (socket_connect_finish (sock, conn))
953                 g_task_return_boolean (task, TRUE);
954         else
955                 g_task_return_error (task, error);
956         g_object_unref (task);
957 }
958
959 gboolean
960 soup_socket_connect_finish_internal (SoupSocket    *sock,
961                                      GAsyncResult  *result,
962                                      GError       **error)
963 {
964         return g_task_propagate_boolean (G_TASK (result), error);
965 }
966
967 void
968 soup_socket_connect_async_internal (SoupSocket          *sock,
969                                     GCancellable        *cancellable,
970                                     GAsyncReadyCallback  callback,
971                                     gpointer             user_data)
972 {
973         SoupSocketPrivate *priv;
974         GSocketClient *client;
975         GTask *task;
976
977         g_return_if_fail (SOUP_IS_SOCKET (sock));
978         priv = SOUP_SOCKET_GET_PRIVATE (sock);
979         g_return_if_fail (!priv->is_server);
980         g_return_if_fail (priv->gsock == NULL);
981         g_return_if_fail (priv->remote_addr != NULL);
982
983         priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
984         task = g_task_new (sock, priv->connect_cancel, callback, user_data);
985
986         client = new_socket_client (sock);
987         g_socket_client_connect_async (client,
988                                        G_SOCKET_CONNECTABLE (priv->remote_addr),
989                                        priv->connect_cancel,
990                                        async_connected, task);
991         g_object_unref (client);
992 }
993
994 /**
995  * SoupSocketCallback:
996  * @sock: the #SoupSocket
997  * @status: an HTTP status code indicating success or failure
998  * @user_data: the data passed to soup_socket_connect_async()
999  *
1000  * The callback function passed to soup_socket_connect_async().
1001  **/
1002
1003 typedef struct {
1004         SoupSocket *sock;
1005         SoupSocketCallback callback;
1006         gpointer user_data;
1007 } SoupSocketAsyncConnectData;
1008
1009 static void
1010 legacy_connect_async_cb (GObject       *object,
1011                          GAsyncResult  *result,
1012                          gpointer       user_data)
1013 {
1014         SoupSocket *sock = SOUP_SOCKET (object);
1015         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1016         SoupSocketAsyncConnectData *sacd = user_data;
1017         GError *error = NULL;
1018         guint status;
1019
1020         if (priv->async_context && !priv->use_thread_context)
1021                 g_main_context_pop_thread_default (priv->async_context);
1022
1023         if (soup_socket_connect_finish_internal (sock, result, &error))
1024                 status = SOUP_STATUS_OK;
1025         else
1026                 status = socket_legacy_error (sock, error);
1027
1028         sacd->callback (sock, status, sacd->user_data);
1029         g_object_unref (sacd->sock);
1030         g_slice_free (SoupSocketAsyncConnectData, sacd);
1031 }
1032
1033 /**
1034  * soup_socket_connect_async:
1035  * @sock: a client #SoupSocket (which must not already be connected)
1036  * @cancellable: a #GCancellable, or %NULL
1037  * @callback: (scope async): callback to call after connecting
1038  * @user_data: data to pass to @callback
1039  *
1040  * Begins asynchronously connecting to @sock's remote address. The
1041  * socket will call @callback when it succeeds or fails (but not
1042  * before returning from this function).
1043  *
1044  * If @cancellable is non-%NULL, it can be used to cancel the
1045  * connection. @callback will still be invoked in this case, with a
1046  * status of %SOUP_STATUS_CANCELLED.
1047  **/
1048 void
1049 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
1050                            SoupSocketCallback callback, gpointer user_data)
1051 {
1052         SoupSocketPrivate *priv;
1053         SoupSocketAsyncConnectData *sacd;
1054
1055         g_return_if_fail (SOUP_IS_SOCKET (sock));
1056         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1057         g_return_if_fail (!priv->is_server);
1058         g_return_if_fail (priv->gsock == NULL);
1059         g_return_if_fail (priv->remote_addr != NULL);
1060
1061         sacd = g_slice_new0 (SoupSocketAsyncConnectData);
1062         sacd->sock = g_object_ref (sock);
1063         sacd->callback = callback;
1064         sacd->user_data = user_data;
1065
1066         if (priv->async_context && !priv->use_thread_context)
1067                 g_main_context_push_thread_default (priv->async_context);
1068
1069         soup_socket_connect_async_internal (sock, cancellable,
1070                                             legacy_connect_async_cb,
1071                                             sacd);
1072 }
1073
1074 gboolean
1075 soup_socket_connect_sync_internal (SoupSocket    *sock,
1076                                    GCancellable  *cancellable,
1077                                    GError       **error)
1078 {
1079         SoupSocketPrivate *priv;
1080         GSocketClient *client;
1081         GSocketConnection *conn;
1082
1083         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
1084         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1085         g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
1086         g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
1087         g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
1088
1089         priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
1090
1091         client = new_socket_client (sock);
1092         conn = g_socket_client_connect (client,
1093                                         G_SOCKET_CONNECTABLE (priv->remote_addr),
1094                                         priv->connect_cancel, error);
1095         g_object_unref (client);
1096
1097         return socket_connect_finish (sock, conn);
1098 }
1099
1100 /**
1101  * soup_socket_connect_sync:
1102  * @sock: a client #SoupSocket (which must not already be connected)
1103  * @cancellable: a #GCancellable, or %NULL
1104  *
1105  * Attempt to synchronously connect @sock to its remote address.
1106  *
1107  * If @cancellable is non-%NULL, it can be used to cancel the
1108  * connection, in which case soup_socket_connect_sync() will return
1109  * %SOUP_STATUS_CANCELLED.
1110  *
1111  * Return value: a success or failure code.
1112  **/
1113 guint
1114 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
1115 {
1116         SoupSocketPrivate *priv;
1117         GError *error = NULL;
1118
1119         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_STATUS_MALFORMED);
1120         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1121         g_return_val_if_fail (!priv->is_server, SOUP_STATUS_MALFORMED);
1122         g_return_val_if_fail (priv->gsock == NULL, SOUP_STATUS_MALFORMED);
1123         g_return_val_if_fail (priv->remote_addr != NULL, SOUP_STATUS_MALFORMED);
1124
1125         if (soup_socket_connect_sync_internal (sock, cancellable, &error))
1126                 return SOUP_STATUS_OK;
1127         else
1128                 return socket_legacy_error (sock, error);
1129 }
1130
1131 /**
1132  * soup_socket_get_fd:
1133  * @sock: a #SoupSocket
1134  *
1135  * Gets @sock's underlying file descriptor.
1136  *
1137  * Note that fiddling with the file descriptor may break the
1138  * #SoupSocket.
1139  *
1140  * Return value: @sock's file descriptor.
1141  */
1142 int
1143 soup_socket_get_fd (SoupSocket *sock)
1144 {
1145         g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
1146
1147         return g_socket_get_fd (SOUP_SOCKET_GET_PRIVATE (sock)->gsock);
1148 }
1149
1150 GSocket *
1151 soup_socket_get_gsocket (SoupSocket *sock)
1152 {
1153         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1154
1155         return SOUP_SOCKET_GET_PRIVATE (sock)->gsock;
1156 }
1157
1158 GIOStream *
1159 soup_socket_get_connection (SoupSocket *sock)
1160 {
1161         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1162
1163         return SOUP_SOCKET_GET_PRIVATE (sock)->conn;
1164 }
1165
1166 GIOStream *
1167 soup_socket_get_iostream (SoupSocket *sock)
1168 {
1169         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1170
1171         return SOUP_SOCKET_GET_PRIVATE (sock)->iostream;
1172 }
1173
1174 static GSource *
1175 soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond,
1176                           GPollableSourceFunc callback, gpointer user_data,
1177                           GCancellable *cancellable)
1178 {
1179         GSource *watch;
1180         GMainContext *async_context;
1181
1182         if (cond == G_IO_IN)
1183                 watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable);
1184         else
1185                 watch = g_pollable_output_stream_create_source (G_POLLABLE_OUTPUT_STREAM (priv->ostream), cancellable);
1186         g_source_set_callback (watch, (GSourceFunc)callback, user_data, NULL);
1187
1188         if (priv->use_thread_context)
1189                 async_context = g_main_context_get_thread_default ();
1190         else
1191                 async_context = priv->async_context;
1192
1193         g_source_attach (watch, async_context);
1194         g_source_unref (watch);
1195
1196         return watch;
1197 }
1198
1199 static gboolean
1200 listen_watch (GObject *pollable, gpointer data)
1201 {
1202         SoupSocket *sock = data, *new;
1203         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
1204         GSocket *new_gsock;
1205
1206         new_gsock = g_socket_accept (priv->gsock, NULL, NULL);
1207         if (!new_gsock)
1208                 return FALSE;
1209
1210         new = g_object_new (SOUP_TYPE_SOCKET, NULL);
1211         new_priv = SOUP_SOCKET_GET_PRIVATE (new);
1212         new_priv->gsock = new_gsock;
1213         if (priv->async_context)
1214                 new_priv->async_context = g_main_context_ref (priv->async_context);
1215         new_priv->use_thread_context = priv->use_thread_context;
1216         new_priv->non_blocking = priv->non_blocking;
1217         new_priv->is_server = TRUE;
1218         new_priv->ssl = priv->ssl;
1219         if (priv->ssl_creds)
1220                 new_priv->ssl_creds = priv->ssl_creds;
1221         finish_socket_setup (new_priv);
1222
1223         if (new_priv->ssl_creds) {
1224                 if (!soup_socket_start_proxy_ssl (new, NULL, NULL)) {
1225                         g_object_unref (new);
1226                         return TRUE;
1227                 }
1228         }
1229
1230         g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
1231         g_object_unref (new);
1232
1233         return TRUE;
1234 }
1235
1236 /**
1237  * soup_socket_listen:
1238  * @sock: a server #SoupSocket (which must not already be connected or
1239  * listening)
1240  *
1241  * Makes @sock start listening on its local address. When connections
1242  * come in, @sock will emit #SoupSocket::new_connection.
1243  *
1244  * Return value: whether or not @sock is now listening.
1245  **/
1246 gboolean
1247 soup_socket_listen (SoupSocket *sock)
1248
1249 {
1250         SoupSocketPrivate *priv;
1251         GSocketAddress *addr;
1252
1253         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1254         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1255         g_return_val_if_fail (priv->gsock == NULL, FALSE);
1256         g_return_val_if_fail (priv->local_addr != NULL, FALSE);
1257
1258         priv->is_server = TRUE;
1259
1260         /* @local_addr may have its port set to 0. So we intentionally
1261          * don't store it in priv->local_addr, so that if the
1262          * caller calls soup_socket_get_local_address() later, we'll
1263          * have to make a new addr by calling getsockname(), which
1264          * will have the right port number.
1265          */
1266         addr = soup_address_get_gsockaddr (priv->local_addr);
1267         g_return_val_if_fail (addr != NULL, FALSE);
1268
1269         priv->gsock = g_socket_new (g_socket_address_get_family (addr),
1270                                     G_SOCKET_TYPE_STREAM,
1271                                     G_SOCKET_PROTOCOL_DEFAULT,
1272                                     NULL);
1273         if (!priv->gsock)
1274                 goto cant_listen;
1275         finish_socket_setup (priv);
1276
1277         /* Bind */
1278         if (!g_socket_bind (priv->gsock, addr, TRUE, NULL))
1279                 goto cant_listen;
1280         /* Force local_addr to be re-resolved now */
1281         g_object_unref (priv->local_addr);
1282         priv->local_addr = NULL;
1283
1284         /* Listen */
1285         if (!g_socket_listen (priv->gsock, NULL))
1286                 goto cant_listen;
1287
1288         priv->watch_src = soup_socket_create_watch (priv, G_IO_IN,
1289                                                     listen_watch, sock,
1290                                                     NULL);
1291         g_object_unref (addr);
1292         return TRUE;
1293
1294  cant_listen:
1295         if (priv->conn)
1296                 disconnect_internal (sock, TRUE);
1297         g_object_unref (addr);
1298
1299         return FALSE;
1300 }
1301
1302 static void
1303 soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec,
1304                                       gpointer sock)
1305 {
1306         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1307
1308 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
1309         if (!priv->acceptedCertificate)
1310                 priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn));
1311 #else
1312         priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn));
1313 #endif
1314
1315         g_object_notify (sock, "tls-certificate");
1316         g_object_notify (sock, "tls-errors");
1317 }
1318
1319 static gboolean
1320 soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert,
1321                                 GTlsCertificateFlags errors, gpointer sock)
1322 {
1323 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
1324         gboolean accept = FALSE;
1325         SoupSocket *soupSock = sock;
1326         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (soupSock);
1327
1328         if (priv) {
1329 #if ENABLE(TIZEN_DLOG)
1330                 TIZEN_LOGI("[Accept_Certificate] Certificate warning code is [%d], address is [%s]\n", errors, soup_address_get_name (priv->remote_addr));
1331 #endif
1332                 g_signal_emit (sock, signals[ACCEPT_CERTIFICATE], 0, cert, errors, &accept);
1333 #if ENABLE(TIZEN_DLOG)
1334                 TIZEN_LOGI("[Accept_Certificate] Result is [%d].(1:ignore error; 0:not ignore)\n", accept);
1335 #endif
1336                 priv->acceptedCertificate = accept;
1337         }
1338         return accept;
1339 #else
1340         return TRUE;
1341 #endif
1342 }
1343
1344 static gboolean
1345 soup_socket_setup_ssl (SoupSocket    *sock,
1346                        const char    *ssl_host,
1347                        GCancellable  *cancellable,
1348                        GError       **error)
1349 {
1350         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1351         GTlsBackend *backend = g_tls_backend_get_default ();
1352
1353         if (G_IS_TLS_CONNECTION (priv->conn))
1354                 return TRUE;
1355
1356         if (g_cancellable_set_error_if_cancelled (cancellable, error))
1357                 return FALSE;
1358
1359         priv->ssl = TRUE;
1360
1361         if (!priv->is_server) {
1362                 GTlsClientConnection *conn;
1363                 GSocketConnectable *identity;
1364 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE) || ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
1365                 GTlsCertificate *cert=NULL;
1366 #endif
1367                 identity = g_network_address_new (ssl_host, 0);
1368
1369 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
1370                 if (!(cert = soup_get_dynamic_client_certificate (sock, ssl_host)))
1371 #endif
1372 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
1373                         if (!priv->widget_engine || !(cert = soup_get_client_certificate(sock, ssl_host, &priv->cert_lists, CERT_LIST_FILE)))
1374                                         cert = soup_get_client_certificate(sock, ssl_host, &priv->default_cert_lists, DEFAULT_CERT_FILE);
1375 #endif
1376
1377 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE) || ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
1378                 if (cert) {
1379                         conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
1380                                                        cancellable, error,
1381                                                        "base-io-stream", priv->conn,
1382                                                        "server-identity", identity,
1383                                                        "database", priv->ssl_creds,
1384                                                        "certificate", cert,
1385                                                        "require-close-notify", FALSE,
1386                                                        "use-ssl3", FALSE,
1387                                                        NULL);
1388
1389                         g_object_unref (cert);
1390                 }
1391                 else
1392 #endif
1393                         conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
1394                                                        cancellable, error,
1395                                                        "base-io-stream", priv->conn,
1396                                                        "server-identity", identity,
1397                                                        "database", priv->ssl_creds,
1398                                                        "require-close-notify", FALSE,
1399                                                        "use-ssl3", priv->ssl_fallback,
1400                                                        NULL);
1401
1402                 g_object_unref (identity);
1403
1404                 if (!conn)
1405                         return FALSE;
1406
1407                 g_object_unref (priv->conn);
1408                 priv->conn = G_IO_STREAM (conn);
1409
1410                 if (!priv->ssl_strict) {
1411                         g_signal_connect (conn, "accept-certificate",
1412                                           G_CALLBACK (soup_socket_accept_certificate),
1413                                           sock);
1414                 }
1415         } else {
1416                 GTlsServerConnection *conn;
1417
1418                 conn = g_initable_new (g_tls_backend_get_server_connection_type (backend),
1419                                        cancellable, error,
1420                                        "base-io-stream", priv->conn,
1421                                        "certificate", priv->ssl_creds,
1422                                        "use-system-certdb", FALSE,
1423                                        "require-close-notify", FALSE,
1424                                        NULL);
1425                 if (!conn)
1426                         return FALSE;
1427
1428                 g_object_unref (priv->conn);
1429                 priv->conn = G_IO_STREAM (conn);
1430         }
1431
1432         g_signal_connect (priv->conn, "notify::peer-certificate",
1433                           G_CALLBACK (soup_socket_peer_certificate_changed), sock);
1434
1435         g_clear_object (&priv->istream);
1436         g_clear_object (&priv->ostream);
1437         g_clear_object (&priv->iostream);
1438         priv->iostream = soup_io_stream_new (priv->conn, FALSE);
1439         priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
1440         priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
1441
1442         return TRUE;
1443 }
1444
1445 /**
1446  * soup_socket_start_ssl:
1447  * @sock: the socket
1448  * @cancellable: a #GCancellable
1449  *
1450  * Starts using SSL on @socket.
1451  *
1452  * Return value: success or failure
1453  **/
1454 gboolean
1455 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
1456 {
1457         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1458
1459         return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr),
1460                                       cancellable, NULL);
1461 }
1462         
1463 /**
1464  * soup_socket_start_proxy_ssl:
1465  * @sock: the socket
1466  * @ssl_host: hostname of the SSL server
1467  * @cancellable: a #GCancellable
1468  *
1469  * Starts using SSL on @socket, expecting to find a host named
1470  * @ssl_host.
1471  *
1472  * Return value: success or failure
1473  **/
1474 gboolean
1475 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
1476                              GCancellable *cancellable)
1477 {
1478         return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL);
1479 }
1480
1481 gboolean
1482 soup_socket_handshake_sync (SoupSocket    *sock,
1483                             const char    *ssl_host,
1484                             GCancellable  *cancellable,
1485                             GError       **error)
1486 {
1487         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1488
1489         if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error))
1490                 return FALSE;
1491
1492         return g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn),
1493                                            cancellable, error);
1494 }
1495
1496 static void
1497 handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data)
1498 {
1499         GTask *task = user_data;
1500         GError *error = NULL;
1501
1502         if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source),
1503                                                result, &error))
1504                 g_task_return_boolean (task, TRUE);
1505         else
1506                 g_task_return_error (task, error);
1507         g_object_unref (task);
1508 }
1509
1510 void
1511 soup_socket_handshake_async (SoupSocket          *sock,
1512                              const char          *ssl_host,
1513                              GCancellable        *cancellable,
1514                              GAsyncReadyCallback  callback,
1515                              gpointer             user_data)
1516 {
1517         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1518         GTask *task;
1519         GError *error = NULL;
1520
1521 #if ENABLE(TIZEN_PERFORMANCE_TEST_LOG)
1522         prctl_with_url("[EVT] soup handshake start : ", soup_address_get_name(priv->remote_addr));
1523 #endif
1524         task = g_task_new (sock, cancellable, callback, user_data);
1525
1526         if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) {
1527                 g_task_return_error (task, error);
1528                 g_object_unref (task);
1529                 return;
1530         }
1531
1532         g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn),
1533                                           G_PRIORITY_DEFAULT,
1534                                           cancellable, handshake_async_ready,
1535                                           task);
1536 }
1537
1538 gboolean
1539 soup_socket_handshake_finish (SoupSocket    *sock,
1540                               GAsyncResult  *result,
1541                               GError       **error)
1542 {
1543         return g_task_propagate_boolean (G_TASK (result), error);
1544 }
1545
1546 /**
1547  * soup_socket_is_ssl:
1548  * @sock: a #SoupSocket
1549  *
1550  * Tests if @sock is doing (or has attempted to do) SSL.
1551  *
1552  * Return value: %TRUE if @sock has SSL credentials set
1553  **/
1554 gboolean
1555 soup_socket_is_ssl (SoupSocket *sock)
1556 {
1557 #if ENABLE(TIZEN_CHECK_SOCKET_EXISTS_BEFORE_USE_IT)
1558         SoupSocketPrivate *priv;
1559         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1560         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1561 #else
1562         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1563 #endif
1564
1565         return priv->ssl;
1566 }
1567
1568 /**
1569  * soup_socket_disconnect:
1570  * @sock: a #SoupSocket
1571  *
1572  * Disconnects @sock. Any further read or write attempts on it will
1573  * fail.
1574  **/
1575 void
1576 soup_socket_disconnect (SoupSocket *sock)
1577 {
1578         SoupSocketPrivate *priv;
1579         gboolean already_disconnected = FALSE;
1580
1581         g_return_if_fail (SOUP_IS_SOCKET (sock));
1582         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1583
1584         if (priv->connect_cancel) {
1585                 disconnect_internal (sock, FALSE);
1586                 g_cancellable_cancel (priv->connect_cancel);
1587                 return;
1588         } else if (g_mutex_trylock (&priv->iolock)) {
1589                 if (priv->gsock)
1590                         disconnect_internal (sock, TRUE);
1591                 else
1592                         already_disconnected = TRUE;
1593                 g_mutex_unlock (&priv->iolock);
1594         } else {
1595                 /* Another thread is currently doing IO, so
1596                  * we can't close the socket. So just shutdown
1597                  * the file descriptor to force the I/O to fail.
1598                  * (It will actually be closed when the socket
1599                  * is destroyed.)
1600                  */
1601                 g_socket_shutdown (priv->gsock, TRUE, TRUE, NULL);
1602         }
1603
1604         if (already_disconnected)
1605                 return;
1606
1607         /* Keep ref around signals in case the object is unreferenced
1608          * in a handler
1609          */
1610         g_object_ref (sock);
1611
1612         if (priv->non_blocking) {
1613                 /* Give all readers a chance to notice the connection close */
1614                 g_signal_emit (sock, signals[READABLE], 0);
1615         }
1616
1617         /* FIXME: can't disconnect until all data is read */
1618
1619         /* Then let everyone know we're disconnected */
1620         g_signal_emit (sock, signals[DISCONNECTED], 0);
1621
1622         g_object_unref (sock);
1623 }
1624
1625 /**
1626  * soup_socket_is_connected:
1627  * @sock: a #SoupSocket
1628  *
1629  * Tests if @sock is connected to another host
1630  *
1631  * Return value: %TRUE or %FALSE.
1632  **/
1633 gboolean
1634 soup_socket_is_connected (SoupSocket *sock)
1635 {
1636         SoupSocketPrivate *priv;
1637
1638         g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1639         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1640
1641         return priv->conn && !g_io_stream_is_closed (priv->conn);
1642 }
1643
1644 /**
1645  * soup_socket_get_local_address:
1646  * @sock: a #SoupSocket
1647  *
1648  * Returns the #SoupAddress corresponding to the local end of @sock.
1649  *
1650  * Calling this method on an unconnected socket is considered to be
1651  * an error, and produces undefined results.
1652  *
1653  * Return value: (transfer none): the #SoupAddress
1654  **/
1655 SoupAddress *
1656 soup_socket_get_local_address (SoupSocket *sock)
1657 {
1658         SoupSocketPrivate *priv;
1659
1660         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1661         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1662
1663         g_mutex_lock (&priv->addrlock);
1664         if (!priv->local_addr) {
1665                 GSocketAddress *addr;
1666                 struct sockaddr_storage sa;
1667                 gssize sa_len;
1668                 GError *error = NULL;
1669
1670                 if (priv->gsock == NULL) {
1671                         g_warning ("%s: socket not connected", G_STRLOC);
1672                         goto unlock;
1673                 }
1674
1675                 addr = g_socket_get_local_address (priv->gsock, &error);
1676                 if (addr == NULL) {
1677                         g_warning ("%s: %s", G_STRLOC, error->message);
1678                         g_error_free (error);
1679                         goto unlock;
1680                 }
1681                 sa_len = g_socket_address_get_native_size (addr);
1682                 g_socket_address_to_native (addr, &sa, sa_len, NULL);
1683                 priv->local_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
1684                 g_object_unref (addr);
1685         }
1686 unlock:
1687         g_mutex_unlock (&priv->addrlock);
1688
1689         return priv->local_addr;
1690 }
1691
1692 /**
1693  * soup_socket_get_remote_address:
1694  * @sock: a #SoupSocket
1695  *
1696  * Returns the #SoupAddress corresponding to the remote end of @sock.
1697  *
1698  * Calling this method on an unconnected socket is considered to be
1699  * an error, and produces undefined results.
1700  *
1701  * Return value: (transfer none): the #SoupAddress
1702  **/
1703 SoupAddress *
1704 soup_socket_get_remote_address (SoupSocket *sock)
1705 {
1706         SoupSocketPrivate *priv;
1707
1708         g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1709         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1710
1711         g_mutex_lock (&priv->addrlock);
1712         if (!priv->remote_addr) {
1713                 GSocketAddress *addr;
1714                 struct sockaddr_storage sa;
1715                 gssize sa_len;
1716                 GError *error = NULL;
1717
1718                 if (priv->gsock == NULL) {
1719                         g_warning ("%s: socket not connected", G_STRLOC);
1720                         goto unlock;
1721                 }
1722
1723                 addr = g_socket_get_remote_address (priv->gsock, &error);
1724                 if (addr == NULL) {
1725                         g_warning ("%s: %s", G_STRLOC, error->message);
1726                         g_error_free (error);
1727                         goto unlock;
1728                 }
1729                 sa_len = g_socket_address_get_native_size (addr);
1730                 g_socket_address_to_native (addr, &sa, sa_len, NULL);
1731                 priv->remote_addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa, sa_len);
1732                 g_object_unref (addr);
1733         }
1734 unlock:
1735         g_mutex_unlock (&priv->addrlock);
1736
1737         return priv->remote_addr;
1738 }
1739
1740 SoupURI *
1741 soup_socket_get_http_proxy_uri (SoupSocket *sock)
1742 {
1743         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1744         GSocketAddress *addr;
1745         GProxyAddress *paddr;
1746         SoupURI *uri;
1747
1748         if (!priv->gsock)
1749                 return NULL;
1750         addr = g_socket_get_remote_address (priv->gsock, NULL);
1751         if (!addr || !G_IS_PROXY_ADDRESS (addr)) {
1752                 if (addr)
1753                         g_object_unref (addr);
1754                 return NULL;
1755         }
1756
1757         paddr = G_PROXY_ADDRESS (addr);
1758         if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0)
1759                 return NULL;
1760
1761         uri = soup_uri_new (g_proxy_address_get_uri (paddr));
1762         g_object_unref (addr);
1763         return uri;
1764 }
1765
1766 static gboolean
1767 socket_read_watch (GObject *pollable, gpointer user_data)
1768 {
1769         SoupSocket *sock = user_data;
1770         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1771
1772         priv->read_src = NULL;
1773         g_signal_emit (sock, signals[READABLE], 0);
1774         return FALSE;
1775 }
1776
1777 static SoupSocketIOStatus
1778 translate_read_status (SoupSocket *sock, GCancellable *cancellable,
1779                        gssize my_nread, gsize *nread,
1780                        GError *my_err, GError **error)
1781 {
1782         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1783
1784         if (my_nread > 0) {
1785                 g_assert_no_error (my_err);
1786                 *nread = my_nread;
1787                 return SOUP_SOCKET_OK;
1788         } else if (my_nread == 0) {
1789                 g_assert_no_error (my_err);
1790                 *nread = my_nread;
1791                 return SOUP_SOCKET_EOF;
1792         } else if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
1793                 g_clear_error (&my_err);
1794                 if (!priv->read_src) {
1795                         priv->read_src =
1796                                 soup_socket_create_watch (priv, G_IO_IN,
1797                                                           socket_read_watch, sock,
1798                                                           cancellable);
1799                 }
1800                 return SOUP_SOCKET_WOULD_BLOCK;
1801         }
1802
1803         g_propagate_error (error, my_err);
1804         return SOUP_SOCKET_ERROR;
1805 }
1806
1807 /**
1808  * SoupSocketIOStatus:
1809  * @SOUP_SOCKET_OK: Success
1810  * @SOUP_SOCKET_WOULD_BLOCK: Cannot read/write any more at this time
1811  * @SOUP_SOCKET_EOF: End of file
1812  * @SOUP_SOCKET_ERROR: Other error
1813  *
1814  * Return value from the #SoupSocket IO methods.
1815  **/
1816
1817 /**
1818  * soup_socket_read:
1819  * @sock: the socket
1820  * @buffer: buffer to read into
1821  * @len: size of @buffer in bytes
1822  * @nread: (out): on return, the number of bytes read into @buffer
1823  * @cancellable: a #GCancellable, or %NULL
1824  * @error: error pointer
1825  *
1826  * Attempts to read up to @len bytes from @sock into @buffer. If some
1827  * data is successfully read, soup_socket_read() will return
1828  * %SOUP_SOCKET_OK, and *@nread will contain the number of bytes
1829  * actually read (which may be less than @len).
1830  *
1831  * If @sock is non-blocking, and no data is available, the return
1832  * value will be %SOUP_SOCKET_WOULD_BLOCK. In this case, the caller
1833  * can connect to the #SoupSocket::readable signal to know when there
1834  * is more data to read. (NB: You MUST read all available data off the
1835  * socket first. #SoupSocket::readable is only emitted after
1836  * soup_socket_read() returns %SOUP_SOCKET_WOULD_BLOCK, and it is only
1837  * emitted once. See the documentation for #SoupSocket:non-blocking.)
1838  *
1839  * Return value: a #SoupSocketIOStatus, as described above (or
1840  * %SOUP_SOCKET_EOF if the socket is no longer connected, or
1841  * %SOUP_SOCKET_ERROR on any other error, in which case @error will
1842  * also be set).
1843  **/
1844 SoupSocketIOStatus
1845 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1846                   gsize *nread, GCancellable *cancellable, GError **error)
1847 {
1848         SoupSocketPrivate *priv;
1849         SoupSocketIOStatus status;
1850         gssize my_nread;
1851         GError *my_err = NULL;
1852
1853         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1854         g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1855
1856         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1857
1858         g_mutex_lock (&priv->iolock);
1859
1860         if (!priv->istream) {
1861                 status = SOUP_SOCKET_EOF;
1862                 goto out;
1863         }
1864
1865         if (!priv->non_blocking) {
1866                 my_nread = g_input_stream_read (priv->istream, buffer, len,
1867                                                 cancellable, &my_err);
1868         } else {
1869                 my_nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (priv->istream),
1870                                                                      buffer, len,
1871                                                                      cancellable, &my_err);
1872         }
1873         status = translate_read_status (sock, cancellable,
1874                                         my_nread, nread, my_err, error);
1875
1876 out:
1877         g_mutex_unlock (&priv->iolock);
1878
1879         return status;
1880 }
1881
1882 /**
1883  * soup_socket_read_until:
1884  * @sock: the socket
1885  * @buffer: buffer to read into
1886  * @len: size of @buffer in bytes
1887  * @boundary: boundary to read until
1888  * @boundary_len: length of @boundary in bytes
1889  * @nread: (out): on return, the number of bytes read into @buffer
1890  * @got_boundary: on return, whether or not the data in @buffer
1891  * ends with the boundary string
1892  * @cancellable: a #GCancellable, or %NULL
1893  * @error: error pointer
1894  *
1895  * Like soup_socket_read(), but reads no further than the first
1896  * occurrence of @boundary. (If the boundary is found, it will be
1897  * included in the returned data, and *@got_boundary will be set to
1898  * %TRUE.) Any data after the boundary will returned in future reads.
1899  *
1900  * soup_socket_read_until() will almost always return fewer than @len
1901  * bytes: if the boundary is found, then it will only return the bytes
1902  * up until the end of the boundary, and if the boundary is not found,
1903  * then it will leave the last <literal>(boundary_len - 1)</literal>
1904  * bytes in its internal buffer, in case they form the start of the
1905  * boundary string. Thus, @len normally needs to be at least 1 byte
1906  * longer than @boundary_len if you want to make any progress at all.
1907  *
1908  * Return value: as for soup_socket_read()
1909  **/
1910 SoupSocketIOStatus
1911 soup_socket_read_until (SoupSocket *sock, gpointer buffer, gsize len,
1912                         gconstpointer boundary, gsize boundary_len,
1913                         gsize *nread, gboolean *got_boundary,
1914                         GCancellable *cancellable, GError **error)
1915 {
1916         SoupSocketPrivate *priv;
1917         SoupSocketIOStatus status;
1918         gssize my_nread;
1919         GError *my_err = NULL;
1920
1921         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1922         g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1923         g_return_val_if_fail (len >= boundary_len, SOUP_SOCKET_ERROR);
1924
1925         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1926
1927         g_mutex_lock (&priv->iolock);
1928
1929         *got_boundary = FALSE;
1930
1931         if (!priv->istream)
1932                 status = SOUP_SOCKET_EOF;
1933         else {
1934                 my_nread = soup_filter_input_stream_read_until (
1935                         SOUP_FILTER_INPUT_STREAM (priv->istream),
1936                         buffer, len, boundary, boundary_len,
1937                         !priv->non_blocking,
1938                         TRUE, got_boundary, cancellable, &my_err);
1939                 status = translate_read_status (sock, cancellable,
1940                                                 my_nread, nread, my_err, error);
1941         }
1942
1943         g_mutex_unlock (&priv->iolock);
1944         return status;
1945 }
1946
1947 static gboolean
1948 socket_write_watch (GObject *pollable, gpointer user_data)
1949 {
1950         SoupSocket *sock = user_data;
1951         SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1952
1953         priv->write_src = NULL;
1954         g_signal_emit (sock, signals[WRITABLE], 0);
1955         return FALSE;
1956 }
1957
1958 /**
1959  * soup_socket_write:
1960  * @sock: the socket
1961  * @buffer: data to write
1962  * @len: size of @buffer, in bytes
1963  * @nwrote: (out): on return, number of bytes written
1964  * @cancellable: a #GCancellable, or %NULL
1965  * @error: error pointer
1966  *
1967  * Attempts to write @len bytes from @buffer to @sock. If some data is
1968  * successfully written, the return status will be %SOUP_SOCKET_OK,
1969  * and *@nwrote will contain the number of bytes actually written
1970  * (which may be less than @len).
1971  *
1972  * If @sock is non-blocking, and no data could be written right away,
1973  * the return value will be %SOUP_SOCKET_WOULD_BLOCK. In this case,
1974  * the caller can connect to the #SoupSocket::writable signal to know
1975  * when more data can be written. (NB: #SoupSocket::writable is only
1976  * emitted after soup_socket_write() returns %SOUP_SOCKET_WOULD_BLOCK,
1977  * and it is only emitted once. See the documentation for
1978  * #SoupSocket:non-blocking.)
1979  *
1980  * Return value: a #SoupSocketIOStatus, as described above (or
1981  * %SOUP_SOCKET_EOF or %SOUP_SOCKET_ERROR. @error will be set if the
1982  * return value is %SOUP_SOCKET_ERROR.)
1983  **/
1984 SoupSocketIOStatus
1985 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1986                    gsize len, gsize *nwrote,
1987                    GCancellable *cancellable, GError **error)
1988 {
1989         SoupSocketPrivate *priv;
1990         GError *my_err = NULL;
1991         gssize my_nwrote;
1992
1993         g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1994         g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
1995
1996         priv = SOUP_SOCKET_GET_PRIVATE (sock);
1997
1998         g_mutex_lock (&priv->iolock);
1999
2000         if (!priv->conn) {
2001                 g_mutex_unlock (&priv->iolock);
2002                 return SOUP_SOCKET_EOF;
2003         }
2004         if (priv->write_src) {
2005                 g_mutex_unlock (&priv->iolock);
2006                 return SOUP_SOCKET_WOULD_BLOCK;
2007         }
2008
2009         if (!priv->non_blocking) {
2010                 my_nwrote = g_output_stream_write (priv->ostream,
2011                                                    buffer, len,
2012                                                    cancellable, &my_err);
2013         } else {
2014                 my_nwrote = g_pollable_output_stream_write_nonblocking (
2015                         G_POLLABLE_OUTPUT_STREAM (priv->ostream),
2016                         buffer, len, cancellable, &my_err);
2017         }
2018
2019         if (my_nwrote > 0) {
2020                 g_mutex_unlock (&priv->iolock);
2021                 g_clear_error (&my_err);
2022                 *nwrote = my_nwrote;
2023                 return SOUP_SOCKET_OK;
2024         }
2025
2026         if (g_error_matches (my_err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
2027                 g_mutex_unlock (&priv->iolock);
2028                 g_clear_error (&my_err);
2029
2030                 priv->write_src =
2031                         soup_socket_create_watch (priv,
2032                                                   G_IO_OUT,
2033                                                   socket_write_watch, sock, cancellable);
2034                 return SOUP_SOCKET_WOULD_BLOCK;
2035         }
2036
2037         g_mutex_unlock (&priv->iolock);
2038         g_propagate_error (error, my_err);
2039         return SOUP_SOCKET_ERROR;
2040 }