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_EncDec.cc b/library/ranap/RANAP_EncDec.cc
new file mode 100644
index 0000000..7626b7b
--- /dev/null
+++ b/library/ranap/RANAP_EncDec.cc
@@ -0,0 +1,66 @@
+
+#include <string.h>
+#include <stdarg.h>
+#include "RANAP_PDU_Descriptions.hh"
+
+extern "C" {
+#include <fftranscode/transcode.h>
+}
+
+namespace RANAP__Types {
+
+TTCN_Module RANAP__EncDec("RANAP_EncDec", __DATE__, __TIME__);
+
+OCTETSTRING enc__RANAP__PDU(const RANAP__PDU__Descriptions::RANAP__PDU &pdu)
+{
+	uint8_t *aper_buf;
+	int aper_buf_len;
+	TTCN_Buffer TTCN_buf;
+	TTCN_buf.clear();
+
+	/* Encode from abstract data type into BER/DER */
+	pdu.encode(RANAP__PDU__Descriptions::RANAP__PDU_descr_, TTCN_buf,
+		   TTCN_EncDec::CT_BER, BER_ENCODE_DER);
+
+	aper_buf_len = fftranscode_ber2aper(FFTRANSC_T_RANAP, &aper_buf, TTCN_buf.get_data(), TTCN_buf.get_len());
+	if (aper_buf_len < 0) {
+		TTCN_Logger::begin_event_log2str();
+		TTCN_buf.log();
+		TTCN_error("fftranscode_ber2aper failed: %s", (const char *) TTCN_Logger::end_event_log2str());
+	}
+
+	/* make octetstring from output buffer */
+	OCTETSTRING ret_val(aper_buf_len, aper_buf);
+
+	/* release dynamically-allocated output buffer */
+	fftranscode_free(aper_buf);
+
+	return ret_val;
+}
+
+RANAP__PDU__Descriptions::RANAP__PDU dec__RANAP__PDU(const OCTETSTRING &stream)
+{
+	uint8_t *ber_buf;
+	int ber_buf_len;
+
+	/* First, decode APER + re-encode as BER */
+	ber_buf_len = fftranscode_aper2ber(FFTRANSC_T_RANAP, &ber_buf, (const unsigned char *)stream, stream.lengthof());
+	if (ber_buf_len < 0) {
+		TTCN_error("fftranscode_aper2ber failed.");
+	}
+
+	/* Then, re-encode from BER to TITAN representation */
+	RANAP__PDU__Descriptions::RANAP__PDU ret_dcc;
+	TTCN_Buffer TTCN_buf;
+	TTCN_buf.clear();
+	TTCN_buf.put_s(ber_buf_len, ber_buf);
+
+	ret_dcc.decode(RANAP__PDU__Descriptions::RANAP__PDU_descr_, TTCN_buf,
+			TTCN_EncDec::CT_BER, BER_ACCEPT_ALL);
+
+	fftranscode_free(ber_buf);
+
+	return ret_dcc;
+}
+
+}