HNBAP, RUA and RANAP protocol codecs

This patch introduces protocol codecs for the HNBAP, RUA and RANAP
protocols, which is mandatory for testing IuCS, IuPS or Iuh in
the future.

As Eclipse TITAN ASN.1 only supports the BER codec and the above
protocols all use APER, we need to use an external transcoder from
APER to BER and vice-versa.  This was implemented using a proprietary
ASN.1 compiler / trnaslator which sysmocom is packaging as
libfftranscode, which is made available as binary package
for Debian 9 at https://ftp.osmocom.org/binaries/libfftranscode/

Related: OS#2856, OS#2857, OS#2858
Change-Id: If4a72de9bc54d6e6a7daaca78a4d4aa5684203a5
diff --git a/library/ranap/RANAP_CodecPort.ttcn b/library/ranap/RANAP_CodecPort.ttcn
new file mode 100644
index 0000000..07e1b00
--- /dev/null
+++ b/library/ranap/RANAP_CodecPort.ttcn
@@ -0,0 +1,410 @@
+module RANAP_CodecPort {
+
+/* Simple RANAP Codec Port, translating between raw SCCP primitives with
+ * octetstring payload towards the SCCP provider, and RANAP-SCCP primitives
+ * which carry the decoded RANAP data types as payload.
+ *
+ * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
+ * All rights reserved.
+ *
+ * Released under the terms of GNU General Public License, Version 2 or
+ * (at your option) any later version.
+ */
+
+import from General_Types all;
+import from Osmocom_Types all;
+
+import from SCCPasp_Types all;
+import from SCCP_Types all;
+
+import from RANAP_PDU_Descriptions all;
+import from RANAP_Types all;
+
+type record RANAP_N_CONNECT_req
+{
+   SCCP_PAR_Address                 calledAddress,
+   SCCP_PAR_Address                 callingAddress     optional,
+   SCCP_PAR_Expedited_Data_Sel	    expeditedDataSel   optional,
+   SCCP_PAR_Quality_Of_Service      qualityOfService   optional,
+   RANAP_PDU                        userData           optional,
+   SCCP_PAR_Connection_Id           connectionId       optional,
+   SCCP_PAR_Importance              importance         optional
+}
+
+template RANAP_N_CONNECT_req ts_RANAP_CONNECT_req(SCCP_PAR_Address called,
+						 SCCP_PAR_Address calling,
+						 SCCP_PAR_Connection_Id conn_id,
+						 template RANAP_PDU ranap := omit) := {
+	calledAddress := called,
+	callingAddress := calling,
+	expeditedDataSel := omit,
+	qualityOfService := omit,
+	userData := ranap,
+	connectionId := conn_id,
+	importance := omit
+}
+
+type record RANAP_N_CONNECT_ind
+{
+   SCCP_PAR_Address                 calledAddress,
+   SCCP_PAR_Address                 callingAddress     optional,
+   SCCP_PAR_Quality_Of_Service      qualityOfService   optional,
+   RANAP_PDU                        userData           optional,
+   SCCP_PAR_Connection_Id           connectionId       optional,
+   SCCP_PAR_Importance              importance         optional
+}
+
+template RANAP_N_CONNECT_ind tr_RANAP_CONNECT_ind(template SCCP_PAR_Address called,
+						 template SCCP_PAR_Address calling,
+						 template RANAP_PDU payload := *) := {
+	calledAddress := called,
+	callingAddress := calling,
+	qualityOfService := *,
+	userData := payload,
+	connectionId := *,
+	importance := *
+}
+
+type record RANAP_N_CONNECT_res
+{
+   SCCP_PAR_Address			respondingAddress optional,
+   SCCP_PAR_Expedited_Data_Sel		expeditedDataSel  optional,
+   SCCP_PAR_Quality_Of_Service		qualityOfService  optional,
+   RANAP_PDU				userData          optional,
+   SCCP_PAR_Connection_Id		connectionId      optional,
+   SCCP_PAR_Importance 			importance        optional
+}
+
+template RANAP_N_CONNECT_res ts_RANAP_CONNECT_res(SCCP_PAR_Connection_Id conn_id,
+						 template RANAP_PDU ranap := omit) := {
+	respondingAddress := omit,
+	expeditedDataSel := omit,
+	qualityOfService := omit,
+	userData := ranap,
+	connectionId := conn_id,
+	importance := omit
+}
+
+type record RANAP_N_CONNECT_cfm
+{
+  SCCP_PAR_Address              respondingAddress optional,
+  SCCP_PAR_Quality_Of_Service   qualityOfService  optional,
+  RANAP_PDU                     userData           optional,
+  SCCP_PAR_Connection_Id        connectionId      optional,
+  SCCP_PAR_Importance           importance        optional
+}
+
+template RANAP_N_CONNECT_cfm tr_RANAP_CONNECT_cfm(template SCCP_PAR_Connection_Id conn_id,
+						  template RANAP_PDU ranap := *) := {
+	respondingAddress := *,
+	qualityOfService := *,
+	userData := ranap,
+	connectionId := conn_id,
+	importance := *
+}
+
+type record RANAP_N_DATA_req
+{
+  RANAP_PDU               userData               ,
+  SCCP_PAR_Connection_Id  connectionId  optional ,
+  SCCP_PAR_Importance     importance    optional
+}
+
+template RANAP_N_DATA_req ts_RANAP_DATA_req(SCCP_PAR_Connection_Id conn_id,
+					    template RANAP_PDU ranap) := {
+	userData := ranap,
+	connectionId := conn_id,
+	importance := omit
+}
+
+
+type record RANAP_N_DATA_ind
+{
+  RANAP_PDU               userData               ,
+  SCCP_PAR_Connection_Id  connectionId optional  ,
+  SCCP_PAR_Importance     importance   optional
+}
+
+template RANAP_N_DATA_ind tr_RANAP_DATA_ind(SCCP_PAR_Connection_Id conn_id,
+					    template RANAP_PDU ranap := *) := {
+	userData := ranap,
+	connectionId := conn_id,
+	importance := *
+}
+
+
+type record RANAP_N_DISCONNECT_req
+{
+  SCCP_PAR_Address         respondingAddress  optional,
+  SCCP_PAR_Reason          reason                      ,
+  RANAP_PDU                userData           optional ,
+  SCCP_PAR_Connection_Id   connectionId       optional ,
+  SCCP_PAR_Importance      importance         optional
+}
+
+template RANAP_N_DISCONNECT_req ts_RANAP_DISC_req(SCCP_PAR_Connection_Id conn_id,
+						  template SCCP_PAR_Reason reason,
+						  template RANAP_PDU ranap := omit) := {
+	respondingAddress := omit,
+	reason := reason,
+	userData := ranap,
+	connectionId := conn_id,
+	importance := omit
+}
+
+
+type record RANAP_N_DISCONNECT_ind
+{
+  SCCP_PAR_Originator     originator                  ,
+  SCCP_PAR_Address        respondingAddress  optional ,
+  SCCP_PAR_Reason         reason                      ,
+  RANAP_PDU               userData           optional ,
+  SCCP_PAR_Connection_Id  connectionId       optional ,
+  SCCP_PAR_Importance     importance         optional
+}
+
+template RANAP_N_DISCONNECT_ind tr_RANAP_DISC_ind(template SCCP_PAR_Connection_Id conn_id,
+						  template SCCP_PAR_Originator originator,
+						  template SCCP_PAR_Reason reason,
+						  template RANAP_PDU ranap := *) := {
+	originator := originator,
+	respondingAddress:= *,
+	reason := reason,
+	userData := ranap,
+	connectionId := conn_id,
+	importance := *
+}
+
+type record RANAP_N_UNITDATA_req
+{
+  SCCP_PAR_Address          calledAddress               ,
+  SCCP_PAR_Address          callingAddress              ,
+  SCCP_PAR_Sequence_Control sequenceControl    optional ,
+  SCCP_PAR_Return_Option    returnOption       optional ,
+  RANAP_PDU                 userData                    ,
+  SCCP_PAR_Importance       importance         optional
+ }
+
+template RANAP_N_UNITDATA_req ts_RANAP_UNITDATA_req(SCCP_PAR_Address called, SCCP_PAR_Address calling, template RANAP_PDU payload) := {
+	calledAddress := called,
+	callingAddress := calling,
+	sequenceControl := omit,
+	returnOption := omit,
+	userData := payload,
+	importance := omit
+}
+
+type record RANAP_N_UNITDATA_ind
+{
+  SCCP_PAR_Address           calledAddress              ,
+  SCCP_PAR_Address           callingAddress             ,
+  SCCP_PAR_Sequence_Control  sequenceControl  optional  ,
+  SCCP_PAR_Return_Option     returnOption     optional  ,
+  RANAP_PDU                  userData                   ,
+  SCCP_PAR_Importance        importance       optional
+}
+
+template RANAP_N_UNITDATA_ind tr_RANAP_UNITDATA_ind(template SCCP_PAR_Address called, template SCCP_PAR_Address calling, template RANAP_PDU payload) := {
+	calledAddress := called,
+	callingAddress := calling,
+	sequenceControl := *,
+	returnOption := *,
+	userData := payload,
+	importance := *
+}
+
+type record RANAP_N_NOTICE_ind
+{
+  SCCP_PAR_Address               calledAddress            ,
+  SCCP_PAR_Address               callingAddress           ,
+  SCCP_PAR_Reason_For_Return     reasonForReturn          ,
+  RANAP_PDU                      userData                 ,
+  SCCP_PAR_Importance            importance       optional
+}
+
+
+
+private function f_dec_ConnectInd(in ASP_SCCP_N_CONNECT_ind pin, out RANAP_N_CONNECT_ind pout) {
+	pout.calledAddress := pin.calledAddress;
+	pout.callingAddress := pin.callingAddress;
+	pout.qualityOfService := pin.qualityOfService;
+	if (ispresent(pin.userData)) {
+		pout.userData := dec_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_dec_ConnectCfm(in ASP_SCCP_N_CONNECT_cfm pin, out RANAP_N_CONNECT_cfm pout) {
+	pout.respondingAddress := pin.respondingAddress;
+	pout.qualityOfService := pin.qualityOfService;
+	if (ispresent(pin.userData)) {
+		pout.userData := dec_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_dec_DataInd(in ASP_SCCP_N_DATA_ind pin, out RANAP_N_DATA_ind pout) {
+	pout.userData := dec_RANAP_PDU(pin.userData);
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_dec_DisconnectInd(in ASP_SCCP_N_DISCONNECT_ind pin, out RANAP_N_DISCONNECT_ind pout) {
+	pout.originator := pin.originator;
+	pout.respondingAddress := pin.respondingAddress;
+	pout.reason := pin.reason;
+	if (ispresent(pin.userData)) {
+		pout.userData := dec_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_dec_UnitdataInd(in ASP_SCCP_N_UNITDATA_ind pin, out RANAP_N_UNITDATA_ind pout) {
+	pout.calledAddress := pin.calledAddress;
+	pout.callingAddress := pin.callingAddress;
+	pout.sequenceControl := pin.sequenceControl;
+	pout.returnOption := pin.returnOption;
+	pout.userData := dec_RANAP_PDU(pin.userData);
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_dec_NoticeInd(in ASP_SCCP_N_NOTICE_ind pin, out RANAP_N_NOTICE_ind pout) {
+	pout.calledAddress := pin.calledAddress;
+	pout.callingAddress := pin.callingAddress;
+	pout.reasonForReturn := pin.reasonForReturn;
+	pout.userData := dec_RANAP_PDU(pin.userData);
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+
+
+private function f_enc_ConnectReq(in RANAP_N_CONNECT_req pin, out ASP_SCCP_N_CONNECT_req pout) {
+	pout.calledAddress := pin.calledAddress;
+	pout.callingAddress := pin.callingAddress;
+	pout.expeditedDataSel := pin.expeditedDataSel;
+	pout.qualityOfService := pin.qualityOfService;
+	if (ispresent(pin.userData)) {
+		pout.userData := enc_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_enc_ConnectRes(in RANAP_N_CONNECT_res pin, out ASP_SCCP_N_CONNECT_res pout) {
+	pout.respondingAddress := pin.respondingAddress;
+	pout.expeditedDataSel := pin.expeditedDataSel;
+	pout.qualityOfService := pin.qualityOfService;
+	if (ispresent(pin.userData)) {
+		pout.userData := enc_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_enc_DataReq(in RANAP_N_DATA_req pin, out ASP_SCCP_N_DATA_req pout) {
+	pout.userData := enc_RANAP_PDU(pin.userData);
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_enc_DisconnectReq(in RANAP_N_DISCONNECT_req pin, out ASP_SCCP_N_DISCONNECT_req pout) {
+	pout.respondingAddress := pin.respondingAddress;
+	pout.reason := pin.reason;
+	if (ispresent(pin.userData)) {
+		pout.userData := enc_RANAP_PDU(pin.userData);
+	} else {
+		pout.userData := omit;
+	}
+	pout.connectionId := pin.connectionId;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+private function f_enc_UnitdataReq(in RANAP_N_UNITDATA_req pin, out ASP_SCCP_N_UNITDATA_req pout) {
+	pout.calledAddress := pin.calledAddress;
+	pout.callingAddress := pin.callingAddress;
+	pout.userData := enc_RANAP_PDU(pin.userData);
+	pout.sequenceControl := pin.sequenceControl;
+	pout.returnOption := pin.returnOption;
+	pout.importance := pin.importance;
+	//port.setstate(0);
+} with {extension "prototype(fast)" }
+
+
+/* 
+type port RANAP_CODEC_PT message map to SCCPasp_PT {
+	out	RANAP_N_CONNECT_req to ASP_SCCP_N_CONNECT_req with f_enc_ConnectReq(),
+		RANAP_N_CONNECT_res to ASP_SCCP_N_CONNECT_res with f_enc_ConnectRes(),
+		RANAP_N_DATA_req to ASP_SCCP_N_DATA_req with f_enc_DataReq(),
+		RANAP_N_DISCONNECT_req to ASP_SCCP_N_DISCONNECT_req with f_enc_DisconnectReq(),
+		RANAP_N_UNITDATA_req to ASP_SCCP_N_UNITDATA_req with f_enc_UnitdataReq(),
+		ASP_SCCP_N_RESET_req, ASP_SCCP_N_RESET_resp;
+
+	in	RANAP_N_CONNECT_ind from ASP_SCCP_N_CONNECT_ind with f_dec_ConnectInd(),
+		RANAP_N_CONNECT_cfm from ASP_SCCP_N_CONNECT_cfm with f_dec_ConnectCfm(),
+		RANAP_N_DATA_ind from ASP_SCCP_N_DATA_ind with f_dec_DataInd(),
+		RANAP_N_DISCONNECT_ind from ASP_SCCP_N_DISCONNECT_ind with f_dec_DisconnectInd(),
+		RANAP_N_UNITDATA_ind from ASP_SCCP_N_UNITDATA_ind with f_dec_UnitdataInd(),
+		RANAP_N_NOTICE_ind from ASP_SCCP_N_NOTICE_ind with f_dec_NoticeInd(),
+		ASP_SCCP_N_STATE_ind, ASP_SCCP_N_RESET_ind, ASP_SCCP_N_RESET_cfm;
+} with {extension "internal"}
+*/
+
+type port RANAP_CODEC_PT message {
+	out	RANAP_N_CONNECT_req,
+		RANAP_N_CONNECT_res,
+		RANAP_N_DATA_req,
+		RANAP_N_DISCONNECT_req,
+		RANAP_N_UNITDATA_req,
+		ASP_SCCP_N_RESET_req;
+	in	RANAP_N_CONNECT_ind,
+		RANAP_N_CONNECT_cfm,
+		RANAP_N_DATA_ind,
+		RANAP_N_DISCONNECT_ind,
+		RANAP_N_UNITDATA_ind,
+		RANAP_N_NOTICE_ind,
+		ASP_SCCP_N_RESET_ind,
+		ASP_SCCP_N_RESET_cfm,
+		ASP_SCCP_N_STATE_ind;
+} with { extension "internal user SCCPasp_PT
+	out(RANAP_N_CONNECT_req -> ASP_SCCP_N_CONNECT_req: function(f_enc_ConnectReq);
+	    RANAP_N_CONNECT_res -> ASP_SCCP_N_CONNECT_res: function(f_enc_ConnectRes);
+	    RANAP_N_DATA_req -> ASP_SCCP_N_DATA_req: function(f_enc_DataReq);
+	    RANAP_N_DISCONNECT_req -> ASP_SCCP_N_DISCONNECT_req: function(f_enc_DisconnectReq);
+	    RANAP_N_UNITDATA_req -> ASP_SCCP_N_UNITDATA_req: function(f_enc_UnitdataReq);
+	    ASP_SCCP_N_RESET_req -> ASP_SCCP_N_RESET_req: simple)
+	in(ASP_SCCP_N_CONNECT_ind -> RANAP_N_CONNECT_ind: function(f_dec_ConnectInd);
+	   ASP_SCCP_N_CONNECT_cfm -> RANAP_N_CONNECT_cfm: function(f_dec_ConnectCfm);
+	   ASP_SCCP_N_DATA_ind -> RANAP_N_DATA_ind: function(f_dec_DataInd);
+	   ASP_SCCP_N_DISCONNECT_ind -> RANAP_N_DISCONNECT_ind: function(f_dec_DisconnectInd);
+	   ASP_SCCP_N_UNITDATA_ind -> RANAP_N_UNITDATA_ind: function(f_dec_UnitdataInd);
+	   ASP_SCCP_N_NOTICE_ind -> RANAP_N_NOTICE_ind: function(f_dec_NoticeInd);
+	   ASP_SCCP_N_RESET_ind -> ASP_SCCP_N_RESET_ind: simple;
+	   ASP_SCCP_N_RESET_cfm -> ASP_SCCP_N_RESET_cfm: simple;
+	   ASP_SCCP_N_STATE_ind -> ASP_SCCP_N_STATE_ind: simple)"
+}
+
+
+}