|  | /* | 
|  | * QEMU DNS resolver | 
|  | * | 
|  | * Copyright (c) 2016-2017 Red Hat, Inc. | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | 
|  | * | 
|  | */ | 
|  |  | 
|  | #ifndef QIO_DNS_RESOLVER_H | 
|  | #define QIO_DNS_RESOLVER_H | 
|  |  | 
|  | #include "qapi/qapi-types-sockets.h" | 
|  | #include "qom/object.h" | 
|  | #include "io/task.h" | 
|  |  | 
|  | #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver" | 
|  | OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver, | 
|  | QIO_DNS_RESOLVER) | 
|  |  | 
|  |  | 
|  | /** | 
|  | * QIODNSResolver: | 
|  | * | 
|  | * The QIODNSResolver class provides a framework for doing | 
|  | * DNS resolution on SocketAddress objects, independently | 
|  | * of socket creation. | 
|  | * | 
|  | * <example> | 
|  | *   <title>Resolving addresses synchronously</title> | 
|  | *   <programlisting> | 
|  | *    int mylisten(SocketAddress *addr, Error **errp) { | 
|  | *      QIODNSResolver *resolver = qio_dns_resolver_get_instance(); | 
|  | *      SocketAddress **rawaddrs = NULL; | 
|  | *      size_t nrawaddrs = 0; | 
|  | *      Error *err = NULL; | 
|  | *      QIOChannel **socks = NULL; | 
|  | *      size_t nsocks = 0; | 
|  | * | 
|  | *      if (qio_dns_resolver_lookup_sync(dns, addr, &nrawaddrs, | 
|  | *                                       &rawaddrs, errp) < 0) { | 
|  | *          return -1; | 
|  | *      } | 
|  | * | 
|  | *      for (i = 0; i < nrawaddrs; i++) { | 
|  | *         QIOChannel *sock = qio_channel_new(); | 
|  | *         Error *local_err = NULL; | 
|  | *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err); | 
|  | *         if (local_err) { | 
|  | *            error_propagate(&err, local_err); | 
|  | *         } else { | 
|  | *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1); | 
|  | *            socks[nsocks++] = sock; | 
|  | *         } | 
|  | *         qapi_free_SocketAddress(rawaddrs[i]); | 
|  | *      } | 
|  | *      g_free(rawaddrs); | 
|  | * | 
|  | *      if (nsocks == 0) { | 
|  | *         error_propagate(errp, err); | 
|  | *      } else { | 
|  | *         error_free(err); | 
|  | *      } | 
|  | *   } | 
|  | *   </programlisting> | 
|  | * </example> | 
|  | * | 
|  | * <example> | 
|  | *   <title>Resolving addresses asynchronously</title> | 
|  | *   <programlisting> | 
|  | *    typedef struct MyListenData { | 
|  | *       Error *err; | 
|  | *       QIOChannelSocket **socks; | 
|  | *       size_t nsocks; | 
|  | *    } MyListenData; | 
|  | * | 
|  | *    void mylistenresult(QIOTask *task, void *opaque) { | 
|  | *      MyListenData *data = opaque; | 
|  | *      QIODNSResolver *resolver = | 
|  | *         QIO_DNS_RESOLVER(qio_task_get_source(task); | 
|  | *      SocketAddress **rawaddrs = NULL; | 
|  | *      size_t nrawaddrs = 0; | 
|  | *      Error *err = NULL; | 
|  | * | 
|  | *      if (qio_task_propagate_error(task, &data->err)) { | 
|  | *         return; | 
|  | *      } | 
|  | * | 
|  | *      qio_dns_resolver_lookup_result(resolver, task, | 
|  | *                                     &nrawaddrs, &rawaddrs); | 
|  | * | 
|  | *      for (i = 0; i < nrawaddrs; i++) { | 
|  | *         QIOChannel *sock = qio_channel_new(); | 
|  | *         Error *local_err = NULL; | 
|  | *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err); | 
|  | *         if (local_err) { | 
|  | *            error_propagate(&err, local_err); | 
|  | *         } else { | 
|  | *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1); | 
|  | *            socks[nsocks++] = sock; | 
|  | *         } | 
|  | *         qapi_free_SocketAddress(rawaddrs[i]); | 
|  | *      } | 
|  | *      g_free(rawaddrs); | 
|  | * | 
|  | *      if (nsocks == 0) { | 
|  | *         error_propagate(&data->err, err); | 
|  | *      } else { | 
|  | *         error_free(err); | 
|  | *      } | 
|  | *    } | 
|  | * | 
|  | *    void mylisten(SocketAddress *addr, MyListenData *data) { | 
|  | *      QIODNSResolver *resolver = qio_dns_resolver_get_instance(); | 
|  | *      qio_dns_resolver_lookup_async(dns, addr, | 
|  | *                                    mylistenresult, data, NULL); | 
|  | *    } | 
|  | *   </programlisting> | 
|  | * </example> | 
|  | */ | 
|  | struct QIODNSResolver { | 
|  | Object parent; | 
|  | }; | 
|  |  | 
|  |  | 
|  |  | 
|  | /** | 
|  | * qio_dns_resolver_get_instance: | 
|  | * | 
|  | * Get the singleton dns resolver instance. The caller | 
|  | * does not own a reference on the returned object. | 
|  | * | 
|  | * Returns: the single dns resolver instance | 
|  | */ | 
|  | QIODNSResolver *qio_dns_resolver_get_instance(void); | 
|  |  | 
|  | /** | 
|  | * qio_dns_resolver_lookup_sync: | 
|  | * @resolver: the DNS resolver instance | 
|  | * @addr: the address to resolve | 
|  | * @naddr: pointer to hold number of resolved addresses | 
|  | * @addrs: pointer to hold resolved addresses | 
|  | * @errp: pointer to NULL initialized error object | 
|  | * | 
|  | * This will attempt to resolve the address provided | 
|  | * in @addr. If resolution succeeds, @addrs will be filled | 
|  | * with all the resolved addresses. @naddrs will specify | 
|  | * the number of entries allocated in @addrs. The caller | 
|  | * is responsible for freeing each entry in @addrs, as | 
|  | * well as @addrs itself. @naddrs is guaranteed to be | 
|  | * greater than zero on success. | 
|  | * | 
|  | * DNS resolution will be done synchronously so execution | 
|  | * of the caller may be blocked for an arbitrary length | 
|  | * of time. | 
|  | * | 
|  | * Returns: 0 if resolution was successful, -1 on error | 
|  | */ | 
|  | int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver, | 
|  | SocketAddress *addr, | 
|  | size_t *naddrs, | 
|  | SocketAddress ***addrs, | 
|  | Error **errp); | 
|  |  | 
|  | /** | 
|  | * qio_dns_resolver_lookup_async: | 
|  | * @resolver: the DNS resolver instance | 
|  | * @addr: the address to resolve | 
|  | * @func: the callback to invoke on lookup completion | 
|  | * @opaque: data blob to pass to @func | 
|  | * @notify: the callback to free @opaque, or NULL | 
|  | * | 
|  | * This will attempt to resolve the address provided | 
|  | * in @addr. The callback @func will be invoked when | 
|  | * resolution has either completed or failed. On | 
|  | * success, the @func should call the method | 
|  | * qio_dns_resolver_lookup_result() to obtain the | 
|  | * results. | 
|  | * | 
|  | * DNS resolution will be done asynchronously so execution | 
|  | * of the caller will not be blocked. | 
|  | */ | 
|  | void qio_dns_resolver_lookup_async(QIODNSResolver *resolver, | 
|  | SocketAddress *addr, | 
|  | QIOTaskFunc func, | 
|  | gpointer opaque, | 
|  | GDestroyNotify notify); | 
|  |  | 
|  | /** | 
|  | * qio_dns_resolver_lookup_result: | 
|  | * @resolver: the DNS resolver instance | 
|  | * @task: the task object to get results for | 
|  | * @naddr: pointer to hold number of resolved addresses | 
|  | * @addrs: pointer to hold resolved addresses | 
|  | * | 
|  | * This method should be called from the callback passed | 
|  | * to qio_dns_resolver_lookup_async() in order to obtain | 
|  | * results.  @addrs will be filled with all the resolved | 
|  | * addresses. @naddrs will specify the number of entries | 
|  | * allocated in @addrs. The caller is responsible for | 
|  | * freeing each entry in @addrs, as well as @addrs itself. | 
|  | */ | 
|  | void qio_dns_resolver_lookup_result(QIODNSResolver *resolver, | 
|  | QIOTask *task, | 
|  | size_t *naddrs, | 
|  | SocketAddress ***addrs); | 
|  |  | 
|  | #endif /* QIO_DNS_RESOLVER_H */ |