|
Packit |
ae235b |
/* GIO - GLib Input, Output and Streaming Library
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* Copyright (C) 2010 Collabora, Ltd.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* This library is free software; you can redistribute it and/or
|
|
Packit |
ae235b |
* modify it under the terms of the GNU Lesser General Public
|
|
Packit |
ae235b |
* License as published by the Free Software Foundation; either
|
|
Packit |
ae235b |
* version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* This library is distributed in the hope that it will be useful,
|
|
Packit |
ae235b |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
ae235b |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
ae235b |
* Lesser General Public License for more details.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* You should have received a copy of the GNU Lesser General
|
|
Packit |
ae235b |
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#include "config.h"
|
|
Packit |
ae235b |
#include "gproxyaddressenumerator.h"
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#include <string.h>
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#include "gasyncresult.h"
|
|
Packit |
ae235b |
#include "ginetaddress.h"
|
|
Packit |
ae235b |
#include "glibintl.h"
|
|
Packit |
ae235b |
#include "gnetworkaddress.h"
|
|
Packit |
ae235b |
#include "gnetworkingprivate.h"
|
|
Packit |
ae235b |
#include "gproxy.h"
|
|
Packit |
ae235b |
#include "gproxyaddress.h"
|
|
Packit |
ae235b |
#include "gproxyresolver.h"
|
|
Packit |
ae235b |
#include "gtask.h"
|
|
Packit |
ae235b |
#include "gresolver.h"
|
|
Packit |
ae235b |
#include "gsocketaddress.h"
|
|
Packit |
ae235b |
#include "gsocketaddressenumerator.h"
|
|
Packit |
ae235b |
#include "gsocketconnectable.h"
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
#define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
enum
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
PROP_0,
|
|
Packit |
ae235b |
PROP_URI,
|
|
Packit |
ae235b |
PROP_DEFAULT_PORT,
|
|
Packit |
ae235b |
PROP_CONNECTABLE,
|
|
Packit |
ae235b |
PROP_PROXY_RESOLVER
|
|
Packit |
ae235b |
};
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
struct _GProxyAddressEnumeratorPrivate
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
/* Destination address */
|
|
Packit |
ae235b |
GSocketConnectable *connectable;
|
|
Packit |
ae235b |
gchar *dest_uri;
|
|
Packit |
ae235b |
guint16 default_port;
|
|
Packit |
ae235b |
gchar *dest_hostname;
|
|
Packit |
ae235b |
guint16 dest_port;
|
|
Packit |
ae235b |
GList *dest_ips;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Proxy enumeration */
|
|
Packit |
ae235b |
GProxyResolver *proxy_resolver;
|
|
Packit |
ae235b |
gchar **proxies;
|
|
Packit |
ae235b |
gchar **next_proxy;
|
|
Packit |
ae235b |
GSocketAddressEnumerator *addr_enum;
|
|
Packit |
ae235b |
GSocketAddress *proxy_address;
|
|
Packit |
ae235b |
const gchar *proxy_uri;
|
|
Packit |
ae235b |
gchar *proxy_type;
|
|
Packit |
ae235b |
gchar *proxy_username;
|
|
Packit |
ae235b |
gchar *proxy_password;
|
|
Packit |
ae235b |
gboolean supports_hostname;
|
|
Packit |
ae235b |
GList *next_dest_ip;
|
|
Packit |
ae235b |
GError *last_error;
|
|
Packit |
ae235b |
};
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
save_userinfo (GProxyAddressEnumeratorPrivate *priv,
|
|
Packit |
ae235b |
const gchar *proxy)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gchar *userinfo;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_username)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_free (priv->proxy_username);
|
|
Packit |
ae235b |
priv->proxy_username = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_password)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_free (priv->proxy_password);
|
|
Packit |
ae235b |
priv->proxy_password = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (_g_uri_parse_authority (proxy, NULL, NULL, &userinfo, NULL))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (userinfo)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gchar **split = g_strsplit (userinfo, ":", 2);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (split[0] != NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
priv->proxy_username = g_uri_unescape_string (split[0], NULL);
|
|
Packit |
ae235b |
if (split[1] != NULL)
|
|
Packit |
ae235b |
priv->proxy_password = g_uri_unescape_string (split[1], NULL);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_strfreev (split);
|
|
Packit |
ae235b |
g_free (userinfo);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
next_enumerator (GProxyAddressEnumeratorPrivate *priv)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (priv->proxy_address)
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
while (priv->addr_enum == NULL && *priv->next_proxy)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GSocketConnectable *connectable = NULL;
|
|
Packit |
ae235b |
GProxy *proxy;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
priv->proxy_uri = *priv->next_proxy++;
|
|
Packit |
ae235b |
g_free (priv->proxy_type);
|
|
Packit |
ae235b |
priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_type == NULL)
|
|
Packit |
ae235b |
continue;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/* Assumes hostnames are supported for unknown protocols */
|
|
Packit |
ae235b |
priv->supports_hostname = TRUE;
|
|
Packit |
ae235b |
proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
|
|
Packit |
ae235b |
if (proxy)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
priv->supports_hostname = g_proxy_supports_hostname (proxy);
|
|
Packit |
ae235b |
g_object_unref (proxy);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (priv->connectable)
|
|
Packit |
ae235b |
connectable = g_object_ref (priv->connectable);
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
connectable = g_network_address_new (priv->dest_hostname,
|
|
Packit |
ae235b |
priv->dest_port);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GError *error = NULL;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
connectable = g_network_address_parse_uri (priv->proxy_uri, 0, &error);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (error)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_warning ("Invalid proxy URI '%s': %s",
|
|
Packit |
ae235b |
priv->proxy_uri, error->message);
|
|
Packit |
ae235b |
g_error_free (error);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
save_userinfo (priv, priv->proxy_uri);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (connectable)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
priv->addr_enum = g_socket_connectable_enumerate (connectable);
|
|
Packit |
ae235b |
g_object_unref (connectable);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static GSocketAddress *
|
|
Packit |
ae235b |
g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator,
|
|
Packit |
ae235b |
GCancellable *cancellable,
|
|
Packit |
ae235b |
GError **error)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
|
|
Packit |
ae235b |
GSocketAddress *result = NULL;
|
|
Packit |
ae235b |
GError *first_error = NULL;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxies == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
|
|
Packit |
ae235b |
priv->dest_uri,
|
|
Packit |
ae235b |
cancellable,
|
|
Packit |
ae235b |
error);
|
|
Packit |
ae235b |
priv->next_proxy = priv->proxies;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxies == NULL)
|
|
Packit |
ae235b |
return NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
while (result == NULL && (*priv->next_proxy || priv->addr_enum))
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gchar *dest_hostname;
|
|
Packit |
ae235b |
gchar *dest_protocol;
|
|
Packit |
ae235b |
GInetSocketAddress *inetsaddr;
|
|
Packit |
ae235b |
GInetAddress *inetaddr;
|
|
Packit |
ae235b |
guint16 port;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
next_enumerator (priv);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->addr_enum)
|
|
Packit |
ae235b |
continue;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_address == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
priv->proxy_address = g_socket_address_enumerator_next (
|
|
Packit |
ae235b |
priv->addr_enum,
|
|
Packit |
ae235b |
cancellable,
|
|
Packit |
ae235b |
first_error ? NULL : &first_error);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_address == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (priv->addr_enum);
|
|
Packit |
ae235b |
priv->addr_enum = NULL;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->dest_ips)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_resolver_free_addresses (priv->dest_ips);
|
|
Packit |
ae235b |
priv->dest_ips = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
continue;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
result = priv->proxy_address;
|
|
Packit |
ae235b |
priv->proxy_address = NULL;
|
|
Packit |
ae235b |
continue;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->supports_hostname)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GInetAddress *dest_ip;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->dest_ips)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GResolver *resolver;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
resolver = g_resolver_get_default();
|
|
Packit |
ae235b |
priv->dest_ips = g_resolver_lookup_by_name (resolver,
|
|
Packit |
ae235b |
priv->dest_hostname,
|
|
Packit |
ae235b |
cancellable,
|
|
Packit |
ae235b |
first_error ? NULL : &first_error);
|
|
Packit |
ae235b |
g_object_unref (resolver);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->dest_ips)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (priv->proxy_address);
|
|
Packit |
ae235b |
priv->proxy_address = NULL;
|
|
Packit |
ae235b |
continue;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->next_dest_ip)
|
|
Packit |
ae235b |
priv->next_dest_ip = priv->dest_ips;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
|
|
Packit |
ae235b |
dest_hostname = g_inet_address_to_string (dest_ip);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
priv->next_dest_ip = g_list_next (priv->next_dest_ip);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
dest_hostname = g_strdup (priv->dest_hostname);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
dest_protocol = g_uri_parse_scheme (priv->dest_uri);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_return_val_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address),
|
|
Packit |
ae235b |
NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
|
|
Packit |
ae235b |
inetaddr = g_inet_socket_address_get_address (inetsaddr);
|
|
Packit |
ae235b |
port = g_inet_socket_address_get_port (inetsaddr);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
result = g_object_new (G_TYPE_PROXY_ADDRESS,
|
|
Packit |
ae235b |
"address", inetaddr,
|
|
Packit |
ae235b |
"port", port,
|
|
Packit |
ae235b |
"protocol", priv->proxy_type,
|
|
Packit |
ae235b |
"destination-protocol", dest_protocol,
|
|
Packit |
ae235b |
"destination-hostname", dest_hostname,
|
|
Packit |
ae235b |
"destination-port", priv->dest_port,
|
|
Packit |
ae235b |
"username", priv->proxy_username,
|
|
Packit |
ae235b |
"password", priv->proxy_password,
|
|
Packit |
ae235b |
"uri", priv->proxy_uri,
|
|
Packit |
ae235b |
NULL);
|
|
Packit |
ae235b |
g_free (dest_hostname);
|
|
Packit |
ae235b |
g_free (dest_protocol);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->supports_hostname || priv->next_dest_ip == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (priv->proxy_address);
|
|
Packit |
ae235b |
priv->proxy_address = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (result == NULL && first_error)
|
|
Packit |
ae235b |
g_propagate_error (error, first_error);
|
|
Packit |
ae235b |
else if (first_error)
|
|
Packit |
ae235b |
g_error_free (first_error);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
return result;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
complete_async (GTask *task)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->last_error)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_task_return_error (task, priv->last_error);
|
|
Packit |
ae235b |
priv->last_error = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
g_task_return_pointer (task, NULL, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
return_result (GTask *task)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
GSocketAddress *result;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
result = priv->proxy_address;
|
|
Packit |
ae235b |
priv->proxy_address = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
gchar *dest_hostname, *dest_protocol;
|
|
Packit |
ae235b |
GInetSocketAddress *inetsaddr;
|
|
Packit |
ae235b |
GInetAddress *inetaddr;
|
|
Packit |
ae235b |
guint16 port;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->supports_hostname)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GInetAddress *dest_ip;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (!priv->next_dest_ip)
|
|
Packit |
ae235b |
priv->next_dest_ip = priv->dest_ips;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
|
|
Packit |
ae235b |
dest_hostname = g_inet_address_to_string (dest_ip);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
priv->next_dest_ip = g_list_next (priv->next_dest_ip);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
dest_hostname = g_strdup (priv->dest_hostname);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
dest_protocol = g_uri_parse_scheme (priv->dest_uri);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_return_if_fail (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
|
|
Packit |
ae235b |
inetaddr = g_inet_socket_address_get_address (inetsaddr);
|
|
Packit |
ae235b |
port = g_inet_socket_address_get_port (inetsaddr);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
result = g_object_new (G_TYPE_PROXY_ADDRESS,
|
|
Packit |
ae235b |
"address", inetaddr,
|
|
Packit |
ae235b |
"port", port,
|
|
Packit |
ae235b |
"protocol", priv->proxy_type,
|
|
Packit |
ae235b |
"destination-protocol", dest_protocol,
|
|
Packit |
ae235b |
"destination-hostname", dest_hostname,
|
|
Packit |
ae235b |
"destination-port", priv->dest_port,
|
|
Packit |
ae235b |
"username", priv->proxy_username,
|
|
Packit |
ae235b |
"password", priv->proxy_password,
|
|
Packit |
ae235b |
"uri", priv->proxy_uri,
|
|
Packit |
ae235b |
NULL);
|
|
Packit |
ae235b |
g_free (dest_hostname);
|
|
Packit |
ae235b |
g_free (dest_protocol);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->supports_hostname || priv->next_dest_ip == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (priv->proxy_address);
|
|
Packit |
ae235b |
priv->proxy_address = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_task_return_pointer (task, result, g_object_unref);
|
|
Packit |
ae235b |
g_object_unref (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void address_enumerate_cb (GObject *object,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
next_proxy (GTask *task)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (*priv->next_proxy)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_unref (priv->addr_enum);
|
|
Packit |
ae235b |
priv->addr_enum = NULL;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->dest_ips)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_resolver_free_addresses (priv->dest_ips);
|
|
Packit |
ae235b |
priv->dest_ips = NULL;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
next_enumerator (priv);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->addr_enum)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
Packit |
ae235b |
g_task_get_cancellable (task),
|
|
Packit |
ae235b |
address_enumerate_cb,
|
|
Packit |
ae235b |
task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
complete_async (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
dest_hostname_lookup_cb (GObject *object,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GTask *task = user_data;
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_clear_error (&priv->last_error);
|
|
Packit |
ae235b |
priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
|
|
Packit |
ae235b |
result,
|
|
Packit |
ae235b |
&priv->last_error);
|
|
Packit |
ae235b |
if (priv->dest_ips)
|
|
Packit |
ae235b |
return_result (task);
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_clear_object (&priv->proxy_address);
|
|
Packit |
ae235b |
next_proxy (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
address_enumerate_cb (GObject *object,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GTask *task = user_data;
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_clear_error (&priv->last_error);
|
|
Packit |
ae235b |
priv->proxy_address =
|
|
Packit |
ae235b |
g_socket_address_enumerator_next_finish (priv->addr_enum,
|
|
Packit |
ae235b |
result,
|
|
Packit |
ae235b |
&priv->last_error);
|
|
Packit |
ae235b |
if (priv->proxy_address)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (!priv->supports_hostname && !priv->dest_ips)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GResolver *resolver;
|
|
Packit |
ae235b |
resolver = g_resolver_get_default();
|
|
Packit |
ae235b |
g_resolver_lookup_by_name_async (resolver,
|
|
Packit |
ae235b |
priv->dest_hostname,
|
|
Packit |
ae235b |
g_task_get_cancellable (task),
|
|
Packit |
ae235b |
dest_hostname_lookup_cb,
|
|
Packit |
ae235b |
task);
|
|
Packit |
ae235b |
g_object_unref (resolver);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
return_result (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
next_proxy (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
proxy_lookup_cb (GObject *object,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GTask *task = user_data;
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_clear_error (&priv->last_error);
|
|
Packit |
ae235b |
priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
|
|
Packit |
ae235b |
result,
|
|
Packit |
ae235b |
&priv->last_error);
|
|
Packit |
ae235b |
priv->next_proxy = priv->proxies;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->last_error)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
complete_async (task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
next_enumerator (priv);
|
|
Packit |
ae235b |
if (priv->addr_enum)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
Packit |
ae235b |
g_task_get_cancellable (task),
|
|
Packit |
ae235b |
address_enumerate_cb,
|
|
Packit |
ae235b |
task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
complete_async (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
|
|
Packit |
ae235b |
GCancellable *cancellable,
|
|
Packit |
ae235b |
GAsyncReadyCallback callback,
|
|
Packit |
ae235b |
gpointer user_data)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
|
|
Packit |
ae235b |
GTask *task;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
task = g_task_new (enumerator, cancellable, callback, user_data);
|
|
Packit |
ae235b |
g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
|
|
Packit |
ae235b |
g_task_set_task_data (task, priv, NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxies == NULL)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_proxy_resolver_lookup_async (priv->proxy_resolver,
|
|
Packit |
ae235b |
priv->dest_uri,
|
|
Packit |
ae235b |
cancellable,
|
|
Packit |
ae235b |
proxy_lookup_cb,
|
|
Packit |
ae235b |
task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->addr_enum)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
if (priv->proxy_address)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
return_result (task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
Packit |
ae235b |
cancellable,
|
|
Packit |
ae235b |
address_enumerate_cb,
|
|
Packit |
ae235b |
task);
|
|
Packit |
ae235b |
return;
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
complete_async (task);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static GSocketAddress *
|
|
Packit |
ae235b |
g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator,
|
|
Packit |
ae235b |
GAsyncResult *result,
|
|
Packit |
ae235b |
GError **error)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
return g_task_propagate_pointer (G_TASK (result), error);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_constructed (GObject *object)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
Packit |
ae235b |
GSocketConnectable *conn;
|
|
Packit |
ae235b |
guint port;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->dest_uri)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
|
|
Packit |
ae235b |
if (conn)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
g_object_get (conn,
|
|
Packit |
ae235b |
"hostname", &priv->dest_hostname,
|
|
Packit |
ae235b |
"port", &port,
|
|
Packit |
ae235b |
NULL);
|
|
Packit |
ae235b |
priv->dest_port = port;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_unref (conn);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
else
|
|
Packit |
ae235b |
g_warning ("Invalid URI '%s'", priv->dest_uri);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_get_property (GObject *object,
|
|
Packit |
ae235b |
guint property_id,
|
|
Packit |
ae235b |
GValue *value,
|
|
Packit |
ae235b |
GParamSpec *pspec)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
Packit |
ae235b |
switch (property_id)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
case PROP_URI:
|
|
Packit |
ae235b |
g_value_set_string (value, priv->dest_uri);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_DEFAULT_PORT:
|
|
Packit |
ae235b |
g_value_set_uint (value, priv->default_port);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_CONNECTABLE:
|
|
Packit |
ae235b |
g_value_set_object (value, priv->connectable);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_PROXY_RESOLVER:
|
|
Packit |
ae235b |
g_value_set_object (value, priv->proxy_resolver);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
default:
|
|
Packit |
ae235b |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_set_property (GObject *object,
|
|
Packit |
ae235b |
guint property_id,
|
|
Packit |
ae235b |
const GValue *value,
|
|
Packit |
ae235b |
GParamSpec *pspec)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
Packit |
ae235b |
switch (property_id)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
case PROP_URI:
|
|
Packit |
ae235b |
priv->dest_uri = g_value_dup_string (value);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_DEFAULT_PORT:
|
|
Packit |
ae235b |
priv->default_port = g_value_get_uint (value);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_CONNECTABLE:
|
|
Packit |
ae235b |
priv->connectable = g_value_dup_object (value);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
case PROP_PROXY_RESOLVER:
|
|
Packit |
ae235b |
if (priv->proxy_resolver)
|
|
Packit |
ae235b |
g_object_unref (priv->proxy_resolver);
|
|
Packit |
ae235b |
priv->proxy_resolver = g_value_get_object (value);
|
|
Packit |
ae235b |
if (!priv->proxy_resolver)
|
|
Packit |
ae235b |
priv->proxy_resolver = g_proxy_resolver_get_default ();
|
|
Packit |
ae235b |
g_object_ref (priv->proxy_resolver);
|
|
Packit |
ae235b |
break;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
default:
|
|
Packit |
ae235b |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_finalize (GObject *object)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->connectable)
|
|
Packit |
ae235b |
g_object_unref (priv->connectable);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->proxy_resolver)
|
|
Packit |
ae235b |
g_object_unref (priv->proxy_resolver);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_free (priv->dest_uri);
|
|
Packit |
ae235b |
g_free (priv->dest_hostname);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->dest_ips)
|
|
Packit |
ae235b |
g_resolver_free_addresses (priv->dest_ips);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_strfreev (priv->proxies);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
if (priv->addr_enum)
|
|
Packit |
ae235b |
g_object_unref (priv->addr_enum);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_free (priv->proxy_type);
|
|
Packit |
ae235b |
g_free (priv->proxy_username);
|
|
Packit |
ae235b |
g_free (priv->proxy_password);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_clear_error (&priv->last_error);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
self->priv = g_proxy_address_enumerator_get_instance_private (self);
|
|
Packit |
ae235b |
}
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
static void
|
|
Packit |
ae235b |
g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
|
|
Packit |
ae235b |
{
|
|
Packit |
ae235b |
GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
|
|
Packit |
ae235b |
GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
object_class->constructed = g_proxy_address_enumerator_constructed;
|
|
Packit |
ae235b |
object_class->set_property = g_proxy_address_enumerator_set_property;
|
|
Packit |
ae235b |
object_class->get_property = g_proxy_address_enumerator_get_property;
|
|
Packit |
ae235b |
object_class->finalize = g_proxy_address_enumerator_finalize;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
enumerator_class->next = g_proxy_address_enumerator_next;
|
|
Packit |
ae235b |
enumerator_class->next_async = g_proxy_address_enumerator_next_async;
|
|
Packit |
ae235b |
enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_class_install_property (object_class,
|
|
Packit |
ae235b |
PROP_URI,
|
|
Packit |
ae235b |
g_param_spec_string ("uri",
|
|
Packit |
ae235b |
P_("URI"),
|
|
Packit |
ae235b |
P_("The destination URI, use none:// for generic socket"),
|
|
Packit |
ae235b |
NULL,
|
|
Packit |
ae235b |
G_PARAM_READWRITE |
|
|
Packit |
ae235b |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit |
ae235b |
G_PARAM_STATIC_STRINGS));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/**
|
|
Packit |
ae235b |
* GProxyAddressEnumerator:default-port:
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* The default port to use if #GProxyAddressEnumerator:uri does not
|
|
Packit |
ae235b |
* specify one.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* Since: 2.38
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
g_object_class_install_property (object_class,
|
|
Packit |
ae235b |
PROP_DEFAULT_PORT,
|
|
Packit |
ae235b |
g_param_spec_uint ("default-port",
|
|
Packit |
ae235b |
P_("Default port"),
|
|
Packit |
ae235b |
P_("The default port to use if uri does not specify one"),
|
|
Packit |
ae235b |
0, 65535, 0,
|
|
Packit |
ae235b |
G_PARAM_READWRITE |
|
|
Packit |
ae235b |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit |
ae235b |
G_PARAM_STATIC_STRINGS));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
g_object_class_install_property (object_class,
|
|
Packit |
ae235b |
PROP_CONNECTABLE,
|
|
Packit |
ae235b |
g_param_spec_object ("connectable",
|
|
Packit |
ae235b |
P_("Connectable"),
|
|
Packit |
ae235b |
P_("The connectable being enumerated."),
|
|
Packit |
ae235b |
G_TYPE_SOCKET_CONNECTABLE,
|
|
Packit |
ae235b |
G_PARAM_READWRITE |
|
|
Packit |
ae235b |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit |
ae235b |
G_PARAM_STATIC_STRINGS));
|
|
Packit |
ae235b |
|
|
Packit |
ae235b |
/**
|
|
Packit |
ae235b |
* GProxyAddressEnumerator:proxy-resolver:
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* The proxy resolver to use.
|
|
Packit |
ae235b |
*
|
|
Packit |
ae235b |
* Since: 2.36
|
|
Packit |
ae235b |
*/
|
|
Packit |
ae235b |
g_object_class_install_property (object_class,
|
|
Packit |
ae235b |
PROP_PROXY_RESOLVER,
|
|
Packit |
ae235b |
g_param_spec_object ("proxy-resolver",
|
|
Packit |
ae235b |
P_("Proxy resolver"),
|
|
Packit |
ae235b |
P_("The proxy resolver to use."),
|
|
Packit |
ae235b |
G_TYPE_PROXY_RESOLVER,
|
|
Packit |
ae235b |
G_PARAM_READWRITE |
|
|
Packit |
ae235b |
G_PARAM_CONSTRUCT |
|
|
Packit |
ae235b |
G_PARAM_STATIC_STRINGS));
|
|
Packit |
ae235b |
}
|