/*
 * (C) 2019 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
 * All Rights Reserved
 *
 * SPDX-License-Identifier: AGPL-3.0+
 *
 * 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 <osmocom/core/logging.h>

#include <osmocom/sccp/sccp_types.h>
#include <osmocom/sigtran/sccp_sap.h>
#include <osmocom/sigtran/sccp_helpers.h>

#include <osmocom/msc/debug.h>
#include <osmocom/msc/sccp_ran.h>
#include <osmocom/msc/ran_infra.h>

struct osmo_tdef g_sccp_tdefs[] = {
	{}
};

static int sccp_ran_sap_up(struct osmo_prim_hdr *oph, void *_scu);

struct sccp_ran_inst *sccp_ran_init(void *talloc_ctx, struct osmo_sccp_instance *sccp, enum osmo_sccp_ssn ssn,
				    const char *sccp_user_name, struct ran_infra *ran, void *user_data)
{
	struct sccp_ran_inst *sri = talloc(talloc_ctx, struct sccp_ran_inst);
	*sri = (struct sccp_ran_inst){
		.ran = ran,
		.sccp = sccp,
		.user_data = user_data,
	};

	INIT_LLIST_HEAD(&sri->ran_peers);
	INIT_LLIST_HEAD(&sri->ran_conns);

	osmo_sccp_local_addr_by_instance(&sri->local_sccp_addr, sccp, ssn);
	sri->scu = osmo_sccp_user_bind(sccp, sccp_user_name, sccp_ran_sap_up, ssn);
	osmo_sccp_user_set_priv(sri->scu, sri);

	OSMO_ASSERT(!ran->sri);
	ran->sri = sri;

	return sri;
}

static int sccp_ran_sap_up(struct osmo_prim_hdr *oph, void *_scu)
{
	struct osmo_sccp_user *scu = _scu;
	struct sccp_ran_inst *sri = osmo_sccp_user_get_priv(scu);
	struct osmo_scu_prim *prim = (struct osmo_scu_prim *) oph;
	struct osmo_sccp_addr *my_addr;
	struct osmo_sccp_addr *peer_addr;
	uint32_t conn_id;
	int rc;

	if (!sri->ran || !sri->ran->sccp_ran_ops.up_l2) {
		LOG_SCCP_RAN_CL(sri, NULL, LOGL_ERROR, "This RAN type is not set up\n");
		msgb_free(oph->msg);
		return -1;
	}

	switch (OSMO_PRIM_HDR(oph)) {
	case OSMO_PRIM(OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_INDICATION):
		/* indication of new inbound connection request */
		conn_id = prim->u.connect.conn_id;
		my_addr = &prim->u.connect.called_addr;
		peer_addr = &prim->u.connect.calling_addr;
		LOG_SCCP_RAN_CO(sri, peer_addr, conn_id, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_scu_prim_name(oph));

		if (!msgb_l2(oph->msg) || msgb_l2len(oph->msg) == 0) {
			LOG_SCCP_RAN_CO(sri, peer_addr, conn_id, LOGL_NOTICE, "Received invalid N-CONNECT.ind\n");
			rc = -1;
			break;
		}

		if (osmo_sccp_addr_ri_cmp(&sri->local_sccp_addr, my_addr))
			LOG_SCCP_RAN_CO(sri, NULL, conn_id, LOGL_INFO,
					"Called address is %s which is not the locally configured address\n",
					osmo_sccp_inst_addr_name(sri->sccp, my_addr));

		/* ensure the local SCCP socket is ACTIVE */
		osmo_sccp_tx_conn_resp(scu, conn_id, my_addr, NULL, 0);

		rc = sri->ran->sccp_ran_ops.up_l2(sri, peer_addr, true, conn_id, oph->msg);
		if (rc)
			osmo_sccp_tx_disconn(scu, conn_id, my_addr, SCCP_RETURN_CAUSE_UNQUALIFIED);
		break;

	case OSMO_PRIM(OSMO_SCU_PRIM_N_DATA, PRIM_OP_INDICATION):
		/* connection-oriented data received */
		conn_id = prim->u.data.conn_id;
		LOG_SCCP_RAN_CO(sri, NULL, conn_id, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_scu_prim_name(oph));

		rc = sri->ran->sccp_ran_ops.up_l2(sri, NULL, true, conn_id, oph->msg);
		break;

	case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION):
		/* indication of disconnect */
		conn_id = prim->u.disconnect.conn_id;
		LOG_SCCP_RAN_CO(sri, NULL, conn_id, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_scu_prim_name(oph));

		/* If there is no L2 payload in the N-DISCONNECT, no need to dispatch up_l2(). */
		if (msgb_l2len(oph->msg))
			rc = sri->ran->sccp_ran_ops.up_l2(sri, NULL, true, conn_id, oph->msg);
		else
			rc = 0;

		/* Make sure the ran_conn is dropped. It might seem more optimal to combine the disconnect() into
		 * up_l2(), but since an up_l2() dispatch might already cause the ran_conn to be discarded for other
		 * reasons, a separate disconnect() with a separate conn_id lookup is actually necessary. */
		sri->ran->sccp_ran_ops.disconnect(sri, conn_id);
		break;

	case OSMO_PRIM(OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_INDICATION):
		/* connection-less data received */
		my_addr = &prim->u.unitdata.called_addr;
		peer_addr = &prim->u.unitdata.calling_addr;
		LOG_SCCP_RAN_CL(sri, peer_addr, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_scu_prim_name(oph));

		if (osmo_sccp_addr_ri_cmp(&sri->local_sccp_addr, my_addr))
			LOG_SCCP_RAN_CL(sri, NULL, LOGL_INFO,
					"Called address is %s which is not the locally configured address\n",
					osmo_sccp_inst_addr_name(sri->sccp, my_addr));

		rc = sri->ran->sccp_ran_ops.up_l2(sri, peer_addr, false, 0, oph->msg);
		break;

	default:
		LOG_SCCP_RAN_CL(sri, NULL, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_scu_prim_name(oph));
		rc = -1;
		break;
	}

	msgb_free(oph->msg);
	return rc;
}

/* Push some padding if necessary to reach a multiple-of-eight offset to be msgb_push() an osmo_scu_prim that will then
 * be 8-byte aligned. */
static void msgb_pad_mod8(struct msgb *msg)
{
	uint8_t mod8 = (intptr_t)(msg->data) % 8;
	if (mod8)
		msgb_push(msg, mod8);
}

int sccp_ran_down_l2_co_initial(struct sccp_ran_inst *sri,
				const struct osmo_sccp_addr *called_addr,
				uint32_t conn_id, struct msgb *l2)
{
	struct osmo_scu_prim *prim;

	l2->l2h = l2->data;

	msgb_pad_mod8(l2);
	prim = (struct osmo_scu_prim *) msgb_push(l2, sizeof(*prim));
	prim->u.connect = (struct osmo_scu_connect_param){
		.called_addr = *called_addr,
		.calling_addr = sri->local_sccp_addr,
		.sccp_class = 2,
		//.importance = ?,
		.conn_id = conn_id,
	};
	osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_CONNECT, PRIM_OP_REQUEST, l2);
	return osmo_sccp_user_sap_down_nofree(sri->scu, &prim->oph);
}

int sccp_ran_down_l2_co(struct sccp_ran_inst *sri, uint32_t conn_id, struct msgb *l2)
{
	struct osmo_scu_prim *prim;

	l2->l2h = l2->data;

	msgb_pad_mod8(l2);
	prim = (struct osmo_scu_prim *) msgb_push(l2, sizeof(*prim));
	prim->u.data.conn_id = conn_id;
	osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_DATA, PRIM_OP_REQUEST, l2);
	return osmo_sccp_user_sap_down_nofree(sri->scu, &prim->oph);
}

int sccp_ran_down_l2_cl(struct sccp_ran_inst *sri, const struct osmo_sccp_addr *called_addr, struct msgb *l2)
{
	struct osmo_scu_prim *prim;

	l2->l2h = l2->data;

	msgb_pad_mod8(l2);
	prim = (struct osmo_scu_prim *) msgb_push(l2, sizeof(*prim));
	prim->u.unitdata = (struct osmo_scu_unitdata_param){
		.called_addr = *called_addr,
		.calling_addr = sri->local_sccp_addr,
	};
	osmo_prim_init(&prim->oph, SCCP_SAP_USER, OSMO_SCU_PRIM_N_UNITDATA, PRIM_OP_REQUEST, l2);
	return osmo_sccp_user_sap_down_nofree(sri->scu, &prim->oph);
}

int sccp_ran_disconnect(struct sccp_ran_inst *sri, uint32_t conn_id, uint32_t cause)
{
	return osmo_sccp_tx_disconn(sri->scu, conn_id, NULL, cause);
}
