Add some more cases to the app-id unit tests
[glib.git] / gio / gresolver.c
blob0ed7d8f0151df32261adb1f0a14c0498b9880ae5
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
3 /* GIO - GLib Input, Output and Streaming Library
5 * Copyright (C) 2008 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include "config.h"
22 #include <glib.h>
23 #include "glibintl.h"
25 #include "gresolver.h"
26 #include "gnetworkingprivate.h"
27 #include "gasyncresult.h"
28 #include "ginetaddress.h"
29 #include "gtask.h"
30 #include "gsrvtarget.h"
31 #include "gthreadedresolver.h"
32 #include "gioerror.h"
34 #ifdef G_OS_UNIX
35 #include <sys/stat.h>
36 #endif
38 #include <stdlib.h>
41 /**
42 * SECTION:gresolver
43 * @short_description: Asynchronous and cancellable DNS resolver
44 * @include: gio/gio.h
46 * #GResolver provides cancellable synchronous and asynchronous DNS
47 * resolution, for hostnames (g_resolver_lookup_by_address(),
48 * g_resolver_lookup_by_name() and their async variants) and SRV
49 * (service) records (g_resolver_lookup_service()).
51 * #GNetworkAddress and #GNetworkService provide wrappers around
52 * #GResolver functionality that also implement #GSocketConnectable,
53 * making it easy to connect to a remote host/service.
56 enum {
57 RELOAD,
58 LAST_SIGNAL
61 static guint signals[LAST_SIGNAL] = { 0 };
63 struct _GResolverPrivate {
64 #ifdef G_OS_UNIX
65 time_t resolv_conf_timestamp;
66 #else
67 int dummy;
68 #endif
71 /**
72 * GResolver:
74 * The object that handles DNS resolution. Use g_resolver_get_default()
75 * to get the default resolver.
77 * This is an abstract type; subclasses of it implement different resolvers for
78 * different platforms and situations.
80 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT,
81 G_ADD_PRIVATE (GResolver)
82 g_networking_init ();)
84 static GList *
85 srv_records_to_targets (GList *records)
87 const gchar *hostname;
88 guint16 port, priority, weight;
89 GSrvTarget *target;
90 GList *l;
92 for (l = records; l != NULL; l = g_list_next (l))
94 g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname);
95 target = g_srv_target_new (hostname, port, priority, weight);
96 g_variant_unref (l->data);
97 l->data = target;
100 return g_srv_target_list_sort (records);
103 static GList *
104 g_resolver_real_lookup_service (GResolver *resolver,
105 const gchar *rrname,
106 GCancellable *cancellable,
107 GError **error)
109 GList *records;
111 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
112 rrname,
113 G_RESOLVER_RECORD_SRV,
114 cancellable,
115 error);
117 return srv_records_to_targets (records);
120 static void
121 g_resolver_real_lookup_service_async (GResolver *resolver,
122 const gchar *rrname,
123 GCancellable *cancellable,
124 GAsyncReadyCallback callback,
125 gpointer user_data)
127 G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
128 rrname,
129 G_RESOLVER_RECORD_SRV,
130 cancellable,
131 callback,
132 user_data);
135 static GList *
136 g_resolver_real_lookup_service_finish (GResolver *resolver,
137 GAsyncResult *result,
138 GError **error)
140 GList *records;
142 records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
143 result,
144 error);
146 return srv_records_to_targets (records);
149 static void
150 g_resolver_class_init (GResolverClass *resolver_class)
152 /* Automatically pass these over to the lookup_records methods */
153 resolver_class->lookup_service = g_resolver_real_lookup_service;
154 resolver_class->lookup_service_async = g_resolver_real_lookup_service_async;
155 resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish;
158 * GResolver::reload:
159 * @resolver: a #GResolver
161 * Emitted when the resolver notices that the system resolver
162 * configuration has changed.
164 signals[RELOAD] =
165 g_signal_new (I_("reload"),
166 G_TYPE_RESOLVER,
167 G_SIGNAL_RUN_LAST,
168 G_STRUCT_OFFSET (GResolverClass, reload),
169 NULL, NULL,
170 g_cclosure_marshal_VOID__VOID,
171 G_TYPE_NONE, 0);
174 static void
175 g_resolver_init (GResolver *resolver)
177 #ifdef G_OS_UNIX
178 struct stat st;
179 #endif
181 resolver->priv = g_resolver_get_instance_private (resolver);
183 #ifdef G_OS_UNIX
184 if (stat (_PATH_RESCONF, &st) == 0)
185 resolver->priv->resolv_conf_timestamp = st.st_mtime;
186 #endif
189 G_LOCK_DEFINE_STATIC (default_resolver);
190 static GResolver *default_resolver;
193 * g_resolver_get_default:
195 * Gets the default #GResolver. You should unref it when you are done
196 * with it. #GResolver may use its reference count as a hint about how
197 * many threads it should allocate for concurrent DNS resolutions.
199 * Returns: (transfer full): the default #GResolver.
201 * Since: 2.22
203 GResolver *
204 g_resolver_get_default (void)
206 GResolver *ret;
208 G_LOCK (default_resolver);
209 if (!default_resolver)
210 default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
211 ret = g_object_ref (default_resolver);
212 G_UNLOCK (default_resolver);
214 return ret;
218 * g_resolver_set_default:
219 * @resolver: the new default #GResolver
221 * Sets @resolver to be the application's default resolver (reffing
222 * @resolver, and unreffing the previous default resolver, if any).
223 * Future calls to g_resolver_get_default() will return this resolver.
225 * This can be used if an application wants to perform any sort of DNS
226 * caching or "pinning"; it can implement its own #GResolver that
227 * calls the original default resolver for DNS operations, and
228 * implements its own cache policies on top of that, and then set
229 * itself as the default resolver for all later code to use.
231 * Since: 2.22
233 void
234 g_resolver_set_default (GResolver *resolver)
236 G_LOCK (default_resolver);
237 if (default_resolver)
238 g_object_unref (default_resolver);
239 default_resolver = g_object_ref (resolver);
240 G_UNLOCK (default_resolver);
243 /* Bionic has res_init() but it's not in any header */
244 #ifdef __BIONIC__
245 int res_init (void);
246 #endif
248 static void
249 g_resolver_maybe_reload (GResolver *resolver)
251 #ifdef G_OS_UNIX
252 struct stat st;
254 if (stat (_PATH_RESCONF, &st) == 0)
256 if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
258 resolver->priv->resolv_conf_timestamp = st.st_mtime;
259 #ifdef HAVE_RES_INIT
260 res_init ();
261 #endif
262 g_signal_emit (resolver, signals[RELOAD], 0);
265 #endif
268 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
269 static void
270 remove_duplicates (GList *addrs)
272 GList *l;
273 GList *ll;
274 GList *lll;
276 /* TODO: if this is too slow (it's O(n^2) but n is typically really
277 * small), we can do something more clever but note that we must not
278 * change the order of elements...
280 for (l = addrs; l != NULL; l = l->next)
282 GInetAddress *address = G_INET_ADDRESS (l->data);
283 for (ll = l->next; ll != NULL; ll = lll)
285 GInetAddress *other_address = G_INET_ADDRESS (ll->data);
286 lll = ll->next;
287 if (g_inet_address_equal (address, other_address))
289 g_object_unref (other_address);
290 /* we never return the first element */
291 g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
297 /* Note that this does not follow the "FALSE means @error is set"
298 * convention. The return value tells the caller whether it should
299 * return @addrs and @error to the caller right away, or if it should
300 * continue and trying to resolve the name as a hostname.
302 static gboolean
303 handle_ip_address (const char *hostname,
304 GList **addrs,
305 GError **error)
307 GInetAddress *addr;
309 #ifndef G_OS_WIN32
310 struct in_addr ip4addr;
311 #endif
313 addr = g_inet_address_new_from_string (hostname);
314 if (addr)
316 *addrs = g_list_append (NULL, addr);
317 return TRUE;
320 *addrs = NULL;
322 #ifdef G_OS_WIN32
324 /* Reject IPv6 addresses that have brackets ('[' or ']') and/or port numbers,
325 * as no valid addresses should contain these at this point.
326 * Non-standard IPv4 addresses would be rejected during the call to
327 * getaddrinfo() later.
329 if (strrchr (hostname, '[') != NULL ||
330 strrchr (hostname, ']') != NULL)
331 #else
333 /* Reject non-standard IPv4 numbers-and-dots addresses.
334 * g_inet_address_new_from_string() will have accepted any "real" IP
335 * address, so if inet_aton() succeeds, then it's an address we want
336 * to reject.
338 if (inet_aton (hostname, &ip4addr))
339 #endif
341 g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
342 _("Error resolving “%s”: %s"),
343 hostname, gai_strerror (EAI_NONAME));
344 return TRUE;
347 return FALSE;
351 * g_resolver_lookup_by_name:
352 * @resolver: a #GResolver
353 * @hostname: the hostname to look up
354 * @cancellable: (nullable): a #GCancellable, or %NULL
355 * @error: return location for a #GError, or %NULL
357 * Synchronously resolves @hostname to determine its associated IP
358 * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
359 * the textual form of an IP address (in which case this just becomes
360 * a wrapper around g_inet_address_new_from_string()).
362 * On success, g_resolver_lookup_by_name() will return a non-empty #GList of
363 * #GInetAddress, sorted in order of preference and guaranteed to not
364 * contain duplicates. That is, if using the result to connect to
365 * @hostname, you should attempt to connect to the first address
366 * first, then the second if the first fails, etc. If you are using
367 * the result to listen on a socket, it is appropriate to add each
368 * result using e.g. g_socket_listener_add_address().
370 * If the DNS resolution fails, @error (if non-%NULL) will be set to a
371 * value from #GResolverError and %NULL will be returned.
373 * If @cancellable is non-%NULL, it can be used to cancel the
374 * operation, in which case @error (if non-%NULL) will be set to
375 * %G_IO_ERROR_CANCELLED.
377 * If you are planning to connect to a socket on the resolved IP
378 * address, it may be easier to create a #GNetworkAddress and use its
379 * #GSocketConnectable interface.
381 * Returns: (element-type GInetAddress) (transfer full): a non-empty #GList
382 * of #GInetAddress, or %NULL on error. You
383 * must unref each of the addresses and free the list when you are
384 * done with it. (You can use g_resolver_free_addresses() to do this.)
386 * Since: 2.22
388 GList *
389 g_resolver_lookup_by_name (GResolver *resolver,
390 const gchar *hostname,
391 GCancellable *cancellable,
392 GError **error)
394 GList *addrs;
395 gchar *ascii_hostname = NULL;
397 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
398 g_return_val_if_fail (hostname != NULL, NULL);
400 /* Check if @hostname is just an IP address */
401 if (handle_ip_address (hostname, &addrs, error))
402 return addrs;
404 if (g_hostname_is_non_ascii (hostname))
405 hostname = ascii_hostname = g_hostname_to_ascii (hostname);
407 if (!hostname)
409 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
410 _("Invalid hostname"));
411 return NULL;
414 g_resolver_maybe_reload (resolver);
415 addrs = G_RESOLVER_GET_CLASS (resolver)->
416 lookup_by_name (resolver, hostname, cancellable, error);
418 remove_duplicates (addrs);
420 g_free (ascii_hostname);
421 return addrs;
425 * g_resolver_lookup_by_name_async:
426 * @resolver: a #GResolver
427 * @hostname: the hostname to look up the address of
428 * @cancellable: (nullable): a #GCancellable, or %NULL
429 * @callback: (scope async): callback to call after resolution completes
430 * @user_data: (closure): data for @callback
432 * Begins asynchronously resolving @hostname to determine its
433 * associated IP address(es), and eventually calls @callback, which
434 * must call g_resolver_lookup_by_name_finish() to get the result.
435 * See g_resolver_lookup_by_name() for more details.
437 * Since: 2.22
439 void
440 g_resolver_lookup_by_name_async (GResolver *resolver,
441 const gchar *hostname,
442 GCancellable *cancellable,
443 GAsyncReadyCallback callback,
444 gpointer user_data)
446 gchar *ascii_hostname = NULL;
447 GList *addrs;
448 GError *error = NULL;
450 g_return_if_fail (G_IS_RESOLVER (resolver));
451 g_return_if_fail (hostname != NULL);
453 /* Check if @hostname is just an IP address */
454 if (handle_ip_address (hostname, &addrs, &error))
456 GTask *task;
458 task = g_task_new (resolver, cancellable, callback, user_data);
459 g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
460 if (addrs)
461 g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
462 else
463 g_task_return_error (task, error);
464 g_object_unref (task);
465 return;
468 if (g_hostname_is_non_ascii (hostname))
469 hostname = ascii_hostname = g_hostname_to_ascii (hostname);
471 if (!hostname)
473 GTask *task;
475 g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
476 _("Invalid hostname"));
477 task = g_task_new (resolver, cancellable, callback, user_data);
478 g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
479 g_task_return_error (task, error);
480 g_object_unref (task);
481 return;
484 g_resolver_maybe_reload (resolver);
485 G_RESOLVER_GET_CLASS (resolver)->
486 lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
488 g_free (ascii_hostname);
492 * g_resolver_lookup_by_name_finish:
493 * @resolver: a #GResolver
494 * @result: the result passed to your #GAsyncReadyCallback
495 * @error: return location for a #GError, or %NULL
497 * Retrieves the result of a call to
498 * g_resolver_lookup_by_name_async().
500 * If the DNS resolution failed, @error (if non-%NULL) will be set to
501 * a value from #GResolverError. If the operation was cancelled,
502 * @error will be set to %G_IO_ERROR_CANCELLED.
504 * Returns: (element-type GInetAddress) (transfer full): a #GList
505 * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
506 * for more details.
508 * Since: 2.22
510 GList *
511 g_resolver_lookup_by_name_finish (GResolver *resolver,
512 GAsyncResult *result,
513 GError **error)
515 GList *addrs;
517 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
519 if (g_async_result_legacy_propagate_error (result, error))
520 return NULL;
521 else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async))
523 /* Handle the stringified-IP-addr case */
524 return g_task_propagate_pointer (G_TASK (result), error);
527 addrs = G_RESOLVER_GET_CLASS (resolver)->
528 lookup_by_name_finish (resolver, result, error);
530 remove_duplicates (addrs);
532 return addrs;
536 * g_resolver_free_addresses: (skip)
537 * @addresses: a #GList of #GInetAddress
539 * Frees @addresses (which should be the return value from
540 * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
541 * (This is a convenience method; you can also simply free the results
542 * by hand.)
544 * Since: 2.22
546 void
547 g_resolver_free_addresses (GList *addresses)
549 GList *a;
551 for (a = addresses; a; a = a->next)
552 g_object_unref (a->data);
553 g_list_free (addresses);
557 * g_resolver_lookup_by_address:
558 * @resolver: a #GResolver
559 * @address: the address to reverse-resolve
560 * @cancellable: (nullable): a #GCancellable, or %NULL
561 * @error: return location for a #GError, or %NULL
563 * Synchronously reverse-resolves @address to determine its
564 * associated hostname.
566 * If the DNS resolution fails, @error (if non-%NULL) will be set to
567 * a value from #GResolverError.
569 * If @cancellable is non-%NULL, it can be used to cancel the
570 * operation, in which case @error (if non-%NULL) will be set to
571 * %G_IO_ERROR_CANCELLED.
573 * Returns: a hostname (either ASCII-only, or in ASCII-encoded
574 * form), or %NULL on error.
576 * Since: 2.22
578 gchar *
579 g_resolver_lookup_by_address (GResolver *resolver,
580 GInetAddress *address,
581 GCancellable *cancellable,
582 GError **error)
584 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
585 g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
587 g_resolver_maybe_reload (resolver);
588 return G_RESOLVER_GET_CLASS (resolver)->
589 lookup_by_address (resolver, address, cancellable, error);
593 * g_resolver_lookup_by_address_async:
594 * @resolver: a #GResolver
595 * @address: the address to reverse-resolve
596 * @cancellable: (nullable): a #GCancellable, or %NULL
597 * @callback: (scope async): callback to call after resolution completes
598 * @user_data: (closure): data for @callback
600 * Begins asynchronously reverse-resolving @address to determine its
601 * associated hostname, and eventually calls @callback, which must
602 * call g_resolver_lookup_by_address_finish() to get the final result.
604 * Since: 2.22
606 void
607 g_resolver_lookup_by_address_async (GResolver *resolver,
608 GInetAddress *address,
609 GCancellable *cancellable,
610 GAsyncReadyCallback callback,
611 gpointer user_data)
613 g_return_if_fail (G_IS_RESOLVER (resolver));
614 g_return_if_fail (G_IS_INET_ADDRESS (address));
616 g_resolver_maybe_reload (resolver);
617 G_RESOLVER_GET_CLASS (resolver)->
618 lookup_by_address_async (resolver, address, cancellable, callback, user_data);
622 * g_resolver_lookup_by_address_finish:
623 * @resolver: a #GResolver
624 * @result: the result passed to your #GAsyncReadyCallback
625 * @error: return location for a #GError, or %NULL
627 * Retrieves the result of a previous call to
628 * g_resolver_lookup_by_address_async().
630 * If the DNS resolution failed, @error (if non-%NULL) will be set to
631 * a value from #GResolverError. If the operation was cancelled,
632 * @error will be set to %G_IO_ERROR_CANCELLED.
634 * Returns: a hostname (either ASCII-only, or in ASCII-encoded
635 * form), or %NULL on error.
637 * Since: 2.22
639 gchar *
640 g_resolver_lookup_by_address_finish (GResolver *resolver,
641 GAsyncResult *result,
642 GError **error)
644 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
646 if (g_async_result_legacy_propagate_error (result, error))
647 return NULL;
649 return G_RESOLVER_GET_CLASS (resolver)->
650 lookup_by_address_finish (resolver, result, error);
653 static gchar *
654 g_resolver_get_service_rrname (const char *service,
655 const char *protocol,
656 const char *domain)
658 gchar *rrname, *ascii_domain = NULL;
660 if (g_hostname_is_non_ascii (domain))
661 domain = ascii_domain = g_hostname_to_ascii (domain);
663 rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
665 g_free (ascii_domain);
666 return rrname;
670 * g_resolver_lookup_service:
671 * @resolver: a #GResolver
672 * @service: the service type to look up (eg, "ldap")
673 * @protocol: the networking protocol to use for @service (eg, "tcp")
674 * @domain: the DNS domain to look up the service in
675 * @cancellable: (nullable): a #GCancellable, or %NULL
676 * @error: return location for a #GError, or %NULL
678 * Synchronously performs a DNS SRV lookup for the given @service and
679 * @protocol in the given @domain and returns an array of #GSrvTarget.
680 * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
681 * @service and @protocol arguments do not include the leading underscore
682 * that appears in the actual DNS entry.
684 * On success, g_resolver_lookup_service() will return a non-empty #GList of
685 * #GSrvTarget, sorted in order of preference. (That is, you should
686 * attempt to connect to the first target first, then the second if
687 * the first fails, etc.)
689 * If the DNS resolution fails, @error (if non-%NULL) will be set to
690 * a value from #GResolverError and %NULL will be returned.
692 * If @cancellable is non-%NULL, it can be used to cancel the
693 * operation, in which case @error (if non-%NULL) will be set to
694 * %G_IO_ERROR_CANCELLED.
696 * If you are planning to connect to the service, it is usually easier
697 * to create a #GNetworkService and use its #GSocketConnectable
698 * interface.
700 * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
701 * #GSrvTarget, or %NULL on error. You must free each of the targets and the
702 * list when you are done with it. (You can use g_resolver_free_targets() to do
703 * this.)
705 * Since: 2.22
707 GList *
708 g_resolver_lookup_service (GResolver *resolver,
709 const gchar *service,
710 const gchar *protocol,
711 const gchar *domain,
712 GCancellable *cancellable,
713 GError **error)
715 GList *targets;
716 gchar *rrname;
718 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
719 g_return_val_if_fail (service != NULL, NULL);
720 g_return_val_if_fail (protocol != NULL, NULL);
721 g_return_val_if_fail (domain != NULL, NULL);
723 rrname = g_resolver_get_service_rrname (service, protocol, domain);
725 g_resolver_maybe_reload (resolver);
726 targets = G_RESOLVER_GET_CLASS (resolver)->
727 lookup_service (resolver, rrname, cancellable, error);
729 g_free (rrname);
730 return targets;
734 * g_resolver_lookup_service_async:
735 * @resolver: a #GResolver
736 * @service: the service type to look up (eg, "ldap")
737 * @protocol: the networking protocol to use for @service (eg, "tcp")
738 * @domain: the DNS domain to look up the service in
739 * @cancellable: (nullable): a #GCancellable, or %NULL
740 * @callback: (scope async): callback to call after resolution completes
741 * @user_data: (closure): data for @callback
743 * Begins asynchronously performing a DNS SRV lookup for the given
744 * @service and @protocol in the given @domain, and eventually calls
745 * @callback, which must call g_resolver_lookup_service_finish() to
746 * get the final result. See g_resolver_lookup_service() for more
747 * details.
749 * Since: 2.22
751 void
752 g_resolver_lookup_service_async (GResolver *resolver,
753 const gchar *service,
754 const gchar *protocol,
755 const gchar *domain,
756 GCancellable *cancellable,
757 GAsyncReadyCallback callback,
758 gpointer user_data)
760 gchar *rrname;
762 g_return_if_fail (G_IS_RESOLVER (resolver));
763 g_return_if_fail (service != NULL);
764 g_return_if_fail (protocol != NULL);
765 g_return_if_fail (domain != NULL);
767 rrname = g_resolver_get_service_rrname (service, protocol, domain);
769 g_resolver_maybe_reload (resolver);
770 G_RESOLVER_GET_CLASS (resolver)->
771 lookup_service_async (resolver, rrname, cancellable, callback, user_data);
773 g_free (rrname);
777 * g_resolver_lookup_service_finish:
778 * @resolver: a #GResolver
779 * @result: the result passed to your #GAsyncReadyCallback
780 * @error: return location for a #GError, or %NULL
782 * Retrieves the result of a previous call to
783 * g_resolver_lookup_service_async().
785 * If the DNS resolution failed, @error (if non-%NULL) will be set to
786 * a value from #GResolverError. If the operation was cancelled,
787 * @error will be set to %G_IO_ERROR_CANCELLED.
789 * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
790 * #GSrvTarget, or %NULL on error. See g_resolver_lookup_service() for more
791 * details.
793 * Since: 2.22
795 GList *
796 g_resolver_lookup_service_finish (GResolver *resolver,
797 GAsyncResult *result,
798 GError **error)
800 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
802 if (g_async_result_legacy_propagate_error (result, error))
803 return NULL;
805 return G_RESOLVER_GET_CLASS (resolver)->
806 lookup_service_finish (resolver, result, error);
810 * g_resolver_free_targets: (skip)
811 * @targets: a #GList of #GSrvTarget
813 * Frees @targets (which should be the return value from
814 * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
815 * (This is a convenience method; you can also simply free the
816 * results by hand.)
818 * Since: 2.22
820 void
821 g_resolver_free_targets (GList *targets)
823 GList *t;
825 for (t = targets; t; t = t->next)
826 g_srv_target_free (t->data);
827 g_list_free (targets);
831 * g_resolver_lookup_records:
832 * @resolver: a #GResolver
833 * @rrname: the DNS name to lookup the record for
834 * @record_type: the type of DNS record to lookup
835 * @cancellable: (nullable): a #GCancellable, or %NULL
836 * @error: return location for a #GError, or %NULL
838 * Synchronously performs a DNS record lookup for the given @rrname and returns
839 * a list of records as #GVariant tuples. See #GResolverRecordType for
840 * information on what the records contain for each @record_type.
842 * If the DNS resolution fails, @error (if non-%NULL) will be set to
843 * a value from #GResolverError and %NULL will be returned.
845 * If @cancellable is non-%NULL, it can be used to cancel the
846 * operation, in which case @error (if non-%NULL) will be set to
847 * %G_IO_ERROR_CANCELLED.
849 * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
850 * #GVariant, or %NULL on error. You must free each of the records and the list
851 * when you are done with it. (You can use g_list_free_full() with
852 * g_variant_unref() to do this.)
854 * Since: 2.34
856 GList *
857 g_resolver_lookup_records (GResolver *resolver,
858 const gchar *rrname,
859 GResolverRecordType record_type,
860 GCancellable *cancellable,
861 GError **error)
863 GList *records;
865 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
866 g_return_val_if_fail (rrname != NULL, NULL);
868 g_resolver_maybe_reload (resolver);
869 records = G_RESOLVER_GET_CLASS (resolver)->
870 lookup_records (resolver, rrname, record_type, cancellable, error);
872 return records;
876 * g_resolver_lookup_records_async:
877 * @resolver: a #GResolver
878 * @rrname: the DNS name to lookup the record for
879 * @record_type: the type of DNS record to lookup
880 * @cancellable: (nullable): a #GCancellable, or %NULL
881 * @callback: (scope async): callback to call after resolution completes
882 * @user_data: (closure): data for @callback
884 * Begins asynchronously performing a DNS lookup for the given
885 * @rrname, and eventually calls @callback, which must call
886 * g_resolver_lookup_records_finish() to get the final result. See
887 * g_resolver_lookup_records() for more details.
889 * Since: 2.34
891 void
892 g_resolver_lookup_records_async (GResolver *resolver,
893 const gchar *rrname,
894 GResolverRecordType record_type,
895 GCancellable *cancellable,
896 GAsyncReadyCallback callback,
897 gpointer user_data)
899 g_return_if_fail (G_IS_RESOLVER (resolver));
900 g_return_if_fail (rrname != NULL);
902 g_resolver_maybe_reload (resolver);
903 G_RESOLVER_GET_CLASS (resolver)->
904 lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
908 * g_resolver_lookup_records_finish:
909 * @resolver: a #GResolver
910 * @result: the result passed to your #GAsyncReadyCallback
911 * @error: return location for a #GError, or %NULL
913 * Retrieves the result of a previous call to
914 * g_resolver_lookup_records_async(). Returns a non-empty list of records as
915 * #GVariant tuples. See #GResolverRecordType for information on what the
916 * records contain.
918 * If the DNS resolution failed, @error (if non-%NULL) will be set to
919 * a value from #GResolverError. If the operation was cancelled,
920 * @error will be set to %G_IO_ERROR_CANCELLED.
922 * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
923 * #GVariant, or %NULL on error. You must free each of the records and the list
924 * when you are done with it. (You can use g_list_free_full() with
925 * g_variant_unref() to do this.)
927 * Since: 2.34
929 GList *
930 g_resolver_lookup_records_finish (GResolver *resolver,
931 GAsyncResult *result,
932 GError **error)
934 g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
935 return G_RESOLVER_GET_CLASS (resolver)->
936 lookup_records_finish (resolver, result, error);
939 guint64
940 g_resolver_get_serial (GResolver *resolver)
942 g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
944 g_resolver_maybe_reload (resolver);
946 #ifdef G_OS_UNIX
947 return (guint64) resolver->priv->resolv_conf_timestamp;
948 #else
949 return 1;
950 #endif
954 * g_resolver_error_quark:
956 * Gets the #GResolver Error Quark.
958 * Returns: a #GQuark.
960 * Since: 2.22
962 G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)