[libsoup: 2/5] soup-socket: Add SoupSocketProperties to transfer props from session to socket



commit ca47f77b3b672cf158863246702d3e4050f60481
Author: Dan Winship <danw gnome org>
Date:   Mon Dec 9 13:24:27 2013 +0100

    soup-socket: Add SoupSocketProperties to transfer props from session to socket
    
    There are a large number of SoupSession properties that need to be
    propagated through the SoupConnection to the SoupSocket. Wrap them all
    up into a single struct for ease of carrying.

 libsoup/Makefile.am              |    1 +
 libsoup/soup-connection.c        |  168 +++++--------------------------------
 libsoup/soup-connection.h        |   16 +---
 libsoup/soup-session.c           |  124 ++++++++++++++++------------
 libsoup/soup-socket-private.h    |   39 ++++++++-
 libsoup/soup-socket-properties.c |   74 +++++++++++++++++
 libsoup/soup-socket.c            |   61 +++++++++-----
 7 files changed, 250 insertions(+), 233 deletions(-)
---
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index aa5e6eb..25a8dc1 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -177,6 +177,7 @@ libsoup_2_4_la_SOURCES =            \
        soup-session-sync.c             \
        soup-socket.c                   \
        soup-socket-private.h           \
+       soup-socket-properties.c        \
        soup-status.c                   \
        soup-tld.c                      \
        soup-tld-private.h              \
diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c
index 62ba2f5..92571fa 100644
--- a/libsoup/soup-connection.c
+++ b/libsoup/soup-connection.c
@@ -16,20 +16,14 @@
 
 typedef struct {
        SoupSocket  *socket;
+       SoupSocketProperties *socket_props;
 
-       SoupAddress *local_addr;
        SoupURI *remote_uri, *proxy_uri;
-       GProxyResolver *proxy_resolver;
-       GTlsDatabase *tlsdb;
-       gboolean ssl, ssl_strict, ssl_fallback;
-
-       GMainContext *async_context;
-       gboolean      use_thread_context;
+       gboolean ssl, ssl_fallback;
 
        SoupMessage *current_msg;
        SoupConnectionState state;
        time_t       unused_timeout;
-       guint        io_timeout, idle_timeout;
        GSource     *idle_timeout_src;
        gboolean     reusable;
 } SoupConnectionPrivate;
@@ -48,16 +42,9 @@ static guint signals[LAST_SIGNAL] = { 0 };
 enum {
        PROP_0,
 
-       PROP_LOCAL_ADDRESS,
        PROP_REMOTE_URI,
-       PROP_PROXY_RESOLVER,
-       PROP_SSL_CREDS,
-       PROP_SSL_STRICT,
        PROP_SSL_FALLBACK,
-       PROP_ASYNC_CONTEXT,
-       PROP_USE_THREAD_CONTEXT,
-       PROP_TIMEOUT,
-       PROP_IDLE_TIMEOUT,
+       PROP_SOCKET_PROPERTIES,
        PROP_STATE,
 
        LAST_PROP
@@ -82,10 +69,7 @@ soup_connection_finalize (GObject *object)
 
        g_clear_pointer (&priv->remote_uri, soup_uri_free);
        g_clear_pointer (&priv->proxy_uri, soup_uri_free);
-       g_clear_object (&priv->tlsdb);
-       g_clear_object (&priv->proxy_resolver);
-       g_clear_object (&priv->local_addr);
-       g_clear_pointer (&priv->async_context, g_main_context_unref);
+       g_clear_pointer (&priv->socket_props, soup_socket_properties_unref);
 
        G_OBJECT_CLASS (soup_connection_parent_class)->finalize (object);
 }
@@ -108,9 +92,6 @@ soup_connection_set_property (GObject *object, guint prop_id,
        SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object);
 
        switch (prop_id) {
-       case PROP_LOCAL_ADDRESS:
-               priv->local_addr = g_value_dup_object (value);
-               break;
        case PROP_REMOTE_URI:
                priv->remote_uri = g_value_dup_boxed (value);
                if (priv->remote_uri)
@@ -118,33 +99,12 @@ soup_connection_set_property (GObject *object, guint prop_id,
                else
                        priv->ssl = FALSE;
                break;
-       case PROP_PROXY_RESOLVER:
-               priv->proxy_resolver = g_value_dup_object (value);
-               break;
-       case PROP_SSL_CREDS:
-               if (priv->tlsdb)
-                       g_object_unref (priv->tlsdb);
-               priv->tlsdb = g_value_dup_object (value);
-               break;
-       case PROP_SSL_STRICT:
-               priv->ssl_strict = g_value_get_boolean (value);
                break;
        case PROP_SSL_FALLBACK:
                priv->ssl_fallback = g_value_get_boolean (value);
                break;
-       case PROP_ASYNC_CONTEXT:
-               priv->async_context = g_value_get_pointer (value);
-               if (priv->async_context)
-                       g_main_context_ref (priv->async_context);
-               break;
-       case PROP_USE_THREAD_CONTEXT:
-               priv->use_thread_context = g_value_get_boolean (value);
-               break;
-       case PROP_TIMEOUT:
-               priv->io_timeout = g_value_get_uint (value);
-               break;
-       case PROP_IDLE_TIMEOUT:
-               priv->idle_timeout = g_value_get_uint (value);
+       case PROP_SOCKET_PROPERTIES:
+               priv->socket_props = g_value_dup_boxed (value);
                break;
        case PROP_STATE:
                soup_connection_set_state (SOUP_CONNECTION (object), g_value_get_uint (value));
@@ -162,32 +122,14 @@ soup_connection_get_property (GObject *object, guint prop_id,
        SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object);
 
        switch (prop_id) {
-       case PROP_LOCAL_ADDRESS:
-               g_value_set_object (value, priv->local_addr);
-               break;
        case PROP_REMOTE_URI:
                g_value_set_boxed (value, priv->remote_uri);
                break;
-       case PROP_SSL_CREDS:
-               g_value_set_object (value, priv->tlsdb);
-               break;
-       case PROP_SSL_STRICT:
-               g_value_set_boolean (value, priv->ssl_strict);
-               break;
        case PROP_SSL_FALLBACK:
                g_value_set_boolean (value, priv->ssl_fallback);
                break;
-       case PROP_ASYNC_CONTEXT:
-               g_value_set_pointer (value, priv->async_context ? g_main_context_ref (priv->async_context) : 
NULL);
-               break;
-       case PROP_USE_THREAD_CONTEXT:
-               g_value_set_boolean (value, priv->use_thread_context);
-               break;
-       case PROP_TIMEOUT:
-               g_value_set_uint (value, priv->io_timeout);
-               break;
-       case PROP_IDLE_TIMEOUT:
-               g_value_set_uint (value, priv->idle_timeout);
+       case PROP_SOCKET_PROPERTIES:
+               g_value_set_boxed (value, priv->socket_props);
                break;
        case PROP_STATE:
                g_value_set_enum (value, priv->state);
@@ -233,13 +175,6 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
 
        /* properties */
        g_object_class_install_property (
-               object_class, PROP_LOCAL_ADDRESS,
-               g_param_spec_object (SOUP_CONNECTION_LOCAL_ADDRESS,
-                                    "Local address",
-                                    "Address of local end of socket",
-                                    SOUP_TYPE_ADDRESS,
-                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
                object_class, PROP_REMOTE_URI,
                g_param_spec_boxed (SOUP_CONNECTION_REMOTE_URI,
                                    "Remote URI",
@@ -247,27 +182,6 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
                                    SOUP_TYPE_URI,
                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (
-               object_class, PROP_PROXY_RESOLVER,
-               g_param_spec_object (SOUP_CONNECTION_PROXY_RESOLVER,
-                                    "Proxy resolver",
-                                    "GProxyResolver to use",
-                                    G_TYPE_PROXY_RESOLVER,
-                                    G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
-               object_class, PROP_SSL_CREDS,
-               g_param_spec_object (SOUP_CONNECTION_SSL_CREDENTIALS,
-                                    "SSL credentials",
-                                    "SSL credentials for this connection",
-                                    G_TYPE_TLS_DATABASE,
-                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
-               object_class, PROP_SSL_STRICT,
-               g_param_spec_boolean (SOUP_CONNECTION_SSL_STRICT,
-                                     "Strictly validate SSL certificates",
-                                     "Whether certificate errors should be considered a connection error",
-                                     TRUE,
-                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
                object_class, PROP_SSL_FALLBACK,
                g_param_spec_boolean (SOUP_CONNECTION_SSL_FALLBACK,
                                      "SSLv3 fallback",
@@ -275,32 +189,12 @@ soup_connection_class_init (SoupConnectionClass *connection_class)
                                      FALSE,
                                      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (
-               object_class, PROP_ASYNC_CONTEXT,
-               g_param_spec_pointer (SOUP_CONNECTION_ASYNC_CONTEXT,
-                                     "Async GMainContext",
-                                     "GMainContext to dispatch this connection's async I/O in",
-                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
-               object_class, PROP_USE_THREAD_CONTEXT,
-               g_param_spec_boolean (SOUP_CONNECTION_USE_THREAD_CONTEXT,
-                                     "Use thread context",
-                                     "Use g_main_context_get_thread_default",
-                                     FALSE,
-                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-       g_object_class_install_property (
-               object_class, PROP_TIMEOUT,
-               g_param_spec_uint (SOUP_CONNECTION_TIMEOUT,
-                                  "Timeout value",
-                                  "Value in seconds to timeout a blocking I/O",
-                                  0, G_MAXUINT, 0,
-                                  G_PARAM_READWRITE));
-       g_object_class_install_property (
-               object_class, PROP_IDLE_TIMEOUT,
-               g_param_spec_uint (SOUP_CONNECTION_IDLE_TIMEOUT,
-                                  "Idle Timeout",
-                                  "Connection lifetime when idle",
-                                  0, G_MAXUINT, 0,
-                                  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+               object_class, PROP_SOCKET_PROPERTIES,
+               g_param_spec_boxed (SOUP_CONNECTION_SOCKET_PROPERTIES,
+                                   "Socket properties",
+                                   "Socket properties",
+                                   SOUP_TYPE_SOCKET_PROPERTIES,
+                                   G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (
                object_class, PROP_STATE,
                g_param_spec_enum (SOUP_CONNECTION_STATE,
@@ -336,10 +230,10 @@ start_idle_timer (SoupConnection *conn)
 {
        SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
 
-       if (priv->idle_timeout > 0 && !priv->idle_timeout_src) {
+       if (priv->socket_props->idle_timeout > 0 && !priv->idle_timeout_src) {
                priv->idle_timeout_src =
-                       soup_add_timeout (priv->async_context,
-                                         priv->idle_timeout * 1000,
+                       soup_add_timeout (priv->socket_props->async_context,
+                                         priv->socket_props->idle_timeout * 1000,
                                          idle_timeout, conn);
        }
 }
@@ -433,8 +327,7 @@ socket_connect_finished (GTask *task, SoupSocket *sock, GError *error)
        SoupConnection *conn = g_task_get_source_object (task);
        SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
 
-       if (priv->async_context && !priv->use_thread_context)
-               g_main_context_pop_thread_default (priv->async_context);
+       soup_socket_properties_pop_async_context (priv->socket_props);
 
        g_signal_handlers_disconnect_by_func (sock, G_CALLBACK (re_emit_socket_event), conn);
 
@@ -527,23 +420,15 @@ soup_connection_connect_async (SoupConnection      *conn,
 
        priv->socket =
                soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr,
-                                SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb,
-                                SOUP_SOCKET_SSL_STRICT, priv->ssl_strict,
                                 SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback,
-                                SOUP_SOCKET_ASYNC_CONTEXT, priv->async_context,
-                                SOUP_SOCKET_USE_THREAD_CONTEXT, priv->use_thread_context,
-                                SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver,
-                                SOUP_SOCKET_TIMEOUT, priv->io_timeout,
-                                SOUP_SOCKET_CLEAN_DISPOSE, TRUE,
-                                SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr,
+                                SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props,
                                 NULL);
        g_object_unref (remote_addr);
 
        g_signal_connect (priv->socket, "event",
                          G_CALLBACK (re_emit_socket_event), conn);
 
-       if (priv->async_context && !priv->use_thread_context)
-               g_main_context_push_thread_default (priv->async_context);
+       soup_socket_properties_push_async_context (priv->socket_props);
        task = g_task_new (conn, cancellable, callback, user_data);
 
        soup_socket_connect_async_internal (priv->socket, cancellable,
@@ -584,14 +469,9 @@ soup_connection_connect_sync (SoupConnection  *conn,
 
        priv->socket =
                soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr,
-                                SOUP_SOCKET_PROXY_RESOLVER, priv->proxy_resolver,
-                                SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb,
-                                SOUP_SOCKET_SSL_STRICT, priv->ssl_strict,
                                 SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback,
+                                SOUP_SOCKET_SOCKET_PROPERTIES, priv->socket_props,
                                 SOUP_SOCKET_FLAG_NONBLOCKING, FALSE,
-                                SOUP_SOCKET_TIMEOUT, priv->io_timeout,
-                                SOUP_SOCKET_CLEAN_DISPOSE, TRUE,
-                                SOUP_SOCKET_LOCAL_ADDRESS, priv->local_addr,
                                 NULL);
        g_object_unref (remote_addr);
 
@@ -674,8 +554,7 @@ start_ssl_completed (GObject *object, GAsyncResult *result, gpointer user_data)
        SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (conn);
        GError *error = NULL;
 
-       if (priv->async_context && !priv->use_thread_context)
-               g_main_context_pop_thread_default (priv->async_context);
+       soup_socket_properties_pop_async_context (priv->socket_props);
 
        if (soup_socket_handshake_finish (priv->socket, result, &error)) {
                soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL);
@@ -700,8 +579,7 @@ soup_connection_start_ssl_async (SoupConnection      *conn,
 
        soup_connection_event (conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, NULL);
 
-       if (priv->async_context && !priv->use_thread_context)
-               g_main_context_push_thread_default (priv->async_context);
+       soup_socket_properties_push_async_context (priv->socket_props);
        task = g_task_new (conn, cancellable, callback, user_data);
 
        soup_socket_handshake_async (priv->socket, priv->remote_uri->host,
diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h
index 454432d..8df6112 100644
--- a/libsoup/soup-connection.h
+++ b/libsoup/soup-connection.h
@@ -35,18 +35,10 @@ typedef struct {
 GType soup_connection_get_type (void);
 
 
-#define SOUP_CONNECTION_LOCAL_ADDRESS   "local-address"
-#define SOUP_CONNECTION_REMOTE_URI      "remote-uri"
-#define SOUP_CONNECTION_PROXY_RESOLVER  "proxy-resolver"
-#define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds"
-#define SOUP_CONNECTION_SSL_STRICT      "ssl-strict"
-#define SOUP_CONNECTION_SSL_FALLBACK    "ssl-fallback"
-#define SOUP_CONNECTION_ASYNC_CONTEXT   "async-context"
-#define SOUP_CONNECTION_USE_THREAD_CONTEXT "use-thread-context"
-#define SOUP_CONNECTION_TIMEOUT         "timeout"
-#define SOUP_CONNECTION_IDLE_TIMEOUT    "idle-timeout"
-#define SOUP_CONNECTION_STATE           "state"
-#define SOUP_CONNECTION_MESSAGE         "message"
+#define SOUP_CONNECTION_REMOTE_URI        "remote-uri"
+#define SOUP_CONNECTION_SSL_FALLBACK      "ssl-fallback"
+#define SOUP_CONNECTION_SOCKET_PROPERTIES "socket-properties"
+#define SOUP_CONNECTION_STATE             "state"
 
 void            soup_connection_connect_async    (SoupConnection       *conn,
                                                  GCancellable         *cancellable,
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index ca190d1..6deff7e 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -21,6 +21,7 @@
 #include "soup-message-queue.h"
 #include "soup-proxy-resolver-wrapper.h"
 #include "soup-session-private.h"
+#include "soup-socket-private.h"
 
 #define HOST_KEEP_ALIVE 5 * 60 * 1000 /* 5 min in msecs */
 
@@ -90,6 +91,16 @@ typedef struct {
        gboolean ssl_strict;
        gboolean tlsdb_use_default;
 
+       guint io_timeout, idle_timeout;
+       SoupAddress *local_addr;
+
+       GResolver *resolver;
+       GProxyResolver *proxy_resolver;
+       gboolean proxy_use_default;
+       SoupURI *proxy_uri;
+
+       SoupSocketProperties *socket_props;
+
        SoupMessageQueue *queue;
 
        char *user_agent;
@@ -103,9 +114,6 @@ typedef struct {
        GHashTable *conns; /* SoupConnection -> SoupSessionHost */
        guint num_conns;
        guint max_conns, max_conns_per_host;
-       guint io_timeout, idle_timeout;
-
-       SoupAddress *local_addr;
 
        /* Must hold the conn_lock before potentially creating a new
         * SoupSessionHost, adding/removing a connection,
@@ -121,11 +129,6 @@ typedef struct {
        gboolean use_thread_context;
        GSList *run_queue_sources;
 
-       GResolver *resolver;
-       GProxyResolver *proxy_resolver;
-       gboolean proxy_use_default;
-       SoupURI *proxy_uri;
-
        char **http_aliases, **https_aliases;
 
        GHashTable *request_types;
@@ -350,9 +353,42 @@ soup_session_finalize (GObject *object)
 
        g_hash_table_destroy (priv->request_types);
 
+       g_clear_pointer (&priv->socket_props, soup_socket_properties_unref);
+
        G_OBJECT_CLASS (soup_session_parent_class)->finalize (object);
 }
 
+static void
+ensure_socket_props (SoupSession *session)
+{
+       SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+       gboolean ssl_strict;
+
+       if (priv->socket_props)
+               return;
+
+       if (priv->proxy_use_default) {
+               priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ());
+               priv->proxy_use_default = FALSE;
+       }
+       if (priv->tlsdb_use_default) {
+               priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
+               priv->tlsdb_use_default = FALSE;
+       }
+
+       ssl_strict = priv->ssl_strict && (priv->tlsdb != NULL ||
+                                         SOUP_IS_PLAIN_SESSION (priv->session));
+
+       priv->socket_props = soup_socket_properties_new (priv->async_context,
+                                                        priv->use_thread_context,
+                                                        priv->proxy_resolver,
+                                                        priv->local_addr,
+                                                        priv->tlsdb,
+                                                        ssl_strict,
+                                                        priv->io_timeout,
+                                                        priv->idle_timeout);
+}
+
 /* Converts a language in POSIX format and to be RFC2616 compliant    */
 /* Based on code from epiphany-webkit (ephy_langs_append_languages()) */
 static gchar *
@@ -600,19 +636,23 @@ soup_session_set_property (GObject *object, guint prop_id,
        const char *user_agent;
        SoupSessionFeature *feature;
        GMainContext *async_context;
+       gboolean socket_props_changed = FALSE;
 
        switch (prop_id) {
        case PROP_LOCAL_ADDRESS:
                priv->local_addr = g_value_dup_object (value);
+               socket_props_changed = TRUE;
                break;
        case PROP_PROXY_URI:
                set_proxy_resolver (session, g_value_get_boxed (value),
                                    NULL, NULL);
                soup_session_abort (session);
+               socket_props_changed = TRUE;
                break;
        case PROP_PROXY_RESOLVER:
                set_proxy_resolver (session, NULL, NULL,
                                    g_value_get_object (value));
+               socket_props_changed = TRUE;
                break;
        case PROP_MAX_CONNS:
                priv->max_conns = g_value_get_int (value);
@@ -633,15 +673,19 @@ soup_session_set_property (GObject *object, guint prop_id,
                break;
        case PROP_SSL_CA_FILE:
                set_ssl_ca_file (session, g_value_get_string (value));
+               socket_props_changed = TRUE;
                break;
        case PROP_SSL_USE_SYSTEM_CA_FILE:
                set_use_system_ca_file (session, g_value_get_boolean (value));
+               socket_props_changed = TRUE;
                break;
        case PROP_TLS_DATABASE:
                set_tlsdb (session, g_value_get_object (value));
+               socket_props_changed = TRUE;
                break;
        case PROP_SSL_STRICT:
                priv->ssl_strict = g_value_get_boolean (value);
+               socket_props_changed = TRUE;
                break;
        case PROP_ASYNC_CONTEXT:
                async_context = g_value_get_pointer (value);
@@ -650,6 +694,7 @@ soup_session_set_property (GObject *object, guint prop_id,
                priv->async_context = async_context;
                if (priv->async_context)
                        g_main_context_ref (priv->async_context);
+               socket_props_changed = TRUE;
                break;
        case PROP_USE_THREAD_CONTEXT:
                if (!g_value_get_boolean (value))
@@ -662,9 +707,11 @@ soup_session_set_property (GObject *object, guint prop_id,
                        if (priv->async_context)
                                g_main_context_ref (priv->async_context);
                }
+               socket_props_changed = TRUE;
                break;
        case PROP_TIMEOUT:
                priv->io_timeout = g_value_get_uint (value);
+               socket_props_changed = TRUE;
                break;
        case PROP_USER_AGENT:
                g_free (priv->user_agent);
@@ -699,6 +746,7 @@ soup_session_set_property (GObject *object, guint prop_id,
                break;
        case PROP_IDLE_TIMEOUT:
                priv->idle_timeout = g_value_get_uint (value);
+               socket_props_changed = TRUE;
                break;
        case PROP_ADD_FEATURE:
                soup_session_add_feature (session, g_value_get_object (value));
@@ -719,30 +767,12 @@ soup_session_set_property (GObject *object, guint prop_id,
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
                break;
        }
-}
 
-static GProxyResolver *
-get_proxy_resolver (SoupSession *session)
-{
-       SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
-
-       if (priv->proxy_use_default) {
-               priv->proxy_resolver = g_object_ref (g_proxy_resolver_get_default ());
-               priv->proxy_use_default = FALSE;
+       if (priv->socket_props && socket_props_changed) {
+               soup_socket_properties_unref (priv->socket_props);
+               priv->socket_props = NULL;
+               ensure_socket_props (session);
        }
-       return priv->proxy_resolver;
-}
-
-static GTlsDatabase *
-get_tls_database (SoupSession *session)
-{
-       SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
-
-       if (priv->tlsdb_use_default) {
-               priv->tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
-               priv->tlsdb_use_default = FALSE;
-       }
-       return priv->tlsdb;
 }
 
 static void
@@ -762,7 +792,8 @@ soup_session_get_property (GObject *object, guint prop_id,
                g_value_set_boxed (value, priv->proxy_uri);
                break;
        case PROP_PROXY_RESOLVER:
-               g_value_set_object (value, get_proxy_resolver (session));
+               ensure_socket_props (session);
+               g_value_set_object (value, priv->proxy_resolver);
                break;
        case PROP_MAX_CONNS:
                g_value_set_int (value, priv->max_conns);
@@ -782,11 +813,13 @@ soup_session_get_property (GObject *object, guint prop_id,
                break;
        case PROP_SSL_USE_SYSTEM_CA_FILE:
                tlsdb = g_tls_backend_get_default_database (g_tls_backend_get_default ());
-               g_value_set_boolean (value, get_tls_database (session) == tlsdb);
+               ensure_socket_props (session);
+               g_value_set_boolean (value, priv->tlsdb == tlsdb);
                g_clear_object (&tlsdb);
                break;
        case PROP_TLS_DATABASE:
-               g_value_set_object (value, get_tls_database (session));
+               ensure_socket_props (session);
+               g_value_set_object (value, priv->tlsdb);
                break;
        case PROP_SSL_STRICT:
                g_value_set_boolean (value, priv->ssl_strict);
@@ -1739,8 +1772,6 @@ get_connection_for_host (SoupSession *session,
        SoupConnection *conn;
        GSList *conns;
        int num_pending = 0;
-       GProxyResolver *proxy_resolver;
-       GTlsDatabase *tlsdb;
 
        if (priv->disposed)
                return FALSE;
@@ -1777,22 +1808,13 @@ get_connection_for_host (SoupSession *session,
                return NULL;
        }
 
-       proxy_resolver = get_proxy_resolver (session);
-       tlsdb = get_tls_database (session);
-
-       conn = g_object_new (
-               SOUP_TYPE_CONNECTION,
-               SOUP_CONNECTION_REMOTE_URI, host->uri,
-               SOUP_CONNECTION_PROXY_RESOLVER, proxy_resolver,
-               SOUP_CONNECTION_SSL_CREDENTIALS, tlsdb,
-               SOUP_CONNECTION_SSL_STRICT, priv->ssl_strict && (tlsdb != NULL || SOUP_IS_PLAIN_SESSION 
(session)),
-               SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
-               SOUP_CONNECTION_USE_THREAD_CONTEXT, priv->use_thread_context,
-               SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
-               SOUP_CONNECTION_IDLE_TIMEOUT, priv->idle_timeout,
-               SOUP_CONNECTION_SSL_FALLBACK, host->ssl_fallback,
-               SOUP_CONNECTION_LOCAL_ADDRESS, priv->local_addr,
-               NULL);
+       ensure_socket_props (session);
+       conn = g_object_new (SOUP_TYPE_CONNECTION,
+                            SOUP_CONNECTION_REMOTE_URI, host->uri,
+                            SOUP_CONNECTION_SSL_FALLBACK, host->ssl_fallback,
+                            SOUP_CONNECTION_SOCKET_PROPERTIES, priv->socket_props,
+                            NULL);
+
        g_signal_connect (conn, "disconnected",
                          G_CALLBACK (connection_disconnected),
                          session);
diff --git a/libsoup/soup-socket-private.h b/libsoup/soup-socket-private.h
index 2f3fbdc..c0c8dca 100644
--- a/libsoup/soup-socket-private.h
+++ b/libsoup/soup-socket-private.h
@@ -8,8 +8,7 @@
 
 #include "soup-socket.h"
 
-#define SOUP_SOCKET_CLEAN_DISPOSE    "clean-dispose"
-#define SOUP_SOCKET_PROXY_RESOLVER   "proxy-resolver"
+#define SOUP_SOCKET_SOCKET_PROPERTIES "socket-properties"
 
 gboolean   soup_socket_connect_sync_internal   (SoupSocket           *sock,
                                                GCancellable         *cancellable,
@@ -41,4 +40,40 @@ GIOStream *soup_socket_get_iostream            (SoupSocket           *sock);
 
 SoupURI   *soup_socket_get_http_proxy_uri      (SoupSocket           *sock);
 
+
+typedef struct {
+       GMainContext *async_context;
+       gboolean use_thread_context;
+
+       GProxyResolver *proxy_resolver;
+       SoupAddress *local_addr;
+
+       GTlsDatabase *tlsdb;
+       gboolean ssl_strict;
+
+       guint io_timeout;
+       guint idle_timeout;
+
+       /*< private >*/
+       guint ref_count;
+} SoupSocketProperties;
+
+GType soup_socket_properties_get_type (void);
+#define SOUP_TYPE_SOCKET_PROPERTIES (soup_socket_properties_get_type ())
+
+SoupSocketProperties *soup_socket_properties_new   (GMainContext   *async_context,
+                                                   gboolean        use_thread_context,
+                                                   GProxyResolver *proxy_resolver,
+                                                   SoupAddress    *local_addr,
+                                                   GTlsDatabase   *tlsdb,
+                                                   gboolean        ssl_strict,
+                                                   guint           io_timeout,
+                                                   guint           idle_timeout);
+
+SoupSocketProperties *soup_socket_properties_ref   (SoupSocketProperties *props);
+void                  soup_socket_properties_unref (SoupSocketProperties *props);
+
+void soup_socket_properties_push_async_context (SoupSocketProperties *props);
+void soup_socket_properties_pop_async_context  (SoupSocketProperties *props);
+
 #endif /* SOUP_SOCKET_PRIVATE_H */
diff --git a/libsoup/soup-socket-properties.c b/libsoup/soup-socket-properties.c
new file mode 100644
index 0000000..a7ed512
--- /dev/null
+++ b/libsoup/soup-socket-properties.c
@@ -0,0 +1,74 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright 2013 Red Hat, Inc.
+ */
+
+#include "soup-socket-private.h"
+#include "soup.h"
+
+SoupSocketProperties *
+soup_socket_properties_new (GMainContext   *async_context,
+                           gboolean        use_thread_context,
+                           GProxyResolver *proxy_resolver,
+                           SoupAddress    *local_addr,
+                           GTlsDatabase   *tlsdb,
+                           gboolean        ssl_strict,
+                           guint           io_timeout,
+                           guint           idle_timeout)
+{
+       SoupSocketProperties *props;
+
+       props = g_slice_new (SoupSocketProperties);
+       props->ref_count = 1;
+
+       props->async_context = async_context ? g_main_context_ref (async_context) : NULL;
+       props->use_thread_context = use_thread_context;
+
+       props->proxy_resolver = proxy_resolver ? g_object_ref (proxy_resolver) : NULL;
+       props->local_addr = local_addr ? g_object_ref (local_addr) : NULL;
+
+       props->tlsdb = tlsdb ? g_object_ref (tlsdb) : NULL;
+       props->ssl_strict = ssl_strict;
+
+       props->io_timeout = io_timeout;
+       props->idle_timeout = idle_timeout;
+
+       return props;
+}
+
+SoupSocketProperties *
+soup_socket_properties_ref (SoupSocketProperties *props)
+{
+       props->ref_count++;
+       return props;
+}
+
+void
+soup_socket_properties_unref (SoupSocketProperties *props)
+{
+       if (--props->ref_count)
+               return;
+
+       g_clear_pointer (&props->async_context, g_main_context_unref);
+       g_clear_object (&props->proxy_resolver);
+       g_clear_object (&props->local_addr);
+       g_clear_object (&props->tlsdb);
+
+       g_slice_free (SoupSocketProperties, props);
+}
+
+void
+soup_socket_properties_push_async_context (SoupSocketProperties *props)
+{
+       if (props->async_context && !props->use_thread_context)
+               g_main_context_push_thread_default (props->async_context);
+}
+
+void
+soup_socket_properties_pop_async_context (SoupSocketProperties *props)
+{
+       if (props->async_context && !props->use_thread_context)
+               g_main_context_pop_thread_default (props->async_context);
+}
+
+G_DEFINE_BOXED_TYPE (SoupSocketProperties, soup_socket_properties, soup_socket_properties_ref, 
soup_socket_properties_unref)
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 9b9b540..651e960 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -56,10 +56,9 @@ enum {
        PROP_USE_THREAD_CONTEXT,
        PROP_TIMEOUT,
        PROP_TRUSTED_CERTIFICATE,
-       PROP_CLEAN_DISPOSE,
        PROP_TLS_CERTIFICATE,
        PROP_TLS_ERRORS,
-       PROP_PROXY_RESOLVER,
+       PROP_SOCKET_PROPERTIES,
 
        LAST_PROP
 };
@@ -151,6 +150,7 @@ soup_socket_finalize (GObject *object)
        g_clear_object (&priv->remote_addr);
 
        g_clear_object (&priv->proxy_resolver);
+       g_clear_object (&priv->ssl_creds);
 
        if (priv->watch_src) {
                if (priv->clean_dispose && !priv->is_server)
@@ -190,6 +190,7 @@ soup_socket_set_property (GObject *object, guint prop_id,
                          const GValue *value, GParamSpec *pspec)
 {
        SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (object);
+       SoupSocketProperties *props;
 
        switch (prop_id) {
        case PROP_LOCAL_ADDRESS:
@@ -203,6 +204,8 @@ soup_socket_set_property (GObject *object, guint prop_id,
                break;
        case PROP_SSL_CREDENTIALS:
                priv->ssl_creds = g_value_get_pointer (value);
+               if (priv->ssl_creds)
+                       g_object_ref (priv->ssl_creds);
                break;
        case PROP_SSL_STRICT:
                priv->ssl_strict = g_value_get_boolean (value);
@@ -223,11 +226,32 @@ soup_socket_set_property (GObject *object, guint prop_id,
                if (priv->conn)
                        g_socket_set_timeout (priv->gsock, priv->timeout);
                break;
-       case PROP_PROXY_RESOLVER:
-               priv->proxy_resolver = g_value_dup_object (value);
-               break;
-       case PROP_CLEAN_DISPOSE:
-               priv->clean_dispose = g_value_get_boolean (value);
+       case PROP_SOCKET_PROPERTIES:
+               props = g_value_get_boxed (value);
+               if (props) {
+                       g_clear_pointer (&priv->async_context, g_main_context_unref);
+                       if (props->async_context)
+                               priv->async_context = g_main_context_ref (props->async_context);
+                       priv->use_thread_context = props->use_thread_context;
+
+                       g_clear_object (&priv->proxy_resolver);
+                       if (props->proxy_resolver)
+                               priv->proxy_resolver = g_object_ref (props->proxy_resolver);
+                       g_clear_object (&priv->local_addr);
+                       if (props->local_addr)
+                               priv->local_addr = g_object_ref (props->local_addr);
+
+                       g_clear_object (&priv->ssl_creds);
+                       if (props->tlsdb)
+                               priv->ssl_creds = g_object_ref (props->tlsdb);
+                       priv->ssl_strict = props->ssl_strict;
+
+                       priv->timeout = props->io_timeout;
+                       if (priv->conn)
+                               g_socket_set_timeout (priv->gsock, priv->timeout);
+
+                       priv->clean_dispose = TRUE;
+               }
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -284,8 +308,6 @@ soup_socket_get_property (GObject *object, guint prop_id,
        case PROP_TLS_ERRORS:
                g_value_set_flags (value, priv->tls_errors);
                break;
-       case PROP_PROXY_RESOLVER:
-               g_value_set_object (value, priv->proxy_resolver);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -579,13 +601,6 @@ soup_socket_class_init (SoupSocketClass *socket_class)
                                   0, G_MAXUINT, 0,
                                   G_PARAM_READWRITE));
 
-       g_object_class_install_property (
-               object_class, PROP_CLEAN_DISPOSE,
-               g_param_spec_boolean ("clean-dispose",
-                                     "Clean dispose",
-                                     "Warn on unclean dispose",
-                                     FALSE,
-                                     G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
        /**
         * SOUP_SOCKET_TLS_CERTIFICATE:
         *
@@ -622,12 +637,12 @@ soup_socket_class_init (SoupSocketClass *socket_class)
                                    G_PARAM_READABLE));
 
        g_object_class_install_property (
-               object_class, PROP_PROXY_RESOLVER,
-               g_param_spec_object (SOUP_SOCKET_PROXY_RESOLVER,
-                                    "Proxy resolver",
-                                    "GProxyResolver to use",
-                                    G_TYPE_PROXY_RESOLVER,
-                                    G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+                object_class, PROP_SOCKET_PROPERTIES,
+                g_param_spec_boxed (SOUP_SOCKET_SOCKET_PROPERTIES,
+                                    "Socket properties",
+                                    "Socket properties",
+                                    SOUP_TYPE_SOCKET_PROPERTIES,
+                                    G_PARAM_WRITABLE));
 }
 
 
@@ -1004,7 +1019,7 @@ listen_watch (GObject *pollable, gpointer data)
        new_priv->is_server = TRUE;
        new_priv->ssl = priv->ssl;
        if (priv->ssl_creds)
-               new_priv->ssl_creds = priv->ssl_creds;
+               new_priv->ssl_creds = g_object_ref (priv->ssl_creds);
        finish_socket_setup (new_priv);
 
        if (new_priv->ssl_creds) {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]