1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-address.c: Internet address handing
5 * Copyright (C) 2010 Red Hat, Inc.
17 #include <sys/types.h>
21 #include "soup-address.h"
22 #include "soup-enum-types.h"
23 #include "soup-marshal.h"
24 #include "soup-misc.h"
27 * SECTION:soup-address
28 * @short_description: DNS support
30 * #SoupAddress represents the address of a TCP connection endpoint:
31 * both the IP address and the port. (It is somewhat like an
32 * object-oriented version of struct sockaddr.)
48 struct sockaddr_storage *sockaddr;
51 char *name, *physical;
55 GSList *async_lookups;
57 #define SOUP_ADDRESS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_ADDRESS, SoupAddressPrivate))
59 /* sockaddr generic macros */
60 #define SOUP_SIN(priv) ((struct sockaddr_in *)priv->sockaddr)
61 #define SOUP_SIN6(priv) ((struct sockaddr_in6 *)priv->sockaddr)
63 /* sockaddr family macros */
64 #define SOUP_ADDRESS_GET_FAMILY(priv) (priv->sockaddr->ss_family)
65 #define SOUP_ADDRESS_SET_FAMILY(priv, family) \
66 (priv->sockaddr->ss_family = family)
67 #define SOUP_ADDRESS_FAMILY_IS_VALID(family) \
68 (family == AF_INET || family == AF_INET6)
69 #define SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE(family) \
70 (family == AF_INET ? sizeof (struct sockaddr_in) : \
71 sizeof (struct sockaddr_in6))
72 #define SOUP_ADDRESS_FAMILY_DATA_SIZE(family) \
73 (family == AF_INET ? sizeof (struct in_addr) : \
74 sizeof (struct in6_addr))
76 /* sockaddr port macros */
77 #define SOUP_ADDRESS_PORT_IS_VALID(port) (port >= 0 && port <= 65535)
78 #define SOUP_ADDRESS_GET_PORT(priv) \
79 (priv->sockaddr->ss_family == AF_INET ? \
80 SOUP_SIN(priv)->sin_port : \
81 SOUP_SIN6(priv)->sin6_port)
82 #define SOUP_ADDRESS_SET_PORT(priv, port) \
84 if (priv->sockaddr->ss_family == AF_INET) \
85 SOUP_SIN(priv)->sin_port = port; \
87 SOUP_SIN6(priv)->sin6_port = port; \
90 /* sockaddr data macros */
91 #define SOUP_ADDRESS_GET_DATA(priv) \
92 (priv->sockaddr->ss_family == AF_INET ? \
93 (gpointer)&SOUP_SIN(priv)->sin_addr : \
94 (gpointer)&SOUP_SIN6(priv)->sin6_addr)
95 #define SOUP_ADDRESS_SET_DATA(priv, data, length) \
96 memcpy (SOUP_ADDRESS_GET_DATA (priv), data, length)
99 static GObject *constructor (GType type,
100 guint n_construct_properties,
101 GObjectConstructParam *construct_properties);
102 static void set_property (GObject *object, guint prop_id,
103 const GValue *value, GParamSpec *pspec);
104 static void get_property (GObject *object, guint prop_id,
105 GValue *value, GParamSpec *pspec);
107 static void soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface);
108 static GSocketAddressEnumerator *soup_address_connectable_enumerate (GSocketConnectable *connectable);
110 G_DEFINE_TYPE_WITH_CODE (SoupAddress, soup_address, G_TYPE_OBJECT,
111 G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE,
112 soup_address_connectable_iface_init))
115 soup_address_init (SoupAddress *addr)
117 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
119 priv->lock = g_mutex_new ();
123 finalize (GObject *object)
125 SoupAddress *addr = SOUP_ADDRESS (object);
126 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
129 g_free (priv->sockaddr);
133 g_free (priv->physical);
135 g_mutex_free (priv->lock);
137 G_OBJECT_CLASS (soup_address_parent_class)->finalize (object);
141 soup_address_class_init (SoupAddressClass *address_class)
143 GObjectClass *object_class = G_OBJECT_CLASS (address_class);
145 g_type_class_add_private (address_class, sizeof (SoupAddressPrivate));
147 /* virtual method override */
148 object_class->constructor = constructor;
149 object_class->finalize = finalize;
150 object_class->set_property = set_property;
151 object_class->get_property = get_property;
157 * Alias for the #SoupAddress:name property. (The hostname for
160 g_object_class_install_property (
161 object_class, PROP_NAME,
162 g_param_spec_string (SOUP_ADDRESS_NAME,
164 "Hostname for this address",
166 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
168 * SOUP_ADDRESS_FAMILY:
170 * Alias for the #SoupAddress:family property. (The
171 * #SoupAddressFamily for this address.)
173 g_object_class_install_property (
174 object_class, PROP_FAMILY,
175 g_param_spec_enum (SOUP_ADDRESS_FAMILY,
177 "Address family for this address",
178 SOUP_TYPE_ADDRESS_FAMILY,
179 SOUP_ADDRESS_FAMILY_INVALID,
180 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
184 * An alias for the #SoupAddress:port property. (The port for
187 g_object_class_install_property (
188 object_class, PROP_PORT,
189 g_param_spec_int (SOUP_ADDRESS_PORT,
191 "Port for this address",
193 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
195 * SOUP_ADDRESS_PHYSICAL:
197 * An alias for the #SoupAddress:physical property. (The
198 * stringified IP address for this address.)
200 g_object_class_install_property (
201 object_class, PROP_PHYSICAL,
202 g_param_spec_string (SOUP_ADDRESS_PHYSICAL,
204 "IP address for this address",
208 * SOUP_ADDRESS_SOCKADDR:
210 * An alias for the #SoupAddress:sockaddr property. (A pointer
211 * to the struct sockaddr for this address.)
213 g_object_class_install_property (
214 object_class, PROP_SOCKADDR,
215 g_param_spec_pointer (SOUP_ADDRESS_SOCKADDR,
217 "struct sockaddr for this address",
218 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
222 soup_address_connectable_iface_init (GSocketConnectableIface *connectable_iface)
224 connectable_iface->enumerate = soup_address_connectable_enumerate;
228 constructor (GType type,
229 guint n_construct_properties,
230 GObjectConstructParam *construct_properties)
233 SoupAddressPrivate *priv;
235 addr = G_OBJECT_CLASS (soup_address_parent_class)->constructor (
236 type, n_construct_properties, construct_properties);
239 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
241 if (!priv->name && !priv->sockaddr) {
242 g_object_unref (addr);
250 set_property (GObject *object, guint prop_id,
251 const GValue *value, GParamSpec *pspec)
253 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (object);
254 SoupAddressFamily family;
258 /* This is a mess because the properties are mostly orthogonal,
259 * but g_object_constructor wants to set a default value for each
265 priv->name = g_value_dup_string (value);
269 family = g_value_get_enum (value);
270 if (family == SOUP_ADDRESS_FAMILY_INVALID)
272 g_return_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family));
273 g_return_if_fail (priv->sockaddr == NULL);
275 priv->sockaddr = g_malloc0 (SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (family));
276 SOUP_ADDRESS_SET_FAMILY (priv, family);
277 SOUP_ADDRESS_SET_PORT (priv, htons (priv->port));
282 port = g_value_get_int (value);
285 g_return_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port));
289 SOUP_ADDRESS_SET_PORT (priv, htons (port));
293 sa = g_value_get_pointer (value);
296 g_return_if_fail (priv->sockaddr == NULL);
298 len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family);
299 priv->sockaddr = g_memdup (sa, len);
301 priv->port = ntohs (SOUP_ADDRESS_GET_PORT (priv));
304 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
310 get_property (GObject *object, guint prop_id,
311 GValue *value, GParamSpec *pspec)
313 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (object);
317 g_value_set_string (value, priv->name);
321 g_value_set_enum (value, SOUP_ADDRESS_GET_FAMILY (priv));
323 g_value_set_enum (value, 0);
326 g_value_set_int (value, priv->port);
329 g_value_set_string (value, soup_address_get_physical (SOUP_ADDRESS (object)));
332 g_value_set_pointer (value, priv->sockaddr);
335 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
342 * @name: a hostname or physical address
343 * @port: a port number
345 * Creates a #SoupAddress from @name and @port. The #SoupAddress's IP
346 * address may not be available right away; the caller can call
347 * soup_address_resolve_async() or soup_address_resolve_sync() to
348 * force a DNS resolution.
350 * Return value: a #SoupAddress
353 soup_address_new (const char *name, guint port)
355 g_return_val_if_fail (name != NULL, NULL);
356 g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL);
358 return g_object_new (SOUP_TYPE_ADDRESS,
359 SOUP_ADDRESS_NAME, name,
360 SOUP_ADDRESS_PORT, port,
365 * soup_address_new_from_sockaddr:
366 * @sa: a pointer to a sockaddr
369 * Returns a #SoupAddress equivalent to @sa (or %NULL if @sa's
370 * address family isn't supported)
372 * Return value: (allow-none): the new #SoupAddress
375 soup_address_new_from_sockaddr (struct sockaddr *sa, int len)
377 g_return_val_if_fail (sa != NULL, NULL);
378 g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (sa->sa_family), NULL);
379 g_return_val_if_fail (len == SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (sa->sa_family), NULL);
381 return g_object_new (SOUP_TYPE_ADDRESS,
382 SOUP_ADDRESS_SOCKADDR, sa,
388 * @SOUP_ADDRESS_FAMILY_INVALID: an invalid %SoupAddress
389 * @SOUP_ADDRESS_FAMILY_IPV4: an IPv4 address
390 * @SOUP_ADDRESS_FAMILY_IPV6: an IPv6 address
392 * The supported address families.
396 * SOUP_ADDRESS_ANY_PORT:
398 * This can be passed to any #SoupAddress method that expects a port,
399 * to indicate that you don't care what port is used.
403 * soup_address_new_any:
404 * @family: the address family
405 * @port: the port number (usually %SOUP_ADDRESS_ANY_PORT)
407 * Returns a #SoupAddress corresponding to the "any" address
408 * for @family (or %NULL if @family isn't supported), suitable for
409 * passing to soup_socket_server_new().
411 * Return value: (allow-none): the new #SoupAddress
414 soup_address_new_any (SoupAddressFamily family, guint port)
416 g_return_val_if_fail (SOUP_ADDRESS_FAMILY_IS_VALID (family), NULL);
417 g_return_val_if_fail (SOUP_ADDRESS_PORT_IS_VALID (port), NULL);
419 return g_object_new (SOUP_TYPE_ADDRESS,
420 SOUP_ADDRESS_FAMILY, family,
421 SOUP_ADDRESS_PORT, port,
426 * soup_address_get_name:
427 * @addr: a #SoupAddress
429 * Returns the hostname associated with @addr.
431 * This method is not thread-safe; if you call it while @addr is being
432 * resolved in another thread, it may return garbage. You can use
433 * soup_address_is_resolved() to safely test whether or not an address
434 * is resolved before fetching its name or address.
436 * Return value: (allow-none): the hostname, or %NULL if it is not known.
439 soup_address_get_name (SoupAddress *addr)
441 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
443 return SOUP_ADDRESS_GET_PRIVATE (addr)->name;
447 * soup_address_get_sockaddr:
448 * @addr: a #SoupAddress
449 * @len: return location for sockaddr length
451 * Returns the sockaddr associated with @addr, with its length in
452 * *@len. If the sockaddr is not yet known, returns %NULL.
454 * This method is not thread-safe; if you call it while @addr is being
455 * resolved in another thread, it may return garbage. You can use
456 * soup_address_is_resolved() to safely test whether or not an address
457 * is resolved before fetching its name or address.
459 * Return value: (allow-none) (transfer none): the sockaddr, or %NULL
462 soup_address_get_sockaddr (SoupAddress *addr, int *len)
464 SoupAddressPrivate *priv;
466 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
467 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
469 if (priv->sockaddr && len)
470 *len = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv));
471 return (struct sockaddr *)priv->sockaddr;
475 * soup_address_get_gsockaddr:
476 * @addr: a #SoupAddress
478 * Creates a new #GSocketAddress corresponding to @addr (which is assumed
479 * to only have one socket address associated with it).
481 * Return value: (transfer full): a new #GSocketAddress
486 soup_address_get_gsockaddr (SoupAddress *addr)
488 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
490 return g_socket_address_new_from_native (priv->sockaddr,
491 SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)));
494 static GInetAddress *
495 soup_address_make_inet_address (SoupAddress *addr)
497 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
501 gsa = g_socket_address_new_from_native (priv->sockaddr,
502 SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (SOUP_ADDRESS_GET_FAMILY (priv)));
503 gia = g_inet_socket_address_get_address ((GInetSocketAddress *)gsa);
505 g_object_unref (gsa);
510 * soup_address_get_physical:
511 * @addr: a #SoupAddress
513 * Returns the physical address associated with @addr as a string.
514 * (Eg, "127.0.0.1"). If the address is not yet known, returns %NULL.
516 * This method is not thread-safe; if you call it while @addr is being
517 * resolved in another thread, it may return garbage. You can use
518 * soup_address_is_resolved() to safely test whether or not an address
519 * is resolved before fetching its name or address.
521 * Return value: (allow-none): the physical address, or %NULL
524 soup_address_get_physical (SoupAddress *addr)
526 SoupAddressPrivate *priv;
528 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
529 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
534 if (!priv->physical) {
537 gia = soup_address_make_inet_address (addr);
538 priv->physical = g_inet_address_to_string (gia);
539 g_object_unref (gia);
542 return priv->physical;
546 * soup_address_get_port:
547 * @addr: a #SoupAddress
549 * Returns the port associated with @addr.
551 * Return value: the port
554 soup_address_get_port (SoupAddress *addr)
556 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), 0);
558 return SOUP_ADDRESS_GET_PRIVATE (addr)->port;
563 update_addrs (SoupAddress *addr, GList *addrs, GError *error)
565 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
571 if (error->domain == G_IO_ERROR &&
572 error->code == G_IO_ERROR_CANCELLED)
573 return SOUP_STATUS_CANCELLED;
575 return SOUP_STATUS_CANT_RESOLVE;
577 return SOUP_STATUS_CANT_RESOLVE;
578 else if (priv->sockaddr)
579 return SOUP_STATUS_OK;
581 priv->n_addrs = g_list_length (addrs);
582 priv->sockaddr = g_new (struct sockaddr_storage, priv->n_addrs);
583 for (i = 0; addrs; addrs = addrs->next, i++) {
585 gsa = g_inet_socket_address_new (gia, priv->port);
587 if (!g_socket_address_to_native (gsa, &priv->sockaddr[i],
588 sizeof (struct sockaddr_storage),
590 /* can't happen: We know the address format is supported
591 * and the buffer is large enough
593 g_warn_if_reached ();
595 g_object_unref (gsa);
598 return SOUP_STATUS_OK;
602 update_name (SoupAddress *addr, const char *name, GError *error)
604 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
607 if (error->domain == G_IO_ERROR &&
608 error->code == G_IO_ERROR_CANCELLED)
609 return SOUP_STATUS_CANCELLED;
611 return SOUP_STATUS_CANT_RESOLVE;
613 return SOUP_STATUS_CANT_RESOLVE;
615 return SOUP_STATUS_OK;
617 priv->name = g_strdup (name);
618 return SOUP_STATUS_OK;
622 SoupAddressCallback callback;
623 gpointer callback_data;
624 } SoupAddressResolveAsyncData;
627 complete_resolve_async (SoupAddress *addr, guint status)
629 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
630 SoupAddressResolveAsyncData *res_data;
632 GSource *current_source;
633 GMainContext *current_context;
635 lookups = priv->async_lookups;
636 priv->async_lookups = NULL;
638 /* Awful hack; to make soup_socket_connect_async() with an
639 * non-default async_context work correctly, we need to ensure
640 * that the non-default context (which we're now running in)
641 * is the thread-default when the callbacks are run...
643 current_source = g_main_current_source ();
644 if (current_source && !g_source_is_destroyed (current_source))
645 current_context = g_source_get_context (current_source);
647 current_context = NULL;
648 g_main_context_push_thread_default (current_context);
650 for (l = lookups; l; l = l->next) {
653 if (res_data->callback) {
654 res_data->callback (addr, status,
655 res_data->callback_data);
657 g_slice_free (SoupAddressResolveAsyncData, res_data);
659 g_slist_free (lookups);
661 g_main_context_pop_thread_default (current_context);
663 g_object_unref (addr);
667 lookup_resolved (GObject *source, GAsyncResult *result, gpointer user_data)
669 GResolver *resolver = G_RESOLVER (source);
670 SoupAddress *addr = user_data;
671 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
672 GError *error = NULL;
675 if (!priv->sockaddr) {
678 addrs = g_resolver_lookup_by_name_finish (resolver, result,
680 status = update_addrs (addr, addrs, error);
681 g_resolver_free_addresses (addrs);
682 } else if (!priv->name) {
685 name = g_resolver_lookup_by_address_finish (resolver, result,
687 status = update_name (addr, name, error);
690 status = SOUP_STATUS_OK;
692 /* For the enumerator impl, below */
694 g_object_set_data (G_OBJECT (addr), "async-resolved-error", error);
696 complete_resolve_async (addr, status);
698 g_object_set_data (G_OBJECT (addr), "async-resolved-error", NULL);
699 g_object_unref (addr);
701 g_error_free (error);
705 idle_complete_resolve (gpointer addr)
707 complete_resolve_async (addr, SOUP_STATUS_OK);
712 * SoupAddressCallback:
713 * @addr: the #SoupAddress that was resolved
714 * @status: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
715 * %SOUP_STATUS_CANCELLED
716 * @user_data: the user data that was passed to
717 * soup_address_resolve_async()
719 * The callback function passed to soup_address_resolve_async().
723 * soup_address_resolve_async:
724 * @addr: a #SoupAddress
725 * @async_context: (allow-none): the #GMainContext to call @callback from
726 * @cancellable: a #GCancellable object, or %NULL
727 * @callback: (scope async): callback to call with the result
728 * @user_data: data for @callback
730 * Asynchronously resolves the missing half of @addr (its IP address
731 * if it was created with soup_address_new(), or its hostname if it
732 * was created with soup_address_new_from_sockaddr() or
733 * soup_address_new_any().)
735 * If @cancellable is non-%NULL, it can be used to cancel the
736 * resolution. @callback will still be invoked in this case, with a
737 * status of %SOUP_STATUS_CANCELLED.
739 * It is safe to call this more than once on a given address, from the
740 * same thread, with the same @async_context (and doing so will not
741 * result in redundant DNS queries being made). But it is not safe to
742 * call from multiple threads, or with different @async_contexts, or
743 * mixed with calls to soup_address_resolve_sync().
746 soup_address_resolve_async (SoupAddress *addr, GMainContext *async_context,
747 GCancellable *cancellable,
748 SoupAddressCallback callback, gpointer user_data)
750 SoupAddressPrivate *priv;
751 SoupAddressResolveAsyncData *res_data;
753 gboolean already_started;
755 g_return_if_fail (SOUP_IS_ADDRESS (addr));
756 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
757 g_return_if_fail (priv->name || priv->sockaddr);
759 /* We don't need to do locking here because the async case is
760 * not intended to be thread-safe.
763 if (priv->name && priv->sockaddr && !callback)
766 res_data = g_slice_new0 (SoupAddressResolveAsyncData);
767 res_data->callback = callback;
768 res_data->callback_data = user_data;
770 already_started = priv->async_lookups != NULL;
771 priv->async_lookups = g_slist_prepend (priv->async_lookups, res_data);
778 if (priv->name && priv->sockaddr) {
779 soup_add_completion (async_context, idle_complete_resolve, addr);
783 resolver = g_resolver_get_default ();
785 g_main_context_push_thread_default (async_context);
788 g_resolver_lookup_by_name_async (resolver, priv->name,
790 lookup_resolved, addr);
794 gia = soup_address_make_inet_address (addr);
795 g_resolver_lookup_by_address_async (resolver, gia,
797 lookup_resolved, addr);
798 g_object_unref (gia);
802 g_main_context_pop_thread_default (async_context);
803 g_object_unref (resolver);
807 resolve_sync_internal (SoupAddress *addr, GCancellable *cancellable, GError **error)
809 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
812 GError *my_err = NULL;
814 resolver = g_resolver_get_default ();
816 /* We could optimize this to avoid multiple lookups the same
817 * way _resolve_async does, but we don't currently. So, first
818 * lock the mutex to ensure we have a consistent view of
819 * priv->sockaddr and priv->name, unlock it around the
820 * blocking op, and then re-lock it to modify @addr.
822 g_mutex_lock (priv->lock);
823 if (!priv->sockaddr) {
826 g_mutex_unlock (priv->lock);
827 addrs = g_resolver_lookup_by_name (resolver, priv->name,
828 cancellable, &my_err);
829 g_mutex_lock (priv->lock);
831 status = update_addrs (addr, addrs, my_err);
832 g_resolver_free_addresses (addrs);
833 } else if (!priv->name) {
837 g_mutex_unlock (priv->lock);
838 gia = soup_address_make_inet_address (addr);
839 name = g_resolver_lookup_by_address (resolver, gia,
840 cancellable, &my_err);
841 g_object_unref (gia);
842 g_mutex_lock (priv->lock);
844 status = update_name (addr, name, my_err);
847 status = SOUP_STATUS_OK;
848 g_mutex_unlock (priv->lock);
851 g_propagate_error (error, my_err);
852 g_object_unref (resolver);
858 * soup_address_resolve_sync:
859 * @addr: a #SoupAddress
860 * @cancellable: a #GCancellable object, or %NULL
862 * Synchronously resolves the missing half of @addr, as with
863 * soup_address_resolve_async().
865 * If @cancellable is non-%NULL, it can be used to cancel the
866 * resolution. soup_address_resolve_sync() will then return a status
867 * of %SOUP_STATUS_CANCELLED.
869 * It is safe to call this more than once, even from different
870 * threads, but it is not safe to mix calls to
871 * soup_address_resolve_sync() with calls to
872 * soup_address_resolve_async() on the same address.
874 * Return value: %SOUP_STATUS_OK, %SOUP_STATUS_CANT_RESOLVE, or
875 * %SOUP_STATUS_CANCELLED.
878 soup_address_resolve_sync (SoupAddress *addr, GCancellable *cancellable)
880 SoupAddressPrivate *priv;
882 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), SOUP_STATUS_MALFORMED);
883 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
884 g_return_val_if_fail (priv->name || priv->sockaddr, SOUP_STATUS_MALFORMED);
886 return resolve_sync_internal (addr, cancellable, NULL);
890 * soup_address_is_resolved:
891 * @addr: a #SoupAddress
893 * Tests if @addr has already been resolved. Unlike the other
894 * #SoupAddress "get" methods, this is safe to call when @addr might
895 * be being resolved in another thread.
897 * Return value: %TRUE if @addr has been resolved.
900 soup_address_is_resolved (SoupAddress *addr)
902 SoupAddressPrivate *priv;
905 g_return_val_if_fail (SOUP_IS_ADDRESS (addr), FALSE);
906 priv = SOUP_ADDRESS_GET_PRIVATE (addr);
908 g_mutex_lock (priv->lock);
909 resolved = priv->sockaddr && priv->name;
910 g_mutex_unlock (priv->lock);
916 * soup_address_hash_by_name:
917 * @addr: (type Soup.Address): a #SoupAddress
919 * A hash function (for #GHashTable) that corresponds to
920 * soup_address_equal_by_name(), qv
922 * Return value: the named-based hash value for @addr.
927 soup_address_hash_by_name (gconstpointer addr)
929 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
931 g_return_val_if_fail (priv->name != NULL, 0);
932 return g_str_hash (priv->name);
936 * soup_address_equal_by_name:
937 * @addr1: (type Soup.Address): a #SoupAddress with a resolved name
938 * @addr2: (type Soup.Address): another #SoupAddress with a resolved
941 * Tests if @addr1 and @addr2 have the same "name". This method can be
942 * used with soup_address_hash_by_name() to create a #GHashTable that
943 * hashes on address "names".
945 * Comparing by name normally means comparing the addresses by their
946 * hostnames. But if the address was originally created using an IP
947 * address literal, then it will be compared by that instead.
949 * In particular, if "www.example.com" has the IP address 10.0.0.1,
950 * and @addr1 was created with the name "www.example.com" and @addr2
951 * was created with the name "10.0.0.1", then they will compare as
952 * unequal for purposes of soup_address_equal_by_name().
954 * This would be used to distinguish hosts in situations where
955 * different virtual hosts on the same IP address should be considered
956 * different. Eg, for purposes of HTTP authentication or cookies, two
957 * hosts with the same IP address but different names are considered
958 * to be different hosts.
960 * See also soup_address_equal_by_ip(), which compares by IP address
961 * rather than by name.
963 * Return value: whether or not @addr1 and @addr2 have the same name
968 soup_address_equal_by_name (gconstpointer addr1, gconstpointer addr2)
970 SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
971 SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);
973 g_return_val_if_fail (priv1->name != NULL, FALSE);
974 g_return_val_if_fail (priv2->name != NULL, FALSE);
975 return !g_ascii_strcasecmp (priv1->name, priv2->name);
979 * soup_address_hash_by_ip:
980 * @addr: (type Soup.Address): a #SoupAddress
982 * A hash function (for #GHashTable) that corresponds to
983 * soup_address_equal_by_ip(), qv
985 * Return value: the IP-based hash value for @addr.
990 soup_address_hash_by_ip (gconstpointer addr)
992 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr);
995 g_return_val_if_fail (priv->sockaddr != NULL, 0);
997 memcpy (&hash, SOUP_ADDRESS_GET_DATA (priv),
998 MIN (sizeof (hash), SOUP_ADDRESS_FAMILY_DATA_SIZE (priv->sockaddr->ss_family)));
1003 * soup_address_equal_by_ip:
1004 * @addr1: (type Soup.Address): a #SoupAddress with a resolved IP
1006 * @addr2: (type Soup.Address): another #SoupAddress with a resolved
1009 * Tests if @addr1 and @addr2 have the same IP address. This method
1010 * can be used with soup_address_hash_by_ip() to create a
1011 * #GHashTable that hashes on IP address.
1013 * This would be used to distinguish hosts in situations where
1014 * different virtual hosts on the same IP address should be considered
1015 * the same. Eg, if "www.example.com" and "www.example.net" have the
1016 * same IP address, then a single #SoupConnection can be used to talk
1017 * to either of them.
1019 * See also soup_address_equal_by_name(), which compares by name
1020 * rather than by IP address.
1022 * Return value: whether or not @addr1 and @addr2 have the same IP
1028 soup_address_equal_by_ip (gconstpointer addr1, gconstpointer addr2)
1030 SoupAddressPrivate *priv1 = SOUP_ADDRESS_GET_PRIVATE (addr1);
1031 SoupAddressPrivate *priv2 = SOUP_ADDRESS_GET_PRIVATE (addr2);
1034 g_return_val_if_fail (priv1->sockaddr != NULL, FALSE);
1035 g_return_val_if_fail (priv2->sockaddr != NULL, FALSE);
1037 size = SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (priv1->sockaddr->ss_family);
1038 return (priv1->sockaddr->ss_family ==
1039 priv2->sockaddr->ss_family &&
1040 !memcmp (priv1->sockaddr, priv2->sockaddr, size));
1044 #define SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR (_soup_address_address_enumerator_get_type ())
1045 #define SOUP_ADDRESS_ADDRESS_ENUMERATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR, SoupAddressAddressEnumerator))
1048 GSocketAddressEnumerator parent_instance;
1053 } SoupAddressAddressEnumerator;
1056 GSocketAddressEnumeratorClass parent_class;
1058 } SoupAddressAddressEnumeratorClass;
1060 GType _soup_address_address_enumerator_get_type (void);
1061 G_DEFINE_TYPE (SoupAddressAddressEnumerator, _soup_address_address_enumerator, G_TYPE_SOCKET_ADDRESS_ENUMERATOR)
1064 soup_address_address_enumerator_finalize (GObject *object)
1066 SoupAddressAddressEnumerator *addr_enum =
1067 SOUP_ADDRESS_ADDRESS_ENUMERATOR (object);
1069 g_object_unref (addr_enum->addr);
1071 G_OBJECT_CLASS (_soup_address_address_enumerator_parent_class)->finalize (object);
1074 static GSocketAddress *
1075 next_address (SoupAddressAddressEnumerator *addr_enum)
1077 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
1078 struct sockaddr_storage *ss;
1081 /* If there are two addresses but the first one is unusable
1082 * (eg, it's IPv6 and we can only do IPv4), then we don't want to
1083 * try the bad one every time. So we use priv->offset to remember
1084 * the offset of the first usable address (ie, the first address
1085 * that we weren't called again after returning).
1087 next_addr = (addr_enum->orig_offset + addr_enum->n) % priv->n_addrs;
1088 priv->offset = next_addr;
1090 if (addr_enum->n >= priv->n_addrs)
1094 ss = &priv->sockaddr[next_addr];
1095 return g_socket_address_new_from_native (ss, SOUP_ADDRESS_FAMILY_SOCKADDR_SIZE (ss->ss_family));
1098 static GSocketAddress *
1099 soup_address_address_enumerator_next (GSocketAddressEnumerator *enumerator,
1100 GCancellable *cancellable,
1103 SoupAddressAddressEnumerator *addr_enum =
1104 SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
1105 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
1107 if (!priv->sockaddr) {
1108 if (resolve_sync_internal (addr_enum->addr, cancellable, error) != SOUP_STATUS_OK)
1112 return next_address (addr_enum);
1116 got_addresses (SoupAddress *addr, guint status, gpointer user_data)
1118 GSimpleAsyncResult *simple = user_data;
1121 error = g_object_get_data (G_OBJECT (addr), "async-resolved-error");
1123 g_simple_async_result_set_from_error (simple, error);
1125 g_simple_async_result_complete (simple);
1126 g_object_unref (simple);
1130 soup_address_address_enumerator_next_async (GSocketAddressEnumerator *enumerator,
1131 GCancellable *cancellable,
1132 GAsyncReadyCallback callback,
1135 SoupAddressAddressEnumerator *addr_enum =
1136 SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
1137 SoupAddressPrivate *priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
1138 GSimpleAsyncResult *simple;
1140 simple = g_simple_async_result_new (G_OBJECT (enumerator),
1141 callback, user_data,
1142 soup_address_address_enumerator_next_async);
1144 if (!priv->sockaddr) {
1145 soup_address_resolve_async (addr_enum->addr, NULL, cancellable,
1146 got_addresses, simple);
1148 g_simple_async_result_complete_in_idle (simple);
1149 g_object_unref (simple);
1153 static GSocketAddress *
1154 soup_address_address_enumerator_next_finish (GSocketAddressEnumerator *enumerator,
1155 GAsyncResult *result,
1158 SoupAddressAddressEnumerator *addr_enum =
1159 SOUP_ADDRESS_ADDRESS_ENUMERATOR (enumerator);
1160 GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
1162 if (g_simple_async_result_propagate_error (simple, error))
1165 return next_address (addr_enum);
1169 _soup_address_address_enumerator_init (SoupAddressAddressEnumerator *enumerator)
1174 _soup_address_address_enumerator_class_init (SoupAddressAddressEnumeratorClass *addrenum_class)
1176 GObjectClass *object_class = G_OBJECT_CLASS (addrenum_class);
1177 GSocketAddressEnumeratorClass *enumerator_class =
1178 G_SOCKET_ADDRESS_ENUMERATOR_CLASS (addrenum_class);
1180 enumerator_class->next = soup_address_address_enumerator_next;
1181 enumerator_class->next_async = soup_address_address_enumerator_next_async;
1182 enumerator_class->next_finish = soup_address_address_enumerator_next_finish;
1183 object_class->finalize = soup_address_address_enumerator_finalize;
1186 static GSocketAddressEnumerator *
1187 soup_address_connectable_enumerate (GSocketConnectable *connectable)
1189 SoupAddressAddressEnumerator *addr_enum;
1190 SoupAddressPrivate *priv;
1192 addr_enum = g_object_new (SOUP_TYPE_ADDRESS_ADDRESS_ENUMERATOR, NULL);
1193 addr_enum->addr = g_object_ref (connectable);
1195 priv = SOUP_ADDRESS_GET_PRIVATE (addr_enum->addr);
1196 addr_enum->orig_offset = priv->offset;
1198 return (GSocketAddressEnumerator *)addr_enum;