RAN_Emulation: Modularize protocol support

The RAN_Emulation currently unconditionally provides BSSAP and MGCP support.
Let's re-structure the code so that support for those protocols is now
possible to enable/disable at compile time.

This patch is in preparation of introducing RANAP support in RAN_Emulation.

Change-Id: Id53ba3ff05f9946230e0e4a759245de14a0f9fbd
Related: OS#2856
diff --git a/library/RAN_Adapter.ttcnpp b/library/RAN_Adapter.ttcnpp
new file mode 100644
index 0000000..43b4988
--- /dev/null
+++ b/library/RAN_Adapter.ttcnpp
@@ -0,0 +1,165 @@
+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. */
+
+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;
+
+import from BSSMAP_Templates all;
+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 */
+};
+
+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_bssap_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) {
+#ifdef RAN_EMULATION_BSSAP
+	case (BSSAP_TRANSPORT_AoIP) {
+		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));
+		}
+	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
+	case else {
+		setverdict(fail, "Unsuppored RAN_Transport");
+		mtc.stop;
+		}
+	}
+
+	if (isvalue(ops)) {
+		timer T := 5.0;
+		T.start;
+		//T.timeout;
+		log("Connecting BSSMAP Emulation to SCCP_SP_PORT and starting emulation");
+#if RAN_EMULATION_BSSAP
+		/* connect BSSNAP component to upper side of SCCP */
+		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) {
+			/* connect IPA MGCP port with BSSMAP MGCP port */
+			connect(ba.vc_IPA:IPA_MGCP_PORT, ba.vc_RAN:MGCP);
+		}
+		/* start the BSSMAP emulation */
+		ba.vc_RAN.start(RAN_Emulation.main(valueof(ops), ""));
+	}
+
+
+}
+
+function f_bssap_start(inout RAN_Adapter ba) {
+	ba.vc_SCCP.start(SCCPStart(ba.sccp_pars));
+}
+
+
+}