mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-26 15:36:14 +01:00
4894168631
scan-build was complaining that `dest_hostname` and `dest_protocol` were used after being freed, which could potentially happen if the code is built with `G_DISABLE_CHECKS`. This is a false positive, because the state of types in the program should be the same regardless of whether `G_DISABLE_CHECKS` is used. However, the code did smell. If we are trying to free things and return gracefully if the underlying socket address enumerator returns something of the wrong type, why not free the rest of the function’s state, or skip the invalid address and move on to the next one? Or if we are trying to make an assertion, why bother freeing some temporary data at all? This halfway house doesn’t make sense. So turn the `g_return_val_if_fail()` into a full assertion. Signed-off-by: Philip Withnall <pwithnall@gnome.org> Helps: #1767
804 lines
22 KiB
C
804 lines
22 KiB
C
/* GIO - GLib Input, Output and Streaming Library
|
|
*
|
|
* Copyright (C) 2010 Collabora, Ltd.
|
|
*
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General
|
|
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
* Author: Nicolas Dufresne <nicolas.dufresne@collabora.co.uk>
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "gproxyaddressenumerator.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "gasyncresult.h"
|
|
#include "ginetaddress.h"
|
|
#include "gioerror.h"
|
|
#include "glibintl.h"
|
|
#include "glib-private.h"
|
|
#include "gnetworkaddress.h"
|
|
#include "gnetworkingprivate.h"
|
|
#include "gproxy.h"
|
|
#include "gproxyaddress.h"
|
|
#include "gproxyresolver.h"
|
|
#include "gtask.h"
|
|
#include "gresolver.h"
|
|
#include "gsocketaddress.h"
|
|
#include "gsocketaddressenumerator.h"
|
|
#include "gsocketconnectable.h"
|
|
|
|
/**
|
|
* GProxyAddressEnumerator:
|
|
*
|
|
* `GProxyAddressEnumerator` is a wrapper around
|
|
* [class@Gio.SocketAddressEnumerator] which takes the [class@Gio.SocketAddress]
|
|
* instances returned by the [class@Gio.SocketAddressEnumerator]
|
|
* and wraps them in [class@Gio.ProxyAddress] instances, using the given
|
|
* [property@Gio.ProxyAddressEnumerator:proxy-resolver].
|
|
*
|
|
* This enumerator will be returned (for example, by
|
|
* [method@Gio.SocketConnectable.enumerate]) as appropriate when a proxy is
|
|
* configured; there should be no need to manually wrap a
|
|
* [class@Gio.SocketAddressEnumerator] instance with one.
|
|
*/
|
|
|
|
#define GET_PRIVATE(o) (G_PROXY_ADDRESS_ENUMERATOR (o)->priv)
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_URI,
|
|
PROP_DEFAULT_PORT,
|
|
PROP_CONNECTABLE,
|
|
PROP_PROXY_RESOLVER
|
|
};
|
|
|
|
struct _GProxyAddressEnumeratorPrivate
|
|
{
|
|
/* Destination address */
|
|
GSocketConnectable *connectable;
|
|
gchar *dest_uri;
|
|
guint16 default_port;
|
|
gchar *dest_hostname;
|
|
guint16 dest_port;
|
|
GList *dest_ips;
|
|
|
|
/* Proxy enumeration */
|
|
GProxyResolver *proxy_resolver;
|
|
gchar **proxies;
|
|
gchar **next_proxy;
|
|
GSocketAddressEnumerator *addr_enum;
|
|
GSocketAddress *proxy_address;
|
|
const gchar *proxy_uri;
|
|
gchar *proxy_type;
|
|
gchar *proxy_username;
|
|
gchar *proxy_password;
|
|
gboolean supports_hostname;
|
|
GList *next_dest_ip;
|
|
GError *last_error;
|
|
|
|
/* ever_enumerated is TRUE after we've returned a result for the first time
|
|
* via g_proxy_address_enumerator_next() or _next_async(). If FALSE, we have
|
|
* never returned yet, and should return an error if returning NULL because
|
|
* it does not make sense for a proxy resolver to return NULL except on error.
|
|
* (Whereas a DNS resolver would return NULL with no error to indicate "no
|
|
* results", a proxy resolver would want to return "direct://" instead, so
|
|
* NULL without error does not make sense for us.)
|
|
*
|
|
* But if ever_enumerated is TRUE, then we must not report any further errors
|
|
* (except for G_IO_ERROR_CANCELLED), because this is an API contract of
|
|
* GSocketAddressEnumerator.
|
|
*/
|
|
gboolean ever_enumerated;
|
|
};
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GProxyAddressEnumerator, g_proxy_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
|
|
|
|
static void
|
|
save_userinfo (GProxyAddressEnumeratorPrivate *priv,
|
|
const gchar *proxy)
|
|
{
|
|
g_clear_pointer (&priv->proxy_username, g_free);
|
|
g_clear_pointer (&priv->proxy_password, g_free);
|
|
|
|
g_uri_split_with_user (proxy, G_URI_FLAGS_HAS_PASSWORD, NULL,
|
|
&priv->proxy_username, &priv->proxy_password,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
static void
|
|
next_enumerator (GProxyAddressEnumeratorPrivate *priv)
|
|
{
|
|
if (priv->proxy_address)
|
|
return;
|
|
|
|
while (priv->addr_enum == NULL && *priv->next_proxy)
|
|
{
|
|
GSocketConnectable *connectable = NULL;
|
|
GProxy *proxy;
|
|
|
|
priv->proxy_uri = *priv->next_proxy++;
|
|
g_free (priv->proxy_type);
|
|
priv->proxy_type = g_uri_parse_scheme (priv->proxy_uri);
|
|
|
|
if (priv->proxy_type == NULL)
|
|
continue;
|
|
|
|
/* Assumes hostnames are supported for unknown protocols */
|
|
priv->supports_hostname = TRUE;
|
|
proxy = g_proxy_get_default_for_protocol (priv->proxy_type);
|
|
if (proxy)
|
|
{
|
|
priv->supports_hostname = g_proxy_supports_hostname (proxy);
|
|
g_object_unref (proxy);
|
|
}
|
|
|
|
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
{
|
|
if (priv->connectable)
|
|
connectable = g_object_ref (priv->connectable);
|
|
else
|
|
connectable = g_network_address_new (priv->dest_hostname,
|
|
priv->dest_port);
|
|
}
|
|
else
|
|
{
|
|
GError *error = NULL;
|
|
int default_port;
|
|
|
|
default_port = GLIB_PRIVATE_CALL (g_uri_get_default_scheme_port) (priv->proxy_type);
|
|
if (default_port == -1)
|
|
default_port = 0;
|
|
|
|
connectable = g_network_address_parse_uri (priv->proxy_uri, default_port, &error);
|
|
if (error)
|
|
{
|
|
g_warning ("Invalid proxy URI '%s': %s",
|
|
priv->proxy_uri, error->message);
|
|
g_error_free (error);
|
|
}
|
|
|
|
save_userinfo (priv, priv->proxy_uri);
|
|
}
|
|
|
|
if (connectable)
|
|
{
|
|
priv->addr_enum = g_socket_connectable_enumerate (connectable);
|
|
g_object_unref (connectable);
|
|
}
|
|
}
|
|
}
|
|
|
|
static GSocketAddress *
|
|
g_proxy_address_enumerator_next (GSocketAddressEnumerator *enumerator,
|
|
GCancellable *cancellable,
|
|
GError **error)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
|
|
GSocketAddress *result = NULL;
|
|
GError *first_error = NULL;
|
|
|
|
if (!priv->ever_enumerated)
|
|
{
|
|
g_assert (priv->proxies == NULL);
|
|
priv->proxies = g_proxy_resolver_lookup (priv->proxy_resolver,
|
|
priv->dest_uri,
|
|
cancellable,
|
|
error);
|
|
priv->next_proxy = priv->proxies;
|
|
|
|
if (priv->proxies == NULL)
|
|
{
|
|
priv->ever_enumerated = TRUE;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
while (result == NULL && (*priv->next_proxy || priv->addr_enum))
|
|
{
|
|
gchar *dest_hostname;
|
|
gchar *dest_protocol;
|
|
GInetSocketAddress *inetsaddr;
|
|
GInetAddress *inetaddr;
|
|
guint16 port;
|
|
|
|
next_enumerator (priv);
|
|
|
|
if (!priv->addr_enum)
|
|
continue;
|
|
|
|
if (priv->proxy_address == NULL)
|
|
{
|
|
priv->proxy_address = g_socket_address_enumerator_next (
|
|
priv->addr_enum,
|
|
cancellable,
|
|
first_error ? NULL : &first_error);
|
|
}
|
|
|
|
if (priv->proxy_address == NULL)
|
|
{
|
|
g_object_unref (priv->addr_enum);
|
|
priv->addr_enum = NULL;
|
|
|
|
if (priv->dest_ips)
|
|
{
|
|
g_resolver_free_addresses (priv->dest_ips);
|
|
priv->dest_ips = NULL;
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
{
|
|
result = priv->proxy_address;
|
|
priv->proxy_address = NULL;
|
|
continue;
|
|
}
|
|
|
|
if (!priv->supports_hostname)
|
|
{
|
|
GInetAddress *dest_ip;
|
|
|
|
if (!priv->dest_ips)
|
|
{
|
|
GResolver *resolver;
|
|
|
|
resolver = g_resolver_get_default();
|
|
priv->dest_ips = g_resolver_lookup_by_name (resolver,
|
|
priv->dest_hostname,
|
|
cancellable,
|
|
first_error ? NULL : &first_error);
|
|
g_object_unref (resolver);
|
|
|
|
if (!priv->dest_ips)
|
|
{
|
|
g_object_unref (priv->proxy_address);
|
|
priv->proxy_address = NULL;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (!priv->next_dest_ip)
|
|
priv->next_dest_ip = priv->dest_ips;
|
|
|
|
dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
|
|
dest_hostname = g_inet_address_to_string (dest_ip);
|
|
|
|
priv->next_dest_ip = g_list_next (priv->next_dest_ip);
|
|
}
|
|
else
|
|
{
|
|
dest_hostname = g_strdup (priv->dest_hostname);
|
|
}
|
|
|
|
g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
|
|
|
|
dest_protocol = g_uri_parse_scheme (priv->dest_uri);
|
|
|
|
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
|
|
inetaddr = g_inet_socket_address_get_address (inetsaddr);
|
|
port = g_inet_socket_address_get_port (inetsaddr);
|
|
|
|
result = g_object_new (G_TYPE_PROXY_ADDRESS,
|
|
"address", inetaddr,
|
|
"port", port,
|
|
"protocol", priv->proxy_type,
|
|
"destination-protocol", dest_protocol,
|
|
"destination-hostname", dest_hostname,
|
|
"destination-port", priv->dest_port,
|
|
"username", priv->proxy_username,
|
|
"password", priv->proxy_password,
|
|
"uri", priv->proxy_uri,
|
|
NULL);
|
|
g_free (dest_hostname);
|
|
g_free (dest_protocol);
|
|
|
|
if (priv->supports_hostname || priv->next_dest_ip == NULL)
|
|
{
|
|
g_object_unref (priv->proxy_address);
|
|
priv->proxy_address = NULL;
|
|
}
|
|
}
|
|
|
|
if (result == NULL && first_error && (!priv->ever_enumerated || g_error_matches (first_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
|
|
g_propagate_error (error, first_error);
|
|
else if (first_error)
|
|
g_error_free (first_error);
|
|
|
|
if (result == NULL && error != NULL && *error == NULL && !priv->ever_enumerated)
|
|
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unspecified proxy lookup failure"));
|
|
|
|
priv->ever_enumerated = TRUE;
|
|
|
|
return result;
|
|
}
|
|
|
|
static void
|
|
complete_async (GTask *task)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
|
|
if (priv->last_error && (!priv->ever_enumerated || g_error_matches (priv->last_error, G_IO_ERROR, G_IO_ERROR_CANCELLED)))
|
|
{
|
|
g_task_return_error (task, priv->last_error);
|
|
priv->last_error = NULL;
|
|
}
|
|
else if (!priv->ever_enumerated)
|
|
{
|
|
g_task_return_new_error_literal (task, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
_("Unspecified proxy lookup failure"));
|
|
}
|
|
else
|
|
{
|
|
g_task_return_pointer (task, NULL, NULL);
|
|
}
|
|
|
|
priv->ever_enumerated = TRUE;
|
|
|
|
g_clear_error (&priv->last_error);
|
|
g_object_unref (task);
|
|
}
|
|
|
|
static void
|
|
return_result (GTask *task)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
GSocketAddress *result;
|
|
|
|
if (strcmp ("direct", priv->proxy_type) == 0)
|
|
{
|
|
result = priv->proxy_address;
|
|
priv->proxy_address = NULL;
|
|
}
|
|
else
|
|
{
|
|
gchar *dest_hostname, *dest_protocol;
|
|
GInetSocketAddress *inetsaddr;
|
|
GInetAddress *inetaddr;
|
|
guint16 port;
|
|
|
|
if (!priv->supports_hostname)
|
|
{
|
|
GInetAddress *dest_ip;
|
|
|
|
if (!priv->next_dest_ip)
|
|
priv->next_dest_ip = priv->dest_ips;
|
|
|
|
dest_ip = G_INET_ADDRESS (priv->next_dest_ip->data);
|
|
dest_hostname = g_inet_address_to_string (dest_ip);
|
|
|
|
priv->next_dest_ip = g_list_next (priv->next_dest_ip);
|
|
}
|
|
else
|
|
{
|
|
dest_hostname = g_strdup (priv->dest_hostname);
|
|
}
|
|
dest_protocol = g_uri_parse_scheme (priv->dest_uri);
|
|
|
|
g_assert (G_IS_INET_SOCKET_ADDRESS (priv->proxy_address));
|
|
|
|
inetsaddr = G_INET_SOCKET_ADDRESS (priv->proxy_address);
|
|
inetaddr = g_inet_socket_address_get_address (inetsaddr);
|
|
port = g_inet_socket_address_get_port (inetsaddr);
|
|
|
|
result = g_object_new (G_TYPE_PROXY_ADDRESS,
|
|
"address", inetaddr,
|
|
"port", port,
|
|
"protocol", priv->proxy_type,
|
|
"destination-protocol", dest_protocol,
|
|
"destination-hostname", dest_hostname,
|
|
"destination-port", priv->dest_port,
|
|
"username", priv->proxy_username,
|
|
"password", priv->proxy_password,
|
|
"uri", priv->proxy_uri,
|
|
NULL);
|
|
g_free (dest_hostname);
|
|
g_free (dest_protocol);
|
|
|
|
if (priv->supports_hostname || priv->next_dest_ip == NULL)
|
|
{
|
|
g_object_unref (priv->proxy_address);
|
|
priv->proxy_address = NULL;
|
|
}
|
|
}
|
|
|
|
priv->ever_enumerated = TRUE;
|
|
g_task_return_pointer (task, result, g_object_unref);
|
|
g_object_unref (task);
|
|
}
|
|
|
|
static void address_enumerate_cb (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data);
|
|
|
|
static void
|
|
next_proxy (GTask *task)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
|
|
if (*priv->next_proxy)
|
|
{
|
|
g_object_unref (priv->addr_enum);
|
|
priv->addr_enum = NULL;
|
|
|
|
if (priv->dest_ips)
|
|
{
|
|
g_resolver_free_addresses (priv->dest_ips);
|
|
priv->dest_ips = NULL;
|
|
}
|
|
|
|
next_enumerator (priv);
|
|
|
|
if (priv->addr_enum)
|
|
{
|
|
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
g_task_get_cancellable (task),
|
|
address_enumerate_cb,
|
|
task);
|
|
return;
|
|
}
|
|
}
|
|
|
|
complete_async (task);
|
|
}
|
|
|
|
static void
|
|
dest_hostname_lookup_cb (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task = user_data;
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
|
|
g_clear_error (&priv->last_error);
|
|
priv->dest_ips = g_resolver_lookup_by_name_finish (G_RESOLVER (object),
|
|
result,
|
|
&priv->last_error);
|
|
if (priv->dest_ips)
|
|
return_result (task);
|
|
else
|
|
{
|
|
g_clear_object (&priv->proxy_address);
|
|
next_proxy (task);
|
|
}
|
|
}
|
|
|
|
static void
|
|
address_enumerate_cb (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task = user_data;
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
|
|
g_clear_error (&priv->last_error);
|
|
priv->proxy_address =
|
|
g_socket_address_enumerator_next_finish (priv->addr_enum,
|
|
result,
|
|
&priv->last_error);
|
|
if (priv->proxy_address)
|
|
{
|
|
if (!priv->supports_hostname && !priv->dest_ips)
|
|
{
|
|
GResolver *resolver;
|
|
resolver = g_resolver_get_default();
|
|
g_resolver_lookup_by_name_async (resolver,
|
|
priv->dest_hostname,
|
|
g_task_get_cancellable (task),
|
|
dest_hostname_lookup_cb,
|
|
task);
|
|
g_object_unref (resolver);
|
|
return;
|
|
}
|
|
|
|
return_result (task);
|
|
}
|
|
else
|
|
next_proxy (task);
|
|
}
|
|
|
|
static void
|
|
proxy_lookup_cb (GObject *object,
|
|
GAsyncResult *result,
|
|
gpointer user_data)
|
|
{
|
|
GTask *task = user_data;
|
|
GProxyAddressEnumeratorPrivate *priv = g_task_get_task_data (task);
|
|
|
|
g_clear_error (&priv->last_error);
|
|
priv->proxies = g_proxy_resolver_lookup_finish (G_PROXY_RESOLVER (object),
|
|
result,
|
|
&priv->last_error);
|
|
priv->next_proxy = priv->proxies;
|
|
|
|
if (priv->last_error)
|
|
{
|
|
complete_async (task);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
next_enumerator (priv);
|
|
if (priv->addr_enum)
|
|
{
|
|
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
g_task_get_cancellable (task),
|
|
address_enumerate_cb,
|
|
task);
|
|
return;
|
|
}
|
|
}
|
|
|
|
complete_async (task);
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
|
|
GCancellable *cancellable,
|
|
GAsyncReadyCallback callback,
|
|
gpointer user_data)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (enumerator);
|
|
GTask *task;
|
|
|
|
task = g_task_new (enumerator, cancellable, callback, user_data);
|
|
g_task_set_source_tag (task, g_proxy_address_enumerator_next_async);
|
|
g_task_set_task_data (task, priv, NULL);
|
|
|
|
if (priv->proxies == NULL)
|
|
{
|
|
g_proxy_resolver_lookup_async (priv->proxy_resolver,
|
|
priv->dest_uri,
|
|
cancellable,
|
|
proxy_lookup_cb,
|
|
task);
|
|
return;
|
|
}
|
|
|
|
if (priv->addr_enum)
|
|
{
|
|
if (priv->proxy_address)
|
|
{
|
|
return_result (task);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
g_socket_address_enumerator_next_async (priv->addr_enum,
|
|
cancellable,
|
|
address_enumerate_cb,
|
|
task);
|
|
return;
|
|
}
|
|
}
|
|
|
|
complete_async (task);
|
|
}
|
|
|
|
static GSocketAddress *
|
|
g_proxy_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator,
|
|
GAsyncResult *result,
|
|
GError **error)
|
|
{
|
|
g_return_val_if_fail (g_task_is_valid (result, enumerator), NULL);
|
|
|
|
return g_task_propagate_pointer (G_TASK (result), error);
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_constructed (GObject *object)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
GSocketConnectable *conn;
|
|
guint port;
|
|
|
|
if (priv->dest_uri)
|
|
{
|
|
conn = g_network_address_parse_uri (priv->dest_uri, priv->default_port, NULL);
|
|
if (conn)
|
|
{
|
|
g_object_get (conn,
|
|
"hostname", &priv->dest_hostname,
|
|
"port", &port,
|
|
NULL);
|
|
priv->dest_port = port;
|
|
|
|
g_object_unref (conn);
|
|
}
|
|
else
|
|
g_warning ("Invalid URI '%s'", priv->dest_uri);
|
|
}
|
|
|
|
G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->constructed (object);
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
switch (property_id)
|
|
{
|
|
case PROP_URI:
|
|
g_value_set_string (value, priv->dest_uri);
|
|
break;
|
|
|
|
case PROP_DEFAULT_PORT:
|
|
g_value_set_uint (value, priv->default_port);
|
|
break;
|
|
|
|
case PROP_CONNECTABLE:
|
|
g_value_set_object (value, priv->connectable);
|
|
break;
|
|
|
|
case PROP_PROXY_RESOLVER:
|
|
g_value_set_object (value, priv->proxy_resolver);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
switch (property_id)
|
|
{
|
|
case PROP_URI:
|
|
priv->dest_uri = g_value_dup_string (value);
|
|
break;
|
|
|
|
case PROP_DEFAULT_PORT:
|
|
priv->default_port = g_value_get_uint (value);
|
|
break;
|
|
|
|
case PROP_CONNECTABLE:
|
|
priv->connectable = g_value_dup_object (value);
|
|
break;
|
|
|
|
case PROP_PROXY_RESOLVER:
|
|
if (priv->proxy_resolver)
|
|
g_object_unref (priv->proxy_resolver);
|
|
priv->proxy_resolver = g_value_get_object (value);
|
|
if (!priv->proxy_resolver)
|
|
priv->proxy_resolver = g_proxy_resolver_get_default ();
|
|
g_object_ref (priv->proxy_resolver);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_finalize (GObject *object)
|
|
{
|
|
GProxyAddressEnumeratorPrivate *priv = GET_PRIVATE (object);
|
|
|
|
if (priv->connectable)
|
|
g_object_unref (priv->connectable);
|
|
|
|
if (priv->proxy_resolver)
|
|
g_object_unref (priv->proxy_resolver);
|
|
|
|
g_free (priv->dest_uri);
|
|
g_free (priv->dest_hostname);
|
|
|
|
if (priv->dest_ips)
|
|
g_resolver_free_addresses (priv->dest_ips);
|
|
|
|
g_strfreev (priv->proxies);
|
|
|
|
if (priv->addr_enum)
|
|
g_object_unref (priv->addr_enum);
|
|
|
|
g_free (priv->proxy_type);
|
|
g_free (priv->proxy_username);
|
|
g_free (priv->proxy_password);
|
|
|
|
g_clear_error (&priv->last_error);
|
|
|
|
G_OBJECT_CLASS (g_proxy_address_enumerator_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_init (GProxyAddressEnumerator *self)
|
|
{
|
|
self->priv = g_proxy_address_enumerator_get_instance_private (self);
|
|
}
|
|
|
|
static void
|
|
g_proxy_address_enumerator_class_init (GProxyAddressEnumeratorClass *proxy_enumerator_class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (proxy_enumerator_class);
|
|
GSocketAddressEnumeratorClass *enumerator_class = G_SOCKET_ADDRESS_ENUMERATOR_CLASS (proxy_enumerator_class);
|
|
|
|
object_class->constructed = g_proxy_address_enumerator_constructed;
|
|
object_class->set_property = g_proxy_address_enumerator_set_property;
|
|
object_class->get_property = g_proxy_address_enumerator_get_property;
|
|
object_class->finalize = g_proxy_address_enumerator_finalize;
|
|
|
|
enumerator_class->next = g_proxy_address_enumerator_next;
|
|
enumerator_class->next_async = g_proxy_address_enumerator_next_async;
|
|
enumerator_class->next_finish = g_proxy_address_enumerator_next_finish;
|
|
|
|
/**
|
|
* GProxyAddressEnumerator:uri:
|
|
*
|
|
* The destination URI. Use `none://` for a generic socket.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_URI,
|
|
g_param_spec_string ("uri", NULL, NULL,
|
|
NULL,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
/**
|
|
* GProxyAddressEnumerator:default-port:
|
|
*
|
|
* The default port to use if #GProxyAddressEnumerator:uri does not
|
|
* specify one.
|
|
*
|
|
* Since: 2.38
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_DEFAULT_PORT,
|
|
g_param_spec_uint ("default-port", NULL, NULL,
|
|
0, 65535, 0,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
/**
|
|
* GProxyAddressEnumerator:connectable:
|
|
*
|
|
* The connectable being enumerated.
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_CONNECTABLE,
|
|
g_param_spec_object ("connectable", NULL, NULL,
|
|
G_TYPE_SOCKET_CONNECTABLE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS));
|
|
|
|
/**
|
|
* GProxyAddressEnumerator:proxy-resolver:
|
|
*
|
|
* The proxy resolver to use.
|
|
*
|
|
* Since: 2.36
|
|
*/
|
|
g_object_class_install_property (object_class,
|
|
PROP_PROXY_RESOLVER,
|
|
g_param_spec_object ("proxy-resolver", NULL, NULL,
|
|
G_TYPE_PROXY_RESOLVER,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT |
|
|
G_PARAM_STATIC_STRINGS));
|
|
}
|