mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-09 19:06:15 +01:00
gresolver: Add g_resolver_lookup_by_name_with_flags{_async,_finish,}
This allows higher levels to have more control over resolving (ipv4 or ipv6 for now) which allows for optimizations such as requesting both in parallel as RFC 8305 recommends.
This commit is contained in:
parent
af39a37312
commit
d6afa6c988
@ -1917,6 +1917,10 @@ g_resolver_set_default
|
||||
g_resolver_lookup_by_name
|
||||
g_resolver_lookup_by_name_async
|
||||
g_resolver_lookup_by_name_finish
|
||||
GResolverNameLookupFlags
|
||||
g_resolver_lookup_by_name_with_flags
|
||||
g_resolver_lookup_by_name_with_flags_async
|
||||
g_resolver_lookup_by_name_with_flags_finish
|
||||
g_resolver_free_addresses
|
||||
g_resolver_lookup_by_address
|
||||
g_resolver_lookup_by_address_async
|
||||
|
328
gio/gresolver.c
328
gio/gresolver.c
@ -3,6 +3,7 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Copyright (C) 2018 Igalia S.L.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -30,6 +31,7 @@
|
||||
#include "gsrvtarget.h"
|
||||
#include "gthreadedresolver.h"
|
||||
#include "gioerror.h"
|
||||
#include "gcancellable.h"
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#include <sys/stat.h>
|
||||
@ -347,6 +349,60 @@ handle_ip_address (const char *hostname,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GList *
|
||||
lookup_by_name_real (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GList *addrs;
|
||||
gchar *ascii_hostname = NULL;
|
||||
|
||||
g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
|
||||
g_return_val_if_fail (hostname != NULL, NULL);
|
||||
g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
/* Check if @hostname is just an IP address */
|
||||
if (handle_ip_address (hostname, &addrs, error))
|
||||
return addrs;
|
||||
|
||||
if (g_hostname_is_non_ascii (hostname))
|
||||
hostname = ascii_hostname = g_hostname_to_ascii (hostname);
|
||||
|
||||
if (!hostname)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Invalid hostname"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_resolver_maybe_reload (resolver);
|
||||
|
||||
if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
|
||||
{
|
||||
if (!G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
/* Translators: The placeholder is for a function name. */
|
||||
_("%s not implemented"), "lookup_by_name_with_flags");
|
||||
g_free (ascii_hostname);
|
||||
return NULL;
|
||||
}
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_with_flags (resolver, hostname, flags, cancellable, error);
|
||||
}
|
||||
else
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name (resolver, hostname, cancellable, error);
|
||||
|
||||
remove_duplicates (addrs);
|
||||
|
||||
g_free (ascii_hostname);
|
||||
return addrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resolver_lookup_by_name:
|
||||
* @resolver: a #GResolver
|
||||
@ -391,36 +447,187 @@ g_resolver_lookup_by_name (GResolver *resolver,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GList *addrs;
|
||||
gchar *ascii_hostname = NULL;
|
||||
return lookup_by_name_real (resolver,
|
||||
hostname,
|
||||
G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
|
||||
g_return_val_if_fail (hostname != NULL, NULL);
|
||||
/**
|
||||
* g_resolver_lookup_by_name_with_flags:
|
||||
* @resolver: a #GResolver
|
||||
* @hostname: the hostname to look up
|
||||
* @flags: extra #GResolverNameLookupFlags for the lookup
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||
* @error: (nullable): return location for a #GError, or %NULL
|
||||
*
|
||||
* This differs from g_resolver_lookup_by_name() in that you can modify
|
||||
* the lookup behavior with @flags. For example this can be used to limit
|
||||
* results with #G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY.
|
||||
*
|
||||
* Returns: (element-type GInetAddress) (transfer full): a non-empty #GList
|
||||
* of #GInetAddress, or %NULL on error. You
|
||||
* must unref each of the addresses and free the list when you are
|
||||
* done with it. (You can use g_resolver_free_addresses() to do this.)
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
GList *
|
||||
g_resolver_lookup_by_name_with_flags (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
return lookup_by_name_real (resolver,
|
||||
hostname,
|
||||
flags,
|
||||
cancellable,
|
||||
error);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_name_async_real (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
gchar *ascii_hostname = NULL;
|
||||
GList *addrs;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (G_IS_RESOLVER (resolver));
|
||||
g_return_if_fail (hostname != NULL);
|
||||
g_return_if_fail (!(flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY && flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY));
|
||||
|
||||
/* Check if @hostname is just an IP address */
|
||||
if (handle_ip_address (hostname, &addrs, error))
|
||||
return addrs;
|
||||
if (handle_ip_address (hostname, &addrs, &error))
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, lookup_by_name_async_real);
|
||||
if (addrs)
|
||||
g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hostname_is_non_ascii (hostname))
|
||||
hostname = ascii_hostname = g_hostname_to_ascii (hostname);
|
||||
|
||||
if (!hostname)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
GTask *task;
|
||||
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Invalid hostname"));
|
||||
return NULL;
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, lookup_by_name_async_real);
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_resolver_maybe_reload (resolver);
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name (resolver, hostname, cancellable, error);
|
||||
|
||||
if (flags != G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT)
|
||||
{
|
||||
if (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_async == NULL)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_set_error (&error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
/* Translators: The placeholder is for a function name. */
|
||||
_("%s not implemented"), "lookup_by_name_with_flags_async");
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, lookup_by_name_async_real);
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
}
|
||||
else
|
||||
G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_with_flags_async (resolver, hostname, flags, cancellable, callback, user_data);
|
||||
}
|
||||
else
|
||||
G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
|
||||
|
||||
g_free (ascii_hostname);
|
||||
}
|
||||
|
||||
static GList *
|
||||
lookup_by_name_finish_real (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error,
|
||||
gboolean with_flags)
|
||||
{
|
||||
GList *addrs;
|
||||
|
||||
g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
|
||||
g_return_val_if_fail (G_IS_ASYNC_RESULT (result), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
if (g_async_result_legacy_propagate_error (result, error))
|
||||
return NULL;
|
||||
else if (g_async_result_is_tagged (result, lookup_by_name_async_real))
|
||||
{
|
||||
/* Handle the stringified-IP-addr case */
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
if (with_flags)
|
||||
{
|
||||
g_assert (G_RESOLVER_GET_CLASS (resolver)->lookup_by_name_with_flags_finish != NULL);
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_with_flags_finish (resolver, result, error);
|
||||
}
|
||||
else
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_finish (resolver, result, error);
|
||||
|
||||
remove_duplicates (addrs);
|
||||
|
||||
g_free (ascii_hostname);
|
||||
return addrs;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resolver_lookup_by_name_with_flags_async:
|
||||
* @resolver: a #GResolver
|
||||
* @hostname: the hostname to look up the address of
|
||||
* @flags: extra #GResolverNameLookupFlags for the lookup
|
||||
* @cancellable: (nullable): a #GCancellable, or %NULL
|
||||
* @callback: (scope async): callback to call after resolution completes
|
||||
* @user_data: (closure): data for @callback
|
||||
*
|
||||
* Begins asynchronously resolving @hostname to determine its
|
||||
* associated IP address(es), and eventually calls @callback, which
|
||||
* must call g_resolver_lookup_by_name_with_flags_finish() to get the result.
|
||||
* See g_resolver_lookup_by_name() for more details.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
void
|
||||
g_resolver_lookup_by_name_with_flags_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
lookup_by_name_async_real (resolver,
|
||||
hostname,
|
||||
flags,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_resolver_lookup_by_name_async:
|
||||
* @resolver: a #GResolver
|
||||
@ -443,49 +650,12 @@ g_resolver_lookup_by_name_async (GResolver *resolver,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
gchar *ascii_hostname = NULL;
|
||||
GList *addrs;
|
||||
GError *error = NULL;
|
||||
|
||||
g_return_if_fail (G_IS_RESOLVER (resolver));
|
||||
g_return_if_fail (hostname != NULL);
|
||||
|
||||
/* Check if @hostname is just an IP address */
|
||||
if (handle_ip_address (hostname, &addrs, &error))
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
|
||||
if (addrs)
|
||||
g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
|
||||
else
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_hostname_is_non_ascii (hostname))
|
||||
hostname = ascii_hostname = g_hostname_to_ascii (hostname);
|
||||
|
||||
if (!hostname)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("Invalid hostname"));
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
|
||||
g_task_return_error (task, error);
|
||||
g_object_unref (task);
|
||||
return;
|
||||
}
|
||||
|
||||
g_resolver_maybe_reload (resolver);
|
||||
G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
|
||||
|
||||
g_free (ascii_hostname);
|
||||
lookup_by_name_async_real (resolver,
|
||||
hostname,
|
||||
0,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -512,24 +682,40 @@ g_resolver_lookup_by_name_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
GList *addrs;
|
||||
return lookup_by_name_finish_real (resolver,
|
||||
result,
|
||||
error,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
|
||||
|
||||
if (g_async_result_legacy_propagate_error (result, error))
|
||||
return NULL;
|
||||
else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async))
|
||||
{
|
||||
/* Handle the stringified-IP-addr case */
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
addrs = G_RESOLVER_GET_CLASS (resolver)->
|
||||
lookup_by_name_finish (resolver, result, error);
|
||||
|
||||
remove_duplicates (addrs);
|
||||
|
||||
return addrs;
|
||||
/**
|
||||
* g_resolver_lookup_by_name_with_flags_finish:
|
||||
* @resolver: a #GResolver
|
||||
* @result: the result passed to your #GAsyncReadyCallback
|
||||
* @error: return location for a #GError, or %NULL
|
||||
*
|
||||
* Retrieves the result of a call to
|
||||
* g_resolver_lookup_by_name_with_flags_async().
|
||||
*
|
||||
* If the DNS resolution failed, @error (if non-%NULL) will be set to
|
||||
* a value from #GResolverError. If the operation was cancelled,
|
||||
* @error will be set to %G_IO_ERROR_CANCELLED.
|
||||
*
|
||||
* Returns: (element-type GInetAddress) (transfer full): a #GList
|
||||
* of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
|
||||
* for more details.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
GList *
|
||||
g_resolver_lookup_by_name_with_flags_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
return lookup_by_name_finish_real (resolver,
|
||||
result,
|
||||
error,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
322
gio/gresolver.h
322
gio/gresolver.h
@ -1,6 +1,7 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Copyright (C) 2018 Igalia S.L.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -43,158 +44,237 @@ struct _GResolver {
|
||||
GResolverPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* GResolverNameLookupFlags:
|
||||
* @G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT: default behavior (same as g_resolver_lookup_by_name())
|
||||
* @G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY: only resolve ipv4 addresses
|
||||
* @G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY: only resolve ipv6 addresses
|
||||
*
|
||||
* Flags to modify lookup behavior.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
typedef enum {
|
||||
G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT = 0,
|
||||
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY = 1 << 0,
|
||||
G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY = 1 << 1,
|
||||
} GResolverNameLookupFlags;
|
||||
|
||||
struct _GResolverClass {
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* Signals */
|
||||
void ( *reload) (GResolver *resolver);
|
||||
void ( *reload) (GResolver *resolver);
|
||||
|
||||
/* Virtual methods */
|
||||
GList * ( *lookup_by_name) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_by_name_async) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GList * ( *lookup_by_name_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GList * ( *lookup_by_name) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_by_name_async) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GList * ( *lookup_by_name_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
gchar * ( *lookup_by_address) (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_by_address_async) (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gchar * ( *lookup_by_address_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
gchar * ( *lookup_by_address) (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_by_address_async) (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
gchar * ( *lookup_by_address_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GList * ( *lookup_service) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_service_async) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GList * ( *lookup_service_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GList * ( *lookup_service) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
void ( *lookup_service_async) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GList * ( *lookup_service_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GList * ( *lookup_records) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GList * ( *lookup_records) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
void ( *lookup_records_async) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void ( *lookup_records_async) (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
GList * ( *lookup_records_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
/* Padding for future expansion */
|
||||
void (*_g_reserved4) (void);
|
||||
void (*_g_reserved5) (void);
|
||||
void (*_g_reserved6) (void);
|
||||
GList * ( *lookup_records_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
/**
|
||||
* GResolverClass::lookup_by_name_with_flags_async:
|
||||
* @resolver: a #GResolver
|
||||
* @hostname: the hostname to resolve
|
||||
* @flags: extra #GResolverNameLookupFlags to modify the lookup
|
||||
* @cancellable: (nullable): a #GCancellable
|
||||
* @callback: (scope async): a #GAsyncReadyCallback to call when completed
|
||||
* @user_data: (closure): data to pass to @callback
|
||||
*
|
||||
* Asynchronous version of GResolverClass::lookup_by_name_with_flags
|
||||
*
|
||||
* GResolverClass::lookup_by_name_with_flags_finish will be called to get
|
||||
* the result.
|
||||
*
|
||||
* Since: 2.60
|
||||
*/
|
||||
void ( *lookup_by_name_with_flags_async) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
/**
|
||||
* GResolverClass::lookup_by_name_with_flags_finish:
|
||||
* @resolver: a #GResolver
|
||||
* @result: a #GAsyncResult
|
||||
* @error: (nullable): a pointer to a %NULL #GError
|
||||
*
|
||||
* Gets the result from GResolverClass::lookup_by_name_with_flags_async
|
||||
*
|
||||
* Returns: (element-type GInetAddress) (transfer full): List of #GInetAddress.
|
||||
* Since: 2.60
|
||||
*/
|
||||
GList * ( *lookup_by_name_with_flags_finish) (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
/**
|
||||
* GResolverClass::lookup_by_name_with_flags:
|
||||
* @resolver: a #GResolver
|
||||
* @hostname: the hostname to resolve
|
||||
* @flags: extra #GResolverNameLookupFlags to modify the lookup
|
||||
* @cancellable: (nullable): a #GCancellable
|
||||
* @error: (nullable): a pointer to a %NULL #GError
|
||||
*
|
||||
* This is identical to GResolverClass::lookup_by_name except it takes
|
||||
* @flags which modifies the behavior of the lookup. See #GResolverNameLookupFlags
|
||||
* for more details.
|
||||
*
|
||||
* Returns: (element-type GInetAddress) (transfer full): List of #GInetAddress.
|
||||
* Since: 2.60
|
||||
*/
|
||||
GList * ( *lookup_by_name_with_flags) (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
};
|
||||
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GType g_resolver_get_type (void) G_GNUC_CONST;
|
||||
GType g_resolver_get_type (void) G_GNUC_CONST;
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GResolver *g_resolver_get_default (void);
|
||||
GResolver *g_resolver_get_default (void);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_set_default (GResolver *resolver);
|
||||
|
||||
void g_resolver_set_default (GResolver *resolver);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList *g_resolver_lookup_by_name (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GList *g_resolver_lookup_by_name (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_lookup_by_name_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void g_resolver_lookup_by_name_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList *g_resolver_lookup_by_name_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GList *g_resolver_lookup_by_name_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
void g_resolver_lookup_by_name_with_flags_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
GList *g_resolver_lookup_by_name_with_flags_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_2_60
|
||||
GList *g_resolver_lookup_by_name_with_flags (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_free_addresses (GList *addresses);
|
||||
|
||||
void g_resolver_free_addresses (GList *addresses);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gchar *g_resolver_lookup_by_address (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
gchar *g_resolver_lookup_by_address (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_lookup_by_address_async (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void g_resolver_lookup_by_address_async (GResolver *resolver,
|
||||
GInetAddress *address,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gchar *g_resolver_lookup_by_address_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
gchar *g_resolver_lookup_by_address_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList *g_resolver_lookup_service (GResolver *resolver,
|
||||
const gchar *service,
|
||||
const gchar *protocol,
|
||||
const gchar *domain,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GList *g_resolver_lookup_service (GResolver *resolver,
|
||||
const gchar *service,
|
||||
const gchar *protocol,
|
||||
const gchar *domain,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_lookup_service_async (GResolver *resolver,
|
||||
const gchar *service,
|
||||
const gchar *protocol,
|
||||
const gchar *domain,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void g_resolver_lookup_service_async (GResolver *resolver,
|
||||
const gchar *service,
|
||||
const gchar *protocol,
|
||||
const gchar *domain,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GList *g_resolver_lookup_service_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GList *g_resolver_lookup_service_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
GList *g_resolver_lookup_records (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GList *g_resolver_lookup_records (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
void g_resolver_lookup_records_async (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
void g_resolver_lookup_records_async (GResolver *resolver,
|
||||
const gchar *rrname,
|
||||
GResolverRecordType record_type,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
GList *g_resolver_lookup_records_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
|
||||
GList *g_resolver_lookup_records_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
void g_resolver_free_targets (GList *targets);
|
||||
void g_resolver_free_targets (GList *targets);
|
||||
|
||||
|
||||
/**
|
||||
* G_RESOLVER_ERROR:
|
||||
|
@ -3,6 +3,7 @@
|
||||
/* GIO - GLib Input, Output and Streaming Library
|
||||
*
|
||||
* Copyright (C) 2008 Red Hat, Inc.
|
||||
* Copyright (C) 2018 Igalia S.L.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -63,7 +64,27 @@ g_resolver_error_from_addrinfo_error (gint err)
|
||||
}
|
||||
}
|
||||
|
||||
static struct addrinfo addrinfo_hints;
|
||||
typedef struct {
|
||||
char *hostname;
|
||||
int address_family;
|
||||
} LookupData;
|
||||
|
||||
static LookupData *
|
||||
lookup_data_new (const char *hostname,
|
||||
int address_family)
|
||||
{
|
||||
LookupData *data = g_new (LookupData, 1);
|
||||
data->hostname = g_strdup (hostname);
|
||||
data->address_family = address_family;
|
||||
return data;
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_data_free (LookupData *data)
|
||||
{
|
||||
g_free (data->hostname);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
do_lookup_by_name (GTask *task,
|
||||
@ -71,11 +92,24 @@ do_lookup_by_name (GTask *task,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
const char *hostname = task_data;
|
||||
LookupData *lookup_data = task_data;
|
||||
const char *hostname = lookup_data->hostname;
|
||||
struct addrinfo *res = NULL;
|
||||
GList *addresses;
|
||||
gint retval;
|
||||
struct addrinfo addrinfo_hints = { 0 };
|
||||
|
||||
#ifdef AI_ADDRCONFIG
|
||||
addrinfo_hints.ai_flags = AI_ADDRCONFIG;
|
||||
#endif
|
||||
/* socktype and protocol don't actually matter, they just get copied into the
|
||||
* returned addrinfo structures (and then we ignore them). But if
|
||||
* we leave them unset, we'll get back duplicate answers.
|
||||
*/
|
||||
addrinfo_hints.ai_socktype = SOCK_STREAM;
|
||||
addrinfo_hints.ai_protocol = IPPROTO_TCP;
|
||||
|
||||
addrinfo_hints.ai_family = lookup_data->address_family;
|
||||
retval = getaddrinfo (hostname, NULL, &addrinfo_hints, &res);
|
||||
|
||||
if (retval == 0)
|
||||
@ -139,10 +173,53 @@ lookup_by_name (GResolver *resolver,
|
||||
{
|
||||
GTask *task;
|
||||
GList *addresses;
|
||||
LookupData *data;
|
||||
|
||||
data = lookup_data_new (hostname, AF_UNSPEC);
|
||||
task = g_task_new (resolver, cancellable, NULL, NULL);
|
||||
g_task_set_source_tag (task, lookup_by_name);
|
||||
g_task_set_task_data (task, g_strdup (hostname), g_free);
|
||||
g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread_sync (task, do_lookup_by_name);
|
||||
addresses = g_task_propagate_pointer (task, error);
|
||||
g_object_unref (task);
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
static int
|
||||
flags_to_family (GResolverNameLookupFlags flags)
|
||||
{
|
||||
int address_family = AF_UNSPEC;
|
||||
|
||||
if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY)
|
||||
address_family = AF_INET;
|
||||
|
||||
if (flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV6_ONLY)
|
||||
{
|
||||
address_family = AF_INET6;
|
||||
/* You can only filter by one family at a time */
|
||||
g_return_val_if_fail (!(flags & G_RESOLVER_NAME_LOOKUP_FLAGS_IPV4_ONLY), address_family);
|
||||
}
|
||||
|
||||
return address_family;
|
||||
}
|
||||
|
||||
static GList *
|
||||
lookup_by_name_with_flags (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
GTask *task;
|
||||
GList *addresses;
|
||||
LookupData *data;
|
||||
|
||||
data = lookup_data_new (hostname, AF_UNSPEC);
|
||||
task = g_task_new (resolver, cancellable, NULL, NULL);
|
||||
g_task_set_source_tag (task, lookup_by_name_with_flags);
|
||||
g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread_sync (task, do_lookup_by_name);
|
||||
addresses = g_task_propagate_pointer (task, error);
|
||||
@ -151,6 +228,26 @@ lookup_by_name (GResolver *resolver,
|
||||
return addresses;
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_name_with_flags_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
GResolverNameLookupFlags flags,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
LookupData *data;
|
||||
|
||||
data = lookup_data_new (hostname, flags_to_family (flags));
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, lookup_by_name_with_flags_async);
|
||||
g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread (task, do_lookup_by_name);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static void
|
||||
lookup_by_name_async (GResolver *resolver,
|
||||
const gchar *hostname,
|
||||
@ -158,14 +255,12 @@ lookup_by_name_async (GResolver *resolver,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
|
||||
task = g_task_new (resolver, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, lookup_by_name_async);
|
||||
g_task_set_task_data (task, g_strdup (hostname), g_free);
|
||||
g_task_set_return_on_cancel (task, TRUE);
|
||||
g_task_run_in_thread (task, do_lookup_by_name);
|
||||
g_object_unref (task);
|
||||
lookup_by_name_with_flags_async (resolver,
|
||||
hostname,
|
||||
G_RESOLVER_NAME_LOOKUP_FLAGS_DEFAULT,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
static GList *
|
||||
@ -178,6 +273,15 @@ lookup_by_name_finish (GResolver *resolver,
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static GList *
|
||||
lookup_by_name_with_flags_finish (GResolver *resolver,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
|
||||
|
||||
return g_task_propagate_pointer (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static void
|
||||
do_lookup_by_address (GTask *task,
|
||||
@ -970,24 +1074,16 @@ g_threaded_resolver_class_init (GThreadedResolverClass *threaded_class)
|
||||
{
|
||||
GResolverClass *resolver_class = G_RESOLVER_CLASS (threaded_class);
|
||||
|
||||
resolver_class->lookup_by_name = lookup_by_name;
|
||||
resolver_class->lookup_by_name_async = lookup_by_name_async;
|
||||
resolver_class->lookup_by_name_finish = lookup_by_name_finish;
|
||||
resolver_class->lookup_by_address = lookup_by_address;
|
||||
resolver_class->lookup_by_address_async = lookup_by_address_async;
|
||||
resolver_class->lookup_by_address_finish = lookup_by_address_finish;
|
||||
resolver_class->lookup_records = lookup_records;
|
||||
resolver_class->lookup_records_async = lookup_records_async;
|
||||
resolver_class->lookup_records_finish = lookup_records_finish;
|
||||
|
||||
/* Initialize addrinfo_hints */
|
||||
#ifdef AI_ADDRCONFIG
|
||||
addrinfo_hints.ai_flags |= AI_ADDRCONFIG;
|
||||
#endif
|
||||
/* These two don't actually matter, they just get copied into the
|
||||
* returned addrinfo structures (and then we ignore them). But if
|
||||
* we leave them unset, we'll get back duplicate answers.
|
||||
*/
|
||||
addrinfo_hints.ai_socktype = SOCK_STREAM;
|
||||
addrinfo_hints.ai_protocol = IPPROTO_TCP;
|
||||
resolver_class->lookup_by_name = lookup_by_name;
|
||||
resolver_class->lookup_by_name_async = lookup_by_name_async;
|
||||
resolver_class->lookup_by_name_finish = lookup_by_name_finish;
|
||||
resolver_class->lookup_by_name_with_flags = lookup_by_name_with_flags;
|
||||
resolver_class->lookup_by_name_with_flags_async = lookup_by_name_with_flags_async;
|
||||
resolver_class->lookup_by_name_with_flags_finish = lookup_by_name_with_flags_finish;
|
||||
resolver_class->lookup_by_address = lookup_by_address;
|
||||
resolver_class->lookup_by_address_async = lookup_by_address_async;
|
||||
resolver_class->lookup_by_address_finish = lookup_by_address_finish;
|
||||
resolver_class->lookup_records = lookup_records;
|
||||
resolver_class->lookup_records_async = lookup_records_async;
|
||||
resolver_class->lookup_records_finish = lookup_records_finish;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user