Add a MNCC Socket implementation for TTCN-3
Change-Id: I8c334d4c2e630b2b779e73404c44a8df3278c614
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