module Asterisk_Tests {

/* Asterisk test suite in TTCN-3
 * (C) 2024 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
 */

import from TCCOpenSecurity_Functions all;
import from General_Types all;
import from Osmocom_Types all;
import from Native_Functions all;
import from Misc_Helpers all;
import from TELNETasp_PortType all;
import from AMI_Functions all;

import from SDP_Types all;
import from SDP_Templates all;

import from SIP_Emulation all;
import from SIPmsg_Types all;
import from SIP_Templates all;

import from SIP_ConnectionHandler all;
import from IMS_ConnectionHandler all;

modulepar {
	charstring mp_local_sip_host := "127.0.0.2";
	integer mp_local_sip_port := 5060;
	charstring mp_remote_sip_host := "127.0.0.1";
	integer mp_remote_sip_port := 5060;

	charstring mp_local_ims_host := "127.0.0.3";
	integer mp_local_ims_port := 5060;
	charstring mp_ims_imsi := "238010000090828";

	/* Asterisk AMI: */
	charstring mp_ami_remote_host := "127.0.0.1";
	integer mp_ami_remote_port := 5038;
	charstring mp_ami_local_host := "0.0.0.0";
	integer mp_ami_local_port := 0;
	charstring mp_ami_user := "test_user";
	charstring mp_ami_secret := "1234";
	charstring mp_volte_ims_outbound_registration := "volte_ims";
}

type component test_CT {
	/* Manages all local VoIP users Asterisk is serving: */
	var SIP_Emulation_CT vc_SIP;
	/* Manages the IMS server Asterisk connects to: */
	var SIP_Emulation_CT vc_IMS;

	/* Connection towards Asterisk AMI iface: */
	var AMI_Adapter_CT vc_AMI;
	port AMI_Msg_PT AMI_CLIENT;

	port Coord_PT COORD;
	port IMSCoord_PT IMS_COORD;
}

const charstring broadcast_sip_extension := "0500";

/* TODO: need to find correct RES, CK, IK, values for:
 * Response: "a19de225d030e6e0ec20f6de5f9dd80d"
 * CNonce Value: "9a6460bcc3c84a3eac69455a93b67a77"
 */
const charstring c_auth_res := "a19de225d030e6e0";
const charstring c_auth_ck := "9a6460bcc3c84a3eac69455a93b67a77";
const charstring c_auth_ik := "5238297dfcca759bd05d48ff49bc63fa";

function f_init_ConnHdlrPars(integer idx := 1) runs on test_CT return SIPConnHdlrPars {
	var template (value) CallPars cp := t_CallPars(mp_local_sip_host, 1234 + 2*idx);
	var template (value) SIPConnHdlrPars pars := t_Pars(mp_local_sip_host,
							    mp_local_sip_port,
							    mp_remote_sip_host,
							    mp_remote_sip_port,
							    "0" & int2str(str2int(broadcast_sip_extension) + idx),
							    cp := cp);
	return valueof(pars);
}

function f_init_IMS_ConnHdlrPars(integer idx := 1) runs on test_CT return IMS_ConnHdlrPars {
	var template (value) IMS_CallPars cp := t_IMS_CallPars(mp_local_sip_host, 1234 + 2*idx);
	var template (value) IMS_ConnHdlrPars pars := t_IMS_Pars(mp_local_ims_host,
								 mp_local_ims_port,
								 mp_ims_imsi,
								 cp := cp);
	return valueof(pars);
}

/* Initialize connection towards Asterisk AMI */
private function f_init_ami() runs on test_CT {
	var charstring id := "Asterisk_Tests_AMI_EMU";
	vc_AMI := AMI_Adapter_CT.create(id) alive;
	connect(self:AMI_CLIENT, vc_AMI:CLIENT);

	var AMI_Adapter_Parameters ami_pars := {
		remote_host := mp_ami_remote_host,
		remote_port := mp_ami_remote_port,
		local_host := mp_ami_local_host,
		local_port := mp_ami_local_port,
		welcome_str := c_default_AMI_Adapter_pars.welcome_str
	};
	vc_AMI.start(f_AMI_Adapter_main(ami_pars));

	f_ami_action_login(AMI_CLIENT, mp_ami_user, mp_ami_secret);

	timer tReady;
	tReady.start(10.0);
	alt {
	[] AMI_CLIENT.receive(tr_AMI_Event_FullyBooted);
	[] as_ami_rx_ignore(AMI_CLIENT);
	[] tReady.timeout {
		Misc_Helpers.f_shutdown(__BFILE__, __LINE__, fail,
					log2str("AMI FullyBooted timeout: "));
		}
	}
}

/* Local SIP UAs */
private function f_init_sip_local() runs on test_CT {
	var charstring id := "Asterisk_Tests_LOCAL_SIP_EMU";
	f_init_sip(vc_SIP, id);
}

/* IMS Server connection */
private function f_init_sip_ims() runs on test_CT {
	var charstring id := "Asterisk_Tests_IMS_SIP_EMU";
	f_init_sip(vc_IMS, id);
}

function f_init() runs on test_CT {
	var charstring id;

	f_init_ami();
	f_init_sip_local();
	f_init_sip_ims();
	log("end of f_init");
}

function f_shutdown() runs on test_CT {
	/* Tear down AMI Adapter to avoid it keep receiving data from Asterisk
	 * and sending it to us after we stopped, causing error (Broken Pipe): */
	vc_AMI.stop;
	vc_AMI.done;
	log("end of ", testcasename());
	setverdict(pass);
}

function f_start_handler(void_fn fn, SIPConnHdlrPars pars)
runs on test_CT return SIPConnHdlr {
	var SIPConnHdlr vc_conn;
	var charstring id := testcasename() & "-ConnHdlr-" & pars.user;

	vc_conn := SIPConnHdlr.create(id) alive;

	connect(vc_conn:SIP, vc_SIP:CLIENT);
	connect(vc_conn:SIP_PROC, vc_SIP:CLIENT_PROC);

	connect(vc_conn:COORD, self:COORD);

	vc_conn.start(f_handler_init(fn, id, pars));
	return vc_conn;
}

function f_start_handler_IMS(ims_void_fn fn, IMS_ConnHdlrPars pars)
runs on test_CT return IMS_ConnHdlr {
	var IMS_ConnHdlr vc_conn;
	var charstring id := testcasename() & "-IMS_ConnHdlr-" & pars.subscr.imsi;

	vc_conn := IMS_ConnHdlr.create(id) alive;

	connect(vc_conn:SIP, vc_IMS:CLIENT);
	connect(vc_conn:SIP_PROC, vc_IMS:CLIENT_PROC);

	connect(vc_conn:COORD, self:IMS_COORD);

	vc_conn.start(f_ims_handler_init(fn, id, pars));
	return vc_conn;
}

/* Test SIP registration of local clients */
private function f_TC_internal_registration(charstring id) runs on SIPConnHdlr {

	f_SIP_register();
	// f_SIP_deregister();
	setverdict(pass);
}
testcase TC_internal_registration() runs on test_CT {
	var SIPConnHdlrPars pars;
	var SIPConnHdlr vc_conn;
	f_init();
	pars := f_init_ConnHdlrPars();
	vc_conn := f_start_handler(refers(f_TC_internal_registration), pars);
	vc_conn.done;
	f_shutdown();
}

/* Successful SIP MO-MT Call between local clients: */
private function f_TC_internal_call_mo(charstring id) runs on SIPConnHdlr {

	f_SIP_register();
	COORD.send(COORD_CMD_REGISTERED);

	COORD.receive(COORD_CMD_START);
	f_SIP_mo_call_setup();
	COORD.send(COORD_CMD_CALL_ESTABLISHED);

	COORD.receive(COORD_CMD_HANGUP);
	f_SIP_do_call_hangup();

	setverdict(pass);
}
private function f_TC_internal_call_mt(charstring id) runs on SIPConnHdlr {

	f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.cp.called.addr)));

	f_SIP_register();
	COORD.send(COORD_CMD_REGISTERED);

	if (g_pars.cp.mt.exp_cancel) {
		as_SIP_mt_call_cancelled();
		COORD.send(COORD_CMD_CALL_CANCELLED);
		setverdict(pass);
		return;
	}

	as_SIP_mt_call_accept();
	COORD.send(COORD_CMD_CALL_ESTABLISHED);

	/* Once MO hangs up, Asterisk updates us to point RTP to it: */
	as_SIP_exp_call_update(g_pars.cp.sip_seq_nr + 1);
	as_SIP_exp_call_hangup(g_pars.cp.sip_seq_nr + 1);

	setverdict(pass);
}
testcase TC_internal_call_momt() runs on test_CT {
	var SIPConnHdlrPars pars[2];
	var SIPConnHdlr vc_conn[2];

	f_init();

	pars[0] := f_init_ConnHdlrPars(idx := 1);
	pars[1] := f_init_ConnHdlrPars(idx := 2);

	pars[0].cp.calling := pars[0].registrar_sip_record;
	pars[0].cp.called := pars[1].registrar_sip_record;

	pars[1].cp.calling := pars[0].registrar_sip_record;
	pars[1].cp.called := pars[1].local_sip_record;

	vc_conn[0] := f_start_handler(refers(f_TC_internal_call_mo), pars[0]);
	vc_conn[1] := f_start_handler(refers(f_TC_internal_call_mt), pars[1]);

	interleave {
	[] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[0];
	[] COORD.receive(COORD_CMD_REGISTERED) from vc_conn[1];
	}

	COORD.send(COORD_CMD_START) to vc_conn[0];

	interleave {
	[] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[0];
	[] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn[1];
	}

	/* Call on-going */
	f_sleep(1.0);

	COORD.send(COORD_CMD_HANGUP) to vc_conn[0];


	vc_conn[0].done;
	vc_conn[1].done;
	f_shutdown();
}

/* One of the users calls (INVITE) shared extension, which makes all other user
 * equipments ring (INVITE). The first one to pick up the call (OK 200) gets the
 * call established (ACK), others get a CANCEL event. */
private function TC_internal_call_all_Nregistered(integer num_conns := 2) runs on test_CT {
	var SIPConnHdlrList vc_conn_list := {};
	const integer vc_conn_mo_idx := 0; /* Index of MO leg in vc_conn_list */
	const integer vc_conn_mt_idx := 1; /* Index of MT leg in vc_conn_list, peer picking up first the call */
	var SipAddr broadcast_sip_record;
	var SIPConnHdlrPars pars_mo;

	f_init();

	broadcast_sip_record := valueof(ts_SipAddr(ts_HostPort(mp_local_sip_host),
					ts_UserInfo(broadcast_sip_extension)));

	for (var integer i := 0; i < num_conns; i := i + 1) {
		var SIPConnHdlrPars pars;
		var SIPConnHdlr vc_conn;
		pars := f_init_ConnHdlrPars(idx := i + 1);
		if (i == vc_conn_mo_idx) { /* MO */
			pars.cp.calling := pars.registrar_sip_record;
			pars.cp.called := broadcast_sip_record;
			vc_conn := f_start_handler(refers(f_TC_internal_call_mo), pars);
			pars_mo := pars;
		} else { /* MT */
			pars.cp.calling := pars_mo.registrar_sip_record;
			pars.cp.called := pars.local_sip_record;
			pars.cp.mt.wait_coord_cmd_pickup := true;
			if (i != vc_conn_mt_idx) {
				/* Only first MT picking up (OK 200 INVITE) will be ACKed, others CANCELed: */
				pars.cp.mt.exp_cancel := true;
			}
			vc_conn := f_start_handler(refers(f_TC_internal_call_mt), pars);
		}
		vc_conn_list := vc_conn_list & { vc_conn };
	}

	/* Wait all users are registered: */
	for (var integer i := 0; i < num_conns; i := i + 1) {
		/* Note: "from vc_conn_list[i]" can't be used since they may arrive from components in any order: */
		COORD.receive(COORD_CMD_REGISTERED);
	}

	/* Ask MO user to start the call: */
	COORD.send(COORD_CMD_START) to vc_conn_list[vc_conn_mo_idx];

	/* Make sure the desired MT is the one picking up first the call: */
	COORD.send(COORD_CMD_PICKUP) to vc_conn_list[vc_conn_mt_idx];
	interleave {
	[] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_list[vc_conn_mo_idx];
	[] COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_list[vc_conn_mt_idx];
	}

	/* Pick up from other phone calls and expect CANCEL: */
	for (var integer i := 0; i < num_conns; i := i + 1) {
		if (i != vc_conn_mo_idx and i != vc_conn_mt_idx) {
			COORD.send(COORD_CMD_PICKUP) to vc_conn_list[i];
			COORD.receive(COORD_CMD_CALL_CANCELLED) from vc_conn_list[i];
		}
	}

	/* Call on-going */
	f_sleep(1.0);

	COORD.send(COORD_CMD_HANGUP) to vc_conn_list[vc_conn_mo_idx];

	for (var integer i := 0; i < num_conns; i := i + 1) {
		vc_conn_list[i].done;
	}
	f_shutdown();
}
testcase TC_internal_call_all_2registered() runs on test_CT {
	TC_internal_call_all_Nregistered(2);
}
testcase TC_internal_call_all_3registered() runs on test_CT {
	TC_internal_call_all_Nregistered(3);
}
testcase TC_internal_call_all_4registered() runs on test_CT {
	TC_internal_call_all_Nregistered(4);
}

testcase TC_selftest() runs on test_CT {
	f_ami_selftest();
	f_sip_digest_selftest();
	setverdict(pass);
}

private function f_AMI_IMS_register(IMS_ConnHdlrPars pars) runs on test_CT
{
	/* Give some time for IMS_ConnHdlr to register SIP expect. This could be done through IMS_COORD. */
	f_sleep(1.0);
	/* Clear events: */
	AMI_CLIENT.clear;

	/* Announce network information, this should usually happen when UE
	 * becomes attached to network and before IMS APN is set up: */
	f_ami_action_PJSIPAccessNetworkInfo(AMI_CLIENT, mp_volte_ims_outbound_registration,
					    f_ami_gen_PJSIPAccessNetworkInfo_Info_EUTRAN(pars.subscr.uli_str));

	/* Trigger registration: */
	f_ami_action_PJSIPRegister(AMI_CLIENT, mp_volte_ims_outbound_registration);

	var charstring rand_str := oct2str(pars.subscr.rand);
	var charstring autn_str := oct2str(pars.subscr.autn);
	AMI_CLIENT.receive(tr_AMI_Event_AuthRequest(mp_volte_ims_outbound_registration,
						    rand := pattern @nocase rand_str,
						    autn := pattern @nocase autn_str));

	f_ami_action_AuthResponse_RES(AMI_CLIENT,
				      mp_volte_ims_outbound_registration,
				      c_auth_res, c_auth_ck, c_auth_ik);

	AMI_CLIENT.receive(tr_AMI_Event_Registry(f_sip_SipAddr_to_str(pars.subscr.local_sip_record),
						 "sip:" & mp_local_ims_host,
						 "Registered"));

	 /* TODO: test "Action: PJSIPUnregister" */

	 /* TODO: in another test emulating a call, test "Action: DedicatedBearerStatus" */
}

/* Test SIP registration of local clients */
private function f_TC_ims_registration(charstring id) runs on IMS_ConnHdlr {
	f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.subscr.registrar_sip_record.addr)));
	as_IMS_register();
	setverdict(pass);
}
testcase TC_ims_registration() runs on test_CT {
	var IMS_ConnHdlrPars pars;
	var IMS_ConnHdlr vc_conn;
	f_init();
	pars := f_init_IMS_ConnHdlrPars();
	vc_conn := f_start_handler_IMS(refers(f_TC_ims_registration), pars);

	f_AMI_IMS_register(pars);

	vc_conn.done;
	f_shutdown();
}

/* Test SIP registration of local clients */
private function f_TC_ims_call_mo(charstring id) runs on IMS_ConnHdlr {
	f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.subscr.registrar_sip_record.addr)));
	if (ispresent(g_pars.subscr.cp.called)) {
		f_create_sip_expect(valueof(ts_SipUrl_from_Addr_Union(g_pars.subscr.cp.called.addr)));
	}
	as_IMS_register();
	setverdict(pass);
	as_IMS_mo_call_accept();
	setverdict(pass);
	COORD.send(COORD_CMD_CALL_ESTABLISHED);
	as_IMS_exp_call_hangup(g_pars.subscr.cp.sip_seq_nr + 1);
	setverdict(pass);
}
testcase TC_ims_call_mo() runs on test_CT {
	var SIPConnHdlrPars sip_pars;
	var IMS_ConnHdlrPars ims_pars;
	var SIPConnHdlr vc_conn_sip;
	var IMS_ConnHdlr vc_conn_ims;
	const charstring c_ext_msisdn := "90829";

	f_init();

	sip_pars := f_init_ConnHdlrPars(idx := 1);
	ims_pars := f_init_IMS_ConnHdlrPars();

	sip_pars.cp.calling := sip_pars.registrar_sip_record;
	sip_pars.cp.called := valueof(ts_SipAddr(ts_HostPort(sip_pars.remote_sip_host),
						 ts_UserInfo(c_ext_msisdn)));
	ims_pars.subscr.cp.calling := valueof(ts_SipAddr(ts_HostPort(ims_pars.local_sip_host),
							 ts_UserInfo(ims_pars.subscr.msisdn)));
	ims_pars.subscr.cp.called := valueof(ts_SipAddr(ts_HostPort(ims_pars.local_sip_host),
							ts_UserInfo(c_ext_msisdn)));

	vc_conn_ims := f_start_handler_IMS(refers(f_TC_ims_call_mo), ims_pars);
	vc_conn_sip := f_start_handler(refers(f_TC_internal_call_mo), sip_pars);

	COORD.receive(COORD_CMD_REGISTERED) from vc_conn_sip;

	f_AMI_IMS_register(ims_pars);

	COORD.send(COORD_CMD_START) to vc_conn_sip;
	COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_sip;
	IMS_COORD.receive(COORD_CMD_CALL_ESTABLISHED) from vc_conn_ims;

	/* Call on-going */
	f_sleep(1.0);

	COORD.send(COORD_CMD_HANGUP) to vc_conn_sip;

	vc_conn_sip.done;
	vc_conn_ims.done;
	f_shutdown();
}

control {
	execute( TC_internal_registration() );
	execute( TC_internal_call_momt() );
	execute( TC_internal_call_all_2registered() );
	execute( TC_internal_call_all_3registered() );
	execute( TC_internal_call_all_4registered() );
	execute( TC_ims_registration() );
	execute( TC_ims_call_mo() );
}

}
