libsoup r1192 - in trunk: . libsoup



Author: danw
Date: Fri Oct 31 13:05:14 2008
New Revision: 1192
URL: http://svn.gnome.org/viewvc/libsoup?rev=1192&view=rev

Log:
	* libsoup/soup-proxy-resolver.c: new abstract base class for a
	SoupSessionFeature that determines what proxy to use for a given
	URI.

	* libsoup/soup-proxy-resolver-static.c: a SoupProxyResolver that
	always returns the same value.

	* libsoup/soup-session.c (set_property, get_property): implement
	the SOUP_SESSION_PROXY_URI property by creating/destroying a
	SoupProxyResolverStatic as needed.
	(soup_session_get_connection): Use the proxy address passed by the
	caller rather than priv->proxy_uri.

	* libsoup/soup-session-async.c (run_queue): if the session has a
	proxy resolver, use it, and pass the resolved proxy to
	soup_session_get_connection().
	(request_restarted): clear the previously-resolved proxy address
	when restarting the message

	* libsoup/soup-session-sync.c (wait_for_connection): if the
	session has a proxy resolver, use it, and pass the resolved proxy
	to soup_session_get_connection().

	* libsoup/soup-message-queue.h (SoupMessageQueueItem): add
	proxy-address-resolving fields

	* libsoup/soup-status.c (soup_status_proxify): moved from
	soup-connection; turn SOUP_STATUS_CANT_RESOLVE into
	SOUP_STATUS_CANT_RESOLVE_PROXY, and SOUP_STATUS_CANT_CONNECT into
	SOUP_STATUS_CANT_CONNECT_PROXY (and pass all other statuses
	through unchanged)


Added:
   trunk/libsoup/soup-proxy-resolver-static.c
   trunk/libsoup/soup-proxy-resolver-static.h
   trunk/libsoup/soup-proxy-resolver.c
   trunk/libsoup/soup-proxy-resolver.h
Modified:
   trunk/ChangeLog
   trunk/libsoup/Makefile.am
   trunk/libsoup/soup-connection.c
   trunk/libsoup/soup-message-queue.c
   trunk/libsoup/soup-message-queue.h
   trunk/libsoup/soup-session-async.c
   trunk/libsoup/soup-session-private.h
   trunk/libsoup/soup-session-sync.c
   trunk/libsoup/soup-session.c
   trunk/libsoup/soup-status.c
   trunk/libsoup/soup-status.h

Modified: trunk/libsoup/Makefile.am
==============================================================================
--- trunk/libsoup/Makefile.am	(original)
+++ trunk/libsoup/Makefile.am	Fri Oct 31 13:05:14 2008
@@ -65,6 +65,7 @@
 	soup-misc.h     	\
 	soup-multipart.h     	\
 	soup-portability.h	\
+	soup-proxy-resolver.h	\
 	soup-server.h		\
 	soup-session.h		\
 	soup-session-async.h	\
@@ -137,6 +138,9 @@
 	soup-nossl.c     		\
 	soup-path-map.h     		\
 	soup-path-map.c     		\
+	soup-proxy-resolver.c		\
+	soup-proxy-resolver-static.h	\
+	soup-proxy-resolver-static.c	\
 	soup-server.c			\
 	soup-session.c			\
 	soup-session-async.c		\
@@ -153,4 +157,4 @@
 EXTRA_DIST=				\
 	soup-marshal.list		\
 	soup-enum-types.h.tmpl		\
-	soup-enum-types.c.tmpl
+	soup-enum-types.c.tmpl
\ No newline at end of file

Modified: trunk/libsoup/soup-connection.c
==============================================================================
--- trunk/libsoup/soup-connection.c	(original)
+++ trunk/libsoup/soup-connection.c	Fri Oct 31 13:05:14 2008
@@ -408,20 +408,6 @@
 	soup_connection_disconnect (conn);
 }
 
-static inline guint
-proxified_status (SoupConnectionPrivate *priv, guint status)
-{
-	if (!priv->proxy_addr)
-		return status;
-
-	if (status == SOUP_STATUS_CANT_RESOLVE)
-		return SOUP_STATUS_CANT_RESOLVE_PROXY;
-	else if (status == SOUP_STATUS_CANT_CONNECT)
-		return SOUP_STATUS_CANT_CONNECT_PROXY;
-	else
-		return status;
-}
-
 static SoupMessage *
 connect_message (SoupConnectionPrivate *priv)
 {
@@ -460,8 +446,9 @@
 		status = SOUP_STATUS_PROXY_AUTHENTICATION_REQUIRED;
 	}
 
-	g_signal_emit (conn, signals[CONNECT_RESULT], 0,
-		       proxified_status (priv, status));
+	if (priv->proxy_addr)
+		status = soup_status_proxify (status);
+	g_signal_emit (conn, signals[CONNECT_RESULT], 0, status);
 	g_object_unref (msg);
 }
 
@@ -528,8 +515,9 @@
 	start_idle_timer (conn);
 
  done:
-	g_signal_emit (conn, signals[CONNECT_RESULT], 0,
-		       proxified_status (priv, status));
+	if (priv->proxy_addr)
+		status = soup_status_proxify (status);
+	g_signal_emit (conn, signals[CONNECT_RESULT], 0, status);
 }
 
 /* from soup-misc.c... will eventually go away */
@@ -669,7 +657,8 @@
 		}
 	}
 
-	status = proxified_status (priv, status);
+	if (priv->proxy_addr)
+		status = soup_status_proxify (status);
 	g_signal_emit (conn, signals[CONNECT_RESULT], 0, status);
 	return status;
 }

Modified: trunk/libsoup/soup-message-queue.c
==============================================================================
--- trunk/libsoup/soup-message-queue.c	(original)
+++ trunk/libsoup/soup-message-queue.c	Fri Oct 31 13:05:14 2008
@@ -149,6 +149,8 @@
 	g_object_unref (item->cancellable);
 	if (item->msg_addr)
 		g_object_unref (item->msg_addr);
+	if (item->proxy_addr)
+		g_object_unref (item->proxy_addr);
 	g_slice_free (SoupMessageQueueItem, item);
 }
 

Modified: trunk/libsoup/soup-message-queue.h
==============================================================================
--- trunk/libsoup/soup-message-queue.h	(original)
+++ trunk/libsoup/soup-message-queue.h	Fri Oct 31 13:05:14 2008
@@ -26,13 +26,14 @@
 	gpointer callback_data;
 
 	GCancellable *cancellable;
-	SoupAddress *msg_addr;
+	SoupAddress *msg_addr, *proxy_addr;
 
 	guint resolving_msg_addr   : 1;
+	guint resolving_proxy_addr : 1;
 
 	/*< private >*/
 	guint removed              : 1;
-	guint ref_count            : 30;
+	guint ref_count            : 29;
 	SoupMessageQueueItem *prev, *next;
 };
 

Added: trunk/libsoup/soup-proxy-resolver-static.c
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-proxy-resolver-static.c	Fri Oct 31 13:05:14 2008
@@ -0,0 +1,208 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-proxy-resolver-static.c: Static proxy "resolution"
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "soup-proxy-resolver-static.h"
+#include "soup-address.h"
+#include "soup-dns.h"
+#include "soup-message.h"
+#include "soup-misc.h"
+#include "soup-session-feature.h"
+
+typedef struct {
+	SoupURI *proxy_uri;
+
+} SoupProxyResolverStaticPrivate;
+#define SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticPrivate))
+
+static void soup_proxy_resolver_static_interface_init (SoupProxyResolverInterface *proxy_resolver_interface);
+
+G_DEFINE_TYPE_EXTENDED (SoupProxyResolverStatic, soup_proxy_resolver_static, G_TYPE_OBJECT, 0,
+			G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)
+			G_IMPLEMENT_INTERFACE (SOUP_TYPE_PROXY_RESOLVER, soup_proxy_resolver_static_interface_init))
+
+enum {
+	PROP_0,
+
+	PROP_PROXY_URI,
+
+	LAST_PROP
+};
+
+static void set_property (GObject *object, guint prop_id,
+			  const GValue *value, GParamSpec *pspec);
+static void get_property (GObject *object, guint prop_id,
+			  GValue *value, GParamSpec *pspec);
+
+static void get_proxy_async (SoupProxyResolver  *proxy_resolver,
+			     SoupMessage        *msg,
+			     GMainContext       *async_context,
+			     GCancellable       *cancellable,
+			     SoupProxyResolverCallback callback,
+			     gpointer            user_data);
+static guint get_proxy_sync (SoupProxyResolver  *proxy_resolver,
+			     SoupMessage        *msg,
+			     GCancellable       *cancellable,
+			     SoupAddress       **addr);
+
+static void
+soup_proxy_resolver_static_init (SoupProxyResolverStatic *resolver_static)
+{
+}
+
+static void
+finalize (GObject *object)
+{
+	SoupProxyResolverStaticPrivate *priv =
+		SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object);
+
+	if (priv->proxy_uri)
+		soup_uri_free (priv->proxy_uri);
+
+	G_OBJECT_CLASS (soup_proxy_resolver_static_parent_class)->finalize (object);
+}
+
+static void
+soup_proxy_resolver_static_class_init (SoupProxyResolverStaticClass *static_class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (static_class);
+
+	g_type_class_add_private (static_class, sizeof (SoupProxyResolverStaticPrivate));
+
+	object_class->set_property = set_property;
+	object_class->get_property = get_property;
+	object_class->finalize = finalize;
+
+	g_object_class_install_property (
+		object_class, PROP_PROXY_URI,
+		g_param_spec_boxed (SOUP_PROXY_RESOLVER_STATIC_PROXY_URI,
+				    "Proxy URI",
+				    "The HTTP Proxy to use",
+				    SOUP_TYPE_URI,
+				    G_PARAM_READWRITE));
+}
+
+static void
+set_property (GObject *object, guint prop_id,
+	      const GValue *value, GParamSpec *pspec)
+{
+	SoupProxyResolverStaticPrivate *priv =
+		SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object);
+	SoupURI *uri;
+
+	switch (prop_id) {
+	case PROP_PROXY_URI:
+		uri = g_value_get_boxed (value);
+		if (priv->proxy_uri)
+			soup_uri_free (priv->proxy_uri);
+
+		priv->proxy_uri = uri ? soup_uri_copy (uri) : NULL;
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+get_property (GObject *object, guint prop_id,
+	      GValue *value, GParamSpec *pspec)
+{
+	SoupProxyResolverStaticPrivate *priv =
+		SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_PROXY_URI:
+		g_value_set_boxed (value, priv->proxy_uri);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+static void
+soup_proxy_resolver_static_interface_init (SoupProxyResolverInterface *proxy_resolver_interface)
+{
+	proxy_resolver_interface->get_proxy_async = get_proxy_async;
+	proxy_resolver_interface->get_proxy_sync = get_proxy_sync;
+}
+
+SoupProxyResolver *
+soup_proxy_resolver_static_new (SoupURI *proxy_uri)
+{
+	return g_object_new (SOUP_TYPE_PROXY_RESOLVER_STATIC,
+			     SOUP_PROXY_RESOLVER_STATIC_PROXY_URI, proxy_uri,
+			     NULL);
+}
+
+typedef struct {
+	SoupProxyResolver *proxy_resolver;
+	SoupMessage *msg;
+	SoupAddress *addr;
+	SoupProxyResolverCallback callback;
+	gpointer user_data;
+} SoupStaticAsyncData;
+
+static void
+resolved_address (SoupAddress *addr, guint status, gpointer data)
+{
+	SoupStaticAsyncData *ssad = data;
+
+	ssad->callback (ssad->proxy_resolver, ssad->msg,
+			soup_status_proxify (status), addr,
+			ssad->user_data);
+	g_object_unref (ssad->proxy_resolver);
+	g_object_unref (ssad->msg);
+	if (addr)
+		g_object_unref (addr);
+	g_slice_free (SoupStaticAsyncData, ssad);
+}
+
+static void
+get_proxy_async (SoupProxyResolver  *proxy_resolver,
+		 SoupMessage        *msg,
+		 GMainContext       *async_context,
+		 GCancellable       *cancellable,
+		 SoupProxyResolverCallback callback,
+		 gpointer            user_data)
+{
+	SoupProxyResolverStaticPrivate *priv =
+		SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (proxy_resolver);
+	SoupStaticAsyncData *ssad;
+
+	ssad = g_slice_new0 (SoupStaticAsyncData);
+	ssad->proxy_resolver = g_object_ref (proxy_resolver);
+	ssad->msg = g_object_ref (msg);
+	ssad->callback = callback;
+	ssad->user_data = user_data;
+	ssad->addr = soup_address_new (priv->proxy_uri->host,
+				       priv->proxy_uri->port);
+
+	soup_address_resolve_async (ssad->addr, async_context,
+				    cancellable, resolved_address,
+				    ssad);
+}
+
+static guint
+get_proxy_sync (SoupProxyResolver  *proxy_resolver,
+		SoupMessage        *msg,
+		GCancellable       *cancellable,
+		SoupAddress       **addr)
+{
+	SoupProxyResolverStaticPrivate *priv =
+		SOUP_PROXY_RESOLVER_STATIC_GET_PRIVATE (proxy_resolver);
+
+	*addr = soup_address_new (priv->proxy_uri->host,
+				  priv->proxy_uri->port);
+	return soup_status_proxify (soup_address_resolve_sync (*addr, cancellable));
+}

Added: trunk/libsoup/soup-proxy-resolver-static.h
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-proxy-resolver-static.h	Fri Oct 31 13:05:14 2008
@@ -0,0 +1,35 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef SOUP_PROXY_RESOLVER_STATIC_H
+#define SOUP_PROXY_RESOLVER_STATIC_H 1
+
+#include "soup-proxy-resolver.h"
+#include "soup-uri.h"
+
+#define SOUP_TYPE_PROXY_RESOLVER_STATIC            (soup_proxy_resolver_static_get_type ())
+#define SOUP_PROXY_RESOLVER_STATIC(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStatic))
+#define SOUP_PROXY_RESOLVER_STATIC_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticClass))
+#define SOUP_IS_PROXY_RESOLVER_STATIC(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER_STATIC))
+#define SOUP_IS_PROXY_RESOLVER_STATIC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER_STATIC))
+#define SOUP_PROXY_RESOLVER_STATIC_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_PROXY_RESOLVER_STATIC, SoupProxyResolverStaticClass))
+
+typedef struct {
+	GObject parent;
+
+} SoupProxyResolverStatic;
+
+typedef struct {
+	GObjectClass parent_class;
+
+} SoupProxyResolverStaticClass;
+
+GType soup_proxy_resolver_static_get_type (void);
+
+#define SOUP_PROXY_RESOLVER_STATIC_PROXY_URI "proxy-uri"
+
+SoupProxyResolver *soup_proxy_resolver_static_new (SoupURI *proxy_uri);
+
+#endif /* SOUP_PROXY_RESOLVER_STATIC_H */

Added: trunk/libsoup/soup-proxy-resolver.c
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-proxy-resolver.c	Fri Oct 31 13:05:14 2008
@@ -0,0 +1,84 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-proxy-resolver.c: HTTP proxy resolver interface
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "soup-proxy-resolver.h"
+#include "soup-session-feature.h"
+
+GType
+soup_proxy_resolver_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      GType g_define_type_id =
+        g_type_register_static_simple (G_TYPE_INTERFACE,
+                                       g_intern_static_string ("SoupProxyResolver"),
+                                       sizeof (SoupProxyResolverInterface),
+                                       (GClassInitFunc)NULL,
+                                       0,
+                                       (GInstanceInitFunc)NULL,
+                                       (GTypeFlags) 0);
+      g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
+      g_type_interface_add_prerequisite (g_define_type_id, SOUP_TYPE_SESSION_FEATURE);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+  return g_define_type_id__volatile;
+}
+
+/**
+ * soup_proxy_resovler_get_proxy_async:
+ * @proxy_resolver: the #SoupProxyResolver
+ * @msg: the #SoupMessage you want a proxy for
+ * @async_context: the #GMainContext to invoke @callback in
+ * @cancellable: a #GCancellable, or %NULL
+ * @callback: callback to invoke with the proxy address
+ * @user_data: data for @callback
+ *
+ * Asynchronously determines a proxy server address to use for @msg
+ * and calls @callback.
+ **/
+void
+soup_proxy_resolver_get_proxy_async (SoupProxyResolver  *proxy_resolver,
+				     SoupMessage        *msg,
+				     GMainContext       *async_context,
+				     GCancellable       *cancellable,
+				     SoupProxyResolverCallback callback,
+				     gpointer            user_data)
+{
+	SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)->
+		get_proxy_async (proxy_resolver, msg,
+				 async_context, cancellable,
+				 callback, user_data);
+}
+
+/**
+ * soup_proxy_resovler_get_proxy_sync:
+ * @proxy_resolver: the #SoupProxyResolver
+ * @msg: the #SoupMessage you want a proxy for
+ * @cancellable: a #GCancellable, or %NULL
+ * @addr: on return, will contain the proxy address
+ *
+ * Synchronously determines a proxy server address to use for @msg. If
+ * @msg should be sent via proxy, * addr will be set to the address of
+ * the proxy, else it will be set to %NULL.
+ *
+ * Return value: SOUP_STATUS_OK if successful, or a transport-level
+ * error.
+ **/
+guint
+soup_proxy_resolver_get_proxy_sync (SoupProxyResolver  *proxy_resolver,
+				    SoupMessage        *msg,
+				    GCancellable       *cancellable,
+				    SoupAddress       **addr)
+{
+	return SOUP_PROXY_RESOLVER_GET_CLASS (proxy_resolver)->
+		get_proxy_sync (proxy_resolver, msg, cancellable, addr);
+}

Added: trunk/libsoup/soup-proxy-resolver.h
==============================================================================
--- (empty file)
+++ trunk/libsoup/soup-proxy-resolver.h	Fri Oct 31 13:05:14 2008
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2008 Red Hat, Inc.
+ */
+
+#ifndef SOUP_PROXY_RESOLVER_H
+#define SOUP_PROXY_RESOLVER_H 1
+
+#include <libsoup/soup-types.h>
+#include <gio/gio.h>
+
+#define SOUP_TYPE_PROXY_RESOLVER            (soup_proxy_resolver_get_type ())
+#define SOUP_PROXY_RESOLVER(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolver))
+#define SOUP_PROXY_RESOLVER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolverInterface))
+#define SOUP_IS_PROXY_RESOLVER(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), SOUP_TYPE_PROXY_RESOLVER))
+#define SOUP_IS_PROXY_RESOLVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SOUP_TYPE_PROXY_RESOLVER))
+#define SOUP_PROXY_RESOLVER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_INTERFACE ((obj), SOUP_TYPE_PROXY_RESOLVER, SoupProxyResolverInterface))
+
+typedef struct _SoupProxyResolver SoupProxyResolver;
+
+typedef void (*SoupProxyResolverCallback) (SoupProxyResolver *, SoupMessage *,
+					   guint, SoupAddress *, gpointer);
+
+typedef struct {
+	GTypeInterface base;
+
+	/* virtual methods */
+	void (*get_proxy_async) (SoupProxyResolver *, SoupMessage *,
+				 GMainContext *, GCancellable *,
+				 SoupProxyResolverCallback, gpointer);
+	guint (*get_proxy_sync) (SoupProxyResolver *, SoupMessage *,
+				 GCancellable *, SoupAddress **);
+
+} SoupProxyResolverInterface;
+
+GType soup_proxy_resolver_get_type (void);
+
+void  soup_proxy_resolver_get_proxy_async (SoupProxyResolver  *proxy_resolver,
+					   SoupMessage        *msg,
+					   GMainContext       *async_context,
+					   GCancellable       *cancellable,
+					   SoupProxyResolverCallback callback,
+					   gpointer            user_data);
+guint soup_proxy_resolver_get_proxy_sync  (SoupProxyResolver  *proxy_resolver,
+					   SoupMessage        *msg,
+					   GCancellable       *cancellable,
+					   SoupAddress       **addr);
+
+#endif /*SOUP_PROXY_RESOLVER_H*/

Modified: trunk/libsoup/soup-session-async.c
==============================================================================
--- trunk/libsoup/soup-session-async.c	(original)
+++ trunk/libsoup/soup-session-async.c	Fri Oct 31 13:05:14 2008
@@ -9,6 +9,7 @@
 #include <config.h>
 #endif
 
+#include "soup-address.h"
 #include "soup-session-async.h"
 #include "soup-session-private.h"
 #include "soup-address.h"
@@ -150,6 +151,49 @@
 }
 
 static void
+resolved_proxy_addr (SoupProxyResolver *proxy_resolver, SoupMessage *msg,
+		     guint status, SoupAddress *proxy_addr, gpointer user_data)
+{
+	SoupMessageQueueItem *item = user_data;
+	SoupSession *session = item->session;
+
+	if (item->removed) {
+		/* Message was cancelled before its proxy addr resolved */
+		soup_message_queue_item_unref (item);
+		return;
+	}
+
+	if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+		soup_session_cancel_message (session, item->msg, status);
+		soup_message_queue_item_unref (item);
+		return;
+	}
+
+	item->resolving_proxy_addr = FALSE;
+	item->proxy_addr = proxy_addr ? g_object_ref (proxy_addr) : NULL;
+
+	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,
+		    SoupProxyResolver *proxy_resolver)
+{
+	if (item->resolving_proxy_addr)
+		return;
+	item->resolving_proxy_addr = TRUE;
+
+	soup_message_queue_item_ref (item);
+	soup_proxy_resolver_get_proxy_async (proxy_resolver, item->msg,
+					     soup_session_get_async_context (item->session),
+					     item->cancellable,
+					     resolved_proxy_addr, item);
+}
+
+static void
 connection_closed (SoupConnection *conn, gpointer session)
 {
 	/* Run the queue in case anyone was waiting for a connection
@@ -194,6 +238,8 @@
 	SoupSession *session = SOUP_SESSION (sa);
 	SoupMessageQueue *queue = soup_session_get_queue (session);
 	SoupMessageQueueItem *item;
+	SoupProxyResolver *proxy_resolver =
+		soup_session_get_proxy_resolver (session);
 	SoupMessage *msg;
 	SoupConnection *conn;
 	gboolean try_pruning = TRUE, should_prune = FALSE;
@@ -215,8 +261,13 @@
 			resolve_msg_addr (item);
 			continue;
 		}
+		if (proxy_resolver && !item->proxy_addr) {
+			resolve_proxy_addr (item, proxy_resolver);
+			continue;
+		}
 
 		conn = soup_session_get_connection (session, msg,
+						    item->proxy_addr,
 						    &should_prune, &is_new);
 		if (!conn)
 			continue;
@@ -254,6 +305,10 @@
 		g_object_unref (item->msg_addr);
 		item->msg_addr = NULL;
 	}
+	if (item->proxy_addr) {
+		g_object_unref (item->proxy_addr);
+		item->proxy_addr = NULL;
+	}
 
 	run_queue ((SoupSessionAsync *)item->session);
 }

Modified: trunk/libsoup/soup-session-private.h
==============================================================================
--- trunk/libsoup/soup-session-private.h	(original)
+++ trunk/libsoup/soup-session-private.h	Fri Oct 31 13:05:14 2008
@@ -9,6 +9,7 @@
 #include "soup-session.h"
 #include "soup-connection.h"
 #include "soup-message-queue.h"
+#include "soup-proxy-resolver.h"
 
 G_BEGIN_DECLS
 
@@ -17,10 +18,13 @@
 
 SoupConnection   *soup_session_get_connection       (SoupSession *session,
 						     SoupMessage *msg,
+						     SoupAddress *proxy,
 						     gboolean    *try_pruning,
 						     gboolean    *is_new);
 gboolean          soup_session_try_prune_connection (SoupSession *session);
 
+SoupProxyResolver *soup_session_get_proxy_resolver  (SoupSession *session);
+
 G_END_DECLS
 
 #endif /* SOUP_SESSION_PRIVATE_H */

Modified: trunk/libsoup/soup-session-sync.c
==============================================================================
--- trunk/libsoup/soup-session-sync.c	(original)
+++ trunk/libsoup/soup-session-sync.c	Fri Oct 31 13:05:14 2008
@@ -9,6 +9,7 @@
 #include <config.h>
 #endif
 
+#include "soup-address.h"
 #include "soup-session-sync.h"
 #include "soup-session-private.h"
 #include "soup-address.h"
@@ -130,14 +131,30 @@
 wait_for_connection (SoupSession *session, SoupMessage *msg)
 {
 	SoupSessionSyncPrivate *priv = SOUP_SESSION_SYNC_GET_PRIVATE (session);
-	SoupConnection *conn;
 	gboolean try_pruning = FALSE, is_new = FALSE;
+	SoupProxyResolver *proxy_resolver;
+	SoupAddress *proxy_addr = NULL;
+	SoupConnection *conn;
 	guint status;
 
+	proxy_resolver = soup_session_get_proxy_resolver (session);
 	g_mutex_lock (priv->lock);
 
  try_again:
-	conn = soup_session_get_connection (session, msg,
+	if (proxy_addr) {
+		g_object_unref (proxy_addr);
+		proxy_addr = NULL;
+	}
+	if (proxy_resolver) {
+		status = soup_proxy_resolver_get_proxy_sync (proxy_resolver, msg, NULL, &proxy_addr);
+		if (!SOUP_STATUS_IS_SUCCESSFUL (status)) {
+			soup_session_cancel_message (session, msg, status);
+			return NULL;
+		}
+	}
+
+
+	conn = soup_session_get_connection (session, msg, proxy_addr,
 					    &try_pruning, &is_new);
 	if (conn) {
 		if (is_new) {

Modified: trunk/libsoup/soup-session.c
==============================================================================
--- trunk/libsoup/soup-session.c	(original)
+++ trunk/libsoup/soup-session.c	Fri Oct 31 13:05:14 2008
@@ -22,6 +22,7 @@
 #include "soup-marshal.h"
 #include "soup-message-private.h"
 #include "soup-message-queue.h"
+#include "soup-proxy-resolver-static.h"
 #include "soup-session.h"
 #include "soup-session-feature.h"
 #include "soup-session-private.h"
@@ -63,9 +64,7 @@
 } SoupSessionHost;
 
 typedef struct {
-	SoupURI *proxy_uri;
-	SoupAddress *proxy_addr;
-	SoupAuth *proxy_auth;
+	SoupProxyResolver *proxy_resolver;
 
 	char *ssl_ca_file;
 	SoupSSLCredentials *ssl_creds;
@@ -225,11 +224,6 @@
 	if (priv->auth_manager)
 		g_object_unref (priv->auth_manager);
 
-	if (priv->proxy_uri)
-		soup_uri_free (priv->proxy_uri);
-	if (priv->proxy_addr)
-		g_object_unref (priv->proxy_addr);
-
 	if (priv->ssl_creds)
 		soup_ssl_free_client_credentials (priv->ssl_creds);
 
@@ -506,18 +500,6 @@
 }
 
 static gboolean
-safe_uri_equal (SoupURI *a, SoupURI *b)
-{
-	if (!a && !b)
-		return TRUE;
-
-	if ((a && !b) || (b && !a))
-		return FALSE;
-
-	return soup_uri_equal (a, b);
-}
-
-static gboolean
 safe_str_equal (const char *a, const char *b)
 {
 	if (!a && !b)
@@ -536,7 +518,6 @@
 	SoupSession *session = SOUP_SESSION (object);
 	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
 	SoupURI *uri;
-	gboolean need_abort = FALSE;
 	gboolean ca_file_changed = FALSE;
 	const char *new_ca_file, *user_agent;
 
@@ -544,24 +525,16 @@
 	case PROP_PROXY_URI:
 		uri = g_value_get_boxed (value);
 
-		if (!safe_uri_equal (priv->proxy_uri, uri))
-			need_abort = TRUE;
-
-		if (priv->proxy_uri)
-			soup_uri_free (priv->proxy_uri);
-		if (priv->proxy_addr)
-			g_object_unref (priv->proxy_addr);
-
-		priv->proxy_uri = uri ? soup_uri_copy (uri) : NULL;
-		priv->proxy_addr = uri ?
-			soup_address_new (uri->host, uri->port) :
-			NULL;
-
-		if (need_abort) {
-			soup_session_abort (session);
-			cleanup_hosts (priv);
-		}
+		if (uri) {
+			soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER);
+			priv->proxy_resolver = soup_proxy_resolver_static_new (uri);
+			soup_session_add_feature (session, SOUP_SESSION_FEATURE (priv->proxy_resolver));
+			g_object_unref (priv->proxy_resolver);
+		} else if (priv->proxy_resolver && SOUP_IS_PROXY_RESOLVER_STATIC (priv->proxy_resolver))
+			soup_session_remove_feature_by_type (session, SOUP_TYPE_PROXY_RESOLVER);
 
+		soup_session_abort (session);
+		cleanup_hosts (priv);
 		break;
 	case PROP_MAX_CONNS:
 		priv->max_conns = g_value_get_int (value);
@@ -643,7 +616,12 @@
 
 	switch (prop_id) {
 	case PROP_PROXY_URI:
-		g_value_set_boxed (value, priv->proxy_uri);
+		if (priv->proxy_resolver && SOUP_IS_PROXY_RESOLVER_STATIC (priv->proxy_resolver)) {
+			g_object_get_property (G_OBJECT (priv->proxy_resolver),
+					       SOUP_PROXY_RESOLVER_STATIC_PROXY_URI,
+					       value);
+		} else
+			g_value_set_boxed (value, NULL);
 		break;
 	case PROP_MAX_CONNS:
 		g_value_set_int (value, priv->max_conns);
@@ -1008,6 +986,7 @@
  **/
 SoupConnection *
 soup_session_get_connection (SoupSession *session, SoupMessage *msg,
+			     SoupAddress *proxy_addr,
 			     gboolean *try_pruning, gboolean *is_new)
 {
 	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
@@ -1058,7 +1037,7 @@
 
 	conn = soup_connection_new (
 		SOUP_CONNECTION_SERVER_ADDRESS, host->addr,
-		SOUP_CONNECTION_PROXY_ADDRESS, priv->proxy_addr,
+		SOUP_CONNECTION_PROXY_ADDRESS, proxy_addr,
 		SOUP_CONNECTION_SSL_CREDENTIALS, ssl_creds,
 		SOUP_CONNECTION_ASYNC_CONTEXT, priv->async_context,
 		SOUP_CONNECTION_TIMEOUT, priv->io_timeout,
@@ -1371,6 +1350,9 @@
 	priv = SOUP_SESSION_GET_PRIVATE (session);
 	priv->features = g_slist_prepend (priv->features, g_object_ref (feature));
 	soup_session_feature_attach (feature, session);
+
+	if (SOUP_IS_PROXY_RESOLVER (feature))
+		priv->proxy_resolver = SOUP_PROXY_RESOLVER (feature);
 }
 
 /**
@@ -1416,6 +1398,9 @@
 		priv->features = g_slist_remove (priv->features, feature);
 		soup_session_feature_detach (feature, session);
 		g_object_unref (feature);
+
+		if (feature == (SoupSessionFeature *)priv->proxy_resolver)
+			priv->proxy_resolver = NULL;
 	}
 }
 
@@ -1446,3 +1431,11 @@
 		}
 	}
 }
+
+SoupProxyResolver *
+soup_session_get_proxy_resolver (SoupSession *session)
+{
+	SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+
+	return priv->proxy_resolver;
+}

Modified: trunk/libsoup/soup-status.c
==============================================================================
--- trunk/libsoup/soup-status.c	(original)
+++ trunk/libsoup/soup-status.c	Fri Oct 31 13:05:14 2008
@@ -248,6 +248,26 @@
 	return "Unknown Error";
 }
 
+/**
+ * soup_status_proxify:
+ * @status: a status code
+ *
+ * Turns SOUP_STATUS_CANT_RESOLVE into SOUP_STATUS_CANT_RESOLVE_PROXY
+ * and SOUP_STATUS_CANT_CONNECT into SOUP_STATUS_CANT_CONNECT_PROXY.
+ * Other status codes are passed through unchanged.
+ *
+ * Return value: the "proxified" equivalent of @status.
+ **/
+guint
+soup_status_proxify (guint status_code)
+{
+	if (status_code == SOUP_STATUS_CANT_RESOLVE)
+		return SOUP_STATUS_CANT_RESOLVE_PROXY;
+	else if (status_code == SOUP_STATUS_CANT_CONNECT)
+		return SOUP_STATUS_CANT_CONNECT_PROXY;
+	else
+		return status_code;
+}
 
 GQuark
 soup_http_error_quark (void)

Modified: trunk/libsoup/soup-status.h
==============================================================================
--- trunk/libsoup/soup-status.h	(original)
+++ trunk/libsoup/soup-status.h	Fri Oct 31 13:05:14 2008
@@ -92,6 +92,7 @@
 } SoupKnownStatusCode;
 
 const char *soup_status_get_phrase (guint status_code);
+guint       soup_status_proxify    (guint status_code);
 
 #define SOUP_HTTP_ERROR soup_http_error_quark()
 GQuark soup_http_error_quark (void);



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