[PATCH] osmo-ttcn3-hacks[master]: Add a MNCC Socket implementation for TTCN-3

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Wed Jan 3 20:10:23 UTC 2018


Review at  https://gerrit.osmocom.org/5637

Add a MNCC Socket implementation for TTCN-3

Change-Id: I8c334d4c2e630b2b779e73404c44a8df3278c614
---
A library/MNCC_CodecPort.ttcn
A library/MNCC_EncDec.cc
A library/MNCC_Types.ttcn
A library/mncc.h
M msc_tests/gen_links.sh
M msc_tests/regen_makefile.sh
6 files changed, 1,054 insertions(+), 5 deletions(-)


  git pull ssh://gerrit.osmocom.org:29418/osmo-ttcn3-hacks refs/changes/37/5637/1

diff --git a/library/MNCC_CodecPort.ttcn b/library/MNCC_CodecPort.ttcn
new file mode 100644
index 0000000..ce62e39
--- /dev/null
+++ b/library/MNCC_CodecPort.ttcn
@@ -0,0 +1,50 @@
+module MNCC_CodecPort {
+
+import from MNCC_Types all;
+import from UD_PortType all;
+import from UD_Types all;
+
+type record MNCC_send_data {
+	MNCC_PDU	data,
+	integer		id
+};
+
+private function MNCC_to_UD(in MNCC_send_data pin, out UD_send_data pout) {
+	pout.id := pin.id;
+	pout.data := enc_MNCC_PDU(pin.data);
+} with { extension "prototype(fast)" }
+
+private function UD_to_MNCC(in UD_send_data pin, out MNCC_send_data pout) {
+	pout.id := pin.id;
+	pout.data := dec_MNCC_PDU(pin.data);
+} with { extension "prototype(fast)" }
+
+
+type port MNCC_CODEC_PT message {
+	out	UD_close;
+	out	UD_listen;
+	in	UD_listen_result;
+	out	UD_shutdown;
+	out	UD_connect;
+	in	UD_connect_result;
+	inout	MNCC_send_data;
+	in	UD_connected;
+} with { extension "user UD_PT
+	out (
+		UD_close -> UD_close:simple;
+		UD_listen -> UD_listen:simple;
+		UD_shutdown -> UD_shutdown:simple;
+		UD_connect -> UD_connect:simple;
+		MNCC_send_data -> UD_send_data: function(MNCC_to_UD)
+		)
+	in (
+		UD_listen_result -> UD_listen_result:simple;
+		UD_connect_result -> UD_connect_result:simple;
+		UD_send_data -> MNCC_send_data: function(UD_to_MNCC);
+		UD_connected -> UD_connected:simple
+		)"
+
+};
+
+
+}
diff --git a/library/MNCC_EncDec.cc b/library/MNCC_EncDec.cc
new file mode 100644
index 0000000..eec3897
--- /dev/null
+++ b/library/MNCC_EncDec.cc
@@ -0,0 +1,308 @@
+#include "mncc.h"
+#include "MNCC_Types.hh"
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+namespace MNCC__Types {
+
+static void enc_bcap(struct gsm_mncc_bearer_cap *out, const MNCC__bearer__cap& in)
+{
+	out->transfer = in.transfer();
+	out->mode = in.mode();
+	out->coding = in.coding();
+	out->radio = in.radio();
+	out->speech_ctm = in.speech__ctm();
+
+	for (int i = 0; i < in.speech__ver().lengthof(); i++)
+		out->speech_ver[i] = in.speech__ver()[i];
+
+	if (in.data().is_value()) {
+		MNCC__bearer__cap__data data = in.data();
+		out->data.rate_adaption = (gsm48_bcap_ra) (int) data.rate__adaptation();
+		out->data.sig_access = (gsm48_bcap_sig_access) (int) data.sig__access();
+		out->data.async = data.async();
+		out->data.nr_stop_bits = data.nr__stop__bits();
+		out->data.nr_data_bits = data.nr__data__bits();
+		out->data.user_rate = (gsm48_bcap_user_rate) (int) data.user__rate();
+		out->data.parity = (gsm48_bcap_parity) (int) data.parity();
+		out->data.interm_rate = (gsm48_bcap_interm_rate) (int) data.interm__rate();
+		out->data.transp = (gsm48_bcap_transp) (int) data.transp();
+		out->data.modem_type = (gsm48_bcap_modem_type) (int) data.modem__type();
+	}
+
+}
+
+static MNCC__bearer__cap dec_bcap(const struct gsm_mncc_bearer_cap *in)
+{
+	MNCC__bearer__cap__data data;
+	MNCC__speech__vers vers;
+	data = MNCC__bearer__cap__data((GSM48__bcap__ra) in->data.rate_adaption,
+					(GSM48__bcap__sig__access) in->data.sig_access,
+					in->data.async,
+					in->data.nr_stop_bits,
+					in->data.nr_data_bits,
+					(GSM48__bcap__user__rate) in->data.user_rate,
+					(GSM48__bcap__parity) in->data.parity,
+					(GSM48__bcap__interm__rate) in->data.interm_rate,
+					(GSM48__bcap__transp) in->data.transp,
+					(GSM48__bcap__modem__type) in->data.modem_type);
+
+	for (unsigned int i = 0; i < ARRAY_SIZE(in->speech_ver); i++)
+		vers[0] = in->speech_ver[0];
+
+	return MNCC__bearer__cap(in->transfer, in->mode, in->coding, in->radio, in->speech_ctm,
+				 vers, data);
+}
+
+
+static void enc_number(struct gsm_mncc_number *num, const MNCC__number& in)
+{
+	num->type = in.number__type();
+	num->plan = in.plan();
+	num->present = in.presence();
+	num->screen = in.screen();
+	strncpy(num->number, in.number(), sizeof(num->number));
+}
+
+static MNCC__number dec_number(const struct gsm_mncc_number *num)
+{
+	return MNCC__number(num->type, num->plan,num->present, num->screen, num->number);
+}
+
+OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
+{
+	const MNCC__PDU__Signal& in_sig = in.u().signal();
+	struct gsm_mncc mncc;
+	OCTETSTRING ret_val;
+
+	memset(&mncc, 0, sizeof(mncc));
+	mncc.msg_type = in.msg__type();
+
+	if (in_sig.is_value()) {
+		mncc.callref = in_sig.callref();
+		if (in_sig.bearer__cap().is_value()) {
+			enc_bcap(&mncc.bearer_cap, in_sig.bearer__cap());
+			mncc.fields |= MNCC_F_BEARER_CAP;
+		}
+		if (in_sig.called().is_value()) {
+			enc_number(&mncc.called, in_sig.called());
+			mncc.fields |= MNCC_F_CALLED;
+		}
+		if (in_sig.calling().is_value()) {
+			enc_number(&mncc.calling, in_sig.calling());
+			mncc.fields |= MNCC_F_CALLING;
+		}
+		if (in_sig.redirecting().is_value()) {
+			enc_number(&mncc.redirecting, in_sig.redirecting());
+			mncc.fields |= MNCC_F_REDIRECTING;
+		}
+		if (in_sig.connected().is_value()) {
+			enc_number(&mncc.connected, in_sig.connected());
+			mncc.fields |= MNCC_F_CONNECTED;
+		}
+		if (in_sig.cause().is_value()) {
+			const MNCC__cause &cause = in_sig.cause();
+			TTCN_Buffer ttcn_buffer(cause.diag());
+			mncc.cause.location = cause.location();
+			mncc.cause.coding = cause.coding();
+			mncc.cause.rec = cause.rec();
+			mncc.cause.rec_val = cause.rec__val();
+			mncc.cause.value = cause.val();
+			mncc.cause.diag_len = ttcn_buffer.get_len();
+			if (mncc.cause.diag_len > (int) sizeof(mncc.cause.diag)) {
+				TTCN_error("MNCC diagnostics length %u too long", mncc.cause.diag_len);
+				mncc.cause.diag_len = sizeof(mncc.cause.diag);
+			}
+			memcpy(mncc.cause.diag, ttcn_buffer.get_data(), ttcn_buffer.get_len());
+			mncc.fields |= MNCC_F_CAUSE;
+		}
+		if (in_sig.progress().is_value()) {
+			const MNCC__progress &progress = in_sig.progress();
+			mncc.progress.coding = progress.coding();
+			mncc.progress.location = progress.location();
+			mncc.progress.descr = progress.descr();
+			mncc.fields |= MNCC_F_PROGRESS;
+		}
+		if (in_sig.useruser().is_value()) {
+			const MNCC__useruser &useruser = in_sig.useruser();
+			mncc.useruser.proto = useruser.proto();
+			strncpy(mncc.useruser.info, useruser.info(), sizeof(mncc.useruser.info));
+			mncc.fields |= MNCC_F_USERUSER;
+		}
+		if (in_sig.facility().is_value()) {
+			const CHARSTRING &fac = in_sig.facility();
+			strncpy(mncc.facility.info, fac, sizeof(mncc.facility.info));
+			mncc.facility.len = strlen(mncc.facility.info);
+			mncc.fields |= MNCC_F_FACILITY;
+		}
+		if (in_sig.cccap().is_value()) {
+			const MNCC__cccap &cccap = in_sig.cccap();
+			mncc.cccap.dtmf = cccap.dtmf();
+			mncc.cccap.pcp = cccap.pcp();
+			mncc.fields |= MNCC_F_CCCAP;
+		}
+		if (in_sig.ssversion().is_value()) {
+			const CHARSTRING &ssv = in_sig.ssversion();
+			strncpy(mncc.ssversion.info, ssv, sizeof(mncc.ssversion.info));
+			mncc.ssversion.len = strlen(mncc.ssversion.info);
+			mncc.fields |= MNCC_F_SSVERSION;
+		}
+		mncc.clir.sup = in_sig.clir__sup();
+		mncc.clir.inv = in_sig.clir__inv();
+		if (in_sig.signal().is_value()) {
+			const INTEGER &sig = in_sig.signal();
+			mncc.signal = sig;
+			mncc.fields |= MNCC_F_SIGNAL;
+		}
+		if (in_sig.keypad().is_value()) {
+			const INTEGER &kpd = in_sig.keypad();
+			mncc.signal = kpd;
+			mncc.fields |= MNCC_F_KEYPAD;
+		}
+		mncc.more = in_sig.more();
+		mncc.notify = in_sig.notify();
+		if (in_sig.emergency().is_value()) {
+			const INTEGER &emerg = in_sig.emergency();
+			mncc.emergency = emerg;
+			mncc.fields |= MNCC_F_EMERGENCY;
+		}
+		strncpy(mncc.imsi, in_sig.imsi(), sizeof(mncc.imsi));
+		mncc.lchan_type = in_sig.lchan__type();
+		mncc.lchan_mode = in_sig.lchan__mode();
+		ret_val = OCTETSTRING(sizeof(mncc), (uint8_t *)&mncc);
+	} else if (in.u().data().is_value()) {
+		struct gsm_data_frame data;
+		memset(&data, 0, sizeof(data));
+		data.msg_type = in.msg__type();
+		ret_val = OCTETSTRING(sizeof(data), (uint8_t *)&data);
+		ret_val = ret_val & in.u().data().data();
+	} else if (in.u().rtp().is_value()) {
+		struct gsm_mncc_rtp rtp;
+		memset(&rtp, 0, sizeof(rtp));
+		rtp.msg_type = in.msg__type();
+		rtp.callref = in.u().rtp().callref();
+		rtp.ip = in.u().rtp().ip();
+		rtp.port = in.u().rtp().rtp__port();
+		rtp.payload_type = in.u().rtp().payload__type();
+		rtp.payload_msg_type = in.u().rtp().payload__msg__type();
+		ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
+	} else if (in.u().hello().is_value()) {
+		struct gsm_mncc_hello hello;
+		memset(&hello, 0, sizeof(hello));
+		hello.msg_type = in.msg__type();
+		hello.version = in.u().hello().version();
+		hello.mncc_size = in.u().hello().mncc__size();
+		hello.data_frame_size = in.u().hello().data__frame__size();
+		hello.called_offset = in.u().hello().called__offset();
+		hello.signal_offset = in.u().hello().signal__offset();
+		hello.emergency_offset = in.u().hello().emergency__offset();
+		hello.lchan_type_offset = in.u().hello().lchan__type__offset();
+		ret_val = OCTETSTRING(sizeof(hello), (uint8_t *) &hello);
+	}
+
+	return ret_val;
+}
+
+MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
+{
+	TTCN_Buffer ttcn_buffer(in);
+	const struct gsm_mncc *in_mncc;
+	MNCC__PDU__Signal sign;
+	const struct gsm_mncc_hello *in_hello;
+	MNCC__PDU__Hello hello;
+	const struct gsm_data_frame *in_data;
+	MNCC__PDU__Data data;
+	const struct gsm_mncc_rtp *in_rtp;
+	MNCC__PDU__Rtp rtp;
+	MNCC__MsgUnion u;
+
+	in_mncc = (struct gsm_mncc *) ttcn_buffer.get_read_data();
+
+	switch (in_mncc->msg_type) {
+	case MNCC_SOCKET_HELLO:
+		in_hello = (const struct gsm_mncc_hello *) in_mncc;
+		hello = MNCC__PDU__Hello(in_hello->version,
+					 in_hello->mncc_size,
+					 in_hello->data_frame_size,
+					 in_hello->called_offset,
+					 in_hello->signal_offset,
+					 in_hello->emergency_offset,
+					 in_hello->lchan_type_offset);
+		u.hello() = hello;
+		break;
+	case GSM_TCHF_FRAME:
+	case GSM_TCHF_FRAME_EFR:
+	case GSM_TCHH_FRAME:
+	case GSM_TCH_FRAME_AMR:
+	case GSM_BAD_FRAME:
+		in_data = (const struct gsm_data_frame *) in_mncc;
+		u.data() = MNCC__PDU__Data(in_data->callref,
+					   substr(in, offsetof(struct gsm_data_frame, data),
+						  in.lengthof() - offsetof(struct gsm_data_frame, data)));
+		break;
+	case MNCC_RTP_CREATE:
+	case MNCC_RTP_CONNECT:
+	case MNCC_RTP_FREE:
+		in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
+		rtp = MNCC__PDU__Rtp(in_rtp->callref, in_rtp->ip, in_rtp->port, in_rtp->payload_type,
+				     in_rtp->payload_msg_type);
+		u.rtp() = rtp;
+		break;
+	default:
+		sign.callref() = in_mncc->callref;
+		if (in_mncc->fields & MNCC_F_BEARER_CAP) {
+			sign.bearer__cap() = dec_bcap(&in_mncc->bearer_cap);
+		}
+		if (in_mncc->fields & MNCC_F_CALLED)
+			sign.called() = dec_number(&in_mncc->called);
+		if (in_mncc->fields & MNCC_F_CALLING)
+			sign.calling() = dec_number(&in_mncc->calling);
+		if (in_mncc->fields & MNCC_F_REDIRECTING)
+			sign.redirecting() = dec_number(&in_mncc->redirecting);
+		if (in_mncc->fields & MNCC_F_CONNECTED)
+			sign.connected() = dec_number(&in_mncc->connected);
+		if (in_mncc->fields & MNCC_F_CAUSE) {
+			sign.cause() = MNCC__cause(in_mncc->cause.location,
+						   in_mncc->cause.coding,
+						   in_mncc->cause.rec,
+						   in_mncc->cause.rec_val,
+						   in_mncc->cause.value,
+						   OCTETSTRING(in_mncc->cause.diag_len,
+								(const uint8_t *)in_mncc->cause.diag));
+		}
+		if (in_mncc->fields & MNCC_F_USERUSER) {
+			sign.useruser() = MNCC__useruser(in_mncc->useruser.proto,
+							 CHARSTRING(in_mncc->useruser.info));
+		}
+		if (in_mncc->fields & MNCC_F_PROGRESS) {
+			sign.progress() = MNCC__progress(in_mncc->progress.coding,
+							 in_mncc->progress.location,
+							 in_mncc->progress.descr);
+		}
+		if (in_mncc->fields & MNCC_F_EMERGENCY)
+			sign.emergency() = in_mncc->emergency;
+		if (in_mncc->fields & MNCC_F_FACILITY)
+			sign.facility() = CHARSTRING(in_mncc->facility.info);
+		if (in_mncc->fields & MNCC_F_SSVERSION)
+			sign.ssversion() = CHARSTRING(in_mncc->ssversion.info);
+		if (in_mncc->fields & MNCC_F_CCCAP)
+			sign.cccap() = MNCC__cccap(in_mncc->cccap.dtmf, in_mncc->cccap.pcp);
+		if (in_mncc->fields & MNCC_F_KEYPAD)
+			sign.keypad() = in_mncc->keypad;
+		if (in_mncc->fields & MNCC_F_SIGNAL)
+			sign.signal() = in_mncc->signal;
+
+		sign.clir__sup() = in_mncc->clir.sup;
+		sign.clir__inv() = in_mncc->clir.inv;
+		sign.more() = in_mncc->more;
+		sign.notify() = in_mncc->notify;
+		sign.imsi() = CHARSTRING(in_mncc->imsi);
+		sign.lchan__type() = in_mncc->lchan_type;
+		sign.lchan__mode() = in_mncc->lchan_mode;
+		u.signal() = sign;
+		break;
+	}
+	return MNCC__PDU(in_mncc->msg_type, u);
+}
+
+}
diff --git a/library/MNCC_Types.ttcn b/library/MNCC_Types.ttcn
new file mode 100644
index 0000000..956a1ae
--- /dev/null
+++ b/library/MNCC_Types.ttcn
@@ -0,0 +1,387 @@
+module MNCC_Types {
+
+import from Osmocom_Types all;
+
+/* for architectures where 'int' is 32bit like x86_64 */
+type integer int with { variant "FIELDLENGTH(32)" };
+
+
+/* GSM 04.08 Bearer Capability: Rate Adaption */
+type enumerated GSM48_bcap_ra {
+	GSM48_BCAP_RA_NONE	(0),
+	GSM48_BCAP_RA_V110_X30	(1),
+	GSM48_BCAP_RA_X31	(2),
+	GSM48_BCAP_RA_OTHER	(3)
+};
+
+/* GSM 04.08 Bearer Capability: Signalling access protocol */
+type enumerated GSM48_bcap_sig_access {
+	GSM48_BCAP_SA_I440_I450 	(1),
+	GSM48_BCAP_SA_X21		(2),
+	GSM48_BCAP_SA_X28_DP_IN		(3),
+	GSM48_BCAP_SA_X28_DP_UN		(4),
+	GSM48_BCAP_SA_X28_NDP		(5),
+	GSM48_BCAP_SA_X32		(6)
+};
+
+/* GSM 04.08 Bearer Capability: User Rate */
+type enumerated GSM48_bcap_user_rate {
+	GSM48_BCAP_UR_300		(1),
+	GSM48_BCAP_UR_1200		(2),
+	GSM48_BCAP_UR_2400		(3),
+	GSM48_BCAP_UR_4800		(4),
+	GSM48_BCAP_UR_9600		(5),
+	GSM48_BCAP_UR_12000		(6),
+	GSM48_BCAP_UR_1200_75		(7)
+};
+
+/* GSM 04.08 Bearer Capability: Parity */
+type enumerated GSM48_bcap_parity {
+	GSM48_BCAP_PAR_ODD		(0),
+	GSM48_BCAP_PAR_EVEN		(2),
+	GSM48_BCAP_PAR_NONE		(3),
+	GSM48_BCAP_PAR_ZERO		(4),
+	GSM48_BCAP_PAR_ONE		(5)
+};
+
+/* GSM 04.08 Bearer Capability: Intermediate Rate */
+type enumerated GSM48_bcap_interm_rate {
+	GSM48_BCAP_IR_8k		(2),
+	GSM48_BCAP_IR_16k		(3)
+};
+
+/* GSM 04.08 Bearer Capability: Transparency */
+type enumerated GSM48_bcap_transp {
+	GSM48_BCAP_TR_TRANSP		(0),
+	GSM48_BCAP_TR_RLP		(1),
+	GSM48_BCAP_TR_TR_PREF		(2),
+	GSM48_BCAP_TR_RLP_PREF		(3)
+};
+
+/* GSM 04.08 Bearer Capability: Modem Type */
+type enumerated GSM48_bcap_modem_type {
+	GSM48_BCAP_MT_NONE		(0),
+	GSM48_BCAP_MT_V21		(1),
+	GSM48_BCAP_MT_V22		(2),
+	GSM48_BCAP_MT_V22bis		(3),
+	GSM48_BCAP_MT_V23		(4),
+	GSM48_BCAP_MT_V26ter		(5),
+	GSM48_BCAP_MT_V32		(6),
+	GSM48_BCAP_MT_UNDEF		(7),
+	GSM48_BCAP_MT_AUTO_1		(8)
+};
+
+type enumerated MNCC_MsgType {
+	MNCC_SETUP_REQ		('0101'O),
+	MNCC_SETUP_IND		('0102'O),
+	MNCC_SETUP_RSP		('0103'O),
+	MNCC_SETUP_CNF		('0104'O),
+	MNCC_SETUP_COMPL_REQ	('0105'O),
+	MNCC_SETUP_COMPL_IND	('0106'O),
+	MNCC_CALL_CONF_IND	('0107'O),
+	MNCC_CALL_PROC_REQ	('0108'O),
+	MNCC_PROGRESS_REQ	('0109'O),
+	MNCC_ALERT_REQ		('010a'O),
+	MNCC_ALERT_IND		('010b'O),
+	MNCC_NOTIFY_REQ		('010c'O),
+	MNCC_NOTIFY_IND		('010d'O),
+	MNCC_DISC_REQ		('010e'O),
+	MNCC_DISC_IND		('010f'O),
+	MNCC_REL_REQ		('0110'O),
+	MNCC_REL_IND		('0111'O),
+	MNCC_REL_CNF		('0112'O),
+	MNCC_FACILITY_REQ	('0113'O),
+	MNCC_FACILITY_IND	('0114'O),
+	MNCC_START_DTMF_IND	('0115'O),
+	MNCC_START_DTMF_RSP	('0116'O),
+	MNCC_START_DTMF_REJ	('0117'O),
+	MNCC_STOP_DTMF_IND	('0118'O),
+	MNCC_STOP_DTMF_RSP	('0119'O),
+	MNCC_MODIFY_REQ		('011a'O),
+	MNCC_MODIFY_IND		('011b'O),
+	MNCC_MODIFY_RSP		('011c'O),
+	MNCC_MODIFY_CNF		('011d'O),
+	MNCC_MODIFY_REJ		('011e'O),
+	MNCC_HOLD_IND		('011f'O),
+	MNCC_HOLD_CNF		('0120'O),
+	MNCC_HOLD_REJ		('0121'O),
+	MNCC_RETRIEVE_IND	('0122'O),
+	MNCC_RETRIEVE_CNF	('0123'O),
+	MNCC_RETRIEVE_REJ	('0124'O),
+	MNCC_USERINFO_REQ	('0125'O),
+	MNCC_USERINFO_IND	('0126'O),
+	MNCC_REJ_REQ		('0127'O),
+	MNCC_REJ_IND		('0128'O),
+
+	MNCC_BRIDGE		('0200'O),
+	MNCC_FRAME_RECV		('0201'O),
+	MNCC_FRAME_DROP		('0202'O),
+	MNCC_LCHAN_MODIFY	('0203'O),
+	MNCC_RTP_CREATE		('0204'O),
+	MNCC_RTP_CONNECT	('0205'O),
+	MNCC_RTP_FREE		('0206'O),
+
+	GSM_TCHF_FRAME		('0300'O),
+	GSM_TCHF_FRAME_EFR	('0301'O),
+	GSM_TCHH_FRAME		('0302'O),
+	GSM_TCH_FRAME_AMR	('0303'O),
+	GSM_BAD_FRAME		('03ff'O),
+
+	MNCC_SOCKET_HELLO	('0400'O)
+};
+
+const integer GSM_MAX_FACILITY := 128;
+const integer GSM_MAX_SSVERSION := 128;
+const integer GSM_MAX_USERUSER := 128;
+
+type record MNCC_bearer_cap_data {
+	GSM48_bcap_ra		rate_adaptation,
+	GSM48_bcap_sig_access	sig_access,
+	int			async,
+	int			nr_stop_bits,
+	int			nr_data_bits,
+	GSM48_bcap_user_rate	user_rate,
+	GSM48_bcap_parity	parity,
+	GSM48_bcap_interm_rate	interm_rate,
+	GSM48_bcap_transp	transp,
+	GSM48_bcap_modem_type	modem_type
+};
+
+type record length(0..8) of int MNCC_speech_vers;
+
+/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
+type record MNCC_bearer_cap {
+	int			transfer,
+	int			mode,
+	int			coding,
+	int			radio,
+	int			speech_ctm,
+	MNCC_speech_vers	speech_ver,
+	MNCC_bearer_cap_data	data	optional
+};
+
+template MNCC_bearer_cap ts_MNCC_bcap_voice := {
+	transfer	:= 0,	/* speech */
+	mode		:= 0,	/* circuit */
+	coding		:= 0,	/* GSM standard */
+	radio		:= 3,	/* FR/HR, FR preferred */
+	speech_ctm	:= 0,	/* not supported */
+	speech_ver	:= { 0, 2, 4, 1, 5 },
+	data		:= omit
+};
+
+type record MNCC_number {
+	GSM48_type_of_number	number_type,
+	GSM48_num_plan_ind	plan,
+	GSM48_present_ind	presence,
+	GSM48_screening_ind	screen,
+	charstring		number
+};
+
+/* 24.008 10.5.118 */
+type enumerated GSM48_num_plan_ind {
+	GSM48_NUMPLAN_UNKNOWN		(0),
+	GSM48_NUMPLAN_E164		(1),
+	GSM48_NUMPLAN_X121		(3),
+	GSM48_NUMPLAN_F69		(4),
+	GSM48_NUMPLAN_NATIONAL		(8),
+	GSM48_NUMPLAN_PRIVATE		(9),
+	GSM48_NUMPLAN_CTS		(11),
+	GSM48_NUMPLAN_RESERVED		(15)
+};
+
+/* 04.08 10.5.118 */
+type enumerated GSM48_type_of_number {
+	GSM48_TON_UNKNOWN		(0),
+	GSM48_TON_INTERNATIONAL		(1),
+	GSM48_TON_NATIONAL		(2),
+	GSM48_TON_NETWORK_SPECIFIC	(3),
+	GSM48_TON_SHORT_CODE		(4)
+};
+
+/* 04.08 10.5.120 */
+type enumerated GSM48_present_ind {
+	GSM48_PRES_IND_ALLOWED		(0),
+	GSM48_PRES_IND_RESTRICTED	(1),
+	GSM48_PRES_IND_NUM_NOT_AVAIL	(2),
+	GSM48_PRES_IND_RESERVED		(3)
+};
+
+type enumerated GSM48_screening_ind {
+	GSM48_SCR_IND_NOT_SCREENED	(0),
+	GSM48_SCR_IND_VERIF_PASSED	(1),
+	GSM48_SCR_IND_VERIF_FAILED	(2),
+	GSM48_SCR_IND_NETW_PROVIDED	(3)
+};
+
+
+template MNCC_number ts_MNCC_number(charstring number,
+				    GSM48_type_of_number ton := GSM48_TON_INTERNATIONAL,
+				    GSM48_num_plan_ind npi := GSM48_NUMPLAN_E164,
+				    GSM48_present_ind pres := GSM48_PRES_IND_ALLOWED,
+				    GSM48_screening_ind screen := GSM48_SCR_IND_NOT_SCREENED) := {
+	number_type := ton,
+	plan := npi,
+	presence := pres,
+	screen := screen,
+	number := number
+}
+
+type record MNCC_cause {
+	int		location,
+	int		coding,
+	int		rec,
+	int		rec_val,
+	int		val,
+	octetstring	diag
+};
+
+type record MNCC_useruser {
+	int		proto,
+	charstring	info
+};
+
+type record MNCC_progress {
+	int		coding,
+	int		location,
+	int		descr
+};
+
+type record MNCC_cccap {
+	int		dtmf,
+	int		pcp
+};
+
+type enumerated MNCC_bcap {
+	GSM_MNCC_BCAP_SPEECH	(0),
+	GSM_MNCC_BCAP_UNR_DIG	(1),
+	GSM_MNCC_BCAP_AUDIO	(2),
+	GSM_MNCC_BCAP_FAX_G3	(3),
+	GSM_MNCC_BCAP_OTHER_ITC	(4),
+	GSM_MNCC_BCAP_RESERVED	(7)
+};
+
+
+type record MNCC_PDU_Signal {
+	uint32_t	callref,
+
+	MNCC_bearer_cap	bearer_cap optional,
+	MNCC_number	called optional,
+	MNCC_number	calling optional,
+	MNCC_number	redirecting optional,
+	MNCC_number	connected optional,
+	MNCC_cause	cause optional,
+	MNCC_progress	progress optional,
+	MNCC_useruser	useruser optional,
+	charstring	facility optional,
+	MNCC_cccap	cccap optional,
+	charstring	ssversion optional,
+
+	int		clir_sup,
+	int		clir_inv,
+	int		signal optional,
+
+	int		keypad optional,
+	int		more,
+	int		notify (0..127),
+	int		emergency optional,
+	charstring	imsi,
+
+	uint8_t		lchan_type,	/* empty in OSmoMSC */
+	uint8_t		lchan_mode	/* empty in OsmoMSC */
+};
+
+
+type record MNCC_PDU_Data {
+	uint32_t	callref,
+	octetstring	data
+};
+
+type record MNCC_PDU_Rtp {
+	uint32_t	callref,
+	uint32_t	ip,
+	uint16_t	rtp_port,
+	uint32_t	payload_type,
+	uint32_t	payload_msg_type
+};
+
+type record MNCC_PDU_Hello {
+	uint32_t	version,
+	uint32_t	mncc_size,
+	uint32_t	data_frame_size,
+	uint32_t	called_offset,
+	uint32_t	signal_offset,
+	uint32_t	emergency_offset,
+	uint32_t	lchan_type_offset
+};
+
+
+type union MNCC_MsgUnion {
+	MNCC_PDU_Signal	signal,
+	MNCC_PDU_Data	data,
+	MNCC_PDU_Rtp	rtp,
+	MNCC_PDU_Hello	hello
+};
+
+
+type record MNCC_PDU {
+	MNCC_MsgType	msg_type,
+	MNCC_MsgUnion	u
+} with { variant (u) "CROSSTAG(
+			hello, msg_type = MNCC_SOCKET_HELLO;
+			rtp, {	msg_type = MNCC_RTP_CREATE,
+				msg_type = MNCC_RTP_CONNECT,
+				msg_type = MNCC_RTP_FREE };
+			data, {	msg_type = GSM_TCHF_FRAME,
+				msg_type = GSM_TCHF_FRAME_EFR,
+				msg_type = GSM_TCHH_FRAME,
+				msg_type = GSM_TCH_FRAME_AMR,
+				msg_type = GSM_BAD_FRAME };
+			signal, OTHERWISE
+			)"
+};
+
+external function enc_MNCC_PDU(in MNCC_PDU pdu) return octetstring;
+
+external function dec_MNCC_PDU(in octetstring stream) return MNCC_PDU;
+
+
+template MNCC_PDU ts_MNCC_Sign(MNCC_MsgType msg_type, MNCC_PDU_Signal sign) := {
+	msg_type := msg_type,
+	u := {
+		signal := sign
+	}
+}
+
+template MNCC_PDU ts_MNCC_SETUP(uint32_t call_id, charstring called, charstring calling) := {
+	msg_type := MNCC_SETUP_REQ,
+	u := {
+		signal := {
+			callref := call_id,
+			bearer_cap := ts_MNCC_bcap_voice,
+			called := valueof(ts_MNCC_number(called)),
+			calling := valueof(ts_MNCC_number(calling)),
+			redirecting := omit,
+			connected := omit,
+			cause := omit,
+			progress := omit,
+			useruser := omit,
+			facility := omit,
+			cccap := omit,
+			ssversion := omit,
+			clir_sup := 0,
+			clir_inv := 0,
+			signal := omit,
+			keypad := omit,
+			more := 0,
+			notify := 0,
+			emergency := omit,
+			imsi := "1234",
+			lchan_type := 0,
+			lchan_mode := 0
+		}
+	}
+};
+
+
+} with { encode "RAW" ; variant "FIELDORDER(msb)" }
diff --git a/library/mncc.h b/library/mncc.h
new file mode 100644
index 0000000..3e00db8
--- /dev/null
+++ b/library/mncc.h
@@ -0,0 +1,304 @@
+/* This file contains sections copied from
+ * libosmocore/include/osmocom/gsm/protocol/gsm_04_08.h,
+ * libosmocore/include/osmocom/gsm/mncc.h and
+ * openbsc/include/openbsc/mncc.h
+ */
+
+#include <stdint.h>
+
+/* GSM 04.08 Bearer Capability: Rate Adaption */
+enum gsm48_bcap_ra {
+	GSM48_BCAP_RA_NONE	= 0,
+	GSM48_BCAP_RA_V110_X30	= 1,
+	GSM48_BCAP_RA_X31	= 2,
+	GSM48_BCAP_RA_OTHER	= 3,
+};
+
+/* GSM 04.08 Bearer Capability: Signalling access protocol */
+enum gsm48_bcap_sig_access {
+	GSM48_BCAP_SA_I440_I450	= 1,
+	GSM48_BCAP_SA_X21	= 2,
+	GSM48_BCAP_SA_X28_DP_IN	= 3,
+	GSM48_BCAP_SA_X28_DP_UN	= 4,
+	GSM48_BCAP_SA_X28_NDP	= 5,
+	GSM48_BCAP_SA_X32	= 6,
+};
+
+/* GSM 04.08 Bearer Capability: User Rate */
+enum gsm48_bcap_user_rate {
+	GSM48_BCAP_UR_300	= 1,
+	GSM48_BCAP_UR_1200	= 2,
+	GSM48_BCAP_UR_2400	= 3,
+	GSM48_BCAP_UR_4800	= 4,
+	GSM48_BCAP_UR_9600	= 5,
+	GSM48_BCAP_UR_12000	= 6,
+	GSM48_BCAP_UR_1200_75	= 7,
+};
+
+/* GSM 04.08 Bearer Capability: Parity */
+enum gsm48_bcap_parity {
+	GSM48_BCAP_PAR_ODD	= 0,
+	GSM48_BCAP_PAR_EVEN	= 2,
+	GSM48_BCAP_PAR_NONE	= 3,
+	GSM48_BCAP_PAR_ZERO	= 4,
+	GSM48_BCAP_PAR_ONE	= 5,
+};
+
+/* GSM 04.08 Bearer Capability: Intermediate Rate */
+enum gsm48_bcap_interm_rate {
+	GSM48_BCAP_IR_8k	= 2,
+	GSM48_BCAP_IR_16k	= 3,
+};
+
+/* GSM 04.08 Bearer Capability: Transparency */
+enum gsm48_bcap_transp {
+	GSM48_BCAP_TR_TRANSP	= 0,
+	GSM48_BCAP_TR_RLP	= 1,
+	GSM48_BCAP_TR_TR_PREF	= 2,
+	GSM48_BCAP_TR_RLP_PREF	= 3,
+};
+
+/* GSM 04.08 Bearer Capability: Modem Type */
+enum gsm48_bcap_modem_type {
+	GSM48_BCAP_MT_NONE	= 0,
+	GSM48_BCAP_MT_V21	= 1,
+	GSM48_BCAP_MT_V22	= 2,
+	GSM48_BCAP_MT_V22bis	= 3,
+	GSM48_BCAP_MT_V23	= 4,
+	GSM48_BCAP_MT_V26ter	= 5,
+	GSM48_BCAP_MT_V32	= 6,
+	GSM48_BCAP_MT_UNDEF	= 7,
+	GSM48_BCAP_MT_AUTO_1	= 8,
+};
+
+
+
+#define GSM_MAX_FACILITY       128
+#define GSM_MAX_SSVERSION      128
+#define GSM_MAX_USERUSER       128
+
+/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
+struct gsm_mncc_bearer_cap {
+	int		transfer;	/* Information Transfer Capability */
+	int 		mode;		/* Transfer Mode */
+	int		coding;		/* Coding Standard */
+	int		radio;		/* Radio Channel Requirement */
+	int		speech_ctm;	/* CTM text telephony indication */
+	int		speech_ver[8];	/* Speech version indication */
+	struct {
+		enum gsm48_bcap_ra		rate_adaption;
+		enum gsm48_bcap_sig_access	sig_access;
+		int				async;
+		int				nr_stop_bits;
+		int				nr_data_bits;
+		enum gsm48_bcap_user_rate	user_rate;
+		enum gsm48_bcap_parity		parity;
+		enum gsm48_bcap_interm_rate	interm_rate;
+		enum gsm48_bcap_transp		transp;
+		enum gsm48_bcap_modem_type	modem_type;
+	} data;
+};
+
+struct gsm_mncc_number {
+	int 		type;
+	int 		plan;
+	int		present;
+	int		screen;
+	char		number[33];
+};
+
+struct gsm_mncc_cause {
+	int		location;
+	int		coding;
+	int		rec;
+	int		rec_val;
+	int		value;
+	int		diag_len;
+	char		diag[32];
+};
+
+struct gsm_mncc_useruser {
+	int		proto;
+	char		info[GSM_MAX_USERUSER + 1]; /* + termination char */
+};
+
+struct gsm_mncc_progress {
+	int		coding;
+	int		location;
+	int 		descr;
+};
+
+struct gsm_mncc_facility {
+	int		len;
+	char		info[GSM_MAX_FACILITY];
+};
+
+struct gsm_mncc_ssversion {
+	int		len;
+	char		info[GSM_MAX_SSVERSION];
+};
+
+struct gsm_mncc_cccap {
+	int		dtmf;
+	int		pcp;
+};
+
+enum {
+	GSM_MNCC_BCAP_SPEECH	= 0,
+	GSM_MNCC_BCAP_UNR_DIG	= 1,
+	GSM_MNCC_BCAP_AUDIO	= 2,
+	GSM_MNCC_BCAP_FAX_G3	= 3,
+	GSM_MNCC_BCAP_OTHER_ITC = 5,
+	GSM_MNCC_BCAP_RESERVED	= 7,
+};
+
+
+#define MNCC_SETUP_REQ		0x0101
+#define MNCC_SETUP_IND		0x0102
+#define MNCC_SETUP_RSP		0x0103
+#define MNCC_SETUP_CNF		0x0104
+#define MNCC_SETUP_COMPL_REQ	0x0105
+#define MNCC_SETUP_COMPL_IND	0x0106
+/* MNCC_REJ_* is perfomed via MNCC_REL_* */
+#define MNCC_CALL_CONF_IND	0x0107
+#define MNCC_CALL_PROC_REQ	0x0108
+#define MNCC_PROGRESS_REQ	0x0109
+#define MNCC_ALERT_REQ		0x010a
+#define MNCC_ALERT_IND		0x010b
+#define MNCC_NOTIFY_REQ		0x010c
+#define MNCC_NOTIFY_IND		0x010d
+#define MNCC_DISC_REQ		0x010e
+#define MNCC_DISC_IND		0x010f
+#define MNCC_REL_REQ		0x0110
+#define MNCC_REL_IND		0x0111
+#define MNCC_REL_CNF		0x0112
+#define MNCC_FACILITY_REQ	0x0113
+#define MNCC_FACILITY_IND	0x0114
+#define MNCC_START_DTMF_IND	0x0115
+#define MNCC_START_DTMF_RSP	0x0116
+#define MNCC_START_DTMF_REJ	0x0117
+#define MNCC_STOP_DTMF_IND	0x0118
+#define MNCC_STOP_DTMF_RSP	0x0119
+#define MNCC_MODIFY_REQ		0x011a
+#define MNCC_MODIFY_IND		0x011b
+#define MNCC_MODIFY_RSP		0x011c
+#define MNCC_MODIFY_CNF		0x011d
+#define MNCC_MODIFY_REJ		0x011e
+#define MNCC_HOLD_IND		0x011f
+#define MNCC_HOLD_CNF		0x0120
+#define MNCC_HOLD_REJ		0x0121
+#define MNCC_RETRIEVE_IND	0x0122
+#define MNCC_RETRIEVE_CNF	0x0123
+#define MNCC_RETRIEVE_REJ	0x0124
+#define MNCC_USERINFO_REQ	0x0125
+#define MNCC_USERINFO_IND	0x0126
+#define MNCC_REJ_REQ		0x0127
+#define MNCC_REJ_IND		0x0128
+
+#define MNCC_BRIDGE		0x0200
+#define MNCC_FRAME_RECV		0x0201
+#define MNCC_FRAME_DROP		0x0202
+#define MNCC_LCHAN_MODIFY	0x0203
+#define MNCC_RTP_CREATE		0x0204
+#define MNCC_RTP_CONNECT	0x0205
+#define MNCC_RTP_FREE		0x0206
+
+#define GSM_TCHF_FRAME		0x0300
+#define GSM_TCHF_FRAME_EFR	0x0301
+#define GSM_TCHH_FRAME		0x0302
+#define GSM_TCH_FRAME_AMR	0x0303
+#define GSM_BAD_FRAME		0x03ff
+
+#define MNCC_SOCKET_HELLO	0x0400
+
+#define GSM_MAX_FACILITY	128
+#define GSM_MAX_SSVERSION	128
+#define GSM_MAX_USERUSER	128
+
+#define	MNCC_F_BEARER_CAP	0x0001
+#define MNCC_F_CALLED		0x0002
+#define MNCC_F_CALLING		0x0004
+#define MNCC_F_REDIRECTING	0x0008
+#define MNCC_F_CONNECTED	0x0010
+#define MNCC_F_CAUSE		0x0020
+#define MNCC_F_USERUSER		0x0040
+#define MNCC_F_PROGRESS		0x0080
+#define MNCC_F_EMERGENCY	0x0100
+#define MNCC_F_FACILITY		0x0200
+#define MNCC_F_SSVERSION	0x0400
+#define MNCC_F_CCCAP		0x0800
+#define MNCC_F_KEYPAD		0x1000
+#define MNCC_F_SIGNAL		0x2000
+
+struct gsm_mncc {
+	/* context based information */
+	uint32_t	msg_type;
+	uint32_t	callref;
+
+	/* which fields are present */
+	uint32_t	fields;
+
+	/* data derived informations (MNCC_F_ based) */
+	struct gsm_mncc_bearer_cap	bearer_cap;
+	struct gsm_mncc_number		called;
+	struct gsm_mncc_number		calling;
+	struct gsm_mncc_number		redirecting;
+	struct gsm_mncc_number		connected;
+	struct gsm_mncc_cause		cause;
+	struct gsm_mncc_progress	progress;
+	struct gsm_mncc_useruser	useruser;
+	struct gsm_mncc_facility	facility;
+	struct gsm_mncc_cccap		cccap;
+	struct gsm_mncc_ssversion	ssversion;
+	struct	{
+		int		sup;
+		int		inv;
+	} clir;
+	int		signal;
+
+	/* data derived information, not MNCC_F based */
+	int		keypad;
+	int		more;
+	int		notify; /* 0..127 */
+	int		emergency;
+	char		imsi[16];
+
+	unsigned char	lchan_type;
+	unsigned char	lchan_mode;
+};
+
+struct gsm_data_frame {
+	uint32_t	msg_type;
+	uint32_t	callref;
+	unsigned char	data[0];
+};
+
+#define MNCC_SOCK_VERSION	5
+struct gsm_mncc_hello {
+	uint32_t	msg_type;
+	uint32_t	version;
+
+	/* send the sizes of the structs */
+	uint32_t	mncc_size;
+	uint32_t	data_frame_size;
+
+	/* send some offsets */
+	uint32_t	called_offset;
+	uint32_t	signal_offset;
+	uint32_t	emergency_offset;
+	uint32_t	lchan_type_offset;
+};
+
+struct gsm_mncc_rtp {
+	uint32_t	msg_type;
+	uint32_t	callref;
+	uint32_t	ip;
+	uint16_t	port;
+	uint32_t	payload_type;
+	uint32_t	payload_msg_type;
+};
+
+struct gsm_mncc_bridge {
+	uint32_t	msg_type;
+	uint32_t	callref[2];
+};
diff --git a/msc_tests/gen_links.sh b/msc_tests/gen_links.sh
index 62d8453..6625b11 100755
--- a/msc_tests/gen_links.sh
+++ b/msc_tests/gen_links.sh
@@ -11,9 +11,9 @@
 	done
 }
 
-#DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
-#FILES="UD_PT.cc  UD_PT.hh  UD_PortType.ttcn  UD_Types.ttcn"
-#gen_links $DIR $FILES
+DIR=$BASEDIR/titan.TestPorts.UNIX_DOMAIN_SOCKETasp/src
+FILES="UD_PT.cc  UD_PT.hh  UD_PortType.ttcn  UD_Types.ttcn"
+gen_links $DIR $FILES
 
 DIR=$BASEDIR/titan.Libraries.TCCUsefulFunctions/src
 FILES="TCCInterface_Functions.ttcn TCCConversion_Functions.ttcn TCCConversion.cc TCCConversion.hh TCCInterface.cc TCCInterface_ip.h"
@@ -54,5 +54,5 @@
 
 
 DIR=../library
-FILES="General_Types.ttcn Osmocom_Types.ttcn"
+FILES="General_Types.ttcn Osmocom_Types.ttcn MNCC_Types.ttcn MNCC_EncDec.cc MNCC_CodecPort.ttcn mncc.h"
 gen_links $DIR $FILES
diff --git a/msc_tests/regen_makefile.sh b/msc_tests/regen_makefile.sh
index 132da3b..f271c88 100755
--- a/msc_tests/regen_makefile.sh
+++ b/msc_tests/regen_makefile.sh
@@ -1,5 +1,5 @@
 #!/bin/sh
 
-FILES="*.ttcn SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc TCCInterface.cc"
+FILES="*.ttcn SCCP_EncDec.cc  SCTPasp_PT.cc  TCCConversion.cc TCCInterface.cc UD_PT.cc MNCC_EncDec.cc"
 
 ../regen-makefile.sh MSC_Tests.ttcn $FILES

-- 
To view, visit https://gerrit.osmocom.org/5637
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I8c334d4c2e630b2b779e73404c44a8df3278c614
Gerrit-PatchSet: 1
Gerrit-Project: osmo-ttcn3-hacks
Gerrit-Branch: master
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>



More information about the gerrit-log mailing list