module RAN_Adapter {

/* This module implements a 'dumb' RAN adapter.  It creates the M3UA and SCCP components and stacks a
 * BSSAP/RANAP codec port on top.  As a result, it provides the ability to transceive SCCP-User-SAP primitives
 * with deoded BSSAP/RANAP payload.  Use this if you want to have full control about what you transmit or
 * receive, without any automatisms in place.  Allows you to refuse connections or other abnormal behavior. */

/* (C) 2017-2019 Harald Welte <laforge@gnumonks.org>
 * contributions by sysmocom - s.f.m.c. GmbH
 * All rights reserved.
 *
 * 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 General_Types all;
import from Osmocom_Types all;

import from M3UA_Emulation all;
import from MTP3asp_Types all;
import from MTP3asp_PortType all;

import from IPA_Emulation all;

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

import from SCTPasp_Types all;
import from SCTPasp_PortType all;

#ifdef RAN_EMULATION_BSSAP
import from BSSMAP_Templates all;
#endif
import from RAN_Emulation all;

type record RAN_Adapter {
	/* component references */
	M3UA_CT vc_M3UA,		/* only in 3GPP AoIP */
	IPA_Emulation_CT vc_IPA,	/* only in SCCPlite */
	IPA_EventWaiter_CT vc_WAIT,	/* only in SCCPlite */
	SCCP_CT vc_SCCP,

	MSC_SCCP_MTP3_parameters sccp_pars,
	SCCP_PAR_Address sccp_addr_own,
	SCCP_PAR_Address sccp_addr_peer,

	/* handler mode */
	RAN_Emulation_CT vc_RAN
}

type enumerated RAN_Transport {
	BSSAP_TRANSPORT_AoIP,	/* 3GPP AoIP: SCCP over M3UA over SCTP */
	BSSAP_TRANSPORT_SCCPlite_SERVER, /* SCCPlite: SCCP over IPA over TCP */
	BSSAP_TRANSPORT_SCCPlite_CLIENT, /* SCCPlite: SCCP over IPA over TCP */
	RANAP_TRANSPORT_IuCS	/* 3GPP IuCS: SCCP over M3UA over SCTP */
};

type record RAN_Configuration {
	RAN_Transport transport,
	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
};

private function init_pars(inout RAN_Adapter ba, in RAN_Configuration cfg) {
	ba.sccp_pars := {
		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
	};
	ba.sccp_addr_own := valueof(ts_SccpAddr_PC_SSN(cfg.own_pc, cfg.own_ssn, cfg.sio, cfg.sccp_service_type));
	ba.sccp_addr_peer := valueof(ts_SccpAddr_PC_SSN(cfg.peer_pc, cfg.peer_ssn, cfg.sio, cfg.sccp_service_type));
}


function f_ran_adapter_init(inout RAN_Adapter ba, in RAN_Configuration cfg, charstring id,
			template RanOps ops) {
	init_pars(ba, cfg);
	ops.sccp_addr_local := ba.sccp_addr_own;
	ops.sccp_addr_peer := ba.sccp_addr_peer;

	/* create components */
	ba.vc_SCCP := SCCP_CT.create(id & "-SCCP");
	if (isvalue(ops)) {
		ba.vc_RAN := RAN_Emulation_CT.create(id & "-RAN");
	}
	select (cfg.transport) {
	case (BSSAP_TRANSPORT_AoIP, RANAP_TRANSPORT_IuCS) {
		ba.vc_M3UA := M3UA_CT.create(id & "-M3UA");
		map(ba.vc_M3UA:SCTP_PORT, system:sctp);
		/* connect MTP3 service provider (M3UA) to lower side of SCCP */
		connect(ba.vc_M3UA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
		ba.vc_M3UA.start(f_M3UA_Emulation(cfg.sctp_addr, cfg.rctx));
		}
#ifdef IPA_EMULATION_SCCP
	case (BSSAP_TRANSPORT_SCCPlite_SERVER) {
		ba.vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
		map(ba.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
		/* connect MTP3 service provider (IPA) to lower side of SCCP */
		connect(ba.vc_IPA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
		/* connect waiter to general IPA port (for ASP_IPA_Event) */
		ba.vc_WAIT := IPA_EventWaiter_CT.create(id & "-IPA-WAIT");
		connect(ba.vc_IPA:IPA_SP_PORT, ba.vc_WAIT:IPA_SP_PORT);
		ba.vc_WAIT.start(IPA_Emulation.waiter_main());
		ba.vc_IPA.start(IPA_Emulation.main_server(cfg.sctp_addr.local_ip_addr,
							cfg.sctp_addr.local_sctp_port,
							true, IPA_INIT_SEND_IPA_ID_ACK));
		/* wait until we received an IPA CCM ID_ACK */
		ba.vc_WAIT.done;
		disconnect(ba.vc_IPA:IPA_SP_PORT, ba.vc_WAIT:IPA_SP_PORT);
		}
	case (BSSAP_TRANSPORT_SCCPlite_CLIENT) {
		ba.vc_IPA := IPA_Emulation_CT.create(id & "-IPA");
		map(ba.vc_IPA:IPA_PORT, system:IPA_CODEC_PT);
		/* connect MTP3 service provider (IPA) to lower side of SCCP */
		connect(ba.vc_IPA:MTP3_SP_PORT, ba.vc_SCCP:MTP3_SCCP_PORT);
		/* connect waiter to general IPA port (for ASP_IPA_Event) */
		ba.vc_WAIT := IPA_EventWaiter_CT.create(id & "-IPA-WAIT");
		connect(ba.vc_IPA:IPA_SP_PORT, ba.vc_WAIT:IPA_SP_PORT);
		ba.vc_WAIT.start(IPA_Emulation.waiter_main());
		ba.vc_IPA.start(IPA_Emulation.main_client(cfg.sctp_addr.remote_ip_addr,
							cfg.sctp_addr.remote_sctp_port,
							cfg.sctp_addr.local_ip_addr,
							cfg.sctp_addr.local_sctp_port));
		/* wait until we received an IPA CCM ID_ACK */
		ba.vc_WAIT.done;
		disconnect(ba.vc_IPA:IPA_SP_PORT, ba.vc_WAIT:IPA_SP_PORT);
		}
#endif /* SCCP */
	case else {
		setverdict(fail, "Unsuppored RAN_Transport");
		mtc.stop;
		}
	}

	if (isvalue(ops)) {
		timer T := 5.0;
		T.start;
		//T.timeout;
		/* connect BSSNAP component to upper side of SCCP */
		if (cfg.transport == RANAP_TRANSPORT_IuCS) {
#ifdef RAN_EMULATION_RANAP
			log("Connecting RANAP RAN_Emulation to SCCP_SP_PORT");
			ops.protocol := RAN_PROTOCOL_RANAP
			connect(ba.vc_RAN:RANAP, ba.vc_SCCP:SCCP_SP_PORT);
#endif
		} else {
#ifdef RAN_EMULATION_BSSAP
			log("Connecting BSSAP RAN_Emulation to SCCP_SP_PORT");
			connect(ba.vc_RAN:BSSAP, ba.vc_SCCP:SCCP_SP_PORT);
#endif
		}
		if (cfg.transport == BSSAP_TRANSPORT_SCCPlite_SERVER or
		    cfg.transport == BSSAP_TRANSPORT_SCCPlite_CLIENT) {
#ifdef IPA_EMULATION_MGCP
			/* connect IPA MGCP port with BSSMAP MGCP port */
			log("Connecting MGCP RAN Emulation to IPA MGCP PORT");
			connect(ba.vc_IPA:IPA_MGCP_PORT, ba.vc_RAN:MGCP);
#endif
		}
		log("Starting RAN_Emulation");
		ba.vc_RAN.start(RAN_Emulation.main(valueof(ops), ""));
	}


}

function f_ran_adapter_start(inout RAN_Adapter ba) {
	ba.vc_SCCP.start(SCCPStart(ba.sccp_pars));
}


}
