/*
 * 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 "qapi/qapi-types-sockets.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 */
