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.orgReview 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>