/* (C) 2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * Author: Stefan Sperling <ssperling@sysmocom.de>
 * 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 {

import from M3UA_Emulation all;

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

import from SCTPasp_PortType all;

import from Osmocom_CTRL_Adapter all;

import from TELNETasp_PortType all;
import from Osmocom_VTY_Functions all;

type component system_CT {
     port SCTPasp_PT sctp;
};

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

	/* SCCP protocol runs on top of M3UA Emulation.
	 * "System Under Test" is libosmo-sccp's sccp_demo_user example program. */
	var SCCP_CT vc_SCCP_A;
	var M3UA_CT vc_M3UA;
	port SCCPasp_PT A_PORT;
}

type record SCCP_Configuration {
	charstring sccp_service_type,
	SCTP_Association_Address sctp_addr,
	integer own_pc,
	integer own_ssn,
	integer peer_pc,
	integer peer_ssn,
	octetstring sio,
	integer rctx
};

type record of SCCP_Configuration SCCP_Configurations;
modulepar {
	SCCP_Configurations mp_sccp_cfg;
}

function f_init(SCCP_Configuration cfg) runs on MTC_CT {
	var MSC_SCCP_MTP3_parameters v_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
	};

	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");

	/* Create and connect test components for an SCCP connection with M3UA beneath. */
	vc_SCCP_A := SCCP_CT.create;
	vc_M3UA := M3UA_CT.create;
	connect(self:A_PORT, vc_SCCP_A:SCCP_SP_PORT);
	connect(vc_M3UA:MTP3_SP_PORT, vc_SCCP_A:MTP3_SCCP_PORT);
	map(vc_M3UA:SCTP_PORT, system:sctp);

	vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr));
	vc_SCCP_A.start(SCCPStart(v_param));
}

function f_cleanup() runs on MTC_CT {
	all component.stop;
	unmap(vc_M3UA:SCTP_PORT, system:sctp);
	disconnect(vc_M3UA:MTP3_SP_PORT, vc_SCCP_A:MTP3_SCCP_PORT);
	disconnect(self:A_PORT, vc_SCCP_A:SCCP_SP_PORT);
	self.stop
}

/*
 * libosmo-sccp does not support Global Title address as a routing indicator.
 * But sccp_demo_user should not crash if such a message is received (see OS#2666).
 */
testcase TC_routing_global_title_crash() runs on MTC_CT system system_CT {
	timer TL_timer:= 10.0; /* twice the sccp_demo_user connection attempt interval */
	var SCCP_PAR_Address v_CallingAddress;
	var SCCP_PAR_Address v_CalledAddress;
	var octetstring vl_userdata :='12345678901234567890'O;
	var ASP_SCCP_N_UNITDATA_ind vl_N_UNITDATA_ind;

	f_init(mp_sccp_cfg[0]);

	/* Called address with routing indicator set to Global Title Address. This used to trigger the crash. */
	v_CalledAddress := valueof(ts_SccpAddr_GT('012345'H));

	v_CallingAddress := 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));
	A_PORT.send(t_ASP_N_UNITDATA_req(v_CalledAddress, v_CallingAddress, '00000001'B /* sequence control */,
					 '00000001'B /* return option */, vl_userdata, omit));

	/*
	 * Start a timeout within which our DATA packet will be sent out.
	 * The M3UA Emulation layer has buffered the packet and is going
	 * to send it when the sccp_demo_user SCCP client connects.
	 *
	 * libosmo-sccp will echo the packet back at us in an SCCP UDTS packet.
	 * However, the current M3UA Emulation implementation will discard this
	 * response because it arrives on a separate SCTP association and the
	 * emulation only supports one association at a time.
	 *
	 * As a workaround, we wait for a fixed amount of time and then issue
	 * another command to the VTY of sccp_demo_user. If sccp_demo_user
	 * has crashed, this will result in a test failure.
	 */
	TL_timer.start;
	alt {
		[] A_PORT.receive(tr_ASP_N_UNITDATA_ind) -> value vl_N_UNITDATA_ind {
			log("Received data from SCCP client.");
			repeat;
		}

		[] TL_timer.timeout {
			log("Timeout....");
		}
	}
	TL_timer.stop;

	/* Check that the VTY is still active (implying that the process hasn't crashed). */
	f_vty_transceive_ret(SCCP_DEMO_USER_VTY, "?");
	setverdict(pass);

	f_cleanup();
}

control {
	execute( TC_routing_global_title_crash() );
}


}
