/* (C) 2019 by Harald Welte <laforge@gnumonks.org>
 * All Rights Reserved
 *
 * The idea is that these tests are executed against sccp_demo_user from
 * libosmo-sccp.git in server mode.
 *
 * 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 SCCP_Tests_RAW {

import from General_Types all;
import from Osmocom_Types all;

import from M3UA_Emulation all;

import from SCCP_Types all;
import from SCCPasp_Types all;
import from SCCP_Templates all;
import from SCCP_Emulation all;
import from SCCP_CodecPort all;

import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;

import from SCCP_Tests all;

type component SCCP_Test_RAW_CT {
	/* VTY to sccp_demo_user (not used yet) */
	port TELNETasp_PT SCCP_DEMO_USER_VTY;

	/* SCCP raw port runs on top of M3UA Emulation.
	 * "System Under Test" is libosmo-sccp's sccp_demo_user example program. */
	var M3UA_CT vc_M3UA;
	port SCCP_CODEC_PT MTP3;

	var MSC_SCCP_MTP3_parameters g_param;

	/*Configure T(tias) over VTY, seconds */
	var integer g_demo_sccp_timer_ias :=  7 * 60;
	/*Configure T(tiar) over VTY, seconds */
	var integer g_demo_sccp_timer_iar := 15 * 60;
}

type record of charstring Commands;
private function f_cs7_inst_0_cfg(TELNETasp_PT pt, Commands cmds := {})
{
	f_vty_enter_cfg_cs7_inst(pt, 0);
	for (var integer i := 0; i < sizeof(cmds); i := i+1) {
		f_vty_transceive(pt, cmds[i]);
	}
	f_vty_transceive(pt, "end");
}

function f_init_vty() runs on SCCP_Test_RAW_CT {
	if (SCCP_DEMO_USER_VTY.checkstate("Mapped")) {
		/* skip initialization if already executed once */
		return;
	}
	map(self:SCCP_DEMO_USER_VTY, system:SCCP_DEMO_USER_VTY);
	f_vty_set_prompts(SCCP_DEMO_USER_VTY);
	f_vty_transceive(SCCP_DEMO_USER_VTY, "enable");
	f_cs7_inst_0_cfg(SCCP_DEMO_USER_VTY, {"sccp-timer ias " & int2str(g_demo_sccp_timer_ias),
			  "sccp-timer iar " & int2str(g_demo_sccp_timer_iar)});
}

private function f_init_raw(SCCP_Configuration cfg) runs on SCCP_Test_RAW_CT {
	g_param := {
		sio := {
			ni := substr(oct2bit(cfg.sio),0,2),
			prio := substr(oct2bit(cfg.sio),2,2),
			si := substr(oct2bit(cfg.sio),4,4)
		},
		opc := cfg.own_pc,
		dpc := cfg.peer_pc,
		sls := 0,
		sccp_serviceType := cfg.sccp_service_type,
		ssn := cfg.own_ssn
	};

	f_init_vty();

	/* Create and connect test components */
	vc_M3UA := M3UA_CT.create;
	connect(self:MTP3, vc_M3UA:MTP3_SP_PORT);
	map(vc_M3UA:SCTP_PORT, system:sctp);

	vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr));
}

private function f_cleanup() runs on SCCP_Test_RAW_CT {
	all component.stop;
	unmap(vc_M3UA:SCTP_PORT, system:sctp);
	disconnect(vc_M3UA:MTP3_SP_PORT, self:MTP3);
	self.stop
}

private function f_send_sccp(template PDU_SCCP sccp) runs on SCCP_Test_RAW_CT {
	var SCCP_MTP3_TRANSFERreq tx := {
		sio := g_param.sio,
		opc := g_param.opc,
		dpc := g_param.dpc,
		sls := g_param.sls,
		data := valueof(sccp)
	};
	MTP3.send(tx);
}

private function f_exp_sccp(template PDU_SCCP sccp) runs on SCCP_Test_RAW_CT {
	var SCCP_MTP3_TRANSFERind rx;
	var template SCCP_MTP3_TRANSFERind exp := {
		sio := g_param.sio,
		opc := g_param.dpc,
		dpc := g_param.opc,
		sls := g_param.sls,
		data := sccp
	};
	timer T := 10.0;
	T.start;
	alt {
	[] MTP3.receive(exp) -> value rx {
		setverdict(pass);
		}
	[] MTP3.receive {
		setverdict(fail, "Unexpected MTP/SCCP received");
		self.stop
		}
	[] T.timeout {
		setverdict(fail, "Timeout waiting for ", exp);
		self.stop
		}
	}
}

private function f_establish_conn(SCCP_PAR_Address calling, SCCP_PAR_Address called) runs on SCCP_Test_RAW_CT {

	f_send_sccp(ts_SCCP_CR('000001'O, calling, called));
	f_exp_sccp(tr_SCCP_CC('000000'O, '000001'O));
}

private function f_tx_udt_exp(SCCP_PAR_Address calling, SCCP_PAR_Address called, octetstring data) runs on SCCP_Test_RAW_CT {

	f_send_sccp(ts_SCCP_UDT(calling, called, data));
	f_exp_sccp(tr_SCCP_UDT(called, calling, data));
}

/* Verify sccp_demo_user answers a CR with a CC for PC and SSN set up to echo back */
testcase TC_cr_cc() runs on SCCP_Test_RAW_CT {
	var SCCP_PAR_Address calling, called;

	f_init_raw(mp_sccp_cfg[0]);
	f_sleep(1.0);

	called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
	calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
	f_establish_conn(calling, called);
}

/* Verify sccp_demo_user answers a CR with a CC for PC and SSN set up to echo back */
testcase TC_udt_without_cr_cc() runs on SCCP_Test_RAW_CT {
	var SCCP_PAR_Address calling, called;
	var octetstring data := f_rnd_octstring(f_rnd_int(100));

	f_init_raw(mp_sccp_cfg[0]);
	f_sleep(1.0);

	called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
	calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));

	f_tx_udt_exp(calling, called, data);
}

/* Verify T(iar) triggers and releases the channel */
testcase TC_tiar_timeout() runs on SCCP_Test_RAW_CT {
	var SCCP_PAR_Address calling, called;
	var octetstring data := f_rnd_octstring(f_rnd_int(100));

	/* Set T(iar) in sccp_demo_user low enough that it will trigger before other side
	   has time to keep alive with a T(ias). Keep recommended ratio of
	   T(iar) >= T(ias)*2 */
	g_demo_sccp_timer_ias := 2;
	g_demo_sccp_timer_iar := 5;
	f_init_raw(mp_sccp_cfg[0]);
	f_sleep(1.0);

	called := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].peer_pc, mp_sccp_cfg[0].peer_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
	calling := valueof(ts_SccpAddr_PC_SSN(mp_sccp_cfg[0].own_pc, mp_sccp_cfg[0].own_ssn,
					     mp_sccp_cfg[0].sio, mp_sccp_cfg[0].sccp_service_type));
	f_establish_conn(calling, called);
	f_tx_udt_exp(calling, called, data);

	log("Waiting for first IT");
	f_exp_sccp(tr_SCCP_IT(?, ?));
	log("Waiting for second IT");
	f_exp_sccp(tr_SCCP_IT(?, ?));

	log("Waiting for RLSD");
	f_exp_sccp(tr_SCCP_RLSD(?, ?, hex2int('0D'H))); /* Cause: Expiration of Rx Inactivity Timer */
	f_send_sccp(ts_SCCP_RLC('000001'O, '000000'O));
}

control {
	execute( TC_cr_cc() );
	execute( TC_udt_without_cr_cc() );
	execute( TC_tiar_timeout() );
}


}
