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_domain := "ims.mnc001.mcc238.3gppnetwork.org"
	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_domain,
								 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_ims_domain,
						 "Registered"));
}

private function f_AMI_IMS_unregister(IMS_ConnHdlrPars pars) runs on test_CT
{
	f_ami_action_PJSIPUnregister(AMI_CLIENT, mp_volte_ims_outbound_registration);
	AMI_CLIENT.receive(tr_AMI_Event_Registry(f_sip_SipAddr_to_str(pars.subscr.local_sip_record),
						"sip:" & mp_ims_domain,
						"Unregistered"));
}

/* 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();
	as_IMS_unregister();
	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);

	/* Stay registered for one second */
	f_sleep(1.0);

	/* Trigger unregistration: */
	f_AMI_IMS_unregister(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.realm),
							 ts_UserInfo(ims_pars.subscr.msisdn)));
	ims_pars.subscr.cp.called := valueof(ts_SipAddr(ts_HostPort(ims_pars.realm),
							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;

	/* TODO: "Action: DedicatedBearerStatus" */

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

}
