/* GTP Hub Implementation */

/* (C) 2015 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All Rights Reserved
 *
 * gtphub_ext.c -- ext means extern. This file is kept separate so that these
 * functions can be wrapped for gtphub_test.c. When a function and its callers
 * are in the same compilational unit, the wrappability may be optimized away.
 *
 * Author: Neels Hofmeyr
 *
 * 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 <string.h>
#include <unistd.h>

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

#include <osmocom/core/utils.h>
#include <osmocom/gsm/apn.h>

/* TODO split GRX ares from sgsn into a separate struct and allow use without
 * globals. */
#include <openbsc/sgsn.h>
extern struct sgsn_instance *sgsn;

struct sgsn_instance sgsn_inst = { 0 };
struct sgsn_instance *sgsn = &sgsn_inst;

extern void *osmo_gtphub_ctx;

int gtphub_ares_init(struct gtphub *hub)
{
	return sgsn_ares_init(sgsn);
}

struct ggsn_lookup {
	struct llist_head entry;
	struct expiring_item expiry_entry;

	struct gtphub *hub;

	char imsi_str[GSM_IMSI_LENGTH];
	char apn_ni_str[GSM_APN_LENGTH];
	char apn_oi_str[GSM_APN_LENGTH];
	int have_3dig_mnc;
};

static int start_ares_query(struct ggsn_lookup *lookup);

static void ggsn_lookup_cb(void *arg, int status, int timeouts, struct hostent *hostent)
{
	struct ggsn_lookup *lookup = arg;
	LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_cb(%p / %p)", lookup, &lookup->expiry_entry);

	if (status != ARES_SUCCESS) {
		LOGP(DGTPHUB, LOGL_ERROR, "DNS query failed.\n");

		/* Need to try with three digits now */
		if (!lookup->have_3dig_mnc) {
			lookup->have_3dig_mnc = 1;
			if (start_ares_query(lookup) == 0)
				return;
		}

		LOGP(DGTPHUB, LOGL_ERROR, "Failed to resolve GGSN. (%p)\n", lookup);
		goto remove_from_queue;
	}

	struct gsn_addr resolved_addr;
	if (hostent->h_length > sizeof(resolved_addr.buf)) {
		LOGP(DGTPHUB, LOGL_ERROR, "Addr size too large: %d > %d\n",
		     (int)hostent->h_length, (int)sizeof(resolved_addr.buf));
		goto remove_from_queue;
	}

	/* Get the first addr from the list */
	char *addr0 = hostent->h_addr_list[0];
	if (!addr0) {
		LOGP(DGTPHUB, LOGL_ERROR, "No host address.\n");
		goto remove_from_queue;
	}

	memcpy(resolved_addr.buf, addr0, hostent->h_length);
	resolved_addr.len = hostent->h_length;

	LOGP(DGTPHUB, LOGL_NOTICE, "resolved addr %s\n",
	     osmo_hexdump((unsigned char*)&resolved_addr, sizeof(resolved_addr)));

	gtphub_resolved_ggsn(lookup->hub, lookup->apn_oi_str, &resolved_addr,
			     gtphub_now());

remove_from_queue:
	LOGP(DGTPHUB, LOGL_ERROR, "Removing GGSN lookup. (%p / %p)\n", lookup, &lookup->expiry_entry);
	expiring_item_del(&lookup->expiry_entry);
}

static void make_addr_str(struct ggsn_lookup *lookup)
{
	char *apn_oi_str;
	apn_oi_str = osmo_apn_qualify_from_imsi(lookup->imsi_str,
						lookup->apn_ni_str,
						lookup->have_3dig_mnc);
	strncpy(lookup->apn_oi_str, apn_oi_str, sizeof(lookup->apn_oi_str));
	lookup->apn_oi_str[sizeof(lookup->apn_oi_str)-1] = '\0';
}

static int start_ares_query(struct ggsn_lookup *lookup)
{
	LOGP(DGTPHUB, LOGL_DEBUG, "Going to query %s (%p / %p)\n", lookup->apn_oi_str, lookup, &lookup->expiry_entry);

	int rc = sgsn_ares_query(sgsn, lookup->apn_oi_str, ggsn_lookup_cb, lookup);
	if (rc != 0)
		LOGP(DGTPHUB, LOGL_ERROR, "Failed to start ares query.\n");
	return rc;
}

static void ggsn_lookup_del_cb(struct expiring_item *expi)
{
	struct ggsn_lookup *lookup;
	lookup = container_of(expi, struct ggsn_lookup, expiry_entry);

	LOGP(DGTPHUB, LOGL_NOTICE, "ggsn_lookup_del_cb(%p / %p)\n", lookup, expi);

	lookup->expiry_entry.del_cb = 0;
	expiring_item_del(expi);

	llist_del(&lookup->entry);
	talloc_free(lookup);
}

struct gtphub_peer_port *gtphub_resolve_ggsn_addr(struct gtphub *hub,
						  const char *imsi_str,
						  const char *apn_ni_str)
{
	OSMO_ASSERT(imsi_str);
	OSMO_ASSERT(apn_ni_str);

	struct ggsn_lookup *lookup = talloc_zero(osmo_gtphub_ctx, struct ggsn_lookup);
	OSMO_ASSERT(lookup);

	LOGP(DGTPHUB, LOGL_NOTICE, "Request to resolve IMSI '%s' with APN-NI '%s' (%p / %p)\n",
	     imsi_str, apn_ni_str, lookup, &lookup->expiry_entry);

	expiring_item_init(&lookup->expiry_entry);
	lookup->hub = hub;

	strncpy(lookup->imsi_str, imsi_str, sizeof(lookup->imsi_str));
	lookup->imsi_str[sizeof(lookup->imsi_str)-1] = '\0';

	strncpy(lookup->apn_ni_str, apn_ni_str, sizeof(lookup->apn_ni_str));
	lookup->apn_ni_str[sizeof(lookup->apn_ni_str)-1] = '\0';

	make_addr_str(lookup);

	LOGP(DGTPHUB, LOGL_NOTICE, "looking for active queries...\n");
	struct ggsn_lookup *active;
	llist_for_each_entry(active, &hub->ggsn_lookups, entry) {
		if (strncmp(active->apn_oi_str, lookup->apn_oi_str,
			    sizeof(lookup->apn_oi_str)) == 0) {
			/* A query already pending. Just tip our hat. */
			return NULL;
		}
	}

	LOGP(DGTPHUB, LOGL_NOTICE, "looking for already resolved GGSNs...\n");
	struct gtphub_resolved_ggsn *resolved;
	llist_for_each_entry(resolved, &hub->resolved_ggsns, entry) {
		if (strncmp(resolved->apn_oi_str, lookup->apn_oi_str,
			    sizeof(lookup->apn_oi_str)) == 0) {
			/* Already resolved. */
			return resolved->peer;
		}
	}

	/* Kick off a resolution, but so far return nothing. The hope is that
	 * the peer will resend the request (a couple of times), and by then
	 * the GGSN will be resolved. */
	LOGP(DGTPHUB, LOGL_NOTICE, "kick off resolution.\n");

	llist_add(&lookup->entry, &hub->ggsn_lookups);

	lookup->expiry_entry.del_cb = ggsn_lookup_del_cb;
	expiry_add(&hub->expire_seq_maps, &lookup->expiry_entry, gtphub_now());

	start_ares_query(lookup);
	LOGP(DGTPHUB, LOGL_NOTICE, "Resolving %s %s ..."
	     " (Returning failure, hoping for a retry"
	     "once resolution has concluded)\n",
	     imsi_str, apn_ni_str);

	return NULL;
}
