diff options
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | libsoup/soup-address.c | 50 | ||||
-rw-r--r-- | libsoup/soup-address.h | 1 | ||||
-rw-r--r-- | libsoup/soup-connection.c | 259 | ||||
-rw-r--r-- | libsoup/soup-connection.h | 11 | ||||
-rw-r--r-- | libsoup/soup-message-queue.h | 4 | ||||
-rw-r--r-- | libsoup/soup-misc-private.h | 4 | ||||
-rw-r--r-- | libsoup/soup-session-async.c | 99 | ||||
-rw-r--r-- | libsoup/soup-session-sync.c | 36 | ||||
-rw-r--r-- | libsoup/soup-session.c | 38 | ||||
-rw-r--r-- | libsoup/soup-socket.c | 44 |
11 files changed, 276 insertions, 273 deletions
diff --git a/configure.ac b/configure.ac index 97741934..51757fb4 100644 --- a/configure.ac +++ b/configure.ac @@ -72,8 +72,7 @@ dnl *********************** dnl *** Checks for glib *** dnl *********************** -dnl FIXME: should actually be 2.33.0, but glib hasn't bumped yet -GLIB_REQUIRED=2.32.2 +GLIB_REQUIRED=2.33.1 AM_PATH_GLIB_2_0($GLIB_REQUIRED,,,gobject gio) if test "$GLIB_LIBS" = ""; then AC_MSG_ERROR(GLIB $GLIB_REQUIRED or later is required to build libsoup) diff --git a/libsoup/soup-address.c b/libsoup/soup-address.c index 1ac2d328..5f5040f1 100644 --- a/libsoup/soup-address.c +++ b/libsoup/soup-address.c @@ -38,6 +38,7 @@ enum { PROP_NAME, PROP_FAMILY, PROP_PORT, + PROP_PROTOCOL, PROP_PHYSICAL, PROP_SOCKADDR, @@ -50,6 +51,7 @@ typedef struct { char *name, *physical; guint port; + const char *protocol; GMutex lock; GSList *async_lookups; @@ -106,6 +108,7 @@ static void get_property (GObject *object, guint prop_id, static void soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface); static GSocketAddressEnumerator *soup_address_connectable_enumerate (GSocketConnectable *connectable); +static GSocketAddressEnumerator *soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable); G_DEFINE_TYPE_WITH_CODE (SoupAddress, soup_address, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, @@ -192,6 +195,19 @@ soup_address_class_init (SoupAddressClass *address_class) -1, 65535, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); /** + * SOUP_ADDRESS_PROTOCOL: + * + * Alias for the #SoupAddress:protocol property. (The URI scheme + * used with this address.) + **/ + g_object_class_install_property ( + object_class, PROP_PROTOCOL, + g_param_spec_string (SOUP_ADDRESS_PROTOCOL, + "Protocol", + "URI scheme for this address", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + /** * SOUP_ADDRESS_PHYSICAL: * * An alias for the #SoupAddress:physical property. (The @@ -221,7 +237,8 @@ soup_address_class_init (SoupAddressClass *address_class) static void soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface) { - connectable_iface->enumerate = soup_address_connectable_enumerate; + connectable_iface->enumerate = soup_address_connectable_enumerate; + connectable_iface->proxy_enumerate = soup_address_connectable_proxy_enumerate; } static GObject * @@ -289,6 +306,10 @@ set_property (GObject *object, guint prop_id, SOUP_ADDRESS_SET_PORT (priv, htons (port)); break; + case PROP_PROTOCOL: + priv->protocol = g_intern_string (g_value_get_string (value)); + break; + case PROP_SOCKADDR: sa = g_value_get_pointer (value); if (!sa) @@ -328,6 +349,9 @@ get_property (GObject *object, guint prop_id, case PROP_PHYSICAL: g_value_set_string (value, soup_address_get_physical (SOUP_ADDRESS (object))); break; + case PROP_PROTOCOL: + g_value_set_string (value, priv->protocol); + break; case PROP_SOCKADDR: g_value_set_pointer (value, priv->sockaddr); break; @@ -1197,3 +1221,27 @@ soup_address_connectable_enumerate (GSocketConnectable *connectable) return (GSocketAddressEnumerator *)addr_enum; } + +static GSocketAddressEnumerator * +soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable) +{ + SoupAddress *addr = SOUP_ADDRESS (connectable); + SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr); + GSocketAddressEnumerator *proxy_enum; + char *uri; + + /* We cheerily assume "http" here because you shouldn't be + * using SoupAddress any more if you're not doing HTTP anyway. + */ + uri = g_strdup_printf ("%s://%s:%u", + priv->protocol ? priv->protocol : "http", + priv->name ? priv->name : soup_address_get_physical (addr), + priv->port); + proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR, + "connectable", connectable, + "uri", uri, + NULL); + g_free (uri); + + return proxy_enum; +} diff --git a/libsoup/soup-address.h b/libsoup/soup-address.h index 3cea001f..579d1d3c 100644 --- a/libsoup/soup-address.h +++ b/libsoup/soup-address.h @@ -38,6 +38,7 @@ typedef struct { #define SOUP_ADDRESS_NAME "name" #define SOUP_ADDRESS_FAMILY "family" #define SOUP_ADDRESS_PORT "port" +#define SOUP_ADDRESS_PROTOCOL "protocol" #define SOUP_ADDRESS_PHYSICAL "physical" #define SOUP_ADDRESS_SOCKADDR "sockaddr" diff --git a/libsoup/soup-connection.c b/libsoup/soup-connection.c index fffa9543..9b079fa4 100644 --- a/libsoup/soup-connection.c +++ b/libsoup/soup-connection.c @@ -25,6 +25,8 @@ #include "soup-message-queue.h" #include "soup-misc.h" #include "soup-misc-private.h" +#include "soup-proxy-uri-resolver.h" +#include "soup-proxy-resolver-default.h" #include "soup-socket.h" #include "soup-uri.h" #include "soup-enum-types.h" @@ -32,10 +34,11 @@ typedef struct { SoupSocket *socket; - SoupAddress *remote_addr, *tunnel_addr; - SoupURI *proxy_uri; + SoupURI *remote_uri, *proxy_uri; + SoupProxyURIResolver *proxy_resolver; + gboolean use_gproxyresolver; GTlsDatabase *tlsdb; - gboolean ssl, ssl_strict, ssl_fallback; + gboolean ssl, ssl_strict, ssl_fallback; GMainContext *async_context; gboolean use_thread_context; @@ -61,9 +64,8 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, - PROP_REMOTE_ADDRESS, - PROP_TUNNEL_ADDRESS, - PROP_PROXY_URI, + PROP_REMOTE_URI, + PROP_PROXY_RESOLVER, PROP_SSL, PROP_SSL_CREDS, PROP_SSL_STRICT, @@ -94,7 +96,6 @@ static void clear_current_item (SoupConnection *conn); static void soup_connection_init (SoupConnection *conn) { - ; } static void @@ -102,14 +103,15 @@ finalize (GObject *object) { SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object); - if (priv->remote_addr) - g_object_unref (priv->remote_addr); - if (priv->tunnel_addr) - g_object_unref (priv->tunnel_addr); + if (priv->remote_uri) + soup_uri_free (priv->remote_uri); if (priv->proxy_uri) soup_uri_free (priv->proxy_uri); if (priv->tlsdb) g_object_unref (priv->tlsdb); + if (priv->proxy_resolver) + g_object_unref (priv->proxy_resolver); + if (priv->async_context) g_main_context_unref (priv->async_context); @@ -173,26 +175,19 @@ soup_connection_class_init (SoupConnectionClass *connection_class) /* properties */ g_object_class_install_property ( - object_class, PROP_REMOTE_ADDRESS, - g_param_spec_object (SOUP_CONNECTION_REMOTE_ADDRESS, - "Remote address", - "The address of the HTTP or proxy server", - SOUP_TYPE_ADDRESS, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( - object_class, PROP_TUNNEL_ADDRESS, - g_param_spec_object (SOUP_CONNECTION_TUNNEL_ADDRESS, - "Tunnel address", - "The address of the HTTPS server this tunnel connects to", - SOUP_TYPE_ADDRESS, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property ( - object_class, PROP_PROXY_URI, - g_param_spec_boxed (SOUP_CONNECTION_PROXY_URI, - "Proxy URI", - "URI of the HTTP proxy this connection connects to", + object_class, PROP_REMOTE_URI, + g_param_spec_boxed (SOUP_CONNECTION_REMOTE_URI, + "Remote URI", + "The URI of the HTTP server", SOUP_TYPE_URI, - G_PARAM_READWRITE)); + 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", + "SoupProxyURIResolver to use", + SOUP_TYPE_PROXY_URI_RESOLVER, + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); g_object_class_install_property ( object_class, PROP_SSL, g_param_spec_boolean (SOUP_CONNECTION_SSL, @@ -264,38 +259,23 @@ soup_connection_class_init (SoupConnectionClass *connection_class) G_PARAM_READABLE)); } - -SoupConnection * -soup_connection_new (const char *propname1, ...) -{ - SoupConnection *conn; - va_list ap; - - va_start (ap, propname1); - conn = (SoupConnection *)g_object_new_valist (SOUP_TYPE_CONNECTION, - propname1, ap); - va_end (ap); - - return conn; -} - static void set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object); + SoupProxyURIResolver *proxy_resolver; switch (prop_id) { - case PROP_REMOTE_ADDRESS: - priv->remote_addr = g_value_dup_object (value); - break; - case PROP_TUNNEL_ADDRESS: - priv->tunnel_addr = g_value_dup_object (value); + case PROP_REMOTE_URI: + priv->remote_uri = g_value_dup_boxed (value); break; - case PROP_PROXY_URI: - if (priv->proxy_uri) - soup_uri_free (priv->proxy_uri); - priv->proxy_uri = g_value_dup_boxed (value); + case PROP_PROXY_RESOLVER: + proxy_resolver = g_value_get_object (value); + if (proxy_resolver && SOUP_IS_PROXY_RESOLVER_DEFAULT (proxy_resolver)) + priv->use_gproxyresolver = TRUE; + else if (proxy_resolver) + priv->proxy_resolver = g_object_ref (proxy_resolver); break; case PROP_SSL: priv->ssl = g_value_get_boolean (value); @@ -341,14 +321,8 @@ get_property (GObject *object, guint prop_id, SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (object); switch (prop_id) { - case PROP_REMOTE_ADDRESS: - g_value_set_object (value, priv->remote_addr); - break; - case PROP_TUNNEL_ADDRESS: - g_value_set_object (value, priv->tunnel_addr); - break; - case PROP_PROXY_URI: - g_value_set_boxed (value, priv->proxy_uri); + case PROP_REMOTE_URI: + g_value_set_boxed (value, priv->remote_uri); break; case PROP_SSL: g_value_set_boolean (value, priv->ssl); @@ -531,7 +505,6 @@ typedef struct { gpointer callback_data; GCancellable *cancellable; guint event_id; - gboolean tls_handshake; } SoupConnectionAsyncConnectData; static void @@ -546,12 +519,12 @@ socket_connect_finished (SoupSocket *socket, guint status, gpointer user_data) g_signal_connect (priv->socket, "disconnected", G_CALLBACK (socket_disconnected), data->conn); - if (data->tls_handshake) { + if (priv->ssl && !priv->proxy_uri) { soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKED, NULL); } - if (!priv->ssl || !priv->tunnel_addr) { + if (!priv->ssl || !priv->proxy_uri) { soup_connection_event (data->conn, G_SOCKET_CLIENT_COMPLETE, NULL); @@ -580,9 +553,17 @@ static void socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) { SoupConnectionAsyncConnectData *data = user_data; + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + + if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { + socket_connect_finished (sock, status, data); + return; + } - if (SOUP_STATUS_IS_SUCCESSFUL (status) && - data->tls_handshake) { + if (priv->use_gproxyresolver) + priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + + if (priv->ssl && !priv->proxy_uri) { if (soup_socket_start_ssl (sock, data->cancellable)) { soup_connection_event (data->conn, G_SOCKET_CLIENT_TLS_HANDSHAKING, @@ -598,6 +579,54 @@ socket_connect_result (SoupSocket *sock, guint status, gpointer user_data) socket_connect_finished (sock, status, data); } +static void +connect_async_to_uri (SoupConnectionAsyncConnectData *data, SoupURI *uri) +{ + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + SoupAddress *remote_addr; + + remote_addr = soup_address_new (uri->host, uri->port); + 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_USE_PROXY, priv->use_gproxyresolver, + SOUP_SOCKET_TIMEOUT, priv->io_timeout, + SOUP_SOCKET_CLEAN_DISPOSE, TRUE, + NULL); + g_object_unref (remote_addr); + + data->event_id = g_signal_connect (priv->socket, "event", + G_CALLBACK (proxy_socket_event), + data->conn); + + soup_socket_connect_async (priv->socket, data->cancellable, + socket_connect_result, data); +} + +static void +proxy_resolver_result (SoupProxyURIResolver *resolver, + guint status, SoupURI *proxy_uri, + gpointer user_data) +{ + SoupConnectionAsyncConnectData *data = user_data; + SoupConnectionPrivate *priv = SOUP_CONNECTION_GET_PRIVATE (data->conn); + + if (status != SOUP_STATUS_OK) { + socket_connect_finished (NULL, status, data); + return; + } + + if (proxy_uri) { + priv->proxy_uri = soup_uri_copy (proxy_uri); + connect_async_to_uri (data, proxy_uri); + } else + connect_async_to_uri (data, priv->remote_uri); +} + void soup_connection_connect_async (SoupConnection *conn, GCancellable *cancellable, @@ -606,6 +635,7 @@ soup_connection_connect_async (SoupConnection *conn, { SoupConnectionAsyncConnectData *data; SoupConnectionPrivate *priv; + GMainContext *async_context; g_return_if_fail (SOUP_IS_CONNECTION (conn)); priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -618,23 +648,23 @@ soup_connection_connect_async (SoupConnection *conn, data->callback = callback; data->callback_data = user_data; data->cancellable = cancellable ? g_object_ref (cancellable) : NULL; - data->tls_handshake = (priv->ssl && !priv->tunnel_addr); - priv->socket = - soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, priv->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_TIMEOUT, priv->io_timeout, - "clean-dispose", TRUE, - NULL); - data->event_id = g_signal_connect (priv->socket, "event", - G_CALLBACK (proxy_socket_event), - conn); - soup_socket_connect_async (priv->socket, cancellable, - socket_connect_result, data); + if (!priv->proxy_resolver) { + connect_async_to_uri (data, priv->remote_uri); + return; + } + + if (priv->use_thread_context) + async_context = g_main_context_get_thread_default (); + else + async_context = priv->async_context; + + soup_proxy_uri_resolver_get_proxy_uri_async (priv->proxy_resolver, + priv->remote_uri, + async_context, + cancellable, + proxy_resolver_result, + data); } guint @@ -642,6 +672,8 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) { SoupConnectionPrivate *priv; guint status, event_id; + SoupURI *connect_uri; + SoupAddress *remote_addr; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), SOUP_STATUS_MALFORMED); priv = SOUP_CONNECTION_GET_PRIVATE (conn); @@ -649,15 +681,33 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) soup_connection_set_state (conn, SOUP_CONNECTION_CONNECTING); + if (priv->proxy_resolver) { + status = soup_proxy_uri_resolver_get_proxy_uri_sync (priv->proxy_resolver, + priv->remote_uri, + cancellable, + &priv->proxy_uri); + if (status != SOUP_STATUS_OK) + goto fail; + + if (priv->proxy_uri) + connect_uri = priv->proxy_uri; + else + connect_uri = priv->remote_uri; + } else + connect_uri = priv->remote_uri; + + remote_addr = soup_address_new (connect_uri->host, connect_uri->port); priv->socket = - soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, priv->remote_addr, + soup_socket_new (SOUP_SOCKET_REMOTE_ADDRESS, remote_addr, + SOUP_SOCKET_USE_PROXY, priv->use_gproxyresolver, SOUP_SOCKET_SSL_CREDENTIALS, priv->tlsdb, SOUP_SOCKET_SSL_STRICT, priv->ssl_strict, SOUP_SOCKET_SSL_FALLBACK, priv->ssl_fallback, SOUP_SOCKET_FLAG_NONBLOCKING, FALSE, SOUP_SOCKET_TIMEOUT, priv->io_timeout, - "clean-dispose", TRUE, + SOUP_SOCKET_CLEAN_DISPOSE, TRUE, NULL); + g_object_unref (remote_addr); event_id = g_signal_connect (priv->socket, "event", G_CALLBACK (proxy_socket_event), conn); @@ -665,8 +715,11 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) if (!SOUP_STATUS_IS_SUCCESSFUL (status)) goto fail; - - if (priv->ssl && !priv->tunnel_addr) { + + if (priv->use_gproxyresolver) + priv->proxy_uri = soup_socket_get_http_proxy_uri (priv->socket); + + if (priv->ssl && !priv->proxy_uri) { if (!soup_socket_start_ssl (priv->socket, cancellable)) status = SOUP_STATUS_SSL_FAILED; else { @@ -689,7 +742,7 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) g_signal_connect (priv->socket, "disconnected", G_CALLBACK (socket_disconnected), conn); - if (!priv->ssl || !priv->tunnel_addr) { + if (!priv->ssl || !priv->proxy_uri) { soup_connection_event (conn, G_SOCKET_CLIENT_COMPLETE, NULL); @@ -714,15 +767,15 @@ soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable) return status; } -SoupAddress * -soup_connection_get_tunnel_addr (SoupConnection *conn) +gboolean +soup_connection_is_tunnelled (SoupConnection *conn) { SoupConnectionPrivate *priv; - g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - return priv->tunnel_addr; + return priv->ssl && priv->proxy_uri != NULL; } guint @@ -730,16 +783,13 @@ soup_connection_start_ssl_sync (SoupConnection *conn, GCancellable *cancellable) { SoupConnectionPrivate *priv; - const char *server_name; guint status; g_return_val_if_fail (SOUP_IS_CONNECTION (conn), FALSE); priv = SOUP_CONNECTION_GET_PRIVATE (conn); - server_name = soup_address_get_name (priv->tunnel_addr ? - priv->tunnel_addr : - priv->remote_addr); - if (!soup_socket_start_proxy_ssl (priv->socket, server_name, + if (!soup_socket_start_proxy_ssl (priv->socket, + priv->remote_uri->host, cancellable)) return SOUP_STATUS_SSL_FAILED; @@ -789,7 +839,6 @@ soup_connection_start_ssl_async (SoupConnection *conn, gpointer user_data) { SoupConnectionPrivate *priv; - const char *server_name; SoupConnectionAsyncConnectData *data; GMainContext *async_context; @@ -806,10 +855,8 @@ soup_connection_start_ssl_async (SoupConnection *conn, else async_context = priv->async_context; - server_name = soup_address_get_name (priv->tunnel_addr ? - priv->tunnel_addr : - priv->remote_addr); - if (!soup_socket_start_proxy_ssl (priv->socket, server_name, + if (!soup_socket_start_proxy_ssl (priv->socket, + priv->remote_uri->host, cancellable)) { soup_add_completion (async_context, idle_start_ssl_completed, data); @@ -867,6 +914,14 @@ soup_connection_get_socket (SoupConnection *conn) } SoupURI * +soup_connection_get_remote_uri (SoupConnection *conn) +{ + g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); + + return SOUP_CONNECTION_GET_PRIVATE (conn)->remote_uri; +} + +SoupURI * soup_connection_get_proxy_uri (SoupConnection *conn) { g_return_val_if_fail (SOUP_IS_CONNECTION (conn), NULL); diff --git a/libsoup/soup-connection.h b/libsoup/soup-connection.h index 72e61062..52e638f5 100644 --- a/libsoup/soup-connection.h +++ b/libsoup/soup-connection.h @@ -39,9 +39,8 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, guint status, gpointer data); -#define SOUP_CONNECTION_REMOTE_ADDRESS "remote-address" -#define SOUP_CONNECTION_TUNNEL_ADDRESS "tunnel-address" -#define SOUP_CONNECTION_PROXY_URI "proxy-uri" +#define SOUP_CONNECTION_REMOTE_URI "remote-uri" +#define SOUP_CONNECTION_PROXY_RESOLVER "proxy-resolver" #define SOUP_CONNECTION_SSL "ssl" #define SOUP_CONNECTION_SSL_CREDENTIALS "ssl-creds" #define SOUP_CONNECTION_SSL_STRICT "ssl-strict" @@ -53,16 +52,12 @@ typedef void (*SoupConnectionCallback) (SoupConnection *conn, #define SOUP_CONNECTION_STATE "state" #define SOUP_CONNECTION_MESSAGE "message" -SoupConnection *soup_connection_new (const char *propname1, - ...) G_GNUC_NULL_TERMINATED; - void soup_connection_connect_async (SoupConnection *conn, GCancellable *cancellable, SoupConnectionCallback callback, gpointer user_data); guint soup_connection_connect_sync (SoupConnection *conn, GCancellable *cancellable); -SoupAddress *soup_connection_get_tunnel_addr(SoupConnection *conn); guint soup_connection_start_ssl_sync (SoupConnection *conn, GCancellable *cancellable); void soup_connection_start_ssl_async (SoupConnection *conn, @@ -73,8 +68,10 @@ void soup_connection_start_ssl_async (SoupConnection *conn, void soup_connection_disconnect (SoupConnection *conn); SoupSocket *soup_connection_get_socket (SoupConnection *conn); +SoupURI *soup_connection_get_remote_uri (SoupConnection *conn); SoupURI *soup_connection_get_proxy_uri (SoupConnection *conn); gboolean soup_connection_is_via_proxy (SoupConnection *conn); +gboolean soup_connection_is_tunnelled (SoupConnection *conn); SoupConnectionState soup_connection_get_state (SoupConnection *conn); void soup_connection_set_state (SoupConnection *conn, diff --git a/libsoup/soup-message-queue.h b/libsoup/soup-message-queue.h index a9242a1e..7e7a3086 100644 --- a/libsoup/soup-message-queue.h +++ b/libsoup/soup-message-queue.h @@ -15,10 +15,6 @@ G_BEGIN_DECLS typedef enum { SOUP_MESSAGE_STARTING, - SOUP_MESSAGE_RESOLVING_PROXY_URI, - SOUP_MESSAGE_RESOLVED_PROXY_URI, - SOUP_MESSAGE_RESOLVING_PROXY_ADDRESS, - SOUP_MESSAGE_RESOLVED_PROXY_ADDRESS, SOUP_MESSAGE_AWAITING_CONNECTION, SOUP_MESSAGE_GOT_CONNECTION, SOUP_MESSAGE_CONNECTING, diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h index 018d66a1..06978e82 100644 --- a/libsoup/soup-misc-private.h +++ b/libsoup/soup-misc-private.h @@ -22,4 +22,8 @@ GSocket *soup_socket_get_gsocket (SoupSocket *sock); GIOStream *soup_socket_get_connection (SoupSocket *sock); GIOStream *soup_socket_get_iostream (SoupSocket *sock); +#define SOUP_SOCKET_CLEAN_DISPOSE "clean-dispose" +#define SOUP_SOCKET_USE_PROXY "use-proxy" +SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock); + #endif /* SOUP_URI_PRIVATE_H */ diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 90526dca..ea2820ab 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -19,7 +19,6 @@ #include "soup-message-queue.h" #include "soup-misc.h" #include "soup-password-manager.h" -#include "soup-proxy-uri-resolver.h" #include "soup-uri.h" /** @@ -131,90 +130,6 @@ soup_session_async_new_with_options (const char *optname1, ...) return session; } -static gboolean -item_failed (SoupMessageQueueItem *item, guint status) -{ - if (item->removed) { - soup_message_queue_item_unref (item); - return TRUE; - } - - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - item->state = SOUP_MESSAGE_FINISHING; - if (!item->msg->status_code) - soup_session_set_item_status (item->session, item, status); - do_idle_run_queue (item->session); - soup_message_queue_item_unref (item); - return TRUE; - } - - return FALSE; -} - -static void -resolved_proxy_addr (SoupAddress *addr, guint status, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - SoupSession *session = item->session; - - if (item_failed (item, soup_status_proxify (status))) - return; - - item->proxy_addr = g_object_ref (addr); - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - - soup_message_queue_item_unref (item); - - /* If we got here we know session still exists */ - run_queue ((SoupSessionAsync *)session); -} - -static void -resolved_proxy_uri (SoupProxyURIResolver *proxy_resolver, - guint status, SoupURI *proxy_uri, gpointer user_data) -{ - SoupMessageQueueItem *item = user_data; - SoupSession *session = item->session; - - if (item_failed (item, status)) - return; - - if (proxy_uri) { - SoupAddress *proxy_addr; - - item->state = SOUP_MESSAGE_RESOLVING_PROXY_ADDRESS; - - item->proxy_uri = soup_uri_copy (proxy_uri); - proxy_addr = soup_address_new (proxy_uri->host, - proxy_uri->port); - soup_address_resolve_async (proxy_addr, - soup_session_get_async_context (session), - item->cancellable, - resolved_proxy_addr, item); - g_object_unref (proxy_addr); - return; - } - - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - soup_message_queue_item_unref (item); - - /* If we got here we know session still exists */ - run_queue ((SoupSessionAsync *)session); -} - -static void -resolve_proxy_addr (SoupMessageQueueItem *item, - SoupProxyURIResolver *proxy_resolver) -{ - item->state = SOUP_MESSAGE_RESOLVING_PROXY_URI; - - soup_message_queue_item_ref (item); - soup_proxy_uri_resolver_get_proxy_uri_async ( - proxy_resolver, soup_message_get_uri (item->msg), - soup_session_get_async_context (item->session), - item->cancellable, resolved_proxy_uri, item); -} - static void connection_closed (SoupConnection *conn, gpointer session) { @@ -315,7 +230,6 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) { SoupMessageQueueItem *item = user_data; SoupSession *session = item->session; - SoupAddress *tunnel_addr; if (item->state != SOUP_MESSAGE_CONNECTING) { soup_connection_disconnect (conn); @@ -344,8 +258,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) return; } - tunnel_addr = soup_connection_get_tunnel_addr (conn); - if (tunnel_addr) { + if (soup_connection_is_tunnelled (conn)) { SoupMessageQueueItem *tunnel_item; item->state = SOUP_MESSAGE_TUNNELING; @@ -370,7 +283,6 @@ process_queue_item (SoupMessageQueueItem *item, gboolean loop) { SoupSession *session = item->session; - SoupProxyURIResolver *proxy_resolver; if (item->async_context != soup_session_get_async_context (session)) return; @@ -381,13 +293,8 @@ process_queue_item (SoupMessageQueueItem *item, switch (item->state) { case SOUP_MESSAGE_STARTING: - proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, item->msg); - if (!proxy_resolver) { - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - break; - } - resolve_proxy_addr (item, proxy_resolver); - return; + item->state = SOUP_MESSAGE_AWAITING_CONNECTION; + break; case SOUP_MESSAGE_AWAITING_CONNECTION: if (!soup_session_get_connection (session, item, should_prune)) diff --git a/libsoup/soup-session-sync.c b/libsoup/soup-session-sync.c index a09c5b4e..039779a9 100644 --- a/libsoup/soup-session-sync.c +++ b/libsoup/soup-session-sync.c @@ -19,7 +19,6 @@ #include "soup-message-queue.h" #include "soup-misc.h" #include "soup-password-manager.h" -#include "soup-proxy-uri-resolver.h" #include "soup-uri.h" /** @@ -224,7 +223,7 @@ try_again: return; } - if (soup_connection_get_tunnel_addr (item->conn)) { + if (soup_connection_is_tunnelled (item->conn)) { status = tunnel_connect (session, item); if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { soup_connection_disconnect (item->conn); @@ -258,9 +257,6 @@ process_queue_item (SoupMessageQueueItem *item) { SoupSession *session = item->session; SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session); - SoupMessage *msg = item->msg; - SoupProxyURIResolver *proxy_resolver; - guint status; soup_message_queue_item_ref (item); @@ -274,35 +270,7 @@ process_queue_item (SoupMessageQueueItem *item) switch (item->state) { case SOUP_MESSAGE_STARTING: - proxy_resolver = (SoupProxyURIResolver *)soup_session_get_feature_for_message (session, SOUP_TYPE_PROXY_URI_RESOLVER, msg); - if (!proxy_resolver) { - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - break; - } - - status = soup_proxy_uri_resolver_get_proxy_uri_sync ( - proxy_resolver, soup_message_get_uri (msg), - item->cancellable, &item->proxy_uri); - if (!SOUP_STATUS_IS_SUCCESSFUL (status)) { - soup_session_set_item_status (session, item, status); - item->state = SOUP_MESSAGE_FINISHING; - break; - } - if (!item->proxy_uri) { - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - break; - } - - item->proxy_addr = soup_address_new ( - item->proxy_uri->host, item->proxy_uri->port); - status = soup_address_resolve_sync (item->proxy_addr, - item->cancellable); - if (SOUP_STATUS_IS_SUCCESSFUL (status)) - item->state = SOUP_MESSAGE_AWAITING_CONNECTION; - else { - soup_session_set_item_status (session, item, soup_status_proxify (status)); - item->state = SOUP_MESSAGE_FINISHING; - } + item->state = SOUP_MESSAGE_AWAITING_CONNECTION; break; case SOUP_MESSAGE_AWAITING_CONNECTION: diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index 200a25a8..be630a85 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -1494,7 +1494,11 @@ soup_session_host_new (SoupSession *session, SoupURI *uri) host->uri->scheme = SOUP_URI_SCHEME_HTTP; } - host->addr = soup_address_new (host->uri->host, host->uri->port); + host->addr = g_object_new (SOUP_TYPE_ADDRESS, + SOUP_ADDRESS_NAME, host->uri->host, + SOUP_ADDRESS_PORT, host->uri->port, + SOUP_ADDRESS_PROTOCOL, host->uri->scheme, + NULL); host->keep_alive_src = NULL; host->session = session; @@ -1885,19 +1889,13 @@ soup_session_make_connect_message (SoupSession *session, SoupConnection *conn) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupAddress *server_addr = soup_connection_get_tunnel_addr (conn); SoupURI *uri; SoupMessage *msg; SoupMessageQueueItem *item; - uri = soup_uri_new (NULL); - soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTPS); - soup_uri_set_host (uri, soup_address_get_name (server_addr)); - soup_uri_set_port (uri, soup_address_get_port (server_addr)); - soup_uri_set_path (uri, ""); + uri = soup_connection_get_remote_uri (conn); msg = soup_message_new_from_uri (SOUP_METHOD_CONNECT, uri); soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); - soup_uri_free (uri); /* Call the base implementation of soup_session_queue_message * directly, to add msg to the SoupMessageQueue and cause all @@ -1921,10 +1919,8 @@ soup_session_get_connection (SoupSession *session, SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); SoupConnection *conn; SoupSessionHost *host; - SoupAddress *remote_addr, *tunnel_addr; GSList *conns; int num_pending = 0; - SoupURI *uri; gboolean need_new_connection; if (item->conn) { @@ -1971,23 +1967,11 @@ soup_session_get_connection (SoupSession *session, return FALSE; } - if (item->proxy_addr) { - remote_addr = item->proxy_addr; - tunnel_addr = NULL; - } else { - remote_addr = host->addr; - tunnel_addr = NULL; - } - - uri = soup_message_get_uri (item->msg); - if (uri_is_https (priv, uri) && item->proxy_addr) - tunnel_addr = host->addr; - - conn = soup_connection_new ( - SOUP_CONNECTION_REMOTE_ADDRESS, remote_addr, - SOUP_CONNECTION_TUNNEL_ADDRESS, tunnel_addr, - SOUP_CONNECTION_PROXY_URI, item->proxy_uri, - SOUP_CONNECTION_SSL, uri_is_https (priv, uri), + conn = g_object_new ( + SOUP_TYPE_CONNECTION, + SOUP_CONNECTION_REMOTE_URI, host->uri, + SOUP_CONNECTION_PROXY_RESOLVER, soup_session_get_feature (session, SOUP_TYPE_PROXY_URI_RESOLVER), + SOUP_CONNECTION_SSL, uri_is_https (priv, soup_message_get_uri (item->msg)), SOUP_CONNECTION_SSL_CREDENTIALS, priv->tlsdb, SOUP_CONNECTION_SSL_STRICT, (priv->tlsdb != NULL) && priv->ssl_strict, SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context, diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c index 1658d090..feb11626 100644 --- a/libsoup/soup-socket.c +++ b/libsoup/soup-socket.c @@ -23,6 +23,7 @@ #include "soup-marshal.h" #include "soup-misc.h" #include "soup-misc-private.h" +#include "soup-uri.h" /** * SECTION:soup-socket @@ -64,6 +65,7 @@ enum { PROP_CLEAN_DISPOSE, PROP_TLS_CERTIFICATE, PROP_TLS_ERRORS, + PROP_USE_PROXY, LAST_PROP }; @@ -83,6 +85,7 @@ typedef struct { guint ssl_fallback:1; guint clean_dispose:1; guint use_thread_context:1; + guint use_proxy:1; gpointer ssl_creds; GMainContext *async_context; @@ -501,6 +504,14 @@ soup_socket_class_init (SoupSocketClass *socket_class) "Errors with the peer's TLS certificate", G_TYPE_TLS_CERTIFICATE_FLAGS, 0, G_PARAM_READABLE)); + + g_object_class_install_property ( + object_class, PROP_USE_PROXY, + g_param_spec_boolean (SOUP_SOCKET_USE_PROXY, + "Use proxy", + "Use #GProxyResolver", + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } @@ -560,6 +571,9 @@ set_property (GObject *object, guint prop_id, if (priv->conn) g_socket_set_timeout (priv->gsock, priv->timeout); break; + case PROP_USE_PROXY: + priv->use_proxy = g_value_get_boolean (value); + break; case PROP_CLEAN_DISPOSE: priv->clean_dispose = g_value_get_boolean (value); break; @@ -618,6 +632,9 @@ get_property (GObject *object, guint prop_id, case PROP_TLS_ERRORS: g_value_set_flags (value, priv->tls_errors); break; + case PROP_USE_PROXY: + g_value_set_boolean (value, priv->use_proxy); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -768,6 +785,10 @@ soup_socket_connect_async (SoupSocket *sock, GCancellable *cancellable, client = g_socket_client_new (); g_signal_connect (client, "event", G_CALLBACK (proxy_socket_client_event), sock); + if (priv->use_proxy) + g_socket_client_add_application_proxy (client, "http"); + else + g_socket_client_set_enable_proxy (client, FALSE); if (priv->timeout) g_socket_client_set_timeout (client, priv->timeout); g_socket_client_connect_async (client, @@ -813,6 +834,10 @@ soup_socket_connect_sync (SoupSocket *sock, GCancellable *cancellable) client = g_socket_client_new (); g_signal_connect (client, "event", G_CALLBACK (proxy_socket_client_event), sock); + if (priv->use_proxy) + g_socket_client_add_application_proxy (client, "http"); + else + g_socket_client_set_enable_proxy (client, FALSE); if (priv->timeout) g_socket_client_set_timeout (client, priv->timeout); conn = g_socket_client_connect (client, @@ -1328,6 +1353,25 @@ soup_socket_get_remote_address (SoupSocket *sock) return priv->remote_addr; } +SoupURI * +soup_socket_get_http_proxy_uri (SoupSocket *sock) +{ + SoupSocketPrivate *priv = SOUP_SOCKET_GET_PRIVATE (sock); + GSocketAddress *addr; + GProxyAddress *paddr; + + if (!priv->gsock) + return NULL; + addr = g_socket_get_remote_address (priv->gsock, NULL); + if (!addr || !G_IS_PROXY_ADDRESS (addr)) + return NULL; + + paddr = G_PROXY_ADDRESS (addr); + if (strcmp (g_proxy_address_get_protocol (paddr), "http") != 0) + return NULL; + + return soup_uri_new (g_proxy_address_get_uri (paddr)); +} static gboolean socket_read_watch (GObject *pollable, gpointer user_data) |