/* BSC (CBSP) Connection Handler of CBC test suite in TTCN-3
 * (C) 2022 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de>
 * All rights reserved.
 *
 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

module BSC_ConnectionHandler {

import from Osmocom_Types all;

import from BSSAP_Types all;
import from BSSMAP_Templates all;
import from CBSP_Types all;
import from CBSP_Templates all;
import from CBSP_Adapter all;
import from CBSP_CodecPort all;

import from CBS_Message all;

type function void_fn() runs on BSC_ConnHdlr;

/* Coordinate with test_CT: */
type port BSC_ConnHdlr_Coord_PT message {
	inout charstring;
} with { extension "internal" };

/* this component represents a single subscriber connection */
type component BSC_ConnHdlr extends CBSP_Adapter_CT {
	var BSC_ConnHdlrPars g_pars;
	port BSC_ConnHdlr_Coord_PT COORD;
}

type record BSC_ConnHdlrPars {
	charstring bsc_host,
	integer bsc_cbsp_port,
	charstring cbc_host,
	integer cbc_cbsp_port,
	boolean tcp_is_client,
	void_fn start_fn,
	CBS_Message exp_cbs_msg optional,
	BSSMAP_FIELD_CellIdentificationList cell_list_success optional,
	CBSP_FailureListItems tx_fail_list optional
};

function f_BSC_ConnHdlr_main(charstring id, BSC_ConnHdlrPars pars) runs on BSC_ConnHdlr {
	g_pars := pars;
	if (g_pars.tcp_is_client) {
		CBSP_Adapter.f_connect(g_pars.cbc_host, g_pars.cbc_cbsp_port,
					g_pars.bsc_host, g_pars.bsc_cbsp_port);
	} else {
		CBSP_Adapter.f_bind(g_pars.bsc_host, g_pars.bsc_cbsp_port);
		CBSP_Adapter.f_wait_client_connect();
	}

	var BSSMAP_FIELD_CellIdentificationList cell_list := {
		cIl_allInBSS := ''O
	};
	activate(as_cbsp_keepalive_ack(0));
	f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_CBS, CBSP_RI_DATA_LOST));
	f_cbsp_send(ts_CBSP_RESTART(cell_list, CBSP_BC_MSGT_EMERG, CBSP_RI_DATA_LOST));
	as_cbsp_reset(0);
	COORD.send(COORD_MSG_CONNECTED);

	g_pars.start_fn.apply();
}

altstep as_cbsp_reset(integer idx) runs on CBSP_Adapter_CT {
	var CBSP_RecvFrom rf;
	[] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_RESET)) -> value rf {
		var CBSP_IE ie;
		f_cbsp_find_ie(rf.msg, CBSP_IEI_CELL_LIST, ie);
		CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx],
				ts_CBSP_RESET_COMPL(ie.body.cell_list.cell_id)));
	}
}

/* receive + acknowledge KEEP-ALIVE */
altstep as_cbsp_keepalive_ack(integer idx) runs on CBSP_Adapter_CT {
	[] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_KEEP_ALIVE)) {
		CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], ts_CBSP_KEEP_ALIVE_COMPL));
	}
}

/* receive + ignore RESTART */
altstep as_cbsp_restart(integer idx) runs on CBSP_Adapter_CT {
	[] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], tr_CBSP_RESTART));
}

function f_cbsp_tx_write_compl(CBS_Message msg, integer idx := 0,
			      template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
			      template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit)
runs on BSC_ConnHdlr {
	var template (value) CBSP_PDU tx;
	var template (value) BSSMAP_FIELD_CellIdentificationList tx_list;
	if (istemplatekind(tx_cell_list, "omit")) {
		/* use the "expected list" when confirming the write-replace */
		tx_list := msg.cell_list;
	} else {
		/* use an user-provided different list of cells */
		tx_list := valueof(tx_cell_list);
	}
	if (istemplatekind(tx_compl_list, "omit")) {
		if (msg_id_is_etws(msg.msg_id)) {
			tx := ts_CBSP_WRITE_EMERG_COMPL(msg.msg_id, msg.ser_nr, tx_list);
		} else {
			tx := ts_CBSP_WRITE_CBS_COMPL(msg.msg_id, msg.ser_nr, tx_list, msg.channel_ind);
		}
	} else {
		if (msg_id_is_etws(msg.msg_id)) {
			tx := ts_CBSP_REPLACE_EMERG_COMPL(msg.msg_id, msg.ser_nr, msg.old_ser_nr,
							  tx_list);
		} else {
			tx := ts_CBSP_REPLACE_CBS_COMPL(msg.msg_id, msg.ser_nr, msg.old_ser_nr,
							valueof(tx_compl_list), tx_list,
							msg.channel_ind);
		}
	}
	CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
}

function f_cbsp_tx_write_fail(CBS_Message msg, integer idx := 0,
				      template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
				      template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit,
				      template (omit) CBSP_FailureListItems tx_fail_list := omit)
runs on BSC_ConnHdlr {
	var template (value) CBSP_PDU tx;
	tx := ts_CBSP_WRITE_CBS_FAIL(msg.msg_id, msg.ser_nr, valueof(tx_fail_list),
				     tx_compl_list, tx_cell_list, msg.channel_ind);
	CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
}

/* handle a CBSP-WRITE-REPLACE and respond to it with COMPLETE or FAILURE depending on arguments */
function f_cbsp_handle_write(CBS_Message msg, integer idx := 0,
			      template (omit) BSSMAP_FIELD_CellIdentificationList tx_cell_list := omit,
			      template (omit) CBSP_FailureListItems tx_fail_list := omit,
			      template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit)
runs on BSC_ConnHdlr {
	var template CBSP_IEs content_ies := {};
	var template (present) CBSP_PDU rx_templ;
	var CBSP_RecvFrom rf;
	if (msg_id_is_etws(msg.msg_id)) {
		rx_templ := tr_CBSP_WRITE_EMERG(msg.msg_id, msg.ser_nr, msg.cell_list, 1,
						hex2int('180'H) + (msg.msg_id - 4352),
						msg.num_bcast_req, 0)
	} else {
		for (var integer i := 0; i < lengthof(msg.content); i := i+1) {
			//content_ies[i] := tr_CbspMsgContent(msg.content[i].payload, msg.content[i].user_len);
			content_ies[i] := tr_CbspMsgContent(?, ?);
		}
		rx_templ := tr_CBSP_WRITE_CBS(msg.msg_id, msg.ser_nr, msg.cell_list, msg.channel_ind,
					      msg.category, msg.rep_period, msg.num_bcast_req, msg.dcs,
					      content_ies);
	}
	alt {
	[] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], rx_templ)) -> value rf {
		var template (value) CBSP_PDU tx;
		if (istemplatekind(tx_fail_list, "omit")) {
			f_cbsp_tx_write_compl(msg, idx, tx_cell_list, tx_compl_list);
		} else {
			f_cbsp_tx_write_fail(msg, idx, tx_cell_list, tx_compl_list, tx_fail_list);
		}
		}
	[] as_cbsp_keepalive_ack(idx) { repeat; }
	[] CBSP[idx].receive {
		setverdict(fail, "Received unexpected CBSP in index ", idx);
		}
	}
}

/* handle a CBSP-KILL and respond to it with COMPLETE or FAILURE depending on arguments */
function f_cbsp_handle_kill(integer idx, uint16_t msg_id, uint16_t ser_nr,
				    template BSSMAP_FIELD_CellIdentificationList exp_list,
				    template (omit) BSSMAP_FIELD_CellIdentificationList tx_list,
				    template (omit) CBSP_FailureListItems tx_fail_list := omit,
				    template (omit) CBSP_IE_NumBcastComplList tx_compl_list := omit,
				    template (omit) uint8_t channel_ind := omit)
runs on BSC_ConnHdlr {
	var template (present) CBSP_PDU rx_templ;
	var CBSP_RecvFrom rf;

	rx_templ := tr_CBSP_KILL(msg_id, ser_nr, exp_list, channel_ind);
	alt {
	[] CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], rx_templ)) -> value rf {
		var template (value) CBSP_PDU tx;
		if (istemplatekind(tx_fail_list, "omit")) {
			tx := ts_CBSP_KILL_COMPL(msg_id, ser_nr, tx_compl_list, tx_list, channel_ind);
		} else {
			tx := ts_CBSP_KILL_FAIL(msg_id, ser_nr, valueof(tx_fail_list), tx_compl_list,
						tx_list, channel_ind);
		}
		CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], tx));
		}
	[] as_cbsp_keepalive_ack(idx) { repeat; }
	[] CBSP[idx].receive {
		setverdict(fail, "Received unexpected CBSP in index ", idx);
		}
	}
}

}
