229 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			229 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * 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 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 "qemu-common.h"
 | |
| #include "qom/object.h"
 | |
| #include "io/task.h"
 | |
| 
 | |
| #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
 | |
| #define QIO_DNS_RESOLVER(obj)                                    \
 | |
|     OBJECT_CHECK(QIODNSResolver, (obj), TYPE_QIO_DNS_RESOLVER)
 | |
| #define QIO_DNS_RESOLVER_CLASS(klass)                                    \
 | |
|     OBJECT_CLASS_CHECK(QIODNSResolverClass, klass, TYPE_QIO_DNS_RESOLVER)
 | |
| #define QIO_DNS_RESOLVER_GET_CLASS(obj)                                  \
 | |
|     OBJECT_GET_CLASS(QIODNSResolverClass, obj, TYPE_QIO_DNS_RESOLVER)
 | |
| 
 | |
| typedef struct QIODNSResolver QIODNSResolver;
 | |
| typedef struct QIODNSResolverClass QIODNSResolverClass;
 | |
| 
 | |
| /**
 | |
|  * 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;
 | |
| };
 | |
| 
 | |
| struct QIODNSResolverClass {
 | |
|     ObjectClass 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 */
 |