Exemplo n.º 1
0
/**
 * soup_address_equal_by_name:
 * @addr1: (type Soup.Address): a #SoupAddress with a resolved name
 * @addr2: (type Soup.Address): another #SoupAddress with a resolved
 *   name
 *
 * Tests if @addr1 and @addr2 have the same "name". This method can be
 * used with soup_address_hash_by_name() to create a #GHashTable that
 * hashes on address "names".
 *
 * Comparing by name normally means comparing the addresses by their
 * hostnames. But if the address was originally created using an IP
 * address literal, then it will be compared by that instead.
 *
 * In particular, if "www.example.com" has the IP address 10.0.0.1,
 * and @addr1 was created with the name "www.example.com" and @addr2
 * was created with the name "10.0.0.1", then they will compare as
 * unequal for purposes of soup_address_equal_by_name().
 *
 * This would be used to distinguish hosts in situations where
 * different virtual hosts on the same IP address should be considered
 * different. Eg, for purposes of HTTP authentication or cookies, two
 * hosts with the same IP address but different names are considered
 * to be different hosts.
 *
 * See also soup_address_equal_by_ip(), which compares by IP address
 * rather than by name.
 *
 * Return value: whether or not @addr1 and @addr2 have the same name
 *
 * Since: 2.26
 **/
gboolean
soup_address_equal_by_name (gconstpointer addr1, gconstpointer addr2)
{
	SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
	SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);

	g_return_val_if_fail (priv1->name != NULL, FALSE);
	g_return_val_if_fail (priv2->name != NULL, FALSE);
	return !g_ascii_strcasecmp (priv1->name, priv2->name);
}
Exemplo n.º 2
0
/**
 * soup_address_equal_by_ip:
 * @addr1: (type Soup.Address): a #SoupAddress with a resolved IP
 *   address
 * @addr2: (type Soup.Address): another #SoupAddress with a resolved
 *   IP address
 *
 * Tests if @addr1 and @addr2 have the same IP address. This method
 * can be used with soup_address_hash_by_ip() to create a
 * #GHashTable that hashes on IP address.
 *
 * This would be used to distinguish hosts in situations where
 * different virtual hosts on the same IP address should be considered
 * the same. Eg, if "www.example.com" and "www.example.net" have the
 * same IP address, then a single connection can be used to talk
 * to either of them.
 *
 * See also soup_address_equal_by_name(), which compares by name
 * rather than by IP address.
 *
 * Return value: whether or not @addr1 and @addr2 have the same IP
 * address.
 *
 * Since: 2.26
 **/
gboolean
soup_address_equal_by_ip (gconstpointer addr1, gconstpointer addr2)
{
	SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
	SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);
	int size;

	g_return_val_if_fail (priv1->sockaddr != NULL, FALSE);
	g_return_val_if_fail (priv2->sockaddr != NULL, FALSE);

	size = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (priv1->sockaddr->ss_family);
	return (priv1->sockaddr->ss_family ==
		priv2->sockaddr->ss_family &&
		!memcmp (priv1->sockaddr, priv2->sockaddr, size));
}
Exemplo n.º 3
0
/**
 * soup_address_get_name:
 * @addr: a #SoupAddress
 *
 * Returns the hostname associated with @addr.
 *
 * This method is not thread-safe; if you call it while @addr is being
 * resolved in another thread, it may return garbage. You can use
 * soup_address_is_resolved() to safely test whether or not an address
 * is resolved before fetching its name or address.
 *
 * Return value: (allow-none): the hostname, or %NULL if it is not known.
 **/
const char *
soup_address_get_name (SoupAddress *addr)
{
	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);

	return SOUP_ADDRESS_GET_PRIVATE (addr)->name;
}
Exemplo n.º 4
0
static void
soup_address_init (SoupAddress *addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	g_mutex_init (&priv->lock);
}
Exemplo n.º 5
0
/**
 * soup_address_resolve_async:
 * @addr: a #SoupAddress
 * @async_context: (allow-none): the #GMainContext to call @callback from
 * @cancellable: a #GCancellable object, or %NULL
 * @callback: (scope async): callback to call with the result
 * @user_data: data for @callback
 *
 * Asynchronously resolves the missing half of @addr (its IP address
 * if it was created with soup_address_new(), or its hostname if it
 * was created with soup_address_new_from_sockaddr() or
 * soup_address_new_any().)
 *
 * If @cancellable is non-%NULL, it can be used to cancel the
 * resolution. @callback will still be invoked in this case, with a
 * status of %SOUP_STATUS_CANCELLED.
 *
 * It is safe to call this more than once on a given address, from the
 * same thread, with the same @async_context (and doing so will not
 * result in redundant DNS queries being made). But it is not safe to
 * call from multiple threads, or with different @async_contexts, or
 * mixed with calls to soup_address_resolve_sync().
 **/
void
soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context,
			    GCancellable *cancellable,
			    SoupAddressCallback callback, gpointer user_data)
{
	SoupAddressPrivate *priv;
	SoupAddressResolveAsyncData *res_data;
	GResolver *resolver;
	gboolean already_started;

	g_return_if_fail (SOUP_IS_ADDRESS (addr));
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	g_return_if_fail (priv->name || priv->sockaddr);

	/* We don't need to do locking here because the async case is
	 * not intended to be thread-safe.
	 */

	if (priv->name && priv->sockaddr && !callback)
		return;

	res_data = g_slice_new0 (SoupAddressResolveAsyncData);
	res_data->callback = callback;
	res_data->callback_data = user_data;

	already_started = priv->async_lookups != NULL;
	priv->async_lookups = g_slist_prepend (priv->async_lookups, res_data);

	if (already_started)
		return;

	g_object_ref (addr);

	if (priv->name && priv->sockaddr) {
		soup_add_completion (async_context, idle_complete_resolve, addr);
		return;
	}

	resolver = g_resolver_get_default ();
	if (async_context)
		g_main_context_push_thread_default (async_context);

	if (priv->name) {
		g_resolver_lookup_by_name_async (resolver, priv->name,
						 cancellable,
						 lookup_resolved, addr);
	} else {
		GInetAddress *gia;

		gia = soup_address_make_inet_address (addr);
		g_resolver_lookup_by_address_async (resolver, gia,
						    cancellable,
						    lookup_resolved, addr);
		g_object_unref (gia);
	}

	if (async_context)
		g_main_context_pop_thread_default (async_context);
	g_object_unref (resolver);
}
Exemplo n.º 6
0
/**
 * soup_address_get_port:
 * @addr: a #SoupAddress
 *
 * Returns the port associated with @addr.
 *
 * Return value: the port
 **/
guint
soup_address_get_port (SoupAddress *addr)
{
	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), 0);

	return SOUP_ADDRESS_GET_PRIVATE (addr)->port;
}
Exemplo n.º 7
0
static GSocketAddressEnumerator *
soup_address_connectable_proxy_enumerate (GSocketConnectable *connectable)
{
	SoupAddress *addr = SOUP_ADDRESS (connectable);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GSocketAddressEnumerator *proxy_enum;
	SoupURI *uri;
	char *uri_string;

	/* We cheerily assume "http" here because you shouldn't be
	 * using SoupAddress any more if you're not doing HTTP anyway.
	 */
	uri = soup_uri_new (NULL);
	soup_uri_set_scheme (uri, priv->protocol ? priv->protocol : "http");
	soup_uri_set_host (uri, priv->name ? priv->name : soup_address_get_physical (addr));
	soup_uri_set_port (uri, priv->port);
	soup_uri_set_path (uri, "");
	uri_string = soup_uri_to_string_internal (uri, FALSE, TRUE);

	proxy_enum = g_object_new (G_TYPE_PROXY_ADDRESS_ENUMERATOR,
				   "connectable", connectable,
				   "uri", uri_string,
				   NULL);
	g_free (uri_string);
	soup_uri_free (uri);

	return proxy_enum;
}
Exemplo n.º 8
0
static void
soup_address_get_property (GObject *object, guint prop_id,
			   GValue *value, GParamSpec *pspec)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (object);

	switch (prop_id) {
	case PROP_NAME:
		g_value_set_string (value, priv->name);
		break;
	case PROP_FAMILY:
		if (priv->sockaddr)
			g_value_set_enum (value, SOUP_ADDRESS_GET_FAMILY (priv));
		else
			g_value_set_enum (value, 0);
		break;
	case PROP_PORT:
		g_value_set_int (value, priv->port);
		break;
	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;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}
Exemplo n.º 9
0
/**
 * soup_address_hash_by_name:
 * @addr: (type Soup.Address): a #SoupAddress
 *
 * A hash function (for #GHashTable) that corresponds to
 * soup_address_equal_by_name(), qv
 *
 * Return value: the named-based hash value for @addr.
 *
 * Since: 2.26
 **/
guint
soup_address_hash_by_name (gconstpointer addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	g_return_val_if_fail (priv->name != NULL, 0);
	return g_str_hash (priv->name);
}
Exemplo n.º 10
0
/**
 * soup_address_get_gsockaddr:
 * @addr: a #SoupAddress
 *
 * Creates a new #GSocketAddress corresponding to @addr (which is assumed
 * to only have one socket address associated with it).
 *
 * Return value: (transfer full): a new #GSocketAddress
 *
 * Since: 2.32
 */
GSocketAddress *
soup_address_get_gsockaddr (SoupAddress *addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	return g_socket_address_new_from_native (priv->sockaddr,
						 SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)));
}
Exemplo n.º 11
0
static guint
resolve_sync_internal (SoupAddress *addr, GCancellable *cancellable, GError **error)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GResolver *resolver;
	guint status;
	GError *my_err = NULL;

	resolver = g_resolver_get_default ();

	/* We could optimize this to avoid multiple lookups the same
	 * way _resolve_async does, but we don't currently. So, first
	 * lock the mutex to ensure we have a consistent view of
	 * priv->sockaddr and priv->name, unlock it around the
	 * blocking op, and then re-lock it to modify @addr.
	 */
	g_mutex_lock (&priv->lock);

	if (priv->name && !priv->sockaddr)
		maybe_resolve_ip (addr);

	if (!priv->sockaddr) {
		GList *addrs;

		g_mutex_unlock (&priv->lock);
		addrs = g_resolver_lookup_by_name (resolver, priv->name,
						   cancellable, &my_err);
		g_mutex_lock (&priv->lock);

		status = update_addrs (addr, addrs, my_err);
		g_resolver_free_addresses (addrs);
	} else if (!priv->name) {
		GInetAddress *gia;
		char *name;

		g_mutex_unlock (&priv->lock);
		gia = soup_address_make_inet_address (addr);
		name = g_resolver_lookup_by_address (resolver, gia,
						     cancellable, &my_err);
		g_object_unref (gia);
		g_mutex_lock (&priv->lock);

		status = update_name (addr, name, my_err);
		g_free (name);
	} else
		status = SOUP_STATUS_OK;

	g_mutex_unlock (&priv->lock);

	if (my_err)
		g_propagate_error (error, my_err);
	g_object_unref (resolver);

	return status;
}
Exemplo n.º 12
0
/**
 * soup_address_resolve_sync:
 * @addr: a #SoupAddress
 * @cancellable: a #GCancellable object, or %NULL
 *
 * Synchronously resolves the missing half of @addr, as with
 * soup_address_resolve_async().
 *
 * If @cancellable is non-%NULL, it can be used to cancel the
 * resolution. soup_address_resolve_sync() will then return a status
 * of %SOUP_STATUS_CANCELLED.
 *
 * It is safe to call this more than once, even from different
 * threads, but it is not safe to mix calls to
 * soup_address_resolve_sync() with calls to
 * soup_address_resolve_async() on the same address.
 *
 * Return value: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
 * %SOUP_STATUS_CANCELLED.
 **/
guint
soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable)
{
	SoupAddressPrivate *priv;

	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED);
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	g_return_val_if_fail (priv->name || priv->sockaddr, SOUP_STATUS_MALFORMED);

	return resolve_sync_internal (addr, cancellable, NULL);
}
Exemplo n.º 13
0
/**
 * soup_address_get_sockaddr:
 * @addr: a #SoupAddress
 * @len: return location for sockaddr length
 *
 * Returns the sockaddr associated with @addr, with its length in
 * *@len. If the sockaddr is not yet known, returns %NULL.
 *
 * This method is not thread-safe; if you call it while @addr is being
 * resolved in another thread, it may return garbage. You can use
 * soup_address_is_resolved() to safely test whether or not an address
 * is resolved before fetching its name or address.
 *
 * Return value: (allow-none) (transfer none): the sockaddr, or %NULL
 **/
struct sockaddr *
soup_address_get_sockaddr (SoupAddress *addr, int *len)
{
	SoupAddressPrivate *priv;

	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	if (priv->sockaddr && len)
		*len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv));
	return (struct sockaddr *)priv->sockaddr;
}
Exemplo n.º 14
0
/**
 * soup_address_hash_by_ip:
 * @addr: (type Soup.Address): a #SoupAddress
 *
 * A hash function (for #GHashTable) that corresponds to
 * soup_address_equal_by_ip(), qv
 *
 * Return value: the IP-based hash value for @addr.
 *
 * Since: 2.26
 **/
guint
soup_address_hash_by_ip (gconstpointer addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	guint hash;

	g_return_val_if_fail (priv->sockaddr != NULL, 0);

	memcpy (&hash, SOUP_ADDRESS_GET_DATA (priv),
		MIN (sizeof (hash), SOUP_ADDRESS_FAMILY_DATA_SIZE (priv->sockaddr->ss_family)));
	return hash;
}
Exemplo n.º 15
0
static GInetAddress *
soup_address_make_inet_address (SoupAddress *addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GSocketAddress *gsa;
	GInetAddress *gia;

	gsa = g_socket_address_new_from_native (priv->sockaddr,
						SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)));
	gia = g_inet_socket_address_get_address ((GInetSocketAddress *)gsa);
	g_object_ref (gia);
	g_object_unref (gsa);
	return gia;
}
Exemplo n.º 16
0
static void
soup_address_finalize (GObject *object)
{
	SoupAddress *addr = SOUP_ADDRESS (object);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	g_free (priv->sockaddr);
	g_free (priv->name);
	g_free (priv->physical);

	g_mutex_clear (&priv->lock);

	G_OBJECT_CLASS (soup_address_parent_class)->finalize (object);
}
Exemplo n.º 17
0
static GSocketAddressEnumerator *
soup_address_connectable_enumerate (GSocketConnectable *connectable)
{
	SoupAddressAddressEnumerator *addr_enum;
	SoupAddressPrivate *priv;

	addr_enum = g_object_new (SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR, NULL);
	addr_enum->addr = g_object_ref (connectable);

	priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
	addr_enum->orig_offset = priv->offset;

	return (GSocketAddressEnumerator *)addr_enum;
}
Exemplo n.º 18
0
/**
 * soup_address_is_resolved:
 * @addr: a #SoupAddress
 *
 * Tests if @addr has already been resolved. Unlike the other
 * #SoupAddress "get" methods, this is safe to call when @addr might
 * be being resolved in another thread.
 *
 * Return value: %TRUE if @addr has been resolved.
 **/
gboolean
soup_address_is_resolved (SoupAddress *addr)
{
	SoupAddressPrivate *priv;
	gboolean resolved;

	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), FALSE);
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	g_mutex_lock (&priv->lock);
	resolved = priv->sockaddr && priv->name;
	g_mutex_unlock (&priv->lock);

	return resolved;
}
Exemplo n.º 19
0
/* Tries to resolve priv->name as an IP address, possibly including an
 * IPv6 scope id.
 */
static void
maybe_resolve_ip (SoupAddress *addr)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	const char *pct, *ip;
	char *tmp = NULL;
	GSocketConnectable *gaddr;
	GSocketAddressEnumerator *sa_enum;
	GSocketAddress *saddr;

	if (priv->sockaddr || !priv->name)
		return;

	pct = strchr (priv->name, '%');
	if (pct)
		ip = tmp = g_strndup (priv->name, pct - priv->name);
	else
		ip = priv->name;

	if (!g_hostname_is_ip_address (ip)) {
		g_free (tmp);
		return;
	}
	g_free (tmp);

	gaddr = g_network_address_new (priv->name, priv->port);
	if (!gaddr)
		return;

	sa_enum = g_socket_connectable_enumerate (gaddr);
	saddr = g_socket_address_enumerator_next (sa_enum, NULL, NULL);
	if (saddr) {
		priv->n_addrs = 1;
		priv->sockaddr = g_new (struct sockaddr_storage, 1);
		if (!g_socket_address_to_native (saddr, priv->sockaddr,
						 sizeof (struct sockaddr_storage),
						 NULL)) {
			/* can't happen: We know the address format is supported
			 * and the buffer is large enough
			 */
			g_warn_if_reached ();
		}
		g_object_unref (saddr);
	}

	g_object_unref (sa_enum);
	g_object_unref (gaddr);
}
Exemplo n.º 20
0
static GSocketAddress *
soup_address_address_enumerator_next (GSocketAddressEnumerator  *enumerator,
				      GCancellable              *cancellable,
				      GError                   **error)
{
	SoupAddressAddressEnumerator *addr_enum =
		SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);

	if (!priv->sockaddr) {
		if (resolve_sync_internal (addr_enum->addr, cancellable, error) != SOUP_STATUS_OK)
			return NULL;
	}

	return next_address (addr_enum);
}
Exemplo n.º 21
0
static guint
update_name (SoupAddress *addr, const char *name, GError *error)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	if (error) {
		if (error->domain == G_IO_ERROR &&
		    error->code == G_IO_ERROR_CANCELLED)
			return SOUP_STATUS_CANCELLED;
		else
			return SOUP_STATUS_CANT_RESOLVE;
	} else if (!name)
		return SOUP_STATUS_CANT_RESOLVE;
	else if (priv->name)
		return SOUP_STATUS_OK;

	priv->name = g_strdup (name);
	return SOUP_STATUS_OK;
}
Exemplo n.º 22
0
static void
soup_address_address_enumerator_next_async (GSocketAddressEnumerator  *enumerator,
					    GCancellable              *cancellable,
					    GAsyncReadyCallback        callback,
					    gpointer                   user_data)
{
	SoupAddressAddressEnumerator *addr_enum =
		SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
	GTask *task;

	task = g_task_new (enumerator, cancellable, callback, user_data);
	if (!priv->sockaddr) {
		soup_address_resolve_async (addr_enum->addr,
					    g_main_context_get_thread_default (),
					    cancellable, got_addresses, task);
	} else {
		g_task_return_pointer (task, next_address (addr_enum), g_object_unref);
		g_object_unref (task);
	}
}
Exemplo n.º 23
0
/**
 * soup_address_get_physical:
 * @addr: a #SoupAddress
 *
 * Returns the physical address associated with @addr as a string.
 * (Eg, "127.0.0.1"). If the address is not yet known, returns %NULL.
 *
 * This method is not thread-safe; if you call it while @addr is being
 * resolved in another thread, it may return garbage. You can use
 * soup_address_is_resolved() to safely test whether or not an address
 * is resolved before fetching its name or address.
 *
 * Return value: (allow-none): the physical address, or %NULL
 **/
const char *
soup_address_get_physical (SoupAddress *addr)
{
	SoupAddressPrivate *priv;

	g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	if (!priv->sockaddr)
		return NULL;

	if (!priv->physical) {
		GInetAddress *gia;

		gia = soup_address_make_inet_address (addr);
		priv->physical = g_inet_address_to_string (gia);
		g_object_unref (gia);
	}

	return priv->physical;
}
Exemplo n.º 24
0
static GObject *
soup_address_constructor (GType                  type,
			  guint                  n_construct_properties,
			  GObjectConstructParam *construct_properties)
{
	GObject *addr;
	SoupAddressPrivate *priv;

	addr = G_OBJECT_CLASS (soup_address_parent_class)->constructor (
		type, n_construct_properties, construct_properties);
	if (!addr)
		return NULL;
	priv = SOUP_ADDRESS_GET_PRIVATE (addr);

	if (!priv->name && !priv->sockaddr) {
		g_object_unref (addr);
		return NULL;
	}

	return addr;
}
Exemplo n.º 25
0
static void
complete_resolve_async (SoupAddress *addr, guint status)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	SoupAddressResolveAsyncData *res_data;
	GSList *lookups, *l;
	GSource *current_source;
	GMainContext *current_context;

	lookups = priv->async_lookups;
	priv->async_lookups = NULL;

	/* Awful hack; to make soup_socket_connect_async() with an
	 * non-default async_context work correctly, we need to ensure
	 * that the non-default context (which we're now running in)
	 * is the thread-default when the callbacks are run...
	 */
	current_source = g_main_current_source ();
	if (current_source && !g_source_is_destroyed (current_source))
		current_context = g_source_get_context (current_source);
	else
		current_context = NULL;
	g_main_context_push_thread_default (current_context);

	for (l = lookups; l; l = l->next) {
		res_data = l->data;

		if (res_data->callback) {
			res_data->callback (addr, status,
					    res_data->callback_data);
		}
		g_slice_free (SoupAddressResolveAsyncData, res_data);
	}
	g_slist_free (lookups);

	g_main_context_pop_thread_default (current_context);

	g_object_unref (addr);
}
Exemplo n.º 26
0
static void
lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data)
{
	GResolver *resolver = G_RESOLVER (source);
	SoupAddressResolveAsyncData *res_data = user_data;
	SoupAddress *addr = res_data->addr;
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GError *error = NULL;
	guint status;

	if (!priv->sockaddr) {
		GList *addrs;

		addrs = g_resolver_lookup_by_name_finish (resolver, result,
							  &error);
		status = update_addrs (addr, addrs, error);
		g_resolver_free_addresses (addrs);
	} else if (!priv->name) {
		char *name;

		name = g_resolver_lookup_by_address_finish (resolver, result,
							    &error);
		status = update_name (addr, name, error);
		g_free (name);
	} else
		status = SOUP_STATUS_OK;

	/* For the enumerator impl, below */
	g_object_ref (addr);
	g_object_set_data (G_OBJECT (addr), "async-resolved-error", error);

	complete_resolve_async (res_data, status);

	g_object_set_data (G_OBJECT (addr), "async-resolved-error", NULL);
	g_object_unref (addr);
	if (error)
		g_error_free (error);
}
Exemplo n.º 27
0
static guint
update_addrs (SoupAddress *addr, GList *addrs, GError *error)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
	GInetAddress *gia;
	GSocketAddress *gsa;
	int i;

	if (error) {
		if (error->domain == G_IO_ERROR &&
		    error->code == G_IO_ERROR_CANCELLED)
			return SOUP_STATUS_CANCELLED;
		else
			return SOUP_STATUS_CANT_RESOLVE;
	} else if (!addrs)
		return SOUP_STATUS_CANT_RESOLVE;
	else if (priv->sockaddr)
		return SOUP_STATUS_OK;

	priv->n_addrs = g_list_length (addrs);
	priv->sockaddr = g_new (struct sockaddr_storage, priv->n_addrs);
	for (i = 0; addrs; addrs = addrs->next, i++) {
		gia = addrs->data;
		gsa = g_inet_socket_address_new (gia, priv->port);

		if (!g_socket_address_to_native (gsa, &priv->sockaddr[i],
						 sizeof (struct sockaddr_storage),
						 NULL)) {
			/* can't happen: We know the address format is supported
			 * and the buffer is large enough
			 */
			g_warn_if_reached ();
		}
		g_object_unref (gsa);
	}

	return SOUP_STATUS_OK;
}
Exemplo n.º 28
0
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;
}
Exemplo n.º 29
0
static void
soup_address_address_enumerator_next_async (GSocketAddressEnumerator  *enumerator,
					    GCancellable              *cancellable,
					    GAsyncReadyCallback        callback,
					    gpointer                   user_data)
{
	SoupAddressAddressEnumerator *addr_enum =
		SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
	GSimpleAsyncResult *simple;

	simple = g_simple_async_result_new (G_OBJECT (enumerator),
					    callback, user_data,
					    soup_address_address_enumerator_next_async);

	if (!priv->sockaddr) {
		soup_address_resolve_async (addr_enum->addr, NULL, cancellable,
					    got_addresses, simple);
	} else {
		g_simple_async_result_complete_in_idle (simple);
		g_object_unref (simple);
	}
}
Exemplo n.º 30
0
static GSocketAddress *
next_address (SoupAddressAddressEnumerator *addr_enum)
{
	SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
	struct sockaddr_storage *ss;
	int next_addr;

	/* If there are two addresses but the first one is unusable
	 * (eg, it's IPv6 and we can only do IPv4), then we don't want to
	 * try the bad one every time. So we use priv->offset to remember
	 * the offset of the first usable address (ie, the first address
	 * that we weren't called again after returning).
	 */
	next_addr = (addr_enum->orig_offset + addr_enum->n) % priv->n_addrs;
	priv->offset = next_addr;

	if (addr_enum->n >= priv->n_addrs)
		return NULL;
	addr_enum->n++;

	ss = &priv->sockaddr[next_addr];
	return g_socket_address_new_from_native (ss, SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (ss->ss_family));
}