/* Mapper between RUA ContextID (24 bit, per HNB) and the SUA/SCCP
 * Connection ID (32bit, per signalling link) */

/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
 * 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/>.
 *
 */

/* an expired mapping is destroyed  after 1..2 * EXPIRY_TIMER_SECS */
#define EXPIRY_TIMER_SECS	23

#include <osmocom/core/timer.h>

#include <osmocom/iuh/hnbgw.h>
#include <osmocom/iuh/context_map.h>

const struct value_string hnbgw_context_map_state_names[] = {
	{MAP_S_NULL     , "not-initialized"},
	{MAP_S_ACTIVE   , "active"},
	{MAP_S_RESERVED1, "inactive-reserved"},
	{MAP_S_RESERVED2, "inactive-discard"},
	{0, NULL}
};

/* is a given SCCP USER SAP Connection ID in use for a given CN link? */
static int cn_id_in_use(struct hnbgw_cnlink *cn, uint32_t id)
{
	struct hnbgw_context_map *map;

	llist_for_each_entry(map, &cn->map_list, cn_list) {
		if (map->scu_conn_id == id)
			return 1;
	}
	return 0;
}

/* try to allocate a new SCCP User SAP Connection ID */
static int alloc_cn_conn_id(struct hnbgw_cnlink *cn, uint32_t *id_out)
{
	uint32_t i;
	uint32_t id;

	for (i = 0; i < 0xffffffff; i++) {
		id = cn->next_conn_id++;
		if (!cn_id_in_use(cn, id)) {
			*id_out = id;
			return 1;
		}
	}
	return -1;
}

/* Map from a HNB + ContextID to the SCCP-side Connection ID */
struct hnbgw_context_map *
context_map_alloc_by_hnb(struct hnb_context *hnb, uint32_t rua_ctx_id,
			 bool is_ps,
			 struct hnbgw_cnlink *cn_if_new)
{
	struct hnbgw_context_map *map;
	uint32_t new_scu_conn_id;

	llist_for_each_entry(map, &hnb->map_list, hnb_list) {
		if (map->state != MAP_S_ACTIVE)
			continue;
		if (map->cn_link != cn_if_new) {
			continue;
		}
		if (map->rua_ctx_id == rua_ctx_id
		    && map->is_ps == is_ps) {
			return map;
		}
	}

	if (alloc_cn_conn_id(cn_if_new, &new_scu_conn_id) < 0) {
		LOGHNB(hnb, DMAIN, LOGL_ERROR, "Unable to allocate CN connection ID\n");
		return NULL;
	}

	LOGHNB(hnb, DMAIN, LOGL_INFO, "Creating new Mapping RUA CTX %p/%u <-> SCU Conn ID %p/%u\n",
		hnb, rua_ctx_id, cn_if_new, new_scu_conn_id);

	/* alloate a new map entry */
	map = talloc_zero(hnb, struct hnbgw_context_map);
	map->state = MAP_S_NULL;
	map->cn_link = cn_if_new;
	map->hnb_ctx = hnb;
	map->rua_ctx_id = rua_ctx_id;
	map->is_ps = is_ps;
	map->scu_conn_id = new_scu_conn_id;

	/* put it into both lists */
	llist_add_tail(&map->hnb_list, &hnb->map_list);
	llist_add_tail(&map->cn_list, &cn_if_new->map_list);
	map->state = MAP_S_ACTIVE;

	return map;
}

/* Map from a CN + Connection ID to HNB + Context ID */
struct hnbgw_context_map *
context_map_by_cn(struct hnbgw_cnlink *cn, uint32_t scu_conn_id)
{
	struct hnbgw_context_map *map;

	llist_for_each_entry(map, &cn->map_list, cn_list) {
		if (map->state != MAP_S_ACTIVE)
			continue;
		if (map->scu_conn_id == scu_conn_id) {
			return map;
		}
	}
	/* we don't allocate new mappings in the CN->HNB
	 * direction, as the RUA=SCCP=SUA connections are always
	 * established from HNB towards CN. */
	LOGP(DMAIN, LOGL_NOTICE, "Unable to resolve map for CN " "connection ID %p/%u\n", cn, scu_conn_id);
	return NULL;
}

void context_map_deactivate(struct hnbgw_context_map *map)
{
	/* set the state to reserved. We still show up in the list and
	 * avoid re-allocation of the context-id until we are cleaned up
	 * by the context_map garbage collector timer */

	if (map->state != MAP_S_RESERVED2)
		map->state = MAP_S_RESERVED1;
}

static struct osmo_timer_list context_map_tmr;

static void context_map_tmr_cb(void *data)
{
	struct hnb_gw *gw = data;
	struct hnbgw_cnlink *cn = gw->sccp.cnlink;
	struct hnbgw_context_map *map, *next_map;

	DEBUGP(DMAIN, "Running context mapper garbage collection\n");
	llist_for_each_entry_safe(map, next_map, &cn->map_list, cn_list) {
		switch (map->state) {
		case MAP_S_RESERVED1:
			/* first time we see this reserved
			 * entry: mark it for stage 2 */
			map->state = MAP_S_RESERVED2;
			break;
		case MAP_S_RESERVED2:
			/* second time we see this reserved
			 * entry: remove it */
			map->state = MAP_S_NULL;
			llist_del(&map->cn_list);
			llist_del(&map->hnb_list);
			talloc_free(map);
			break;
		default:
			break;
		}
	}
	/* re-schedule this timer */
	osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0);
}

int context_map_init(struct hnb_gw *gw)
{
	context_map_tmr.cb = context_map_tmr_cb;
	context_map_tmr.data = gw;
	osmo_timer_schedule(&context_map_tmr, EXPIRY_TIMER_SECS, 0);

	return 0;
}
