/* 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
};

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));
	activate(as_cbsp_restart(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")) {
		tx := ts_CBSP_WRITE_CBS_COMPL(msg.msg_id, msg.ser_nr, tx_list, msg.channel_ind);
	} 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_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),
				     omit, 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;
	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_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);
		}
	}
}

}
