/* C-ARES DNS resolver integration */

/*
 * (C) 2015 by Holger Hans Peter Freyther
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <openbsc/sgsn.h>
#include <openbsc/debug.h>

#include <netdb.h>

struct cares_event_fd {
	struct llist_head head;
	struct osmo_fd fd;
};

struct cares_cb_data {
	ares_host_callback cb;
	void *data;
};

static void osmo_ares_reschedule(struct sgsn_instance *sgsn);
static void ares_cb(void *_arg, int status, int timeouts, struct hostent *hostent)
{
	struct cares_cb_data *arg = _arg;

	arg->cb(arg->data, status, timeouts, hostent);
	osmo_ares_reschedule(sgsn);
	talloc_free(arg);
}

static int ares_osmo_fd_cb(struct osmo_fd *fd, unsigned int what)
{
	LOGP(DGPRS, LOGL_DEBUG, "C-ares fd(%d) ready(%d)\n", fd->fd, what);

	ares_process_fd(sgsn->ares_channel,
			(what & BSC_FD_READ) ? fd->fd : ARES_SOCKET_BAD,
			(what & BSC_FD_WRITE) ? fd->fd : ARES_SOCKET_BAD);
	osmo_ares_reschedule(sgsn);
	return 0;
}

static void ares_timeout_cb(void *data)
{
	struct sgsn_instance *sgsn = data;

	LOGP(DGPRS, LOGL_DEBUG, "C-ares triggering timeout\n");
	ares_process_fd(sgsn->ares_channel, ARES_SOCKET_BAD, ARES_SOCKET_BAD);
	osmo_ares_reschedule(sgsn);
}

static void osmo_ares_reschedule(struct sgsn_instance *sgsn)
{
	struct timeval *timeout, tv;

	osmo_timer_del(&sgsn->ares_timer);
	timeout = ares_timeout(sgsn->ares_channel, NULL, &tv);
	if (timeout) {
		sgsn->ares_timer.cb = ares_timeout_cb;
		sgsn->ares_timer.data = sgsn;

		LOGP(DGPRS, LOGL_DEBUG, "C-ares scheduling timeout %llu.%llu\n",
			(unsigned long long) tv.tv_sec,
			(unsigned long long) tv.tv_usec);
		osmo_timer_schedule(&sgsn->ares_timer, tv.tv_sec, tv.tv_usec);
	}
}

static void setup_ares_osmo_fd(void *data, int fd, int read, int write)
{
	struct cares_event_fd *ufd, *tmp;

	/* delete the entry */
	if (read == 0 && write == 0) {
		llist_for_each_entry_safe(ufd, tmp, &sgsn->ares_fds, head) {
			if (ufd->fd.fd != fd)
				continue;

			LOGP(DGPRS, LOGL_DEBUG,
				"Removing C-ares watched fd (%d)\n", fd);
			osmo_fd_unregister(&ufd->fd);
			llist_del(&ufd->head);
			talloc_free(ufd);
			return;
		}
	}

	/* Search for the fd or create a new one */
	llist_for_each_entry(ufd, &sgsn->ares_fds, head) {
		if (ufd->fd.fd != fd)
			continue;

		LOGP(DGPRS, LOGL_DEBUG, "Updating C-ares fd (%d)\n", fd);
		goto update_fd;
	}

	LOGP(DGPRS, LOGL_DEBUG, "Registering C-ares fd (%d)\n", fd);
	ufd = talloc_zero(tall_bsc_ctx, struct cares_event_fd);
	ufd->fd.fd = fd;
	ufd->fd.cb = ares_osmo_fd_cb;
	ufd->fd.data = data;
	if (osmo_fd_register(&ufd->fd) != 0)
		LOGP(DGPRS, LOGL_ERROR, "Failed to register C-ares fd (%d)\n", fd);
	llist_add(&ufd->head, &sgsn->ares_fds);

update_fd:
	if (read)
		ufd->fd.when |= BSC_FD_READ;
	else
		ufd->fd.when &= ~BSC_FD_READ;

	if (write)
		ufd->fd.when |= BSC_FD_WRITE;
	else
		ufd->fd.when &= ~BSC_FD_WRITE;

	osmo_ares_reschedule(sgsn);
}

int sgsn_ares_query(struct sgsn_instance *sgsn, const char *name,
			ares_host_callback cb, void *data)
{
	struct cares_cb_data *cb_data;

	cb_data = talloc_zero(tall_bsc_ctx, struct cares_cb_data);
	cb_data->cb = cb;
	cb_data->data = data;
	ares_gethostbyname(sgsn->ares_channel, name, AF_INET, ares_cb, cb_data);
	osmo_ares_reschedule(sgsn);
	return 0;
}

int sgsn_ares_init(struct sgsn_instance *sgsn)
{
	struct ares_options options;
	int optmask;
	int rc;

	INIT_LLIST_HEAD(&sgsn->ares_fds);
	memset(&options, 0, sizeof(options));
	options.sock_state_cb = setup_ares_osmo_fd;
	options.sock_state_cb_data = sgsn;

	optmask = ARES_OPT_FLAGS | ARES_OPT_SOCK_STATE_CB | ARES_OPT_DOMAINS;

	if (sgsn->ares_servers)
		optmask |= ARES_OPT_SERVERS;

	ares_library_init(ARES_LIB_INIT_ALL);
	rc = ares_init_options(&sgsn->ares_channel, &options, optmask);
	if (rc != ARES_SUCCESS)
		return rc;

	if (sgsn->ares_servers)
		rc = ares_set_servers(sgsn->ares_channel, sgsn->ares_servers);

	return rc;
}

osmo_static_assert(ARES_SUCCESS == 0, ares_success_zero);
