1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-socket.c: Socket networking code.
5 * Copyright (C) 2000-2003, Ximian, Inc.
14 #include <gio/gnetworking.h>
16 #include "soup-socket.h"
18 #include "soup-filter-input-stream.h"
19 #include "soup-io-stream.h"
20 #include "soup-misc-private.h"
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
29 #define MAX_STRING_LEN 256
30 #define HWCLOCK_LOG(s) {const char *str=s; prctl(PR_TASK_PERF_USER_TRACE, str, strlen(str));}
32 static void prctl_with_url(const char *prestr, const char *url)
34 char s[MAX_STRING_LEN] = "";
36 int len_pre = strlen(prestr);
37 int len_url = strlen(url);
39 strncpy(s, prestr, len_pre);
40 if(len_pre + len_url < len_max) {
41 strncpy(s+len_pre, url, len_url);
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);
49 prctl(PR_TASK_PERF_USER_TRACE, s, strlen(s));
55 * @short_description: A network socket
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.
63 G_DEFINE_TYPE (SoupSocket, soup_socket, G_TYPE_OBJECT)
71 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
72 DYNAMIC_CERTIFICATEPATH,
74 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
81 static guint signals[LAST_SIGNAL] = { 0 };
94 PROP_USE_THREAD_CONTEXT,
96 PROP_TRUSTED_CERTIFICATE,
101 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
109 SoupAddress *local_addr, *remote_addr;
110 GIOStream *conn, *iostream;
112 GInputStream *istream;
113 GOutputStream *ostream;
114 GTlsCertificateFlags tls_errors;
115 GProxyResolver *proxy_resolver;
117 guint non_blocking:1;
121 guint ssl_fallback:1;
122 guint clean_dispose:1;
123 guint use_thread_context:1;
126 GMainContext *async_context;
128 GSource *read_src, *write_src;
130 GMutex iolock, addrlock;
133 GCancellable *connect_cancel;
134 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
135 gboolean widget_engine;
137 gchar **default_cert_lists;
139 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
140 gboolean acceptedCertificate;
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"
149 #define SOUP_SOCKET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SOCKET, SoupSocketPrivate))
151 static void soup_socket_peer_certificate_changed (GObject *conn,
156 soup_socket_init (SoupSocket *sock)
158 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
160 priv->non_blocking = TRUE;
161 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
162 priv->cert_lists = NULL;
163 priv->default_cert_lists = NULL;
165 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
166 priv->acceptedCertificate = FALSE;
168 g_mutex_init (&priv->addrlock);
169 g_mutex_init (&priv->iolock);
173 disconnect_internal (SoupSocket *sock, gboolean close)
175 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
177 g_clear_object (&priv->gsock);
178 if (priv->conn && close)
179 g_io_stream_close (priv->conn, NULL, NULL);
181 if (priv->read_src) {
182 g_source_destroy (priv->read_src);
183 priv->read_src = NULL;
185 if (priv->write_src) {
186 g_source_destroy (priv->write_src);
187 priv->write_src = NULL;
192 soup_socket_finalize (GObject *object)
194 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
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);
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);
209 if (priv->clean_dispose)
210 g_warning ("Disposing socket %p while still connected", object);
211 disconnect_internal (SOUP_SOCKET (object), TRUE);
214 g_clear_object (&priv->conn);
215 g_clear_object (&priv->iostream);
216 g_clear_object (&priv->istream);
217 g_clear_object (&priv->ostream);
219 g_clear_object (&priv->local_addr);
220 g_clear_object (&priv->remote_addr);
222 g_clear_object (&priv->proxy_resolver);
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);
229 g_clear_pointer (&priv->async_context, g_main_context_unref);
231 g_mutex_clear (&priv->addrlock);
232 g_mutex_clear (&priv->iolock);
234 G_OBJECT_CLASS (soup_socket_parent_class)->finalize (object);
239 finish_socket_setup (SoupSocketPrivate *priv)
245 priv->conn = (GIOStream *)g_socket_connection_factory_create_connection (priv->gsock);
247 priv->iostream = soup_io_stream_new (priv->conn, FALSE);
249 priv->istream = g_object_ref (g_io_stream_get_input_stream (priv->iostream));
251 priv->ostream = g_object_ref (g_io_stream_get_output_stream (priv->iostream));
253 g_socket_set_timeout (priv->gsock, priv->timeout);
254 g_socket_set_option (priv->gsock, IPPROTO_TCP, TCP_NODELAY, TRUE, NULL);
258 soup_socket_set_property (GObject *object, guint prop_id,
259 const GValue *value, GParamSpec *pspec)
261 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
264 case PROP_LOCAL_ADDRESS:
265 priv->local_addr = (SoupAddress *)g_value_dup_object (value);
267 case PROP_REMOTE_ADDRESS:
268 priv->remote_addr = (SoupAddress *)g_value_dup_object (value);
270 case PROP_NON_BLOCKING:
271 priv->non_blocking = g_value_get_boolean (value);
273 case PROP_SSL_CREDENTIALS:
274 priv->ssl_creds = g_value_get_pointer (value);
276 case PROP_SSL_STRICT:
277 priv->ssl_strict = g_value_get_boolean (value);
279 case PROP_SSL_FALLBACK:
280 priv->ssl_fallback = g_value_get_boolean (value);
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);
287 case PROP_USE_THREAD_CONTEXT:
288 priv->use_thread_context = g_value_get_boolean (value);
291 priv->timeout = g_value_get_uint (value);
293 g_socket_set_timeout (priv->gsock, priv->timeout);
295 case PROP_PROXY_RESOLVER:
296 priv->proxy_resolver = g_value_dup_object (value);
298 case PROP_CLEAN_DISPOSE:
299 priv->clean_dispose = g_value_get_boolean (value);
301 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
302 case PROP_WIDGET_ENGINE:
303 priv->widget_engine = g_value_get_boolean (value);
307 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
313 soup_socket_get_property (GObject *object, guint prop_id,
314 GValue *value, GParamSpec *pspec)
316 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
319 case PROP_LOCAL_ADDRESS:
320 g_value_set_object (value, soup_socket_get_local_address (SOUP_SOCKET (object)));
322 case PROP_REMOTE_ADDRESS:
323 g_value_set_object (value, soup_socket_get_remote_address (SOUP_SOCKET (object)));
325 case PROP_NON_BLOCKING:
326 g_value_set_boolean (value, priv->non_blocking);
329 g_value_set_boolean (value, priv->is_server);
331 case PROP_SSL_CREDENTIALS:
332 g_value_set_pointer (value, priv->ssl_creds);
334 case PROP_SSL_STRICT:
335 g_value_set_boolean (value, priv->ssl_strict);
337 case PROP_SSL_FALLBACK:
338 g_value_set_boolean (value, priv->ssl_fallback);
340 case PROP_TRUSTED_CERTIFICATE:
341 g_value_set_boolean (value, priv->tls_errors == 0);
343 case PROP_ASYNC_CONTEXT:
344 g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : NULL);
346 case PROP_USE_THREAD_CONTEXT:
347 g_value_set_boolean (value, priv->use_thread_context);
350 g_value_set_uint (value, priv->timeout);
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)));
356 g_value_set_object (value, NULL);
358 case PROP_TLS_ERRORS:
359 g_value_set_flags (value, priv->tls_errors);
361 case PROP_PROXY_RESOLVER:
362 g_value_set_object (value, priv->proxy_resolver);
364 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
365 case PROP_WIDGET_ENGINE:
366 g_value_set_boolean (value, priv->widget_engine);
370 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
376 soup_socket_class_init (SoupSocketClass *socket_class)
378 GObjectClass *object_class = G_OBJECT_CLASS (socket_class);
380 g_type_class_add_private (socket_class, sizeof (SoupSocketPrivate));
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;
390 * SoupSocket::readable:
393 * Emitted when an async socket is readable. See
394 * soup_socket_read(), soup_socket_read_until() and
395 * #SoupSocket:non-blocking.
398 g_signal_new ("readable",
399 G_OBJECT_CLASS_TYPE (object_class),
401 G_STRUCT_OFFSET (SoupSocketClass, readable),
407 * SoupSocket::writable:
410 * Emitted when an async socket is writable. See
411 * soup_socket_write() and #SoupSocket:non-blocking.
414 g_signal_new ("writable",
415 G_OBJECT_CLASS_TYPE (object_class),
417 G_STRUCT_OFFSET (SoupSocketClass, writable),
423 * SoupSocket::disconnected:
426 * Emitted when the socket is disconnected, for whatever
429 signals[DISCONNECTED] =
430 g_signal_new ("disconnected",
431 G_OBJECT_CLASS_TYPE (object_class),
433 G_STRUCT_OFFSET (SoupSocketClass, disconnected),
439 * SoupSocket::new-connection:
441 * @new: the new socket
443 * Emitted when a listening socket (set up with
444 * soup_socket_listen()) receives a new connection.
446 * You must ref the @new if you want to keep it; otherwise it
447 * will be destroyed after the signal is emitted.
449 signals[NEW_CONNECTION] =
450 g_signal_new ("new_connection",
451 G_OBJECT_CLASS_TYPE (object_class),
453 G_STRUCT_OFFSET (SoupSocketClass, new_connection),
461 * @event: the event that occurred
462 * @connection: the current connection state
464 * Emitted when a network-related event occurs. See
465 * #GSocketClient::event for more details.
470 g_signal_new ("event",
471 G_OBJECT_CLASS_TYPE (object_class),
477 G_TYPE_SOCKET_CLIENT_EVENT,
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),
491 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
492 signals[ACCEPT_CERTIFICATE] =
493 g_signal_new ("accept-certificate",
494 G_OBJECT_CLASS_TYPE (object_class),
500 G_TYPE_TLS_CERTIFICATE,
501 G_TYPE_TLS_CERTIFICATE_FLAGS);
506 * SOUP_SOCKET_LOCAL_ADDRESS:
508 * Alias for the #SoupSocket:local-address property. (Address
509 * of local end of socket.)
511 g_object_class_install_property (
512 object_class, PROP_LOCAL_ADDRESS,
513 g_param_spec_object (SOUP_SOCKET_LOCAL_ADDRESS,
515 "Address of local end of socket",
517 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
519 * SOUP_SOCKET_REMOTE_ADDRESS:
521 * Alias for the #SoupSocket:remote-address property. (Address
522 * of remote end of socket.)
524 g_object_class_install_property (
525 object_class, PROP_REMOTE_ADDRESS,
526 g_param_spec_object (SOUP_SOCKET_REMOTE_ADDRESS,
528 "Address of remote end of socket",
530 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
532 * SoupSocket:non-blocking:
534 * Whether or not the socket uses non-blocking I/O.
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).
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.
556 * SOUP_SOCKET_FLAG_NONBLOCKING:
558 * Alias for the #SoupSocket:non-blocking property. (Whether
559 * or not the socket uses non-blocking I/O.)
561 g_object_class_install_property (
562 object_class, PROP_NON_BLOCKING,
563 g_param_spec_boolean (SOUP_SOCKET_FLAG_NONBLOCKING,
565 "Whether or not the socket uses non-blocking I/O",
569 * SOUP_SOCKET_IS_SERVER:
571 * Alias for the #SoupSocket:is-server property. (Whether or
572 * not the socket is a server socket.)
574 g_object_class_install_property (
575 object_class, PROP_IS_SERVER,
576 g_param_spec_boolean (SOUP_SOCKET_IS_SERVER,
578 "Whether or not the socket is a server socket",
582 * SOUP_SOCKET_SSL_CREDENTIALS:
584 * Alias for the #SoupSocket:ssl-creds property.
585 * (SSL credential information.)
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!
591 g_object_class_install_property (
592 object_class, PROP_SSL_CREDENTIALS,
593 g_param_spec_pointer (SOUP_SOCKET_SSL_CREDENTIALS,
595 "SSL credential information, passed from the session to the SSL implementation",
598 * SOUP_SOCKET_SSL_STRICT:
600 * Alias for the #SoupSocket:ssl-strict property.
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",
608 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
610 * SOUP_SOCKET_SSL_FALLBACK:
612 * Alias for the #SoupSocket:ssl-fallback property.
614 g_object_class_install_property (
615 object_class, PROP_SSL_FALLBACK,
616 g_param_spec_boolean (SOUP_SOCKET_SSL_FALLBACK,
618 "Use SSLv3 instead of TLS (client-side only)",
620 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
622 * SOUP_SOCKET_TRUSTED_CERTIFICATE:
624 * Alias for the #SoupSocket:trusted-certificate
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",
635 * SOUP_SOCKET_ASYNC_CONTEXT:
637 * Alias for the #SoupSocket:async-context property. (The
638 * socket's #GMainContext.)
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));
648 * SOUP_SOCKET_USE_THREAD_CONTEXT:
650 * Alias for the #SoupSocket:use-thread-context property. (Use
651 * g_main_context_get_thread_default())
656 * SoupSocket:use-thread-context:
658 * Use g_main_context_get_thread_default().
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",
668 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
671 * SOUP_SOCKET_TIMEOUT:
673 * Alias for the #SoupSocket:timeout property. (The timeout
674 * in seconds for blocking socket I/O operations.)
676 g_object_class_install_property (
677 object_class, PROP_TIMEOUT,
678 g_param_spec_uint (SOUP_SOCKET_TIMEOUT,
680 "Value in seconds to timeout a blocking I/O",
684 g_object_class_install_property (
685 object_class, PROP_CLEAN_DISPOSE,
686 g_param_spec_boolean ("clean-dispose",
688 "Warn on unclean dispose",
690 G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
692 * SOUP_SOCKET_TLS_CERTIFICATE:
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.
701 g_object_class_install_property (
702 object_class, PROP_TLS_CERTIFICATE,
703 g_param_spec_object (SOUP_SOCKET_TLS_CERTIFICATE,
705 "The peer's TLS certificate",
706 G_TYPE_TLS_CERTIFICATE,
709 * SOUP_SOCKET_TLS_ERRORS:
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.
718 g_object_class_install_property (
719 object_class, PROP_TLS_ERRORS,
720 g_param_spec_flags (SOUP_SOCKET_TLS_ERRORS,
722 "Errors with the peer's TLS certificate",
723 G_TYPE_TLS_CERTIFICATE_FLAGS, 0,
726 g_object_class_install_property (
727 object_class, PROP_PROXY_RESOLVER,
728 g_param_spec_object (SOUP_SOCKET_PROXY_RESOLVER,
730 "GProxyResolver to use",
731 G_TYPE_PROXY_RESOLVER,
732 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
734 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE)
736 * SOUP_SOCKET_WIDGET_ENGINE:
738 * Alias for the #SoupSocket:widget-engine property.
740 g_object_class_install_property (
741 object_class, PROP_WIDGET_ENGINE,
742 g_param_spec_boolean (SOUP_SOCKET_WIDGET_ENGINE,
744 "Whether or not to be running Widget Engine",
746 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
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)
754 GTlsCertificate* cert = NULL;
755 GError* pGError = NULL;
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);
761 g_warning ("Could not read SSL certificate from : %s", pGError->message);
762 g_error_free (pGError);
766 g_warning ("Could not acess cert=%s, key=%s\n", cert_file, key_file);
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)
776 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
777 GTlsCertificate* cert = NULL;
778 GError* pGError = NULL;
780 gchar* cert_file = NULL;
781 gchar* key_file = NULL;
784 if (!ssl_host || !ssl_host[0] || !priv)
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);
796 /* keep certficate list's infomation */
797 *cert_list = g_strsplit (cert_list_file, ",", 0);
798 g_free (cert_list_file);
801 for (i = 0; (*cert_list)[i]; i++) {
802 gchar **path = g_strsplit ((*cert_list)[i], ":", 0);
804 /* verify format (url:certpath:keypath) */
805 if (path[0] && path[1] && path[2]) {
806 /* remove white space */
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]);
821 if (!cert_file || !key_file)
824 cert = soup_make_client_certificate(cert_file, key_file);
832 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
833 static GTlsCertificate *soup_get_dynamic_client_certificate(SoupSocket *sock, const char* ssl_host)
835 const char* get_certpath = NULL;
837 g_signal_emit (sock, signals[DYNAMIC_CERTIFICATEPATH], 0, ssl_host, &get_certpath);
838 TIZEN_LOGI("Get Certpath[%s] \n", get_certpath);
843 return soup_make_client_certificate(get_certpath, get_certpath);
849 * @optname1: name of first property to set (or %NULL)
850 * @...: value of @optname1, followed by additional property/value pairs
852 * Creates a new (disconnected) socket
854 * Return value: the new socket
857 soup_socket_new (const char *optname1, ...)
862 va_start (ap, optname1);
863 sock = (SoupSocket *)g_object_new_valist (SOUP_TYPE_SOCKET,
871 re_emit_socket_client_event (GSocketClient *client,
872 GSocketClientEvent event,
873 GSocketConnectable *connectable,
874 GIOStream *connection,
877 SoupSocket *sock = user_data;
879 g_signal_emit (sock, signals[EVENT], 0,
884 socket_connect_finish (SoupSocket *sock, GSocketConnection *conn)
886 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
888 g_clear_object (&priv->connect_cancel);
891 priv->conn = (GIOStream *)conn;
892 priv->gsock = g_object_ref (g_socket_connection_get_socket (conn));
893 finish_socket_setup (priv);
900 socket_legacy_error (SoupSocket *sock, GError *error)
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;
909 status = SOUP_STATUS_CANT_CONNECT;
911 g_error_free (error);
915 static GSocketClient *
916 new_socket_client (SoupSocket *sock)
918 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
919 GSocketClient *client = g_socket_client_new ();
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");
927 g_socket_client_set_enable_proxy (client, FALSE);
929 g_socket_client_set_timeout (client, priv->timeout);
931 if (priv->local_addr) {
932 GSocketAddress *addr;
934 addr = soup_address_get_gsockaddr (priv->local_addr);
935 g_socket_client_set_local_address (client, addr);
936 g_object_unref (addr);
943 async_connected (GObject *client, GAsyncResult *result, gpointer data)
946 SoupSocket *sock = g_task_get_source_object (task);
947 GSocketConnection *conn;
948 GError *error = NULL;
950 conn = g_socket_client_connect_finish (G_SOCKET_CLIENT (client),
952 if (socket_connect_finish (sock, conn))
953 g_task_return_boolean (task, TRUE);
955 g_task_return_error (task, error);
956 g_object_unref (task);
960 soup_socket_connect_finish_internal (SoupSocket *sock,
961 GAsyncResult *result,
964 return g_task_propagate_boolean (G_TASK (result), error);
968 soup_socket_connect_async_internal (SoupSocket *sock,
969 GCancellable *cancellable,
970 GAsyncReadyCallback callback,
973 SoupSocketPrivate *priv;
974 GSocketClient *client;
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);
983 priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
984 task = g_task_new (sock, priv->connect_cancel, callback, user_data);
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);
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()
1000 * The callback function passed to soup_socket_connect_async().
1005 SoupSocketCallback callback;
1007 } SoupSocketAsyncConnectData;
1010 legacy_connect_async_cb (GObject *object,
1011 GAsyncResult *result,
1014 SoupSocket *sock = SOUP_SOCKET (object);
1015 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1016 SoupSocketAsyncConnectData *sacd = user_data;
1017 GError *error = NULL;
1020 if (priv->async_context && !priv->use_thread_context)
1021 g_main_context_pop_thread_default (priv->async_context);
1023 if (soup_socket_connect_finish_internal (sock, result, &error))
1024 status = SOUP_STATUS_OK;
1026 status = socket_legacy_error (sock, error);
1028 sacd->callback (sock, status, sacd->user_data);
1029 g_object_unref (sacd->sock);
1030 g_slice_free (SoupSocketAsyncConnectData, sacd);
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
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).
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.
1049 soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable,
1050 SoupSocketCallback callback, gpointer user_data)
1052 SoupSocketPrivate *priv;
1053 SoupSocketAsyncConnectData *sacd;
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);
1061 sacd = g_slice_new0 (SoupSocketAsyncConnectData);
1062 sacd->sock = g_object_ref (sock);
1063 sacd->callback = callback;
1064 sacd->user_data = user_data;
1066 if (priv->async_context && !priv->use_thread_context)
1067 g_main_context_push_thread_default (priv->async_context);
1069 soup_socket_connect_async_internal (sock, cancellable,
1070 legacy_connect_async_cb,
1075 soup_socket_connect_sync_internal (SoupSocket *sock,
1076 GCancellable *cancellable,
1079 SoupSocketPrivate *priv;
1080 GSocketClient *client;
1081 GSocketConnection *conn;
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);
1089 priv->connect_cancel = cancellable ? g_object_ref (cancellable) : g_cancellable_new ();
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);
1097 return socket_connect_finish (sock, conn);
1101 * soup_socket_connect_sync:
1102 * @sock: a client #SoupSocket (which must not already be connected)
1103 * @cancellable: a #GCancellable, or %NULL
1105 * Attempt to synchronously connect @sock to its remote address.
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.
1111 * Return value: a success or failure code.
1114 soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable)
1116 SoupSocketPrivate *priv;
1117 GError *error = NULL;
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);
1125 if (soup_socket_connect_sync_internal (sock, cancellable, &error))
1126 return SOUP_STATUS_OK;
1128 return socket_legacy_error (sock, error);
1132 * soup_socket_get_fd:
1133 * @sock: a #SoupSocket
1135 * Gets @sock's underlying file descriptor.
1137 * Note that fiddling with the file descriptor may break the
1140 * Return value: @sock's file descriptor.
1143 soup_socket_get_fd (SoupSocket *sock)
1145 g_return_val_if_fail (SOUP_IS_SOCKET (sock), -1);
1147 return g_socket_get_fd (SOUP_SOCKET_GET_PRIVATE (sock)->gsock);
1151 soup_socket_get_gsocket (SoupSocket *sock)
1153 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1155 return SOUP_SOCKET_GET_PRIVATE (sock)->gsock;
1159 soup_socket_get_connection (SoupSocket *sock)
1161 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1163 return SOUP_SOCKET_GET_PRIVATE (sock)->conn;
1167 soup_socket_get_iostream (SoupSocket *sock)
1169 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1171 return SOUP_SOCKET_GET_PRIVATE (sock)->iostream;
1175 soup_socket_create_watch (SoupSocketPrivate *priv, GIOCondition cond,
1176 GPollableSourceFunc callback, gpointer user_data,
1177 GCancellable *cancellable)
1180 GMainContext *async_context;
1182 if (cond == G_IO_IN)
1183 watch = g_pollable_input_stream_create_source (G_POLLABLE_INPUT_STREAM (priv->istream), cancellable);
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);
1188 if (priv->use_thread_context)
1189 async_context = g_main_context_get_thread_default ();
1191 async_context = priv->async_context;
1193 g_source_attach (watch, async_context);
1194 g_source_unref (watch);
1200 listen_watch (GObject *pollable, gpointer data)
1202 SoupSocket *sock = data, *new;
1203 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock), *new_priv;
1206 new_gsock = g_socket_accept (priv->gsock, NULL, NULL);
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);
1223 if (new_priv->ssl_creds) {
1224 if (!soup_socket_start_proxy_ssl (new, NULL, NULL)) {
1225 g_object_unref (new);
1230 g_signal_emit (sock, signals[NEW_CONNECTION], 0, new);
1231 g_object_unref (new);
1237 * soup_socket_listen:
1238 * @sock: a server #SoupSocket (which must not already be connected or
1241 * Makes @sock start listening on its local address. When connections
1242 * come in, @sock will emit #SoupSocket::new_connection.
1244 * Return value: whether or not @sock is now listening.
1247 soup_socket_listen (SoupSocket *sock)
1250 SoupSocketPrivate *priv;
1251 GSocketAddress *addr;
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);
1258 priv->is_server = TRUE;
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.
1266 addr = soup_address_get_gsockaddr (priv->local_addr);
1267 g_return_val_if_fail (addr != NULL, FALSE);
1269 priv->gsock = g_socket_new (g_socket_address_get_family (addr),
1270 G_SOCKET_TYPE_STREAM,
1271 G_SOCKET_PROTOCOL_DEFAULT,
1275 finish_socket_setup (priv);
1278 if (!g_socket_bind (priv->gsock, addr, TRUE, NULL))
1280 /* Force local_addr to be re-resolved now */
1281 g_object_unref (priv->local_addr);
1282 priv->local_addr = NULL;
1285 if (!g_socket_listen (priv->gsock, NULL))
1288 priv->watch_src = soup_socket_create_watch (priv, G_IO_IN,
1291 g_object_unref (addr);
1296 disconnect_internal (sock, TRUE);
1297 g_object_unref (addr);
1303 soup_socket_peer_certificate_changed (GObject *conn, GParamSpec *pspec,
1306 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
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));
1312 priv->tls_errors = g_tls_connection_get_peer_certificate_errors (G_TLS_CONNECTION (priv->conn));
1315 g_object_notify (sock, "tls-certificate");
1316 g_object_notify (sock, "tls-errors");
1320 soup_socket_accept_certificate (GTlsConnection *conn, GTlsCertificate *cert,
1321 GTlsCertificateFlags errors, gpointer sock)
1323 #if ENABLE(TIZEN_TV_CERTIFICATE_HANDLING)
1324 gboolean accept = FALSE;
1325 SoupSocket *soupSock = sock;
1326 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (soupSock);
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));
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);
1336 priv->acceptedCertificate = accept;
1345 soup_socket_setup_ssl (SoupSocket *sock,
1346 const char *ssl_host,
1347 GCancellable *cancellable,
1350 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1351 GTlsBackend *backend = g_tls_backend_get_default ();
1353 if (G_IS_TLS_CONNECTION (priv->conn))
1356 if (g_cancellable_set_error_if_cancelled (cancellable, error))
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;
1367 identity = g_network_address_new (ssl_host, 0);
1369 #if ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
1370 if (!(cert = soup_get_dynamic_client_certificate (sock, ssl_host)))
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);
1377 #if ENABLE(TIZEN_TV_CLIENT_CERTIFICATE) || ENABLE(TIZEN_TV_DYNAMIC_CERTIFICATE_LOADING)
1379 conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
1381 "base-io-stream", priv->conn,
1382 "server-identity", identity,
1383 "database", priv->ssl_creds,
1384 "certificate", cert,
1385 "require-close-notify", FALSE,
1389 g_object_unref (cert);
1393 conn = g_initable_new (g_tls_backend_get_client_connection_type (backend),
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,
1402 g_object_unref (identity);
1407 g_object_unref (priv->conn);
1408 priv->conn = G_IO_STREAM (conn);
1410 if (!priv->ssl_strict) {
1411 g_signal_connect (conn, "accept-certificate",
1412 G_CALLBACK (soup_socket_accept_certificate),
1416 GTlsServerConnection *conn;
1418 conn = g_initable_new (g_tls_backend_get_server_connection_type (backend),
1420 "base-io-stream", priv->conn,
1421 "certificate", priv->ssl_creds,
1422 "use-system-certdb", FALSE,
1423 "require-close-notify", FALSE,
1428 g_object_unref (priv->conn);
1429 priv->conn = G_IO_STREAM (conn);
1432 g_signal_connect (priv->conn, "notify::peer-certificate",
1433 G_CALLBACK (soup_socket_peer_certificate_changed), sock);
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));
1446 * soup_socket_start_ssl:
1448 * @cancellable: a #GCancellable
1450 * Starts using SSL on @socket.
1452 * Return value: success or failure
1455 soup_socket_start_ssl (SoupSocket *sock, GCancellable *cancellable)
1457 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1459 return soup_socket_setup_ssl (sock, soup_address_get_name (priv->remote_addr),
1464 * soup_socket_start_proxy_ssl:
1466 * @ssl_host: hostname of the SSL server
1467 * @cancellable: a #GCancellable
1469 * Starts using SSL on @socket, expecting to find a host named
1472 * Return value: success or failure
1475 soup_socket_start_proxy_ssl (SoupSocket *sock, const char *ssl_host,
1476 GCancellable *cancellable)
1478 return soup_socket_setup_ssl (sock, ssl_host, cancellable, NULL);
1482 soup_socket_handshake_sync (SoupSocket *sock,
1483 const char *ssl_host,
1484 GCancellable *cancellable,
1487 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1489 if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, error))
1492 return g_tls_connection_handshake (G_TLS_CONNECTION (priv->conn),
1493 cancellable, error);
1497 handshake_async_ready (GObject *source, GAsyncResult *result, gpointer user_data)
1499 GTask *task = user_data;
1500 GError *error = NULL;
1502 if (g_tls_connection_handshake_finish (G_TLS_CONNECTION (source),
1504 g_task_return_boolean (task, TRUE);
1506 g_task_return_error (task, error);
1507 g_object_unref (task);
1511 soup_socket_handshake_async (SoupSocket *sock,
1512 const char *ssl_host,
1513 GCancellable *cancellable,
1514 GAsyncReadyCallback callback,
1517 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1519 GError *error = NULL;
1521 #if ENABLE(TIZEN_PERFORMANCE_TEST_LOG)
1522 prctl_with_url("[EVT] soup handshake start : ", soup_address_get_name(priv->remote_addr));
1524 task = g_task_new (sock, cancellable, callback, user_data);
1526 if (!soup_socket_setup_ssl (sock, ssl_host, cancellable, &error)) {
1527 g_task_return_error (task, error);
1528 g_object_unref (task);
1532 g_tls_connection_handshake_async (G_TLS_CONNECTION (priv->conn),
1534 cancellable, handshake_async_ready,
1539 soup_socket_handshake_finish (SoupSocket *sock,
1540 GAsyncResult *result,
1543 return g_task_propagate_boolean (G_TASK (result), error);
1547 * soup_socket_is_ssl:
1548 * @sock: a #SoupSocket
1550 * Tests if @sock is doing (or has attempted to do) SSL.
1552 * Return value: %TRUE if @sock has SSL credentials set
1555 soup_socket_is_ssl (SoupSocket *sock)
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);
1562 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1569 * soup_socket_disconnect:
1570 * @sock: a #SoupSocket
1572 * Disconnects @sock. Any further read or write attempts on it will
1576 soup_socket_disconnect (SoupSocket *sock)
1578 SoupSocketPrivate *priv;
1579 gboolean already_disconnected = FALSE;
1581 g_return_if_fail (SOUP_IS_SOCKET (sock));
1582 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1584 if (priv->connect_cancel) {
1585 disconnect_internal (sock, FALSE);
1586 g_cancellable_cancel (priv->connect_cancel);
1588 } else if (g_mutex_trylock (&priv->iolock)) {
1590 disconnect_internal (sock, TRUE);
1592 already_disconnected = TRUE;
1593 g_mutex_unlock (&priv->iolock);
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
1601 g_socket_shutdown (priv->gsock, TRUE, TRUE, NULL);
1604 if (already_disconnected)
1607 /* Keep ref around signals in case the object is unreferenced
1610 g_object_ref (sock);
1612 if (priv->non_blocking) {
1613 /* Give all readers a chance to notice the connection close */
1614 g_signal_emit (sock, signals[READABLE], 0);
1617 /* FIXME: can't disconnect until all data is read */
1619 /* Then let everyone know we're disconnected */
1620 g_signal_emit (sock, signals[DISCONNECTED], 0);
1622 g_object_unref (sock);
1626 * soup_socket_is_connected:
1627 * @sock: a #SoupSocket
1629 * Tests if @sock is connected to another host
1631 * Return value: %TRUE or %FALSE.
1634 soup_socket_is_connected (SoupSocket *sock)
1636 SoupSocketPrivate *priv;
1638 g_return_val_if_fail (SOUP_IS_SOCKET (sock), FALSE);
1639 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1641 return priv->conn && !g_io_stream_is_closed (priv->conn);
1645 * soup_socket_get_local_address:
1646 * @sock: a #SoupSocket
1648 * Returns the #SoupAddress corresponding to the local end of @sock.
1650 * Calling this method on an unconnected socket is considered to be
1651 * an error, and produces undefined results.
1653 * Return value: (transfer none): the #SoupAddress
1656 soup_socket_get_local_address (SoupSocket *sock)
1658 SoupSocketPrivate *priv;
1660 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1661 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1663 g_mutex_lock (&priv->addrlock);
1664 if (!priv->local_addr) {
1665 GSocketAddress *addr;
1666 struct sockaddr_storage sa;
1668 GError *error = NULL;
1670 if (priv->gsock == NULL) {
1671 g_warning ("%s: socket not connected", G_STRLOC);
1675 addr = g_socket_get_local_address (priv->gsock, &error);
1677 g_warning ("%s: %s", G_STRLOC, error->message);
1678 g_error_free (error);
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);
1687 g_mutex_unlock (&priv->addrlock);
1689 return priv->local_addr;
1693 * soup_socket_get_remote_address:
1694 * @sock: a #SoupSocket
1696 * Returns the #SoupAddress corresponding to the remote end of @sock.
1698 * Calling this method on an unconnected socket is considered to be
1699 * an error, and produces undefined results.
1701 * Return value: (transfer none): the #SoupAddress
1704 soup_socket_get_remote_address (SoupSocket *sock)
1706 SoupSocketPrivate *priv;
1708 g_return_val_if_fail (SOUP_IS_SOCKET (sock), NULL);
1709 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1711 g_mutex_lock (&priv->addrlock);
1712 if (!priv->remote_addr) {
1713 GSocketAddress *addr;
1714 struct sockaddr_storage sa;
1716 GError *error = NULL;
1718 if (priv->gsock == NULL) {
1719 g_warning ("%s: socket not connected", G_STRLOC);
1723 addr = g_socket_get_remote_address (priv->gsock, &error);
1725 g_warning ("%s: %s", G_STRLOC, error->message);
1726 g_error_free (error);
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);
1735 g_mutex_unlock (&priv->addrlock);
1737 return priv->remote_addr;
1741 soup_socket_get_http_proxy_uri (SoupSocket *sock)
1743 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1744 GSocketAddress *addr;
1745 GProxyAddress *paddr;
1750 addr = g_socket_get_remote_address (priv->gsock, NULL);
1751 if (!addr || !G_IS_PROXY_ADDRESS (addr)) {
1753 g_object_unref (addr);
1757 paddr = G_PROXY_ADDRESS (addr);
1758 if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0)
1761 uri = soup_uri_new (g_proxy_address_get_uri (paddr));
1762 g_object_unref (addr);
1767 socket_read_watch (GObject *pollable, gpointer user_data)
1769 SoupSocket *sock = user_data;
1770 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1772 priv->read_src = NULL;
1773 g_signal_emit (sock, signals[READABLE], 0);
1777 static SoupSocketIOStatus
1778 translate_read_status (SoupSocket *sock, GCancellable *cancellable,
1779 gssize my_nread, gsize *nread,
1780 GError *my_err, GError **error)
1782 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1785 g_assert_no_error (my_err);
1787 return SOUP_SOCKET_OK;
1788 } else if (my_nread == 0) {
1789 g_assert_no_error (my_err);
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) {
1796 soup_socket_create_watch (priv, G_IO_IN,
1797 socket_read_watch, sock,
1800 return SOUP_SOCKET_WOULD_BLOCK;
1803 g_propagate_error (error, my_err);
1804 return SOUP_SOCKET_ERROR;
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
1814 * Return value from the #SoupSocket IO methods.
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
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).
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.)
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
1845 soup_socket_read (SoupSocket *sock, gpointer buffer, gsize len,
1846 gsize *nread, GCancellable *cancellable, GError **error)
1848 SoupSocketPrivate *priv;
1849 SoupSocketIOStatus status;
1851 GError *my_err = NULL;
1853 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1854 g_return_val_if_fail (nread != NULL, SOUP_SOCKET_ERROR);
1856 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1858 g_mutex_lock (&priv->iolock);
1860 if (!priv->istream) {
1861 status = SOUP_SOCKET_EOF;
1865 if (!priv->non_blocking) {
1866 my_nread = g_input_stream_read (priv->istream, buffer, len,
1867 cancellable, &my_err);
1869 my_nread = g_pollable_input_stream_read_nonblocking (G_POLLABLE_INPUT_STREAM (priv->istream),
1871 cancellable, &my_err);
1873 status = translate_read_status (sock, cancellable,
1874 my_nread, nread, my_err, error);
1877 g_mutex_unlock (&priv->iolock);
1883 * soup_socket_read_until:
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
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.
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.
1908 * Return value: as for soup_socket_read()
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)
1916 SoupSocketPrivate *priv;
1917 SoupSocketIOStatus status;
1919 GError *my_err = NULL;
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);
1925 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1927 g_mutex_lock (&priv->iolock);
1929 *got_boundary = FALSE;
1932 status = SOUP_SOCKET_EOF;
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);
1943 g_mutex_unlock (&priv->iolock);
1948 socket_write_watch (GObject *pollable, gpointer user_data)
1950 SoupSocket *sock = user_data;
1951 SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock);
1953 priv->write_src = NULL;
1954 g_signal_emit (sock, signals[WRITABLE], 0);
1959 * soup_socket_write:
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
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).
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.)
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.)
1985 soup_socket_write (SoupSocket *sock, gconstpointer buffer,
1986 gsize len, gsize *nwrote,
1987 GCancellable *cancellable, GError **error)
1989 SoupSocketPrivate *priv;
1990 GError *my_err = NULL;
1993 g_return_val_if_fail (SOUP_IS_SOCKET (sock), SOUP_SOCKET_ERROR);
1994 g_return_val_if_fail (nwrote != NULL, SOUP_SOCKET_ERROR);
1996 priv = SOUP_SOCKET_GET_PRIVATE (sock);
1998 g_mutex_lock (&priv->iolock);
2001 g_mutex_unlock (&priv->iolock);
2002 return SOUP_SOCKET_EOF;
2004 if (priv->write_src) {
2005 g_mutex_unlock (&priv->iolock);
2006 return SOUP_SOCKET_WOULD_BLOCK;
2009 if (!priv->non_blocking) {
2010 my_nwrote = g_output_stream_write (priv->ostream,
2012 cancellable, &my_err);
2014 my_nwrote = g_pollable_output_stream_write_nonblocking (
2015 G_POLLABLE_OUTPUT_STREAM (priv->ostream),
2016 buffer, len, cancellable, &my_err);
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;
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);
2031 soup_socket_create_watch (priv,
2033 socket_write_watch, sock, cancellable);
2034 return SOUP_SOCKET_WOULD_BLOCK;
2037 g_mutex_unlock (&priv->iolock);
2038 g_propagate_error (error, my_err);
2039 return SOUP_SOCKET_ERROR;