module CBSP_Adapter {

/* CBSP Adapter layer, sitting on top of CBSP_CodecPort.
 * test suites can 'inherit' in order to have a CBSP connection to the IUT which they're testing
 *
 * (C) 2018-2019 by Harald Welte <laforge@gnumonks.org>
 * All rights reserved.
 *
 * Released under the terms of GNU General Public License, Version 2 or
 * (at your option) any later version.
 */


import from Osmocom_Types all;
import from General_Types all;
import from CBSP_Types all;
import from CBSP_Templates all;
import from CBSP_CodecPort all;
import from CBSP_CodecPort_CtrlFunct all;
import from IPL4asp_Types all;
import from IPL4asp_PortType all;
import from Socket_API_Definitions all;

const integer NUM_CBSP := 3;

type component CBSP_Adapter_CT {
	/* down-facing port to CBSP Codec port */
	port CBSP_CODEC_PT CBSP[NUM_CBSP];
	var IPL4asp_Types.ConnectionId g_cbsp_conn_id[NUM_CBSP] := { -1, -1, -1 };
}

private function f_set_tcp_segmentation(integer idx) runs on CBSP_Adapter_CT {
	/* Set function for dissecting the binary stream into packets */
	var f_IPL4_getMsgLen vl_f := refers(f_IPL4_fixedMsgLen);
	/* Offset: 1, size of length: 3, delta: 4, multiplier: 1, big-endian */
	CBSP_CodecPort_CtrlFunct.f_IPL4_setGetMsgLen(CBSP[idx], g_cbsp_conn_id[idx], vl_f, {1, 3, 4, 1, 0});
}

function f_connect(charstring remote_host, IPL4asp_Types.PortNumber remote_port,
		   charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
runs on CBSP_Adapter_CT {
	var IPL4asp_Types.Result res;
	map(self:CBSP[idx], system:CBSP);
	if (g_cbsp_conn_id[idx] != -1) {
		CBSP_CodecPort_CtrlFunct.f_IPL4_close(CBSP[idx], g_cbsp_conn_id[idx], {tcp := {}});
		g_cbsp_conn_id[idx] := -1;
	}
	res := CBSP_CodecPort_CtrlFunct.f_IPL4_connect(CBSP[idx], remote_host, remote_port,
							local_host, local_port, 0, { tcp :={} });
	if (not ispresent(res.connId)) {
		setverdict(fail, "Could not connect to CBSP port, check your configuration ",
			"{remote ", remote_host, ":", remote_port, " local ", local_host, ":", local_port, "}");
		mtc.stop;
	}
	g_cbsp_conn_id[idx] := res.connId;

	f_set_tcp_segmentation(idx);
}

/* Function to use to bind to a local port as IPA server, accepting remote clients */
function f_bind(charstring local_host, IPL4asp_Types.PortNumber local_port, integer idx := 0)
runs on CBSP_Adapter_CT {
	var IPL4asp_Types.Result res;
	map(self:CBSP[idx], system:CBSP);
	if (g_cbsp_conn_id[idx] != -1) {
		CBSP_CodecPort_CtrlFunct.f_IPL4_close(CBSP[idx], g_cbsp_conn_id[idx], {tcp := {}});
		g_cbsp_conn_id[idx] := -1;
	}
	res := CBSP_CodecPort_CtrlFunct.f_IPL4_listen(CBSP[idx], local_host, local_port, { tcp:={} });
	if (not ispresent(res.connId)) {
		setverdict(fail, "Could not bind to CBSP port, check your configuration ",
			   "{local ", local_host, ":", local_port, "}");
		mtc.stop;
	}
	g_cbsp_conn_id[idx] := res.connId;

	f_set_tcp_segmentation(idx);
}

function f_cbsp_send(template (value) CBSP_PDU pdu, integer idx := 0) runs on CBSP_Adapter_CT {
	CBSP[idx].send(ts_CBSP_Send(g_cbsp_conn_id[idx], pdu));
}

function f_cbsp_exp(template CBSP_PDU exp, integer idx := 0) runs on CBSP_Adapter_CT return CBSP_PDU {
	var CBSP_RecvFrom rf;
	CBSP[idx].receive(tr_CBSP_Recv(g_cbsp_conn_id[idx], exp)) -> value rf;
	return rf.msg;
}


}
