gio: port networking classes from GSimpleAsyncResult to GTask
[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, write to the
19  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "config.h"
24 #include <glib.h>
25 #include "glibintl.h"
26
27 #include "gresolver.h"
28 #include "gnetworkingprivate.h"
29 #include "gasyncresult.h"
30 #include "ginetaddress.h"
31 #include "ginetsocketaddress.h"
32 #include "gsimpleasyncresult.h"
33 #include "gtask.h"
34 #include "gsrvtarget.h"
35 #include "gthreadedresolver.h"
36
37 #ifdef G_OS_UNIX
38 #include <sys/stat.h>
39 #endif
40
41 #include <stdlib.h>
42
43
44 /**
45  * SECTION:gresolver
46  * @short_description: Asynchronous and cancellable DNS resolver
47  * @include: gio/gio.h
48  *
49  * #GResolver provides cancellable synchronous and asynchronous DNS
50  * resolution, for hostnames (g_resolver_lookup_by_address(),
51  * g_resolver_lookup_by_name() and their async variants) and SRV
52  * (service) records (g_resolver_lookup_service()).
53  *
54  * #GNetworkAddress and #GNetworkService provide wrappers around
55  * #GResolver functionality that also implement #GSocketConnectable,
56  * making it easy to connect to a remote host/service.
57  */
58
59 enum {
60   RELOAD,
61   LAST_SIGNAL
62 };
63
64 static guint signals[LAST_SIGNAL] = { 0 };
65
66 struct _GResolverPrivate {
67 #ifdef G_OS_UNIX
68   time_t resolv_conf_timestamp;
69 #else
70   int dummy;
71 #endif
72 };
73
74 /**
75  * GResolver:
76  *
77  * The object that handles DNS resolution. Use g_resolver_get_default()
78  * to get the default resolver.
79  */
80 G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT)
81
82 static GList *
83 srv_records_to_targets (GList *records)
84 {
85   const gchar *hostname;
86   guint16 port, priority, weight;
87   GSrvTarget *target;
88   GList *l;
89
90   for (l = records; l != NULL; l = g_list_next (l))
91     {
92       g_variant_get (l->data, "(qqq&s)", &priority, &weight, &port, &hostname);
93       target = g_srv_target_new (hostname, port, priority, weight);
94       g_variant_unref (l->data);
95       l->data = target;
96     }
97
98   return g_srv_target_list_sort (records);
99 }
100
101 static GList *
102 g_resolver_real_lookup_service (GResolver            *resolver,
103                                 const gchar          *rrname,
104                                 GCancellable         *cancellable,
105                                 GError              **error)
106 {
107   GList *records;
108
109   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records (resolver,
110                                                              rrname,
111                                                              G_RESOLVER_RECORD_SRV,
112                                                              cancellable,
113                                                              error);
114
115   return srv_records_to_targets (records);
116 }
117
118 static void
119 g_resolver_real_lookup_service_async (GResolver            *resolver,
120                                       const gchar          *rrname,
121                                       GCancellable         *cancellable,
122                                       GAsyncReadyCallback   callback,
123                                       gpointer              user_data)
124 {
125   G_RESOLVER_GET_CLASS (resolver)->lookup_records_async (resolver,
126                                                          rrname,
127                                                          G_RESOLVER_RECORD_SRV,
128                                                          cancellable,
129                                                          callback,
130                                                          user_data);
131 }
132
133 static GList *
134 g_resolver_real_lookup_service_finish (GResolver            *resolver,
135                                        GAsyncResult         *result,
136                                        GError              **error)
137 {
138   GList *records;
139
140   records = G_RESOLVER_GET_CLASS (resolver)->lookup_records_finish (resolver,
141                                                                     result,
142                                                                     error);
143
144   return srv_records_to_targets (records);
145 }
146
147 static void
148 g_resolver_class_init (GResolverClass *resolver_class)
149 {
150   /* Automatically pass these over to the lookup_records methods */
151   resolver_class->lookup_service = g_resolver_real_lookup_service;
152   resolver_class->lookup_service_async = g_resolver_real_lookup_service_async;
153   resolver_class->lookup_service_finish = g_resolver_real_lookup_service_finish;
154
155   g_type_class_add_private (resolver_class, sizeof (GResolverPrivate));
156
157   /* Make sure _g_networking_init() has been called */
158   g_type_ensure (G_TYPE_INET_ADDRESS);
159
160   /* Initialize _g_resolver_addrinfo_hints */
161 #ifdef AI_ADDRCONFIG
162   _g_resolver_addrinfo_hints.ai_flags |= AI_ADDRCONFIG;
163 #endif
164   /* These two don't actually matter, they just get copied into the
165    * returned addrinfo structures (and then we ignore them). But if
166    * we leave them unset, we'll get back duplicate answers.
167    */
168   _g_resolver_addrinfo_hints.ai_socktype = SOCK_STREAM;
169   _g_resolver_addrinfo_hints.ai_protocol = IPPROTO_TCP;
170
171   /**
172    * GResolver::reload:
173    * @resolver: a #GResolver
174    *
175    * Emitted when the resolver notices that the system resolver
176    * configuration has changed.
177    **/
178   signals[RELOAD] =
179     g_signal_new (I_("reload"),
180                   G_TYPE_RESOLVER,
181                   G_SIGNAL_RUN_LAST,
182                   G_STRUCT_OFFSET (GResolverClass, reload),
183                   NULL, NULL,
184                   g_cclosure_marshal_VOID__VOID,
185                   G_TYPE_NONE, 0);
186 }
187
188 static void
189 g_resolver_init (GResolver *resolver)
190 {
191 #ifdef G_OS_UNIX
192   struct stat st;
193 #endif
194
195   resolver->priv = G_TYPE_INSTANCE_GET_PRIVATE (resolver, G_TYPE_RESOLVER, GResolverPrivate);
196
197 #ifdef G_OS_UNIX
198   if (stat (_PATH_RESCONF, &st) == 0)
199     resolver->priv->resolv_conf_timestamp = st.st_mtime;
200 #endif
201 }
202
203 static GResolver *default_resolver;
204
205 /**
206  * g_resolver_get_default:
207  *
208  * Gets the default #GResolver. You should unref it when you are done
209  * with it. #GResolver may use its reference count as a hint about how
210  * many threads it should allocate for concurrent DNS resolutions.
211  *
212  * Return value: (transfer full): the default #GResolver.
213  *
214  * Since: 2.22
215  */
216 GResolver *
217 g_resolver_get_default (void)
218 {
219   if (!default_resolver)
220     default_resolver = g_object_new (G_TYPE_THREADED_RESOLVER, NULL);
221
222   return g_object_ref (default_resolver);
223 }
224
225 /**
226  * g_resolver_set_default:
227  * @resolver: the new default #GResolver
228  *
229  * Sets @resolver to be the application's default resolver (reffing
230  * @resolver, and unreffing the previous default resolver, if any).
231  * Future calls to g_resolver_get_default() will return this resolver.
232  *
233  * This can be used if an application wants to perform any sort of DNS
234  * caching or "pinning"; it can implement its own #GResolver that
235  * calls the original default resolver for DNS operations, and
236  * implements its own cache policies on top of that, and then set
237  * itself as the default resolver for all later code to use.
238  *
239  * Since: 2.22
240  */
241 void
242 g_resolver_set_default (GResolver *resolver)
243 {
244   if (default_resolver)
245     g_object_unref (default_resolver);
246   default_resolver = g_object_ref (resolver);
247 }
248
249
250 static void
251 g_resolver_maybe_reload (GResolver *resolver)
252 {
253 #ifdef G_OS_UNIX
254   struct stat st;
255
256   if (stat (_PATH_RESCONF, &st) == 0)
257     {
258       if (st.st_mtime != resolver->priv->resolv_conf_timestamp)
259         {
260           resolver->priv->resolv_conf_timestamp = st.st_mtime;
261           res_init ();
262           g_signal_emit (resolver, signals[RELOAD], 0);
263         }
264     }
265 #endif
266 }
267
268 /* filter out duplicates, cf. https://bugzilla.gnome.org/show_bug.cgi?id=631379 */
269 static void
270 remove_duplicates (GList *addrs)
271 {
272   GList *l;
273   GList *ll;
274   GList *lll;
275
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...
279    */
280   for (l = addrs; l != NULL; l = l->next)
281     {
282       GInetAddress *address = G_INET_ADDRESS (l->data);
283       for (ll = l->next; ll != NULL; ll = lll)
284         {
285           GInetAddress *other_address = G_INET_ADDRESS (ll->data);
286           lll = ll->next;
287           if (g_inet_address_equal (address, other_address))
288             {
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);
292             }
293         }
294     }
295 }
296
297
298 /**
299  * g_resolver_lookup_by_name:
300  * @resolver: a #GResolver
301  * @hostname: the hostname to look up
302  * @cancellable: (allow-none): a #GCancellable, or %NULL
303  * @error: return location for a #GError, or %NULL
304  *
305  * Synchronously resolves @hostname to determine its associated IP
306  * address(es). @hostname may be an ASCII-only or UTF-8 hostname, or
307  * the textual form of an IP address (in which case this just becomes
308  * a wrapper around g_inet_address_new_from_string()).
309  *
310  * On success, g_resolver_lookup_by_name() will return a #GList of
311  * #GInetAddress, sorted in order of preference and guaranteed to not
312  * contain duplicates. That is, if using the result to connect to
313  * @hostname, you should attempt to connect to the first address
314  * first, then the second if the first fails, etc. If you are using
315  * the result to listen on a socket, it is appropriate to add each
316  * result using e.g. g_socket_listener_add_address().
317  *
318  * If the DNS resolution fails, @error (if non-%NULL) will be set to a
319  * value from #GResolverError.
320  *
321  * If @cancellable is non-%NULL, it can be used to cancel the
322  * operation, in which case @error (if non-%NULL) will be set to
323  * %G_IO_ERROR_CANCELLED.
324  *
325  * If you are planning to connect to a socket on the resolved IP
326  * address, it may be easier to create a #GNetworkAddress and use its
327  * #GSocketConnectable interface.
328  *
329  * Return value: (element-type GInetAddress) (transfer full): a #GList
330  * of #GInetAddress, or %NULL on error. You
331  * must unref each of the addresses and free the list when you are
332  * done with it. (You can use g_resolver_free_addresses() to do this.)
333  *
334  * Since: 2.22
335  */
336 GList *
337 g_resolver_lookup_by_name (GResolver     *resolver,
338                            const gchar   *hostname,
339                            GCancellable  *cancellable,
340                            GError       **error)
341 {
342   GInetAddress *addr;
343   GList *addrs;
344   gchar *ascii_hostname = NULL;
345
346   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
347   g_return_val_if_fail (hostname != NULL, NULL);
348
349   /* Check if @hostname is just an IP address */
350   addr = g_inet_address_new_from_string (hostname);
351   if (addr)
352     return g_list_append (NULL, addr);
353
354   if (g_hostname_is_non_ascii (hostname))
355     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
356
357   g_resolver_maybe_reload (resolver);
358   addrs = G_RESOLVER_GET_CLASS (resolver)->
359     lookup_by_name (resolver, hostname, cancellable, error);
360
361   remove_duplicates (addrs);
362
363   g_free (ascii_hostname);
364   return addrs;
365 }
366
367 /**
368  * g_resolver_lookup_by_name_async:
369  * @resolver: a #GResolver
370  * @hostname: the hostname to look up the address of
371  * @cancellable: (allow-none): a #GCancellable, or %NULL
372  * @callback: (scope async): callback to call after resolution completes
373  * @user_data: (closure): data for @callback
374  *
375  * Begins asynchronously resolving @hostname to determine its
376  * associated IP address(es), and eventually calls @callback, which
377  * must call g_resolver_lookup_by_name_finish() to get the result.
378  * See g_resolver_lookup_by_name() for more details.
379  *
380  * Since: 2.22
381  */
382 void
383 g_resolver_lookup_by_name_async (GResolver           *resolver,
384                                  const gchar         *hostname,
385                                  GCancellable        *cancellable,
386                                  GAsyncReadyCallback  callback,
387                                  gpointer             user_data)
388 {
389   GInetAddress *addr;
390   gchar *ascii_hostname = NULL;
391
392   g_return_if_fail (G_IS_RESOLVER (resolver));
393   g_return_if_fail (hostname != NULL);
394
395   /* Check if @hostname is just an IP address */
396   addr = g_inet_address_new_from_string (hostname);
397   if (addr)
398     {
399       GTask *task;
400
401       task = g_task_new (resolver, cancellable, callback, user_data);
402       g_task_set_source_tag (task, g_resolver_lookup_by_name_async);
403       g_task_return_pointer (task, g_list_append (NULL, addr),
404                              (GDestroyNotify) g_resolver_free_addresses);
405       g_object_unref (task);
406       return;
407     }
408
409   if (g_hostname_is_non_ascii (hostname))
410     hostname = ascii_hostname = g_hostname_to_ascii (hostname);
411
412   g_resolver_maybe_reload (resolver);
413   G_RESOLVER_GET_CLASS (resolver)->
414     lookup_by_name_async (resolver, hostname, cancellable, callback, user_data);
415
416   g_free (ascii_hostname);
417 }
418
419 /**
420  * g_resolver_lookup_by_name_finish:
421  * @resolver: a #GResolver
422  * @result: the result passed to your #GAsyncReadyCallback
423  * @error: return location for a #GError, or %NULL
424  *
425  * Retrieves the result of a call to
426  * g_resolver_lookup_by_name_async().
427  *
428  * If the DNS resolution failed, @error (if non-%NULL) will be set to
429  * a value from #GResolverError. If the operation was cancelled,
430  * @error will be set to %G_IO_ERROR_CANCELLED.
431  *
432  * Return value: (element-type GInetAddress) (transfer full): a #GList
433  * of #GInetAddress, or %NULL on error. See g_resolver_lookup_by_name()
434  * for more details.
435  *
436  * Since: 2.22
437  */
438 GList *
439 g_resolver_lookup_by_name_finish (GResolver     *resolver,
440                                   GAsyncResult  *result,
441                                   GError       **error)
442 {
443   GList *addrs;
444
445   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
446
447   if (g_async_result_legacy_propagate_error (result, error))
448     return NULL;
449   else if (g_async_result_is_tagged (result, g_resolver_lookup_by_name_async))
450     {
451       /* Handle the stringified-IP-addr case */
452       return g_task_propagate_pointer (G_TASK (result), error);
453     }
454
455   addrs = G_RESOLVER_GET_CLASS (resolver)->
456     lookup_by_name_finish (resolver, result, error);
457
458   remove_duplicates (addrs);
459
460   return addrs;
461 }
462
463 /**
464  * g_resolver_free_addresses: (skip)
465  * @addresses: a #GList of #GInetAddress
466  *
467  * Frees @addresses (which should be the return value from
468  * g_resolver_lookup_by_name() or g_resolver_lookup_by_name_finish()).
469  * (This is a convenience method; you can also simply free the results
470  * by hand.)
471  *
472  * Since: 2.22
473  */
474 void
475 g_resolver_free_addresses (GList *addresses)
476 {
477   GList *a;
478
479   for (a = addresses; a; a = a->next)
480     g_object_unref (a->data);
481   g_list_free (addresses);
482 }
483
484 /**
485  * g_resolver_lookup_by_address:
486  * @resolver: a #GResolver
487  * @address: the address to reverse-resolve
488  * @cancellable: (allow-none): a #GCancellable, or %NULL
489  * @error: return location for a #GError, or %NULL
490  *
491  * Synchronously reverse-resolves @address to determine its
492  * associated hostname.
493  *
494  * If the DNS resolution fails, @error (if non-%NULL) will be set to
495  * a value from #GResolverError.
496  *
497  * If @cancellable is non-%NULL, it can be used to cancel the
498  * operation, in which case @error (if non-%NULL) will be set to
499  * %G_IO_ERROR_CANCELLED.
500  *
501  * Return value: a hostname (either ASCII-only, or in ASCII-encoded
502  *     form), or %NULL on error.
503  *
504  * Since: 2.22
505  */
506 gchar *
507 g_resolver_lookup_by_address (GResolver     *resolver,
508                               GInetAddress  *address,
509                               GCancellable  *cancellable,
510                               GError       **error)
511 {
512   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
513   g_return_val_if_fail (G_IS_INET_ADDRESS (address), NULL);
514
515   g_resolver_maybe_reload (resolver);
516   return G_RESOLVER_GET_CLASS (resolver)->
517     lookup_by_address (resolver, address, cancellable, error);
518 }
519
520 /**
521  * g_resolver_lookup_by_address_async:
522  * @resolver: a #GResolver
523  * @address: the address to reverse-resolve
524  * @cancellable: (allow-none): a #GCancellable, or %NULL
525  * @callback: (scope async): callback to call after resolution completes
526  * @user_data: (closure): data for @callback
527  *
528  * Begins asynchronously reverse-resolving @address to determine its
529  * associated hostname, and eventually calls @callback, which must
530  * call g_resolver_lookup_by_address_finish() to get the final result.
531  *
532  * Since: 2.22
533  */
534 void
535 g_resolver_lookup_by_address_async (GResolver           *resolver,
536                                     GInetAddress        *address,
537                                     GCancellable        *cancellable,
538                                     GAsyncReadyCallback  callback,
539                                     gpointer             user_data)
540 {
541   g_return_if_fail (G_IS_RESOLVER (resolver));
542   g_return_if_fail (G_IS_INET_ADDRESS (address));
543
544   g_resolver_maybe_reload (resolver);
545   G_RESOLVER_GET_CLASS (resolver)->
546     lookup_by_address_async (resolver, address, cancellable, callback, user_data);
547 }
548
549 /**
550  * g_resolver_lookup_by_address_finish:
551  * @resolver: a #GResolver
552  * @result: the result passed to your #GAsyncReadyCallback
553  * @error: return location for a #GError, or %NULL
554  *
555  * Retrieves the result of a previous call to
556  * g_resolver_lookup_by_address_async().
557  *
558  * If the DNS resolution failed, @error (if non-%NULL) will be set to
559  * a value from #GResolverError. If the operation was cancelled,
560  * @error will be set to %G_IO_ERROR_CANCELLED.
561  *
562  * Return value: a hostname (either ASCII-only, or in ASCII-encoded
563  * form), or %NULL on error.
564  *
565  * Since: 2.22
566  */
567 gchar *
568 g_resolver_lookup_by_address_finish (GResolver     *resolver,
569                                      GAsyncResult  *result,
570                                      GError       **error)
571 {
572   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
573
574   if (g_async_result_legacy_propagate_error (result, error))
575     return NULL;
576
577   return G_RESOLVER_GET_CLASS (resolver)->
578     lookup_by_address_finish (resolver, result, error);
579 }
580
581 static gchar *
582 g_resolver_get_service_rrname (const char *service,
583                                const char *protocol,
584                                const char *domain)
585 {
586   gchar *rrname, *ascii_domain = NULL;
587
588   if (g_hostname_is_non_ascii (domain))
589     domain = ascii_domain = g_hostname_to_ascii (domain);
590
591   rrname = g_strdup_printf ("_%s._%s.%s", service, protocol, domain);
592
593   g_free (ascii_domain);
594   return rrname;
595 }
596
597 /**
598  * g_resolver_lookup_service:
599  * @resolver: a #GResolver
600  * @service: the service type to look up (eg, "ldap")
601  * @protocol: the networking protocol to use for @service (eg, "tcp")
602  * @domain: the DNS domain to look up the service in
603  * @cancellable: (allow-none): a #GCancellable, or %NULL
604  * @error: return location for a #GError, or %NULL
605  *
606  * Synchronously performs a DNS SRV lookup for the given @service and
607  * @protocol in the given @domain and returns an array of #GSrvTarget.
608  * @domain may be an ASCII-only or UTF-8 hostname. Note also that the
609  * @service and @protocol arguments <emphasis>do not</emphasis>
610  * include the leading underscore that appears in the actual DNS
611  * entry.
612  *
613  * On success, g_resolver_lookup_service() will return a #GList of
614  * #GSrvTarget, sorted in order of preference. (That is, you should
615  * attempt to connect to the first target first, then the second if
616  * the first fails, etc.)
617  *
618  * If the DNS resolution fails, @error (if non-%NULL) will be set to
619  * a value from #GResolverError.
620  *
621  * If @cancellable is non-%NULL, it can be used to cancel the
622  * operation, in which case @error (if non-%NULL) will be set to
623  * %G_IO_ERROR_CANCELLED.
624  *
625  * If you are planning to connect to the service, it is usually easier
626  * to create a #GNetworkService and use its #GSocketConnectable
627  * interface.
628  *
629  * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
630  * or %NULL on error. You must free each of the targets and the list when you are
631  * done with it. (You can use g_resolver_free_targets() to do this.)
632  *
633  * Since: 2.22
634  */
635 GList *
636 g_resolver_lookup_service (GResolver     *resolver,
637                            const gchar   *service,
638                            const gchar   *protocol,
639                            const gchar   *domain,
640                            GCancellable  *cancellable,
641                            GError       **error)
642 {
643   GList *targets;
644   gchar *rrname;
645
646   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
647   g_return_val_if_fail (service != NULL, NULL);
648   g_return_val_if_fail (protocol != NULL, NULL);
649   g_return_val_if_fail (domain != NULL, NULL);
650
651   rrname = g_resolver_get_service_rrname (service, protocol, domain);
652
653   g_resolver_maybe_reload (resolver);
654   targets = G_RESOLVER_GET_CLASS (resolver)->
655     lookup_service (resolver, rrname, cancellable, error);
656
657   g_free (rrname);
658   return targets;
659 }
660
661 /**
662  * g_resolver_lookup_service_async:
663  * @resolver: a #GResolver
664  * @service: the service type to look up (eg, "ldap")
665  * @protocol: the networking protocol to use for @service (eg, "tcp")
666  * @domain: the DNS domain to look up the service in
667  * @cancellable: (allow-none): a #GCancellable, or %NULL
668  * @callback: (scope async): callback to call after resolution completes
669  * @user_data: (closure): data for @callback
670  *
671  * Begins asynchronously performing a DNS SRV lookup for the given
672  * @service and @protocol in the given @domain, and eventually calls
673  * @callback, which must call g_resolver_lookup_service_finish() to
674  * get the final result. See g_resolver_lookup_service() for more
675  * details.
676  *
677  * Since: 2.22
678  */
679 void
680 g_resolver_lookup_service_async (GResolver           *resolver,
681                                  const gchar         *service,
682                                  const gchar         *protocol,
683                                  const gchar         *domain,
684                                  GCancellable        *cancellable,
685                                  GAsyncReadyCallback  callback,
686                                  gpointer             user_data)
687 {
688   gchar *rrname;
689
690   g_return_if_fail (G_IS_RESOLVER (resolver));
691   g_return_if_fail (service != NULL);
692   g_return_if_fail (protocol != NULL);
693   g_return_if_fail (domain != NULL);
694
695   rrname = g_resolver_get_service_rrname (service, protocol, domain);
696
697   g_resolver_maybe_reload (resolver);
698   G_RESOLVER_GET_CLASS (resolver)->
699     lookup_service_async (resolver, rrname, cancellable, callback, user_data);
700
701   g_free (rrname);
702 }
703
704 /**
705  * g_resolver_lookup_service_finish:
706  * @resolver: a #GResolver
707  * @result: the result passed to your #GAsyncReadyCallback
708  * @error: return location for a #GError, or %NULL
709  *
710  * Retrieves the result of a previous call to
711  * g_resolver_lookup_service_async().
712  *
713  * If the DNS resolution failed, @error (if non-%NULL) will be set to
714  * a value from #GResolverError. If the operation was cancelled,
715  * @error will be set to %G_IO_ERROR_CANCELLED.
716  *
717  * Return value: (element-type GSrvTarget) (transfer full): a #GList of #GSrvTarget,
718  * or %NULL on error. See g_resolver_lookup_service() for more details.
719  *
720  * Since: 2.22
721  */
722 GList *
723 g_resolver_lookup_service_finish (GResolver     *resolver,
724                                   GAsyncResult  *result,
725                                   GError       **error)
726 {
727   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
728
729   if (g_async_result_legacy_propagate_error (result, error))
730     return NULL;
731
732   return G_RESOLVER_GET_CLASS (resolver)->
733     lookup_service_finish (resolver, result, error);
734 }
735
736 /**
737  * g_resolver_free_targets: (skip)
738  * @targets: a #GList of #GSrvTarget
739  *
740  * Frees @targets (which should be the return value from
741  * g_resolver_lookup_service() or g_resolver_lookup_service_finish()).
742  * (This is a convenience method; you can also simply free the
743  * results by hand.)
744  *
745  * Since: 2.22
746  */
747 void
748 g_resolver_free_targets (GList *targets)
749 {
750   GList *t;
751
752   for (t = targets; t; t = t->next)
753     g_srv_target_free (t->data);
754   g_list_free (targets);
755 }
756
757 /**
758  * g_resolver_lookup_records:
759  * @resolver: a #GResolver
760  * @rrname: the DNS name to lookup the record for
761  * @record_type: the type of DNS record to lookup
762  * @cancellable: (allow-none): a #GCancellable, or %NULL
763  * @error: return location for a #GError, or %NULL
764  *
765  * Synchronously performs a DNS record lookup for the given @rrname and returns
766  * a list of records as #GVariant tuples. See #GResolverRecordType for
767  * information on what the records contain for each @record_type.
768  *
769  * If the DNS resolution fails, @error (if non-%NULL) will be set to
770  * a value from #GResolverError.
771  *
772  * If @cancellable is non-%NULL, it can be used to cancel the
773  * operation, in which case @error (if non-%NULL) will be set to
774  * %G_IO_ERROR_CANCELLED.
775  *
776  * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
777  * or %NULL on error. You must free each of the records and the list when you are
778  * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
779  *
780  * Since: 2.34
781  */
782 GList *
783 g_resolver_lookup_records (GResolver            *resolver,
784                            const gchar          *rrname,
785                            GResolverRecordType   record_type,
786                            GCancellable         *cancellable,
787                            GError              **error)
788 {
789   GList *records;
790
791   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
792   g_return_val_if_fail (rrname != NULL, NULL);
793
794   g_resolver_maybe_reload (resolver);
795   records = G_RESOLVER_GET_CLASS (resolver)->
796     lookup_records (resolver, rrname, record_type, cancellable, error);
797
798   return records;
799 }
800
801 /**
802  * g_resolver_lookup_records_async:
803  * @resolver: a #GResolver
804  * @rrname: the DNS name to lookup the record for
805  * @record_type: the type of DNS record to lookup
806  * @cancellable: (allow-none): a #GCancellable, or %NULL
807  * @callback: (scope async): callback to call after resolution completes
808  * @user_data: (closure): data for @callback
809  *
810  * Begins asynchronously performing a DNS lookup for the given
811  * @rrname, and eventually calls @callback, which must call
812  * g_resolver_lookup_records_finish() to get the final result. See
813  * g_resolver_lookup_records() for more details.
814  *
815  * Since: 2.34
816  */
817 void
818 g_resolver_lookup_records_async (GResolver           *resolver,
819                                  const gchar         *rrname,
820                                  GResolverRecordType  record_type,
821                                  GCancellable        *cancellable,
822                                  GAsyncReadyCallback  callback,
823                                  gpointer             user_data)
824 {
825   g_return_if_fail (G_IS_RESOLVER (resolver));
826   g_return_if_fail (rrname != NULL);
827
828   g_resolver_maybe_reload (resolver);
829   G_RESOLVER_GET_CLASS (resolver)->
830     lookup_records_async (resolver, rrname, record_type, cancellable, callback, user_data);
831 }
832
833 /**
834  * g_resolver_lookup_records_finish:
835  * @resolver: a #GResolver
836  * @result: the result passed to your #GAsyncReadyCallback
837  * @error: return location for a #GError, or %NULL
838  *
839  * Retrieves the result of a previous call to
840  * g_resolver_lookup_records_async(). Returns a list of records as #GVariant
841  * tuples. See #GResolverRecordType for information on what the records contain.
842  *
843  * If the DNS resolution failed, @error (if non-%NULL) will be set to
844  * a value from #GResolverError. If the operation was cancelled,
845  * @error will be set to %G_IO_ERROR_CANCELLED.
846  *
847  * Return value: (element-type GVariant) (transfer full): a #GList of #GVariant,
848  * or %NULL on error. You must free each of the records and the list when you are
849  * done with it. (You can use g_list_free_full() with g_variant_unref() to do this.)
850  *
851  * Since: 2.34
852  */
853 GList *
854 g_resolver_lookup_records_finish (GResolver     *resolver,
855                                   GAsyncResult  *result,
856                                   GError       **error)
857 {
858   g_return_val_if_fail (G_IS_RESOLVER (resolver), NULL);
859   return G_RESOLVER_GET_CLASS (resolver)->
860     lookup_records_finish (resolver, result, error);
861 }
862
863 /**
864  * g_resolver_error_quark:
865  *
866  * Gets the #GResolver Error Quark.
867  *
868  * Return value: a #GQuark.
869  *
870  * Since: 2.22
871  */
872 G_DEFINE_QUARK (g-resolver-error-quark, g_resolver_error)
873
874 static GResolverError
875 g_resolver_error_from_addrinfo_error (gint err)
876 {
877   switch (err)
878     {
879     case EAI_FAIL:
880 #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)
881     case EAI_NODATA:
882 #endif
883     case EAI_NONAME:
884       return G_RESOLVER_ERROR_NOT_FOUND;
885
886     case EAI_AGAIN:
887       return G_RESOLVER_ERROR_TEMPORARY_FAILURE;
888
889     default:
890       return G_RESOLVER_ERROR_INTERNAL;
891     }
892 }
893
894 struct addrinfo _g_resolver_addrinfo_hints;
895
896 /* Private method to process a getaddrinfo() response. */
897 GList *
898 _g_resolver_addresses_from_addrinfo (const char       *hostname,
899                                      struct addrinfo  *res,
900                                      gint              gai_retval,
901                                      GError          **error)
902 {
903   struct addrinfo *ai;
904   GSocketAddress *sockaddr;
905   GInetAddress *addr;
906   GList *addrs;
907
908   if (gai_retval != 0)
909     {
910       g_set_error (error, G_RESOLVER_ERROR,
911                    g_resolver_error_from_addrinfo_error (gai_retval),
912                    _("Error resolving '%s': %s"),
913                    hostname, gai_strerror (gai_retval));
914       return NULL;
915     }
916
917   g_return_val_if_fail (res != NULL, NULL);
918
919   addrs = NULL;
920   for (ai = res; ai; ai = ai->ai_next)
921     {
922       sockaddr = g_socket_address_new_from_native (ai->ai_addr, ai->ai_addrlen);
923       if (!sockaddr || !G_IS_INET_SOCKET_ADDRESS (sockaddr))
924         continue;
925
926       addr = g_object_ref (g_inet_socket_address_get_address ((GInetSocketAddress *)sockaddr));
927       addrs = g_list_prepend (addrs, addr);
928       g_object_unref (sockaddr);
929     }
930
931   return g_list_reverse (addrs);
932 }
933
934 /* Private method to set up a getnameinfo() request */
935 void
936 _g_resolver_address_to_sockaddr (GInetAddress            *address,
937                                  struct sockaddr_storage *sa,
938                                  gsize                   *len)
939 {
940   GSocketAddress *sockaddr;
941
942   sockaddr = g_inet_socket_address_new (address, 0);
943   g_socket_address_to_native (sockaddr, (struct sockaddr *)sa, sizeof (*sa), NULL);
944   *len = g_socket_address_get_native_size (sockaddr);
945   g_object_unref (sockaddr);
946 }
947
948 /* Private method to process a getnameinfo() response. */
949 char *
950 _g_resolver_name_from_nameinfo (GInetAddress  *address,
951                                 const gchar   *name,
952                                 gint           gni_retval,
953                                 GError       **error)
954 {
955   if (gni_retval != 0)
956     {
957       gchar *phys;
958
959       phys = g_inet_address_to_string (address);
960       g_set_error (error, G_RESOLVER_ERROR,
961                    g_resolver_error_from_addrinfo_error (gni_retval),
962                    _("Error reverse-resolving '%s': %s"),
963                    phys ? phys : "(unknown)", gai_strerror (gni_retval));
964       g_free (phys);
965       return NULL;
966     }
967
968   return g_strdup (name);
969 }
970
971 #if defined(G_OS_UNIX)
972
973 static gboolean
974 parse_short (guchar  **p,
975              guchar   *end,
976              guint16  *value)
977 {
978   if (*p + 2 > end)
979     return FALSE;
980   GETSHORT (*value, *p);
981   return TRUE;
982 }
983
984 static gboolean
985 parse_long (guchar  **p,
986             guchar   *end,
987             guint32  *value)
988 {
989   if (*p + 4 > end)
990     return FALSE;
991   GETLONG (*value, *p);
992   return TRUE;
993 }
994
995 static GVariant *
996 parse_res_srv (guchar  *answer,
997                guchar  *end,
998                guchar  *p)
999 {
1000   gchar namebuf[1024];
1001   guint16 priority, weight, port;
1002   gint n;
1003
1004   if (!parse_short (&p, end, &priority) ||
1005       !parse_short (&p, end, &weight) ||
1006       !parse_short (&p, end, &port))
1007     return NULL;
1008
1009   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1010   if (n < 0)
1011     return NULL;
1012   *p += n;
1013
1014   return g_variant_new ("(qqqs)",
1015                         priority,
1016                         weight,
1017                         port,
1018                         namebuf);
1019 }
1020
1021 static GVariant *
1022 parse_res_soa (guchar  *answer,
1023                guchar  *end,
1024                guchar  *p)
1025 {
1026   gchar mnamebuf[1024];
1027   gchar rnamebuf[1024];
1028   guint32 serial, refresh, retry, expire, ttl;
1029   gint n;
1030
1031   n = dn_expand (answer, end, p, mnamebuf, sizeof (mnamebuf));
1032   if (n < 0)
1033     return NULL;
1034   p += n;
1035
1036   n = dn_expand (answer, end, p, rnamebuf, sizeof (rnamebuf));
1037   if (n < 0)
1038     return NULL;
1039   p += n;
1040
1041   if (!parse_long (&p, end, &serial) ||
1042       !parse_long (&p, end, &refresh) ||
1043       !parse_long (&p, end, &retry) ||
1044       !parse_long (&p, end, &expire) ||
1045       !parse_long (&p, end, &ttl))
1046     return NULL;
1047
1048   return g_variant_new ("(ssuuuuu)",
1049                         mnamebuf,
1050                         rnamebuf,
1051                         serial,
1052                         refresh,
1053                         retry,
1054                         expire,
1055                         ttl);
1056 }
1057
1058 static GVariant *
1059 parse_res_ns (guchar  *answer,
1060               guchar  *end,
1061               guchar  *p)
1062 {
1063   gchar namebuf[1024];
1064   gint n;
1065
1066   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1067   if (n < 0)
1068     return NULL;
1069
1070   return g_variant_new ("(s)", namebuf);
1071 }
1072
1073 static GVariant *
1074 parse_res_mx (guchar  *answer,
1075               guchar  *end,
1076               guchar  *p)
1077 {
1078   gchar namebuf[1024];
1079   guint16 preference;
1080   gint n;
1081
1082   if (!parse_short (&p, end, &preference))
1083     return NULL;
1084
1085   n = dn_expand (answer, end, p, namebuf, sizeof (namebuf));
1086   if (n < 0)
1087     return NULL;
1088   p += n;
1089
1090   return g_variant_new ("(qs)",
1091                         preference,
1092                         namebuf);
1093 }
1094
1095 static GVariant *
1096 parse_res_txt (guchar  *answer,
1097                guchar  *end,
1098                guchar  *p)
1099 {
1100   GVariant *record;
1101   GPtrArray *array;
1102   gsize len;
1103
1104   array = g_ptr_array_new_with_free_func (g_free);
1105   while (p < end)
1106     {
1107       len = *(p++);
1108       if (len > p - end)
1109         break;
1110       g_ptr_array_add (array, g_strndup ((gchar *)p, len));
1111       p += len;
1112     }
1113
1114   record = g_variant_new ("(@as)",
1115                           g_variant_new_strv ((const gchar **)array->pdata, array->len));
1116   g_ptr_array_free (array, TRUE);
1117   return record;
1118 }
1119
1120 gint
1121 _g_resolver_record_type_to_rrtype (GResolverRecordType type)
1122 {
1123   switch (type)
1124   {
1125     case G_RESOLVER_RECORD_SRV:
1126       return T_SRV;
1127     case G_RESOLVER_RECORD_TXT:
1128       return T_TXT;
1129     case G_RESOLVER_RECORD_SOA:
1130       return T_SOA;
1131     case G_RESOLVER_RECORD_NS:
1132       return T_NS;
1133     case G_RESOLVER_RECORD_MX:
1134       return T_MX;
1135   }
1136   g_return_val_if_reached (-1);
1137 }
1138
1139 /* Private method to process a res_query response into GSrvTargets */
1140 GList *
1141 _g_resolver_records_from_res_query (const gchar      *rrname,
1142                                     gint              rrtype,
1143                                     guchar           *answer,
1144                                     gint              len,
1145                                     gint              herr,
1146                                     GError          **error)
1147 {
1148   gint count;
1149   guchar *end, *p;
1150   guint16 type, qclass, rdlength;
1151   guint32 ttl;
1152   HEADER *header;
1153   GList *records;
1154   GVariant *record;
1155   gint n, i;
1156
1157   if (len <= 0)
1158     {
1159       GResolverError errnum;
1160       const gchar *format;
1161
1162       if (len == 0 || herr == HOST_NOT_FOUND || herr == NO_DATA)
1163         {
1164           errnum = G_RESOLVER_ERROR_NOT_FOUND;
1165           format = _("No DNS record of the requested type for '%s'");
1166         }
1167       else if (herr == TRY_AGAIN)
1168         {
1169           errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
1170           format = _("Temporarily unable to resolve '%s'");
1171         }
1172       else
1173         {
1174           errnum = G_RESOLVER_ERROR_INTERNAL;
1175           format = _("Error resolving '%s'");
1176         }
1177
1178       g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
1179       return NULL;
1180     }
1181
1182   records = NULL;
1183
1184   header = (HEADER *)answer;
1185   p = answer + sizeof (HEADER);
1186   end = answer + len;
1187
1188   /* Skip query */
1189   count = ntohs (header->qdcount);
1190   for (i = 0; i < count && p < end; i++)
1191     {
1192       n = dn_skipname (p, end);
1193       if (n < 0)
1194         break;
1195       p += n;
1196       p += 4;
1197     }
1198
1199   /* Incomplete response */
1200   if (i < count)
1201     {
1202       g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
1203                    _("Incomplete data received for '%s'"), rrname);
1204       return NULL;
1205     }
1206
1207   /* Read answers */
1208   count = ntohs (header->ancount);
1209   for (i = 0; i < count && p < end; i++)
1210     {
1211       n = dn_skipname (p, end);
1212       if (n < 0)
1213         break;
1214       p += n;
1215
1216       if (!parse_short (&p, end, &type) ||
1217           !parse_short (&p, end, &qclass) ||
1218           !parse_long (&p, end, &ttl) ||
1219           !parse_short (&p, end, &rdlength))
1220         break;
1221
1222       ttl = ttl; /* To avoid -Wunused-but-set-variable */
1223
1224       if (p + rdlength > end)
1225         break;
1226
1227       if (type == rrtype && qclass == C_IN)
1228         {
1229           switch (rrtype)
1230             {
1231             case T_SRV:
1232               record = parse_res_srv (answer, end, p);
1233               break;
1234             case T_MX:
1235               record = parse_res_mx (answer, end, p);
1236               break;
1237             case T_SOA:
1238               record = parse_res_soa (answer, end, p);
1239               break;
1240             case T_NS:
1241               record = parse_res_ns (answer, end, p);
1242               break;
1243             case T_TXT:
1244               record = parse_res_txt (answer, p + rdlength, p);
1245               break;
1246             default:
1247               g_warn_if_reached ();
1248               record = NULL;
1249               break;
1250             }
1251
1252           if (record != NULL)
1253             records = g_list_prepend (records, record);
1254         }
1255
1256       p += rdlength;
1257     }
1258
1259   /* Somehow got a truncated response */
1260   if (i < count)
1261     {
1262       g_list_free_full (records, (GDestroyNotify)g_variant_unref);
1263       g_set_error (error, G_RESOLVER_ERROR, G_RESOLVER_ERROR_TEMPORARY_FAILURE,
1264                    _("Incomplete data received for '%s'"), rrname);
1265       return NULL;
1266     }
1267
1268   return records;
1269 }
1270
1271 #elif defined(G_OS_WIN32)
1272 static GVariant *
1273 parse_dns_srv (DNS_RECORD *rec)
1274 {
1275   return g_variant_new ("(qqqs)",
1276                         (guint16)rec->Data.SRV.wPriority,
1277                         (guint16)rec->Data.SRV.wWeight,
1278                         (guint16)rec->Data.SRV.wPort,
1279                         rec->Data.SRV.pNameTarget);
1280 }
1281
1282 static GVariant *
1283 parse_dns_soa (DNS_RECORD *rec)
1284 {
1285   return g_variant_new ("(ssuuuuu)",
1286                         rec->Data.SOA.pNamePrimaryServer,
1287                         rec->Data.SOA.pNameAdministrator,
1288                         (guint32)rec->Data.SOA.dwSerialNo,
1289                         (guint32)rec->Data.SOA.dwRefresh,
1290                         (guint32)rec->Data.SOA.dwRetry,
1291                         (guint32)rec->Data.SOA.dwExpire,
1292                         (guint32)rec->Data.SOA.dwDefaultTtl);
1293 }
1294
1295 static GVariant *
1296 parse_dns_ns (DNS_RECORD *rec)
1297 {
1298   return g_variant_new ("(s)", rec->Data.NS.pNameHost);
1299 }
1300
1301 static GVariant *
1302 parse_dns_mx (DNS_RECORD *rec)
1303 {
1304   return g_variant_new ("(qs)",
1305                         (guint16)rec->Data.MX.wPreference,
1306                         rec->Data.MX.pNameExchange);
1307 }
1308
1309 static GVariant *
1310 parse_dns_txt (DNS_RECORD *rec)
1311 {
1312   GVariant *record;
1313   GPtrArray *array;
1314   DWORD i;
1315
1316   array = g_ptr_array_new ();
1317   for (i = 0; i < rec->Data.TXT.dwStringCount; i++)
1318     g_ptr_array_add (array, rec->Data.TXT.pStringArray[i]);
1319   record = g_variant_new ("(@as)",
1320                           g_variant_new_strv ((const gchar **)array->pdata, array->len));
1321   g_ptr_array_free (array, TRUE);
1322   return record;
1323 }
1324
1325 WORD
1326 _g_resolver_record_type_to_dnstype (GResolverRecordType type)
1327 {
1328   switch (type)
1329   {
1330     case G_RESOLVER_RECORD_SRV:
1331       return DNS_TYPE_SRV;
1332     case G_RESOLVER_RECORD_TXT:
1333       return DNS_TYPE_TEXT;
1334     case G_RESOLVER_RECORD_SOA:
1335       return DNS_TYPE_SOA;
1336     case G_RESOLVER_RECORD_NS:
1337       return DNS_TYPE_NS;
1338     case G_RESOLVER_RECORD_MX:
1339       return DNS_TYPE_MX;
1340   }
1341   g_return_val_if_reached (-1);
1342 }
1343
1344 /* Private method to process a DnsQuery response into GVariants */
1345 GList *
1346 _g_resolver_records_from_DnsQuery (const gchar  *rrname,
1347                                    WORD          dnstype,
1348                                    DNS_STATUS    status,
1349                                    DNS_RECORD   *results,
1350                                    GError      **error)
1351 {
1352   DNS_RECORD *rec;
1353   gpointer record;
1354   GList *records;
1355
1356   if (status != ERROR_SUCCESS)
1357     {
1358       GResolverError errnum;
1359       const gchar *format;
1360
1361       if (status == DNS_ERROR_RCODE_NAME_ERROR)
1362         {
1363           errnum = G_RESOLVER_ERROR_NOT_FOUND;
1364           format = _("No DNS record of the requested type for '%s'");
1365         }
1366       else if (status == DNS_ERROR_RCODE_SERVER_FAILURE)
1367         {
1368           errnum = G_RESOLVER_ERROR_TEMPORARY_FAILURE;
1369           format = _("Temporarily unable to resolve '%s'");
1370         }
1371       else
1372         {
1373           errnum = G_RESOLVER_ERROR_INTERNAL;
1374           format = _("Error resolving '%s'");
1375         }
1376
1377       g_set_error (error, G_RESOLVER_ERROR, errnum, format, rrname);
1378       return NULL;
1379     }
1380
1381   records = NULL;
1382   for (rec = results; rec; rec = rec->pNext)
1383     {
1384       if (rec->wType != dnstype)
1385         continue;
1386       switch (dnstype)
1387         {
1388         case DNS_TYPE_SRV:
1389           record = parse_dns_srv (rec);
1390           break;
1391         case DNS_TYPE_SOA:
1392           record = parse_dns_soa (rec);
1393           break;
1394         case DNS_TYPE_NS:
1395           record = parse_dns_ns (rec);
1396           break;
1397         case DNS_TYPE_MX:
1398           record = parse_dns_mx (rec);
1399           break;
1400         case DNS_TYPE_TEXT:
1401           record = parse_dns_txt (rec);
1402           break;
1403         default:
1404           g_warn_if_reached ();
1405           record = NULL;
1406           break;
1407         }
1408       if (record != NULL)
1409         records = g_list_prepend (records, g_variant_ref_sink (record));
1410     }
1411
1412   return records;
1413 }
1414
1415 #endif