summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--libsoup/soup-address.c50
-rw-r--r--libsoup/soup-address.h1
-rw-r--r--libsoup/soup-connection.c259
-rw-r--r--libsoup/soup-connection.h11
-rw-r--r--libsoup/soup-message-queue.h4
-rw-r--r--libsoup/soup-misc-private.h4
-rw-r--r--libsoup/soup-session-async.c99
-rw-r--r--libsoup/soup-session-sync.c36
-rw-r--r--libsoup/soup-session.c38
-rw-r--r--libsoup/soup-socket.c44
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)