X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gio%2Fgnetworkaddress.c;h=5cb4c74388188176e03d13a2780d0e0d3d0bc5fd;hb=634b69219979c084837c59874e5b2aec01a1d3e4;hp=1335d94632653bf1524f2af08958e62fa001b402;hpb=c910c3e7a319db88749418cedbebe05fbe1b9324;p=platform%2Fupstream%2Fglib.git diff --git a/gio/gnetworkaddress.c b/gio/gnetworkaddress.c index 1335d94..5cb4c74 100644 --- a/gio/gnetworkaddress.c +++ b/gio/gnetworkaddress.c @@ -15,9 +15,7 @@ * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. + * Public License along with this library; if not, see . */ #include "config.h" @@ -65,6 +63,8 @@ struct _GNetworkAddressPrivate { guint16 port; GList *sockaddrs; gchar *scheme; + + gint64 resolver_serial; }; enum { @@ -88,6 +88,7 @@ static GSocketAddressEnumerator *g_network_address_connectable_enumerate static GSocketAddressEnumerator *g_network_address_connectable_proxy_enumerate (GSocketConnectable *connectable); G_DEFINE_TYPE_WITH_CODE (GNetworkAddress, g_network_address, G_TYPE_OBJECT, + G_ADD_PRIVATE (GNetworkAddress) G_IMPLEMENT_INTERFACE (G_TYPE_SOCKET_CONNECTABLE, g_network_address_connectable_iface_init)) @@ -116,8 +117,6 @@ g_network_address_class_init (GNetworkAddressClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (GNetworkAddressPrivate)); - gobject_class->set_property = g_network_address_set_property; gobject_class->get_property = g_network_address_get_property; gobject_class->finalize = g_network_address_finalize; @@ -159,8 +158,7 @@ g_network_address_connectable_iface_init (GSocketConnectableIface *connectable_i static void g_network_address_init (GNetworkAddress *addr) { - addr->priv = G_TYPE_INSTANCE_GET_PRIVATE (addr, G_TYPE_NETWORK_ADDRESS, - GNetworkAddressPrivate); + addr->priv = g_network_address_get_instance_private (addr); } static void @@ -183,8 +181,7 @@ g_network_address_set_property (GObject *object, break; case PROP_SCHEME: - if (addr->priv->scheme) - g_free (addr->priv->scheme); + g_free (addr->priv->scheme); addr->priv->scheme = g_value_dup_string (value); break; @@ -226,7 +223,8 @@ g_network_address_get_property (GObject *object, static void g_network_address_set_addresses (GNetworkAddress *addr, - GList *addresses) + GList *addresses, + guint64 resolver_serial) { GList *a; GSocketAddress *sockaddr; @@ -241,33 +239,24 @@ g_network_address_set_addresses (GNetworkAddress *addr, } g_list_free (addresses); addr->priv->sockaddrs = g_list_reverse (addr->priv->sockaddrs); + + addr->priv->resolver_serial = resolver_serial; } static gboolean g_network_address_parse_sockaddr (GNetworkAddress *addr) { - struct addrinfo hints, *res = NULL; GSocketAddress *sockaddr; - gchar port[32]; - - memset (&hints, 0, sizeof (hints)); - hints.ai_flags = AI_NUMERICHOST -#ifdef AI_NUMERICSERV - | AI_NUMERICSERV -#endif - ; - g_snprintf (port, sizeof (port), "%u", addr->priv->port); - - if (getaddrinfo (addr->priv->hostname, port, &hints, &res) != 0) - return FALSE; - sockaddr = g_socket_address_new_from_native (res->ai_addr, res->ai_addrlen); - freeaddrinfo (res); - if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr)) + sockaddr = g_inet_socket_address_new_from_string (addr->priv->hostname, + addr->priv->port); + if (sockaddr) + { + addr->priv->sockaddrs = g_list_prepend (addr->priv->sockaddrs, sockaddr); + return TRUE; + } + else return FALSE; - - addr->priv->sockaddrs = g_list_prepend (addr->priv->sockaddrs, sockaddr); - return TRUE; } /** @@ -278,7 +267,7 @@ g_network_address_parse_sockaddr (GNetworkAddress *addr) * Creates a new #GSocketConnectable for connecting to the given * @hostname and @port. * - * Return value: (transfer full) (type GNetworkAddress): the new #GNetworkAddress + * Returns: (transfer full) (type GNetworkAddress): the new #GNetworkAddress * * Since: 2.22 */ @@ -320,7 +309,7 @@ g_network_address_new (const gchar *hostname, * is deprecated, because it depends on the contents of /etc/services, * which is generally quite sparse on platforms other than Linux.) * - * Return value: (transfer full): the new #GNetworkAddress, or %NULL on error + * Returns: (transfer full): the new #GNetworkAddress, or %NULL on error * * Since: 2.22 */ @@ -463,7 +452,7 @@ _g_uri_parse_authority (const char *uri, char **userinfo) { char *tmp_str; - const char *start, *p; + const char *start, *p, *at, *delim; char c; g_return_val_if_fail (uri != NULL, FALSE); @@ -503,7 +492,14 @@ _g_uri_parse_authority (const char *uri, start += 2; - if (strchr (start, '@') != NULL) + /* check if the @ sign is part of the authority before attempting to + * decode the userinfo */ + delim = strpbrk (start, "/?#[]"); + at = strchr (start, '@'); + if (at && delim && at > delim) + at = NULL; + + if (at != NULL) { /* Decode userinfo: * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) @@ -557,6 +553,8 @@ _g_uri_parse_authority (const char *uri, /* If IPv6 or IPvFuture */ if (*p == '[') { + gboolean has_scope_id = FALSE, has_bad_scope_id = FALSE; + start++; p++; while (1) @@ -566,6 +564,14 @@ _g_uri_parse_authority (const char *uri, if (c == ']') break; + if (c == '%' && !has_scope_id) + { + has_scope_id = TRUE; + if (p[0] != '2' || p[1] != '5') + has_bad_scope_id = TRUE; + continue; + } + /* unreserved / sub-delims */ if (!(g_ascii_isalnum (c) || strchr (G_URI_OTHER_UNRESERVED, c) || @@ -574,6 +580,16 @@ _g_uri_parse_authority (const char *uri, c == '.')) goto error; } + + if (host) + { + if (has_bad_scope_id) + *host = g_strndup (start, p - start - 1); + else + *host = g_uri_unescape_segment (start, p - 1, NULL); + } + + c = *p++; } else { @@ -606,14 +622,14 @@ _g_uri_parse_authority (const char *uri, strchr (G_URI_RESERVED_CHARS_SUBCOMPONENT_DELIMITERS, c))) goto error; } - } - if (host) - *host = g_uri_unescape_segment (start, p - 1, NULL); + if (host) + *host = g_uri_unescape_segment (start, p - 1, NULL); + } if (c == ':') { - /* Decode pot: + /* Decode port: * port = *DIGIT */ guint tmp = 0; @@ -711,7 +727,7 @@ _g_uri_from_authority (const gchar *protocol, * g_network_address_parse() allows #GSocketClient to determine * when to use application-specific proxy protocols. * - * Return value: (transfer full): the new #GNetworkAddress, or %NULL on error + * Returns: (transfer full): the new #GNetworkAddress, or %NULL on error * * Since: 2.26 */ @@ -757,7 +773,7 @@ g_network_address_parse_uri (const gchar *uri, * Gets @addr's hostname. This might be either UTF-8 or ASCII-encoded, * depending on what @addr was created with. * - * Return value: @addr's hostname + * Returns: @addr's hostname * * Since: 2.22 */ @@ -775,7 +791,7 @@ g_network_address_get_hostname (GNetworkAddress *addr) * * Gets @addr's port number * - * Return value: @addr's port (which may be 0) + * Returns: @addr's port (which may be 0) * * Since: 2.22 */ @@ -793,7 +809,7 @@ g_network_address_get_port (GNetworkAddress *addr) * * Gets @addr's scheme * - * Return value: @addr's scheme (%NULL if not built from URI) + * Returns: @addr's scheme (%NULL if not built from URI) * * Since: 2.26 */ @@ -846,26 +862,39 @@ g_network_address_address_enumerator_next (GSocketAddressEnumerator *enumerator if (addr_enum->addresses == NULL) { - if (!addr_enum->addr->priv->sockaddrs) - g_network_address_parse_sockaddr (addr_enum->addr); - if (!addr_enum->addr->priv->sockaddrs) + GNetworkAddress *addr = addr_enum->addr; + GResolver *resolver = g_resolver_get_default (); + gint64 serial = g_resolver_get_serial (resolver); + + if (addr->priv->resolver_serial != 0 && + addr->priv->resolver_serial != serial) + { + /* Resolver has reloaded, discard cached addresses */ + g_list_free_full (addr->priv->sockaddrs, g_object_unref); + addr->priv->sockaddrs = NULL; + } + + if (!addr->priv->sockaddrs) + g_network_address_parse_sockaddr (addr); + if (!addr->priv->sockaddrs) { - GResolver *resolver = g_resolver_get_default (); GList *addresses; addresses = g_resolver_lookup_by_name (resolver, - addr_enum->addr->priv->hostname, + addr->priv->hostname, cancellable, error); - g_object_unref (resolver); - if (!addresses) - return NULL; + { + g_object_unref (resolver); + return NULL; + } - g_network_address_set_addresses (addr_enum->addr, addresses); + g_network_address_set_addresses (addr, addresses, serial); } - addr_enum->addresses = addr_enum->addr->priv->sockaddrs; + addr_enum->addresses = addr->priv->sockaddrs; addr_enum->next = addr_enum->addresses; + g_object_unref (resolver); } if (addr_enum->next == NULL) @@ -916,7 +945,10 @@ got_addresses (GObject *source_object, addresses = g_resolver_lookup_by_name_finish (resolver, result, &error); if (!error) - g_network_address_set_addresses (addr_enum->addr, addresses); + { + g_network_address_set_addresses (addr_enum->addr, addresses, + g_resolver_get_serial (resolver)); + } } have_addresses (addr_enum, task, error); } @@ -936,25 +968,36 @@ g_network_address_address_enumerator_next_async (GSocketAddressEnumerator *enum if (addr_enum->addresses == NULL) { - if (!addr_enum->addr->priv->sockaddrs) + GNetworkAddress *addr = addr_enum->addr; + GResolver *resolver = g_resolver_get_default (); + gint64 serial = g_resolver_get_serial (resolver); + + if (addr->priv->resolver_serial != 0 && + addr->priv->resolver_serial != serial) { - if (g_network_address_parse_sockaddr (addr_enum->addr)) + /* Resolver has reloaded, discard cached addresses */ + g_list_free_full (addr->priv->sockaddrs, g_object_unref); + addr->priv->sockaddrs = NULL; + } + + if (!addr->priv->sockaddrs) + { + if (g_network_address_parse_sockaddr (addr)) have_addresses (addr_enum, task, NULL); else { - GResolver *resolver = g_resolver_get_default (); - g_resolver_lookup_by_name_async (resolver, - addr_enum->addr->priv->hostname, + addr->priv->hostname, cancellable, got_addresses, task); - g_object_unref (resolver); } + g_object_unref (resolver); return; } - addr_enum->addresses = addr_enum->addr->priv->sockaddrs; + addr_enum->addresses = addr->priv->sockaddrs; addr_enum->next = addr_enum->addresses; + g_object_unref (resolver); } if (addr_enum->next)