diff options
Diffstat (limited to 'libsoup/soup-session.c')
-rw-r--r-- | libsoup/soup-session.c | 245 |
1 files changed, 132 insertions, 113 deletions
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 78511564..a0820964 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -33,7 +33,7 @@ typedef struct { GHashTable *auths; /* scheme:realm -> SoupAuth */ } SoupSessionHost; -struct SoupSessionPrivate { +typedef struct { SoupUri *proxy_uri; guint max_conns, max_conns_per_host; gboolean use_ntlm; @@ -54,11 +54,12 @@ struct SoupSessionPrivate { * Must not emit signals or destroy objects while holding it. */ GMutex *host_lock; -}; +} SoupSessionPrivate; +#define SOUP_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_SESSION, SoupSessionPrivate)) static guint host_uri_hash (gconstpointer key); static gboolean host_uri_equal (gconstpointer v1, gconstpointer v2); -static void free_host (SoupSessionHost *host, SoupSession *session); +static void free_host (SoupSessionHost *host); static void setup_message (SoupMessageFilter *filter, SoupMessage *msg); @@ -71,8 +72,11 @@ static void cancel_message (SoupSession *session, SoupMessage *msg); #define SOUP_SESSION_MAX_CONNS_DEFAULT 10 #define SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT 4 -#define PARENT_TYPE G_TYPE_OBJECT -static GObjectClass *parent_class; +static void filter_iface_init (SoupMessageFilterClass *filter_class); + +G_DEFINE_TYPE_EXTENDED (SoupSession, soup_session, G_TYPE_OBJECT, 0, + G_IMPLEMENT_INTERFACE (SOUP_TYPE_MESSAGE_FILTER, + filter_iface_init)) enum { AUTHENTICATE, @@ -83,15 +87,15 @@ enum { static guint signals[LAST_SIGNAL] = { 0 }; enum { - PROP_0, + PROP_0, - PROP_PROXY_URI, - PROP_MAX_CONNS, - PROP_MAX_CONNS_PER_HOST, - PROP_USE_NTLM, - PROP_SSL_CA_FILE, + PROP_PROXY_URI, + PROP_MAX_CONNS, + PROP_MAX_CONNS_PER_HOST, + PROP_USE_NTLM, + PROP_SSL_CA_FILE, - LAST_PROP + LAST_PROP }; static void set_property (GObject *object, guint prop_id, @@ -100,74 +104,74 @@ static void get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static void -init (GObject *object) +soup_session_init (SoupSession *session) { - SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - session->priv = g_new0 (SoupSessionPrivate, 1); - session->priv->host_lock = g_mutex_new (); session->queue = soup_message_queue_new (); - session->priv->hosts = g_hash_table_new (host_uri_hash, - host_uri_equal); - session->priv->conns = g_hash_table_new (NULL, NULL); - session->priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT; - session->priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT; + priv->host_lock = g_mutex_new (); + priv->hosts = g_hash_table_new (host_uri_hash, host_uri_equal); + priv->conns = g_hash_table_new (NULL, NULL); + + priv->max_conns = SOUP_SESSION_MAX_CONNS_DEFAULT; + priv->max_conns_per_host = SOUP_SESSION_MAX_CONNS_PER_HOST_DEFAULT; } static gboolean -foreach_free_host (gpointer key, gpointer host, gpointer session) +foreach_free_host (gpointer key, gpointer host, gpointer data) { - free_host (host, session); + free_host (host); return TRUE; } static void -cleanup_hosts (SoupSession *session) +cleanup_hosts (SoupSessionPrivate *priv) { - g_hash_table_foreach_remove (session->priv->hosts, - foreach_free_host, session); + g_hash_table_foreach_remove (priv->hosts, foreach_free_host, NULL); } static void dispose (GObject *object) { SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GSList *f; soup_session_abort (session); - cleanup_hosts (session); + cleanup_hosts (priv); - if (session->priv->filters) { - for (f = session->priv->filters; f; f = f->next) + if (priv->filters) { + for (f = priv->filters; f; f = f->next) g_object_unref (f->data); - g_slist_free (session->priv->filters); - session->priv->filters = NULL; + g_slist_free (priv->filters); + priv->filters = NULL; } - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (soup_session_parent_class)->dispose (object); } static void finalize (GObject *object) { SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - g_mutex_free (session->priv->host_lock); soup_message_queue_destroy (session->queue); - g_hash_table_destroy (session->priv->hosts); - g_hash_table_destroy (session->priv->conns); - g_free (session->priv); - G_OBJECT_CLASS (parent_class)->finalize (object); + g_mutex_free (priv->host_lock); + g_hash_table_destroy (priv->hosts); + g_hash_table_destroy (priv->conns); + + G_OBJECT_CLASS (soup_session_parent_class)->finalize (object); } static void -class_init (GObjectClass *object_class) +soup_session_class_init (SoupSessionClass *session_class) { - SoupSessionClass *session_class = SOUP_SESSION_CLASS (object_class); + GObjectClass *object_class = G_OBJECT_CLASS (session_class); - parent_class = g_type_class_ref (PARENT_TYPE); + g_type_class_add_private (session_class, sizeof (SoupSessionPrivate)); /* virtual method definition */ session_class->queue_message = queue_message; @@ -243,10 +247,10 @@ class_init (GObjectClass *object_class) g_object_class_install_property ( object_class, PROP_SSL_CA_FILE, g_param_spec_string (SOUP_SESSION_SSL_CA_FILE, - "SSL CA file", - "File containing SSL CA certificates", - NULL, - G_PARAM_READWRITE)); + "SSL CA file", + "File containing SSL CA certificates", + NULL, + G_PARAM_READWRITE)); } static void @@ -256,7 +260,6 @@ filter_iface_init (SoupMessageFilterClass *filter_class) filter_class->setup_message = setup_message; } -SOUP_MAKE_TYPE_WITH_IFACE (soup_session, SoupSession, class_init, init, PARENT_TYPE, filter_iface_init, SOUP_TYPE_MESSAGE_FILTER) static gboolean safe_uri_equal (const SoupUri *a, const SoupUri *b) @@ -287,6 +290,7 @@ set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); gpointer pval; gboolean need_abort = FALSE; gboolean ca_file_changed = FALSE; @@ -296,45 +300,45 @@ set_property (GObject *object, guint prop_id, case PROP_PROXY_URI: pval = g_value_get_pointer (value); - if (!safe_uri_equal (session->priv->proxy_uri, pval)) + if (!safe_uri_equal (priv->proxy_uri, pval)) need_abort = TRUE; - if (session->priv->proxy_uri) - soup_uri_free (session->priv->proxy_uri); + if (priv->proxy_uri) + soup_uri_free (priv->proxy_uri); - session->priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL; + priv->proxy_uri = pval ? soup_uri_copy (pval) : NULL; if (need_abort) { soup_session_abort (session); - cleanup_hosts (session); + cleanup_hosts (priv); } break; case PROP_MAX_CONNS: - session->priv->max_conns = g_value_get_int (value); + priv->max_conns = g_value_get_int (value); break; case PROP_MAX_CONNS_PER_HOST: - session->priv->max_conns_per_host = g_value_get_int (value); + priv->max_conns_per_host = g_value_get_int (value); break; case PROP_USE_NTLM: - session->priv->use_ntlm = g_value_get_boolean (value); + priv->use_ntlm = g_value_get_boolean (value); break; case PROP_SSL_CA_FILE: new_ca_file = g_value_get_string (value); - if (!safe_str_equal (session->priv->ssl_ca_file, new_ca_file)) + if (!safe_str_equal (priv->ssl_ca_file, new_ca_file)) ca_file_changed = TRUE; - g_free (session->priv->ssl_ca_file); - session->priv->ssl_ca_file = g_strdup (new_ca_file); + g_free (priv->ssl_ca_file); + priv->ssl_ca_file = g_strdup (new_ca_file); if (ca_file_changed) { - if (session->priv->ssl_creds) { - soup_ssl_free_client_credentials (session->priv->ssl_creds); - session->priv->ssl_creds = NULL; + if (priv->ssl_creds) { + soup_ssl_free_client_credentials (priv->ssl_creds); + priv->ssl_creds = NULL; } - cleanup_hosts (session); + cleanup_hosts (priv); } break; @@ -348,24 +352,25 @@ get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { SoupSession *session = SOUP_SESSION (object); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); switch (prop_id) { case PROP_PROXY_URI: - g_value_set_pointer (value, session->priv->proxy_uri ? - soup_uri_copy (session->priv->proxy_uri) : + g_value_set_pointer (value, priv->proxy_uri ? + soup_uri_copy (priv->proxy_uri) : NULL); break; case PROP_MAX_CONNS: - g_value_set_int (value, session->priv->max_conns); + g_value_set_int (value, priv->max_conns); break; case PROP_MAX_CONNS_PER_HOST: - g_value_set_int (value, session->priv->max_conns_per_host); + g_value_set_int (value, priv->max_conns_per_host); break; case PROP_USE_NTLM: - g_value_set_boolean (value, session->priv->use_ntlm); + g_value_set_boolean (value, priv->use_ntlm); break; case PROP_SSL_CA_FILE: - g_value_set_string (value, session->priv->ssl_ca_file); + g_value_set_string (value, priv->ssl_ca_file); break; default: break; @@ -384,12 +389,14 @@ get_property (GObject *object, guint prop_id, void soup_session_add_filter (SoupSession *session, SoupMessageFilter *filter) { + SoupSessionPrivate *priv; + g_return_if_fail (SOUP_IS_SESSION (session)); g_return_if_fail (SOUP_IS_MESSAGE_FILTER (filter)); + priv = SOUP_SESSION_GET_PRIVATE (session); g_object_ref (filter); - session->priv->filters = g_slist_prepend (session->priv->filters, - filter); + priv->filters = g_slist_prepend (priv->filters, filter); } /** @@ -402,11 +409,13 @@ soup_session_add_filter (SoupSession *session, SoupMessageFilter *filter) void soup_session_remove_filter (SoupSession *session, SoupMessageFilter *filter) { + SoupSessionPrivate *priv; + g_return_if_fail (SOUP_IS_SESSION (session)); g_return_if_fail (SOUP_IS_MESSAGE_FILTER (filter)); + priv = SOUP_SESSION_GET_PRIVATE (session); - session->priv->filters = g_slist_remove (session->priv->filters, - filter); + priv->filters = g_slist_remove (priv->filters, filter); g_object_unref (filter); } @@ -437,15 +446,16 @@ host_uri_equal (gconstpointer v1, gconstpointer v2) static SoupSessionHost * soup_session_host_new (SoupSession *session, const SoupUri *source_uri) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupSessionHost *host; host = g_new0 (SoupSessionHost, 1); host->root_uri = soup_uri_copy_root (source_uri); if (host->root_uri->protocol == SOUP_PROTOCOL_HTTPS && - !session->priv->ssl_creds) { - session->priv->ssl_creds = - soup_ssl_get_client_credentials (session->priv->ssl_ca_file); + !priv->ssl_creds) { + priv->ssl_creds = + soup_ssl_get_client_credentials (priv->ssl_ca_file); } return host; @@ -458,15 +468,16 @@ soup_session_host_new (SoupSession *session, const SoupUri *source_uri) static SoupSessionHost * get_host_for_message (SoupSession *session, SoupMessage *msg) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupSessionHost *host; const SoupUri *source = soup_message_get_uri (msg); - host = g_hash_table_lookup (session->priv->hosts, source); + host = g_hash_table_lookup (priv->hosts, source); if (host) return host; host = soup_session_host_new (session, source); - g_hash_table_insert (session->priv->hosts, host->root_uri, host); + g_hash_table_insert (priv->hosts, host->root_uri, host); return host; } @@ -477,12 +488,14 @@ get_host_for_message (SoupSession *session, SoupMessage *msg) static SoupSessionHost * get_proxy_host (SoupSession *session) { - if (session->priv->proxy_host || !session->priv->proxy_uri) - return session->priv->proxy_host; + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); + + if (priv->proxy_host || !priv->proxy_uri) + return priv->proxy_host; - session->priv->proxy_host = - soup_session_host_new (session, session->priv->proxy_uri); - return session->priv->proxy_host; + priv->proxy_host = + soup_session_host_new (session, priv->proxy_uri); + return priv->proxy_host; } static void @@ -500,7 +513,7 @@ free_auth (gpointer scheme_realm, gpointer auth, gpointer data) } static void -free_host (SoupSessionHost *host, SoupSession *session) +free_host (SoupSessionHost *host) { while (host->connections) { SoupConnection *conn = host->connections->data; @@ -589,11 +602,12 @@ authenticate_auth (SoupSession *session, SoupAuth *auth, SoupMessage *msg, gboolean prior_auth_failed, gboolean proxy) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); const SoupUri *uri; char *username = NULL, *password = NULL; if (proxy) - uri = session->priv->proxy_uri; + uri = priv->proxy_uri; else uri = soup_message_get_uri (msg); @@ -821,9 +835,10 @@ static void setup_message (SoupMessageFilter *filter, SoupMessage *msg) { SoupSession *session = SOUP_SESSION (filter); + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); GSList *f; - for (f = session->priv->filters; f; f = f->next) { + for (f = priv->filters; f; f = f->next) { filter = f->data; soup_message_filter_setup_message (filter, msg); } @@ -834,7 +849,7 @@ setup_message (SoupMessageFilter *filter, SoupMessage *msg) SOUP_HANDLER_POST_BODY, authorize_handler, session); - if (session->priv->proxy_uri) { + if (priv->proxy_uri) { add_auth (session, msg, TRUE); soup_message_add_status_code_handler ( msg, SOUP_STATUS_PROXY_UNAUTHORIZED, @@ -873,22 +888,23 @@ find_oldest_connection (gpointer key, gpointer host, gpointer data) gboolean soup_session_try_prune_connection (SoupSession *session) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupConnection *oldest = NULL; - g_mutex_lock (session->priv->host_lock); - g_hash_table_foreach (session->priv->conns, find_oldest_connection, + g_mutex_lock (priv->host_lock); + g_hash_table_foreach (priv->conns, find_oldest_connection, &oldest); if (oldest) { /* Ref the connection before unlocking the mutex in * case someone else tries to prune it too. */ g_object_ref (oldest); - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); soup_connection_disconnect (oldest); g_object_unref (oldest); return TRUE; } else { - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); return FALSE; } } @@ -897,21 +913,22 @@ static void connection_disconnected (SoupConnection *conn, gpointer user_data) { SoupSession *session = user_data; + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupSessionHost *host; - g_mutex_lock (session->priv->host_lock); + g_mutex_lock (priv->host_lock); - host = g_hash_table_lookup (session->priv->conns, conn); + host = g_hash_table_lookup (priv->conns, conn); if (host) { - g_hash_table_remove (session->priv->conns, conn); + g_hash_table_remove (priv->conns, conn); host->connections = g_slist_remove (host->connections, conn); host->num_conns--; } g_signal_handlers_disconnect_by_func (conn, connection_disconnected, session); - session->priv->num_conns--; + priv->num_conns--; - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); g_object_unref (conn); } @@ -919,27 +936,28 @@ static void connect_result (SoupConnection *conn, guint status, gpointer user_data) { SoupSession *session = user_data; + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupSessionHost *host; SoupMessageQueueIter iter; SoupMessage *msg; - g_mutex_lock (session->priv->host_lock); + g_mutex_lock (priv->host_lock); - host = g_hash_table_lookup (session->priv->conns, conn); + host = g_hash_table_lookup (priv->conns, conn); if (!host) { - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); return; } if (status == SOUP_STATUS_OK) { soup_connection_reserve (conn); host->connections = g_slist_prepend (host->connections, conn); - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); return; } /* The connection failed. */ - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); connection_disconnected (conn, session); if (host->connections) { @@ -1014,17 +1032,18 @@ SoupConnection * soup_session_get_connection (SoupSession *session, SoupMessage *msg, gboolean *try_pruning, gboolean *is_new) { + SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupConnection *conn; SoupSessionHost *host; GSList *conns; - g_mutex_lock (session->priv->host_lock); + g_mutex_lock (priv->host_lock); host = get_host_for_message (session, msg); for (conns = host->connections; conns; conns = conns->next) { if (!soup_connection_is_in_use (conns->data)) { soup_connection_reserve (conns->data); - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); *is_new = FALSE; return conns->data; } @@ -1034,33 +1053,33 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg, /* We already started a connection for this * message, so don't start another one. */ - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); return NULL; } - if (host->num_conns >= session->priv->max_conns_per_host) { - g_mutex_unlock (session->priv->host_lock); + if (host->num_conns >= priv->max_conns_per_host) { + g_mutex_unlock (priv->host_lock); return NULL; } - if (session->priv->num_conns >= session->priv->max_conns) { + if (priv->num_conns >= priv->max_conns) { *try_pruning = TRUE; - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); return NULL; } - /* Make sure session->priv->proxy_host gets set now while + /* Make sure priv->proxy_host gets set now while * we have the host_lock. */ - if (session->priv->proxy_uri) + if (priv->proxy_uri) get_proxy_host (session); conn = g_object_new ( - (session->priv->use_ntlm ? + (priv->use_ntlm ? SOUP_TYPE_CONNECTION_NTLM : SOUP_TYPE_CONNECTION), SOUP_CONNECTION_ORIGIN_URI, host->root_uri, - SOUP_CONNECTION_PROXY_URI, session->priv->proxy_uri, - SOUP_CONNECTION_SSL_CREDENTIALS, session->priv->ssl_creds, + SOUP_CONNECTION_PROXY_URI, priv->proxy_uri, + SOUP_CONNECTION_SSL_CREDENTIALS, priv->ssl_creds, SOUP_CONNECTION_MESSAGE_FILTER, session, NULL); g_signal_connect (conn, "connect_result", @@ -1076,13 +1095,13 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg, G_CALLBACK (connection_reauthenticate), session); - g_hash_table_insert (session->priv->conns, conn, host); + g_hash_table_insert (priv->conns, conn, host); /* We increment the connection counts so it counts against the * totals, but we don't add it to the host's connection list * yet, since it's not ready for use. */ - session->priv->num_conns++; + priv->num_conns++; host->num_conns++; /* Mark the request as connecting, so we don't try to open @@ -1090,7 +1109,7 @@ soup_session_get_connection (SoupSession *session, SoupMessage *msg, */ msg->status = SOUP_MESSAGE_STATUS_CONNECTING; - g_mutex_unlock (session->priv->host_lock); + g_mutex_unlock (priv->host_lock); *is_new = TRUE; return conn; } |