gio: fix a leftover GSimpleAsyncResult usage
[platform/upstream/glib.git] / gio / gresolver.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3 /* GIO - GLib Input, Output and Streaming Library
4  *
5  * Copyright (C) 2008 Red Hat, Inc.
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include "config.h"
22 #include <glib.h>
23 #include "glibintl.h"
24
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
33 #ifdef G_OS_UNIX
34 #include <sys/stat.h>
35 #endif
36
37 #include <stdlib.h>
38
39
40 /**
41  * SECTION:gresolver
42  * @short_description: Asynchronous and cancellable DNS resolver
43  * @include: gio/gio.h
44  *
45  * #GResolver provides cancellable synchronous and asynchronous DNS
46  * resolution, for hostnames (g_resolver_lookup_by_address(),
47  * g_resolver_lookup_by_name() and their async variants) and SRV
48  * (service) records (g_resolver_lookup_service()).
49  *
50  * #GNetworkAddress and #GNetworkService provide wrappers around
51  * #GResolver functionality that also implement #GSocketConnectable,
52  * making it easy to connect to a remote host/service.
53  */
54
55 enum {
56   RELOAD,
57   LAST_SIGNAL
58 };
59
60 static guint signals[LAST_SIGNAL] = { 0 };
61
62 struct _GResolverPrivate {
63 #ifdef G_OS_UNIX
64   time_t resolv_conf_timestamp;
65 #else
66   int dummy;
67 #endif
68 };
69
70 /**
71  * GResolver:
72  *
73  * The object that handles DNS resolution. Use g_resolver_get_default()
74  * to get the default resolver.
75  */
76 G_DEFINE_TYPE_WITH_CODE (GResolver, g_resolver, G_TYPE_OBJECT,
77                          G_ADD_PRIVATE (GResolver)
78                          g_networking_init ();)
79
80 static GList *
81 srv_records_to_targets (GList *records)
82 {
83   const gchar *hostname;
84   guint16 port, priority, weight;
85   GSrvTarget *target;
86   GList *l;
87
88   for (l = records; l != NULL; l = g_list_next (l))
89     {
90       g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname);
91       target = g_srv_target_new (hostname, port, priority, weight);
92       g_variant_unref (l->data);
93       l->data = target;
94     }
95
96   return g_srv_target_list_sort (records);
97 }
98
99 static GList *
100 g_resolver_real_lookup_service (GResolver            *resolver,
101                                 const gchar          *rrname,
102                                 GCancellable         *cancellable,
103                                 GError              **error)
104 {
105   GList *records;
106
107   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
108                                                              rrname,
109                                                              G_RESOLVER_RECORD_SRV,
110                                                              cancellable,
111                                                              error);
112
113   return srv_records_to_targets (records);
114 }
115
116 static void
117 g_resolver_real_lookup_service_async (GResolver            *resolver,
118                                       const gchar          *rrname,
119                                       GCancellable         *cancellable,
120                                       GAsyncReadyCallback   callback,
121                                       gpointer              user_data)
122 {
123   G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
124                                                          rrname,
125                                                          G_RESOLVER_RECORD_SRV,
126                                                          cancellable,
127                                                          callback,
128                                                          user_data);
129 }
130
131 static GList *
132 g_resolver_real_lookup_service_finish (GResolver            *resolver,
133                                        GAsyncResult         *result,
134                                        GError              **error)
135 {
136   GList *records;
137
138   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
139                                                                     result,
140                                                                     error);
141
142   return srv_records_to_targets (records);
143 }
144
145 static void
146 g_resolver_class_init (GResolverClass *resolver_class)
147 {
148   /* Automatically pass these over to the lookup_records methods */
149   resolver_class->lookup_service = g_resolver_real_lookup_service;
150   resolver_class->lookup_service_async = g_resolver_real_lookup_service_async;
151   resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish;
152
153   /**
154    * GResolver::reload:
155    * @resolver: a #GResolver
156    *
157    * Emitted when the resolver notices that the system resolver
158    * configuration has changed.
159    **/
160   signals[RELOAD] =
161     g_signal_new (I_("reload"),
162                   G_TYPE_RESOLVER,
163                   G_SIGNAL_RUN_LAST,
164                   G_STRUCT_OFFSET (GResolverClass, reload),
165                   NULL, NULL,
166                   g_cclosure_marshal_VOID__VOID,
167                   G_TYPE_NONE, 0);
168 }
169
170 static void
171 g_resolver_init (GResolver *resolver)
172 {
173 #ifdef G_OS_UNIX
174   struct stat st;
175 #endif
176
177   resolver->priv = g_resolver_get_instance_private (resolver);
178
179 #ifdef G_OS_UNIX
180   if (stat (_PATH_RESCONF, &st) == 0)
181     resolver->priv->resolv_conf_timestamp = st.st_mtime;
182 #endif
183 }
184
185 static GResolver *default_resolver;
186
187 /**
188  * g_resolver_get_default:
189  *
190  * Gets the default #GResolver. You should unref it when you are done
191  * with it. #GResolver may use its reference count as a hint about how
192  * many threads it should allocate for concurrent DNS resolutions.
193  *
194  * Returns: (transfer full): the default #GResolver.
195  *
196  * Since: 2.22
197  */
198 GResolver *
199 g_resolver_get_default (void)
200 {
201   if (!default_resolver)
202     default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
203
204   return g_object_ref (default_resolver);
205 }
206
207 /**
208  * g_resolver_set_default:
209  * @resolver: the new default #GResolver
210  *
211  * Sets @resolver to be the application's default resolver (reffing
212  * @resolver, and unreffing the previous default resolver, if any).
213  * Future calls to g_resolver_get_default() will return this resolver.
214  *
215  * This can be used if an application wants to perform any sort of DNS
216  * caching or "pinning"; it can implement its own #GResolver that
217  * calls the original default resolver for DNS operations, and
218  * implements its own cache policies on top of that, and then set
219  * itself as the default resolver for all later code to use.
220  *
221  * Since: 2.22
222  */
223 void
224 g_resolver_set_default (GResolver *resolver)
225 {
226   if (default_resolver)
227     g_object_unref (default_resolver);
228   default_resolver = g_object_ref (resolver);
229 }
230
231 /* Bionic has res_init() but it's not in any header */
232 #ifdef __BIONIC__
233 int res_init (void);
234 #endif
235
236 static void
237 g_resolver_maybe_reload (GResolver *resolver)
238 {
239 #ifdef G_OS_UNIX
240   struct stat st;
241
242   if (stat (_PATH_RESCONF, &st) == 0)
243     {
244       if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
245         {
246           resolver->priv->resolv_conf_timestamp = st.st_mtime;
247 #ifdef HAVE_RES_INIT
248           res_init ();
249 #endif
250           g_signal_emit (resolver, signals[RELOAD], 0);
251         }
252     }
253 #endif
254 }
255
256 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
257 static void
258 remove_duplicates (GList *addrs)
259 {
260   GList *l;
261   GList *ll;
262   GList *lll;
263
264   /* TODO: if this is too slow (it's O(n^2) but n is typically really
265    * small), we can do something more clever but note that we must not
266    * change the order of elements...
267    */
268   for (l = addrs; l != NULL; l = l->next)
269     {
270       GInetAddress *address = G_INET_ADDRESS (l->data);
271       for (ll = l->next; ll != NULL; ll = lll)
272         {
273           GInetAddress *other_address = G_INET_ADDRESS (ll->data);
274           lll = ll->next;
275           if (g_inet_address_equal (address, other_address))
276             {
277               g_object_unref (other_address);
278               /* we never return the first element */
279               g_warn_if_fail (g_list_delete_link (addrs, ll) == addrs);
280             }
281         }
282     }
283 }
284
285 /* Note that this does not follow the "FALSE means @error is set"
286  * convention. The return value tells the caller whether it should
287  * return @addrs and @error to the caller right away, or if it should
288  * continue and trying to resolve the name as a hostname.
289  */
290 static gboolean
291 handle_ip_address (const char  *hostname,
292                    GList      **addrs,
293                    GError     **error)
294 {
295   GInetAddress *addr;
296
297 #ifndef G_OS_WIN32
298   struct in_addr ip4addr;
299 #endif
300
301   addr = g_inet_address_new_from_string (hostname);
302   if (addr)
303     {
304       *addrs = g_list_append (NULL, addr);
305       return TRUE;
306     }
307
308   *addrs = NULL;
309
310 #ifdef G_OS_WIN32
311
312   /* Reject IPv6 addresses that have brackets ('[' or ']') and/or port numbers,
313    * as no valid addresses should contain these at this point.
314    * Non-standard IPv4 addresses would be rejected during the call to
315    * getaddrinfo() later.
316    */
317   if (strrchr (hostname, '[') != NULL ||
318       strrchr (hostname, ']') != NULL)
319 #else
320
321   /* Reject non-standard IPv4 numbers-and-dots addresses.
322    * g_inet_address_new_from_string() will have accepted any "real" IP
323    * address, so if inet_aton() succeeds, then it's an address we want
324    * to reject.
325    */
326   if (inet_aton (hostname, &ip4addr))
327 #endif
328     {
329       g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_NOT_FOUND,
330                    _("Error resolving '%s': %s"),
331                    hostname, gai_strerror (EAI_NONAME));
332       return TRUE;
333     }
334
335   return FALSE;
336 }
337
338 /**
339  * g_resolver_lookup_by_name:
340  * @resolver: a #GResolver
341  * @hostname: the hostname to look up
342  * @cancellable: (allow-none): a #GCancellable, or %NULL
343  * @error: return location for a #GError, or %NULL
344  *
345  * Synchronously resolves @hostname to determine its associated IP
346  * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
347  * the textual form of an IP address (in which case this just becomes
348  * a wrapper around g_inet_address_new_from_string()).
349  *
350  * On success, g_resolver_lookup_by_name() will return a non-empty #GList of
351  * #GInetAddress, sorted in order of preference and guaranteed to not
352  * contain duplicates. That is, if using the result to connect to
353  * @hostname, you should attempt to connect to the first address
354  * first, then the second if the first fails, etc. If you are using
355  * the result to listen on a socket, it is appropriate to add each
356  * result using e.g. g_socket_listener_add_address().
357  *
358  * If the DNS resolution fails, @error (if non-%NULL) will be set to a
359  * value from #GResolverError and %NULL will be returned.
360  *
361  * If @cancellable is non-%NULL, it can be used to cancel the
362  * operation, in which case @error (if non-%NULL) will be set to
363  * %G_IO_ERROR_CANCELLED.
364  *
365  * If you are planning to connect to a socket on the resolved IP
366  * address, it may be easier to create a #GNetworkAddress and use its
367  * #GSocketConnectable interface.
368  *
369  * Returns: (element-type GInetAddress) (transfer full): a non-empty #GList
370  * of #GInetAddress, or %NULL on error. You
371  * must unref each of the addresses and free the list when you are
372  * done with it. (You can use g_resolver_free_addresses() to do this.)
373  *
374  * Since: 2.22
375  */
376 GList *
377 g_resolver_lookup_by_name (GResolver     *resolver,
378                            const gchar   *hostname,
379                            GCancellable  *cancellable,
380                            GError       **error)
381 {
382   GList *addrs;
383   gchar *ascii_hostname = NULL;
384
385   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
386   g_return_val_if_fail (hostname != NULL, NULL);
387
388   /* Check if @hostname is just an IP address */
389   if (handle_ip_address (hostname, &addrs, error))
390     return addrs;
391
392   if (g_hostname_is_non_ascii (hostname))
393     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
394
395   g_resolver_maybe_reload (resolver);
396   addrs = G_RESOLVER_GET_CLASS (resolver)->
397     lookup_by_name (resolver, hostname, cancellable, error);
398
399   remove_duplicates (addrs);
400
401   g_free (ascii_hostname);
402   return addrs;
403 }
404
405 /**
406  * g_resolver_lookup_by_name_async:
407  * @resolver: a #GResolver
408  * @hostname: the hostname to look up the address of
409  * @cancellable: (allow-none): a #GCancellable, or %NULL
410  * @callback: (scope async): callback to call after resolution completes
411  * @user_data: (closure): data for @callback
412  *
413  * Begins asynchronously resolving @hostname to determine its
414  * associated IP address(es), and eventually calls @callback, which
415  * must call g_resolver_lookup_by_name_finish() to get the result.
416  * See g_resolver_lookup_by_name() for more details.
417  *
418  * Since: 2.22
419  */
420 void
421 g_resolver_lookup_by_name_async (GResolver           *resolver,
422                                  const gchar         *hostname,
423                                  GCancellable        *cancellable,
424                                  GAsyncReadyCallback  callback,
425                                  gpointer             user_data)
426 {
427   gchar *ascii_hostname = NULL;
428   GList *addrs;
429   GError *error = NULL;
430
431   g_return_if_fail (G_IS_RESOLVER (resolver));
432   g_return_if_fail (hostname != NULL);
433
434   /* Check if @hostname is just an IP address */
435   if (handle_ip_address (hostname, &addrs, &error))
436     {
437       GTask *task;
438
439       task = g_task_new (resolver, cancellable, callback, user_data);
440       g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
441       if (addrs)
442         g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses);
443       else
444         g_task_return_error (task, error);
445       g_object_unref (task);
446       return;
447     }
448
449   if (g_hostname_is_non_ascii (hostname))
450     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
451
452   g_resolver_maybe_reload (resolver);
453   G_RESOLVER_GET_CLASS (resolver)->
454     lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
455
456   g_free (ascii_hostname);
457 }
458
459 /**
460  * g_resolver_lookup_by_name_finish:
461  * @resolver: a #GResolver
462  * @result: the result passed to your #GAsyncReadyCallback
463  * @error: return location for a #GError, or %NULL
464  *
465  * Retrieves the result of a call to
466  * g_resolver_lookup_by_name_async().
467  *
468  * If the DNS resolution failed, @error (if non-%NULL) will be set to
469  * a value from #GResolverError. If the operation was cancelled,
470  * @error will be set to %G_IO_ERROR_CANCELLED.
471  *
472  * Returns: (element-type GInetAddress) (transfer full): a #GList
473  * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
474  * for more details.
475  *
476  * Since: 2.22
477  */
478 GList *
479 g_resolver_lookup_by_name_finish (GResolver     *resolver,
480                                   GAsyncResult  *result,
481                                   GError       **error)
482 {
483   GList *addrs;
484
485   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
486
487   if (g_async_result_legacy_propagate_error (result, error))
488     return NULL;
489   else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async))
490     {
491       /* Handle the stringified-IP-addr case */
492       return g_task_propagate_pointer (G_TASK (result), error);
493     }
494
495   addrs = G_RESOLVER_GET_CLASS (resolver)->
496     lookup_by_name_finish (resolver, result, error);
497
498   remove_duplicates (addrs);
499
500   return addrs;
501 }
502
503 /**
504  * g_resolver_free_addresses: (skip)
505  * @addresses: a #GList of #GInetAddress
506  *
507  * Frees @addresses (which should be the return value from
508  * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
509  * (This is a convenience method; you can also simply free the results
510  * by hand.)
511  *
512  * Since: 2.22
513  */
514 void
515 g_resolver_free_addresses (GList *addresses)
516 {
517   GList *a;
518
519   for (a = addresses; a; a = a->next)
520     g_object_unref (a->data);
521   g_list_free (addresses);
522 }
523
524 /**
525  * g_resolver_lookup_by_address:
526  * @resolver: a #GResolver
527  * @address: the address to reverse-resolve
528  * @cancellable: (allow-none): a #GCancellable, or %NULL
529  * @error: return location for a #GError, or %NULL
530  *
531  * Synchronously reverse-resolves @address to determine its
532  * associated hostname.
533  *
534  * If the DNS resolution fails, @error (if non-%NULL) will be set to
535  * a value from #GResolverError.
536  *
537  * If @cancellable is non-%NULL, it can be used to cancel the
538  * operation, in which case @error (if non-%NULL) will be set to
539  * %G_IO_ERROR_CANCELLED.
540  *
541  * Returns: a hostname (either ASCII-only, or in ASCII-encoded
542  *     form), or %NULL on error.
543  *
544  * Since: 2.22
545  */
546 gchar *
547 g_resolver_lookup_by_address (GResolver     *resolver,
548                               GInetAddress  *address,
549                               GCancellable  *cancellable,
550                               GError       **error)
551 {
552   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
553   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
554
555   g_resolver_maybe_reload (resolver);
556   return G_RESOLVER_GET_CLASS (resolver)->
557     lookup_by_address (resolver, address, cancellable, error);
558 }
559
560 /**
561  * g_resolver_lookup_by_address_async:
562  * @resolver: a #GResolver
563  * @address: the address to reverse-resolve
564  * @cancellable: (allow-none): a #GCancellable, or %NULL
565  * @callback: (scope async): callback to call after resolution completes
566  * @user_data: (closure): data for @callback
567  *
568  * Begins asynchronously reverse-resolving @address to determine its
569  * associated hostname, and eventually calls @callback, which must
570  * call g_resolver_lookup_by_address_finish() to get the final result.
571  *
572  * Since: 2.22
573  */
574 void
575 g_resolver_lookup_by_address_async (GResolver           *resolver,
576                                     GInetAddress        *address,
577                                     GCancellable        *cancellable,
578                                     GAsyncReadyCallback  callback,
579                                     gpointer             user_data)
580 {
581   g_return_if_fail (G_IS_RESOLVER (resolver));
582   g_return_if_fail (G_IS_INET_ADDRESS (address));
583
584   g_resolver_maybe_reload (resolver);
585   G_RESOLVER_GET_CLASS (resolver)->
586     lookup_by_address_async (resolver, address, cancellable, callback, user_data);
587 }
588
589 /**
590  * g_resolver_lookup_by_address_finish:
591  * @resolver: a #GResolver
592  * @result: the result passed to your #GAsyncReadyCallback
593  * @error: return location for a #GError, or %NULL
594  *
595  * Retrieves the result of a previous call to
596  * g_resolver_lookup_by_address_async().
597  *
598  * If the DNS resolution failed, @error (if non-%NULL) will be set to
599  * a value from #GResolverError. If the operation was cancelled,
600  * @error will be set to %G_IO_ERROR_CANCELLED.
601  *
602  * Returns: a hostname (either ASCII-only, or in ASCII-encoded
603  * form), or %NULL on error.
604  *
605  * Since: 2.22
606  */
607 gchar *
608 g_resolver_lookup_by_address_finish (GResolver     *resolver,
609                                      GAsyncResult  *result,
610                                      GError       **error)
611 {
612   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
613
614   if (g_async_result_legacy_propagate_error (result, error))
615     return NULL;
616
617   return G_RESOLVER_GET_CLASS (resolver)->
618     lookup_by_address_finish (resolver, result, error);
619 }
620
621 static gchar *
622 g_resolver_get_service_rrname (const char *service,
623                                const char *protocol,
624                                const char *domain)
625 {
626   gchar *rrname, *ascii_domain = NULL;
627
628   if (g_hostname_is_non_ascii (domain))
629     domain = ascii_domain = g_hostname_to_ascii (domain);
630
631   rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
632
633   g_free (ascii_domain);
634   return rrname;
635 }
636
637 /**
638  * g_resolver_lookup_service:
639  * @resolver: a #GResolver
640  * @service: the service type to look up (eg, "ldap")
641  * @protocol: the networking protocol to use for @service (eg, "tcp")
642  * @domain: the DNS domain to look up the service in
643  * @cancellable: (allow-none): a #GCancellable, or %NULL
644  * @error: return location for a #GError, or %NULL
645  *
646  * Synchronously performs a DNS SRV lookup for the given @service and
647  * @protocol in the given @domain and returns an array of #GSrvTarget.
648  * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
649  * @service and @protocol arguments do not include the leading underscore
650  * that appears in the actual DNS entry.
651  *
652  * On success, g_resolver_lookup_service() will return a non-empty #GList of
653  * #GSrvTarget, sorted in order of preference. (That is, you should
654  * attempt to connect to the first target first, then the second if
655  * the first fails, etc.)
656  *
657  * If the DNS resolution fails, @error (if non-%NULL) will be set to
658  * a value from #GResolverError and %NULL will be returned.
659  *
660  * If @cancellable is non-%NULL, it can be used to cancel the
661  * operation, in which case @error (if non-%NULL) will be set to
662  * %G_IO_ERROR_CANCELLED.
663  *
664  * If you are planning to connect to the service, it is usually easier
665  * to create a #GNetworkService and use its #GSocketConnectable
666  * interface.
667  *
668  * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
669  * #GSrvTarget, or %NULL on error. You must free each of the targets and the
670  * list when you are done with it. (You can use g_resolver_free_targets() to do
671  * this.)
672  *
673  * Since: 2.22
674  */
675 GList *
676 g_resolver_lookup_service (GResolver     *resolver,
677                            const gchar   *service,
678                            const gchar   *protocol,
679                            const gchar   *domain,
680                            GCancellable  *cancellable,
681                            GError       **error)
682 {
683   GList *targets;
684   gchar *rrname;
685
686   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
687   g_return_val_if_fail (service != NULL, NULL);
688   g_return_val_if_fail (protocol != NULL, NULL);
689   g_return_val_if_fail (domain != NULL, NULL);
690
691   rrname = g_resolver_get_service_rrname (service, protocol, domain);
692
693   g_resolver_maybe_reload (resolver);
694   targets = G_RESOLVER_GET_CLASS (resolver)->
695     lookup_service (resolver, rrname, cancellable, error);
696
697   g_free (rrname);
698   return targets;
699 }
700
701 /**
702  * g_resolver_lookup_service_async:
703  * @resolver: a #GResolver
704  * @service: the service type to look up (eg, "ldap")
705  * @protocol: the networking protocol to use for @service (eg, "tcp")
706  * @domain: the DNS domain to look up the service in
707  * @cancellable: (allow-none): a #GCancellable, or %NULL
708  * @callback: (scope async): callback to call after resolution completes
709  * @user_data: (closure): data for @callback
710  *
711  * Begins asynchronously performing a DNS SRV lookup for the given
712  * @service and @protocol in the given @domain, and eventually calls
713  * @callback, which must call g_resolver_lookup_service_finish() to
714  * get the final result. See g_resolver_lookup_service() for more
715  * details.
716  *
717  * Since: 2.22
718  */
719 void
720 g_resolver_lookup_service_async (GResolver           *resolver,
721                                  const gchar         *service,
722                                  const gchar         *protocol,
723                                  const gchar         *domain,
724                                  GCancellable        *cancellable,
725                                  GAsyncReadyCallback  callback,
726                                  gpointer             user_data)
727 {
728   gchar *rrname;
729
730   g_return_if_fail (G_IS_RESOLVER (resolver));
731   g_return_if_fail (service != NULL);
732   g_return_if_fail (protocol != NULL);
733   g_return_if_fail (domain != NULL);
734
735   rrname = g_resolver_get_service_rrname (service, protocol, domain);
736
737   g_resolver_maybe_reload (resolver);
738   G_RESOLVER_GET_CLASS (resolver)->
739     lookup_service_async (resolver, rrname, cancellable, callback, user_data);
740
741   g_free (rrname);
742 }
743
744 /**
745  * g_resolver_lookup_service_finish:
746  * @resolver: a #GResolver
747  * @result: the result passed to your #GAsyncReadyCallback
748  * @error: return location for a #GError, or %NULL
749  *
750  * Retrieves the result of a previous call to
751  * g_resolver_lookup_service_async().
752  *
753  * If the DNS resolution failed, @error (if non-%NULL) will be set to
754  * a value from #GResolverError. If the operation was cancelled,
755  * @error will be set to %G_IO_ERROR_CANCELLED.
756  *
757  * Returns: (element-type GSrvTarget) (transfer full): a non-empty #GList of
758  * #GSrvTarget, or %NULL on error. See g_resolver_lookup_service() for more
759  * details.
760  *
761  * Since: 2.22
762  */
763 GList *
764 g_resolver_lookup_service_finish (GResolver     *resolver,
765                                   GAsyncResult  *result,
766                                   GError       **error)
767 {
768   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
769
770   if (g_async_result_legacy_propagate_error (result, error))
771     return NULL;
772
773   return G_RESOLVER_GET_CLASS (resolver)->
774     lookup_service_finish (resolver, result, error);
775 }
776
777 /**
778  * g_resolver_free_targets: (skip)
779  * @targets: a #GList of #GSrvTarget
780  *
781  * Frees @targets (which should be the return value from
782  * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
783  * (This is a convenience method; you can also simply free the
784  * results by hand.)
785  *
786  * Since: 2.22
787  */
788 void
789 g_resolver_free_targets (GList *targets)
790 {
791   GList *t;
792
793   for (t = targets; t; t = t->next)
794     g_srv_target_free (t->data);
795   g_list_free (targets);
796 }
797
798 /**
799  * g_resolver_lookup_records:
800  * @resolver: a #GResolver
801  * @rrname: the DNS name to lookup the record for
802  * @record_type: the type of DNS record to lookup
803  * @cancellable: (allow-none): a #GCancellable, or %NULL
804  * @error: return location for a #GError, or %NULL
805  *
806  * Synchronously performs a DNS record lookup for the given @rrname and returns
807  * a list of records as #GVariant tuples. See #GResolverRecordType for
808  * information on what the records contain for each @record_type.
809  *
810  * If the DNS resolution fails, @error (if non-%NULL) will be set to
811  * a value from #GResolverError and %NULL will be returned.
812  *
813  * If @cancellable is non-%NULL, it can be used to cancel the
814  * operation, in which case @error (if non-%NULL) will be set to
815  * %G_IO_ERROR_CANCELLED.
816  *
817  * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
818  * #GVariant, or %NULL on error. You must free each of the records and the list
819  * when you are done with it. (You can use g_list_free_full() with
820  * g_variant_unref() to do this.)
821  *
822  * Since: 2.34
823  */
824 GList *
825 g_resolver_lookup_records (GResolver            *resolver,
826                            const gchar          *rrname,
827                            GResolverRecordType   record_type,
828                            GCancellable         *cancellable,
829                            GError              **error)
830 {
831   GList *records;
832
833   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
834   g_return_val_if_fail (rrname != NULL, NULL);
835
836   g_resolver_maybe_reload (resolver);
837   records = G_RESOLVER_GET_CLASS (resolver)->
838     lookup_records (resolver, rrname, record_type, cancellable, error);
839
840   return records;
841 }
842
843 /**
844  * g_resolver_lookup_records_async:
845  * @resolver: a #GResolver
846  * @rrname: the DNS name to lookup the record for
847  * @record_type: the type of DNS record to lookup
848  * @cancellable: (allow-none): a #GCancellable, or %NULL
849  * @callback: (scope async): callback to call after resolution completes
850  * @user_data: (closure): data for @callback
851  *
852  * Begins asynchronously performing a DNS lookup for the given
853  * @rrname, and eventually calls @callback, which must call
854  * g_resolver_lookup_records_finish() to get the final result. See
855  * g_resolver_lookup_records() for more details.
856  *
857  * Since: 2.34
858  */
859 void
860 g_resolver_lookup_records_async (GResolver           *resolver,
861                                  const gchar         *rrname,
862                                  GResolverRecordType  record_type,
863                                  GCancellable        *cancellable,
864                                  GAsyncReadyCallback  callback,
865                                  gpointer             user_data)
866 {
867   g_return_if_fail (G_IS_RESOLVER (resolver));
868   g_return_if_fail (rrname != NULL);
869
870   g_resolver_maybe_reload (resolver);
871   G_RESOLVER_GET_CLASS (resolver)->
872     lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
873 }
874
875 /**
876  * g_resolver_lookup_records_finish:
877  * @resolver: a #GResolver
878  * @result: the result passed to your #GAsyncReadyCallback
879  * @error: return location for a #GError, or %NULL
880  *
881  * Retrieves the result of a previous call to
882  * g_resolver_lookup_records_async(). Returns a non-empty list of records as
883  * #GVariant tuples. See #GResolverRecordType for information on what the
884  * records contain.
885  *
886  * If the DNS resolution failed, @error (if non-%NULL) will be set to
887  * a value from #GResolverError. If the operation was cancelled,
888  * @error will be set to %G_IO_ERROR_CANCELLED.
889  *
890  * Returns: (element-type GVariant) (transfer full): a non-empty #GList of
891  * #GVariant, or %NULL on error. You must free each of the records and the list
892  * when you are done with it. (You can use g_list_free_full() with
893  * g_variant_unref() to do this.)
894  *
895  * Since: 2.34
896  */
897 GList *
898 g_resolver_lookup_records_finish (GResolver     *resolver,
899                                   GAsyncResult  *result,
900                                   GError       **error)
901 {
902   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
903   return G_RESOLVER_GET_CLASS (resolver)->
904     lookup_records_finish (resolver, result, error);
905 }
906
907 guint64
908 g_resolver_get_serial (GResolver *resolver)
909 {
910   g_return_val_if_fail (G_IS_RESOLVER (resolver), 0);
911
912   g_resolver_maybe_reload (resolver);
913
914 #ifdef G_OS_UNIX
915   return (guint64) resolver->priv->resolv_conf_timestamp;
916 #else
917   return 1;
918 #endif
919 }
920
921 /**
922  * g_resolver_error_quark:
923  *
924  * Gets the #GResolver Error Quark.
925  *
926  * Returns: a #GQuark.
927  *
928  * Since: 2.22
929  */
930 G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)