blob: b4937e7791783331cb1cee3c21ebe6c908489c5e [file] [log] [blame]
Harald Welte474fd7d2017-12-29 16:01:39 +01001#include "mncc.h"
2#include "MNCC_Types.hh"
3
4#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
5
6namespace MNCC__Types {
7
8static void enc_bcap(struct gsm_mncc_bearer_cap *out, const MNCC__bearer__cap& in)
9{
10 out->transfer = in.transfer();
11 out->mode = in.mode();
12 out->coding = in.coding();
13 out->radio = in.radio();
14 out->speech_ctm = in.speech__ctm();
15
16 for (int i = 0; i < in.speech__ver().lengthof(); i++)
17 out->speech_ver[i] = in.speech__ver()[i];
18
19 if (in.data().is_value()) {
20 MNCC__bearer__cap__data data = in.data();
21 out->data.rate_adaption = (gsm48_bcap_ra) (int) data.rate__adaptation();
22 out->data.sig_access = (gsm48_bcap_sig_access) (int) data.sig__access();
23 out->data.async = data.async();
24 out->data.nr_stop_bits = data.nr__stop__bits();
25 out->data.nr_data_bits = data.nr__data__bits();
26 out->data.user_rate = (gsm48_bcap_user_rate) (int) data.user__rate();
27 out->data.parity = (gsm48_bcap_parity) (int) data.parity();
28 out->data.interm_rate = (gsm48_bcap_interm_rate) (int) data.interm__rate();
29 out->data.transp = (gsm48_bcap_transp) (int) data.transp();
30 out->data.modem_type = (gsm48_bcap_modem_type) (int) data.modem__type();
31 }
32
33}
34
35static MNCC__bearer__cap dec_bcap(const struct gsm_mncc_bearer_cap *in)
36{
37 MNCC__bearer__cap__data data;
38 MNCC__speech__vers vers;
39 data = MNCC__bearer__cap__data((GSM48__bcap__ra) in->data.rate_adaption,
40 (GSM48__bcap__sig__access) in->data.sig_access,
41 in->data.async,
42 in->data.nr_stop_bits,
43 in->data.nr_data_bits,
44 (GSM48__bcap__user__rate) in->data.user_rate,
45 (GSM48__bcap__parity) in->data.parity,
46 (GSM48__bcap__interm__rate) in->data.interm_rate,
47 (GSM48__bcap__transp) in->data.transp,
48 (GSM48__bcap__modem__type) in->data.modem_type);
49
Harald Welte05566002018-03-26 20:52:45 +020050 for (unsigned int i = 0; i < ARRAY_SIZE(in->speech_ver); i++) {
51 vers[i] = in->speech_ver[i];
52 if (vers[i] == -1)
53 break;
54 }
Harald Welte474fd7d2017-12-29 16:01:39 +010055
56 return MNCC__bearer__cap(in->transfer, in->mode, in->coding, in->radio, in->speech_ctm,
57 vers, data);
58}
59
60
61static void enc_number(struct gsm_mncc_number *num, const MNCC__number& in)
62{
63 num->type = in.number__type();
64 num->plan = in.plan();
65 num->present = in.presence();
66 num->screen = in.screen();
67 strncpy(num->number, in.number(), sizeof(num->number));
68}
69
70static MNCC__number dec_number(const struct gsm_mncc_number *num)
71{
72 return MNCC__number(num->type, num->plan,num->present, num->screen, num->number);
73}
74
75OCTETSTRING enc__MNCC__PDU(const MNCC__PDU& in)
76{
Harald Welte474fd7d2017-12-29 16:01:39 +010077 struct gsm_mncc mncc;
78 OCTETSTRING ret_val;
79
80 memset(&mncc, 0, sizeof(mncc));
81 mncc.msg_type = in.msg__type();
82
Harald Welte1823cb12018-02-11 11:39:29 +010083 switch (in.u().get_selection()) {
84 case MNCC__MsgUnion::ALT_signal: {
85 const MNCC__PDU__Signal& in_sig = in.u().signal();
Harald Welte474fd7d2017-12-29 16:01:39 +010086 mncc.callref = in_sig.callref();
87 if (in_sig.bearer__cap().is_value()) {
88 enc_bcap(&mncc.bearer_cap, in_sig.bearer__cap());
89 mncc.fields |= MNCC_F_BEARER_CAP;
90 }
91 if (in_sig.called().is_value()) {
92 enc_number(&mncc.called, in_sig.called());
93 mncc.fields |= MNCC_F_CALLED;
94 }
95 if (in_sig.calling().is_value()) {
96 enc_number(&mncc.calling, in_sig.calling());
97 mncc.fields |= MNCC_F_CALLING;
98 }
99 if (in_sig.redirecting().is_value()) {
100 enc_number(&mncc.redirecting, in_sig.redirecting());
101 mncc.fields |= MNCC_F_REDIRECTING;
102 }
103 if (in_sig.connected().is_value()) {
104 enc_number(&mncc.connected, in_sig.connected());
105 mncc.fields |= MNCC_F_CONNECTED;
106 }
107 if (in_sig.cause().is_value()) {
108 const MNCC__cause &cause = in_sig.cause();
109 TTCN_Buffer ttcn_buffer(cause.diag());
110 mncc.cause.location = cause.location();
111 mncc.cause.coding = cause.coding();
112 mncc.cause.rec = cause.rec();
113 mncc.cause.rec_val = cause.rec__val();
114 mncc.cause.value = cause.val();
115 mncc.cause.diag_len = ttcn_buffer.get_len();
116 if (mncc.cause.diag_len > (int) sizeof(mncc.cause.diag)) {
117 TTCN_error("MNCC diagnostics length %u too long", mncc.cause.diag_len);
118 mncc.cause.diag_len = sizeof(mncc.cause.diag);
119 }
120 memcpy(mncc.cause.diag, ttcn_buffer.get_data(), ttcn_buffer.get_len());
121 mncc.fields |= MNCC_F_CAUSE;
122 }
123 if (in_sig.progress().is_value()) {
124 const MNCC__progress &progress = in_sig.progress();
125 mncc.progress.coding = progress.coding();
126 mncc.progress.location = progress.location();
127 mncc.progress.descr = progress.descr();
128 mncc.fields |= MNCC_F_PROGRESS;
129 }
130 if (in_sig.useruser().is_value()) {
131 const MNCC__useruser &useruser = in_sig.useruser();
132 mncc.useruser.proto = useruser.proto();
133 strncpy(mncc.useruser.info, useruser.info(), sizeof(mncc.useruser.info));
134 mncc.fields |= MNCC_F_USERUSER;
135 }
136 if (in_sig.facility().is_value()) {
137 const CHARSTRING &fac = in_sig.facility();
138 strncpy(mncc.facility.info, fac, sizeof(mncc.facility.info));
139 mncc.facility.len = strlen(mncc.facility.info);
140 mncc.fields |= MNCC_F_FACILITY;
141 }
142 if (in_sig.cccap().is_value()) {
143 const MNCC__cccap &cccap = in_sig.cccap();
144 mncc.cccap.dtmf = cccap.dtmf();
145 mncc.cccap.pcp = cccap.pcp();
146 mncc.fields |= MNCC_F_CCCAP;
147 }
148 if (in_sig.ssversion().is_value()) {
149 const CHARSTRING &ssv = in_sig.ssversion();
150 strncpy(mncc.ssversion.info, ssv, sizeof(mncc.ssversion.info));
151 mncc.ssversion.len = strlen(mncc.ssversion.info);
152 mncc.fields |= MNCC_F_SSVERSION;
153 }
154 mncc.clir.sup = in_sig.clir__sup();
155 mncc.clir.inv = in_sig.clir__inv();
156 if (in_sig.signal().is_value()) {
157 const INTEGER &sig = in_sig.signal();
158 mncc.signal = sig;
159 mncc.fields |= MNCC_F_SIGNAL;
160 }
161 if (in_sig.keypad().is_value()) {
Harald Welted13700d2018-02-02 20:06:52 +0100162 const CHARSTRING &kpd = in_sig.keypad();
163 mncc.signal = (int) kpd[0].get_char();
Harald Welte474fd7d2017-12-29 16:01:39 +0100164 mncc.fields |= MNCC_F_KEYPAD;
165 }
166 mncc.more = in_sig.more();
167 mncc.notify = in_sig.notify();
168 if (in_sig.emergency().is_value()) {
169 const INTEGER &emerg = in_sig.emergency();
170 mncc.emergency = emerg;
171 mncc.fields |= MNCC_F_EMERGENCY;
172 }
173 strncpy(mncc.imsi, in_sig.imsi(), sizeof(mncc.imsi));
174 mncc.lchan_type = in_sig.lchan__type();
175 mncc.lchan_mode = in_sig.lchan__mode();
176 ret_val = OCTETSTRING(sizeof(mncc), (uint8_t *)&mncc);
Harald Welte1823cb12018-02-11 11:39:29 +0100177 }
178 break;
179 case MNCC__MsgUnion::ALT_data:
Harald Welte474fd7d2017-12-29 16:01:39 +0100180 struct gsm_data_frame data;
181 memset(&data, 0, sizeof(data));
182 data.msg_type = in.msg__type();
183 ret_val = OCTETSTRING(sizeof(data), (uint8_t *)&data);
184 ret_val = ret_val & in.u().data().data();
Harald Welte1823cb12018-02-11 11:39:29 +0100185 break;
186 case MNCC__MsgUnion::ALT_rtp:
Harald Welte474fd7d2017-12-29 16:01:39 +0100187 struct gsm_mncc_rtp rtp;
188 memset(&rtp, 0, sizeof(rtp));
189 rtp.msg_type = in.msg__type();
190 rtp.callref = in.u().rtp().callref();
191 rtp.ip = in.u().rtp().ip();
192 rtp.port = in.u().rtp().rtp__port();
193 rtp.payload_type = in.u().rtp().payload__type();
194 rtp.payload_msg_type = in.u().rtp().payload__msg__type();
195 ret_val = OCTETSTRING(sizeof(rtp), (uint8_t *) &rtp);
Harald Welte1823cb12018-02-11 11:39:29 +0100196 break;
197 case MNCC__MsgUnion::ALT_hello:
Harald Welte474fd7d2017-12-29 16:01:39 +0100198 struct gsm_mncc_hello hello;
199 memset(&hello, 0, sizeof(hello));
200 hello.msg_type = in.msg__type();
201 hello.version = in.u().hello().version();
202 hello.mncc_size = in.u().hello().mncc__size();
203 hello.data_frame_size = in.u().hello().data__frame__size();
204 hello.called_offset = in.u().hello().called__offset();
205 hello.signal_offset = in.u().hello().signal__offset();
206 hello.emergency_offset = in.u().hello().emergency__offset();
207 hello.lchan_type_offset = in.u().hello().lchan__type__offset();
208 ret_val = OCTETSTRING(sizeof(hello), (uint8_t *) &hello);
Harald Welte1823cb12018-02-11 11:39:29 +0100209 break;
Harald Welte474fd7d2017-12-29 16:01:39 +0100210 }
211
212 return ret_val;
213}
214
215MNCC__PDU dec__MNCC__PDU(const OCTETSTRING& in)
216{
217 TTCN_Buffer ttcn_buffer(in);
218 const struct gsm_mncc *in_mncc;
219 MNCC__PDU__Signal sign;
220 const struct gsm_mncc_hello *in_hello;
221 MNCC__PDU__Hello hello;
222 const struct gsm_data_frame *in_data;
223 MNCC__PDU__Data data;
224 const struct gsm_mncc_rtp *in_rtp;
225 MNCC__PDU__Rtp rtp;
226 MNCC__MsgUnion u;
227
228 in_mncc = (struct gsm_mncc *) ttcn_buffer.get_read_data();
229
Harald Welte8a10e862018-01-17 13:58:26 +0100230 sign.set_implicit_omit();
231 hello.set_implicit_omit();
232 data.set_implicit_omit();
233 rtp.set_implicit_omit();
234
Harald Welte474fd7d2017-12-29 16:01:39 +0100235 switch (in_mncc->msg_type) {
236 case MNCC_SOCKET_HELLO:
237 in_hello = (const struct gsm_mncc_hello *) in_mncc;
238 hello = MNCC__PDU__Hello(in_hello->version,
239 in_hello->mncc_size,
240 in_hello->data_frame_size,
241 in_hello->called_offset,
242 in_hello->signal_offset,
243 in_hello->emergency_offset,
244 in_hello->lchan_type_offset);
245 u.hello() = hello;
246 break;
247 case GSM_TCHF_FRAME:
248 case GSM_TCHF_FRAME_EFR:
249 case GSM_TCHH_FRAME:
250 case GSM_TCH_FRAME_AMR:
251 case GSM_BAD_FRAME:
252 in_data = (const struct gsm_data_frame *) in_mncc;
253 u.data() = MNCC__PDU__Data(in_data->callref,
254 substr(in, offsetof(struct gsm_data_frame, data),
255 in.lengthof() - offsetof(struct gsm_data_frame, data)));
256 break;
257 case MNCC_RTP_CREATE:
258 case MNCC_RTP_CONNECT:
259 case MNCC_RTP_FREE:
260 in_rtp = (const struct gsm_mncc_rtp *) in_mncc;
261 rtp = MNCC__PDU__Rtp(in_rtp->callref, in_rtp->ip, in_rtp->port, in_rtp->payload_type,
262 in_rtp->payload_msg_type);
263 u.rtp() = rtp;
264 break;
265 default:
266 sign.callref() = in_mncc->callref;
267 if (in_mncc->fields & MNCC_F_BEARER_CAP) {
268 sign.bearer__cap() = dec_bcap(&in_mncc->bearer_cap);
269 }
270 if (in_mncc->fields & MNCC_F_CALLED)
271 sign.called() = dec_number(&in_mncc->called);
272 if (in_mncc->fields & MNCC_F_CALLING)
273 sign.calling() = dec_number(&in_mncc->calling);
274 if (in_mncc->fields & MNCC_F_REDIRECTING)
275 sign.redirecting() = dec_number(&in_mncc->redirecting);
276 if (in_mncc->fields & MNCC_F_CONNECTED)
277 sign.connected() = dec_number(&in_mncc->connected);
278 if (in_mncc->fields & MNCC_F_CAUSE) {
279 sign.cause() = MNCC__cause(in_mncc->cause.location,
280 in_mncc->cause.coding,
281 in_mncc->cause.rec,
282 in_mncc->cause.rec_val,
283 in_mncc->cause.value,
284 OCTETSTRING(in_mncc->cause.diag_len,
285 (const uint8_t *)in_mncc->cause.diag));
286 }
287 if (in_mncc->fields & MNCC_F_USERUSER) {
288 sign.useruser() = MNCC__useruser(in_mncc->useruser.proto,
289 CHARSTRING(in_mncc->useruser.info));
290 }
291 if (in_mncc->fields & MNCC_F_PROGRESS) {
292 sign.progress() = MNCC__progress(in_mncc->progress.coding,
293 in_mncc->progress.location,
294 in_mncc->progress.descr);
295 }
296 if (in_mncc->fields & MNCC_F_EMERGENCY)
297 sign.emergency() = in_mncc->emergency;
298 if (in_mncc->fields & MNCC_F_FACILITY)
299 sign.facility() = CHARSTRING(in_mncc->facility.info);
300 if (in_mncc->fields & MNCC_F_SSVERSION)
301 sign.ssversion() = CHARSTRING(in_mncc->ssversion.info);
302 if (in_mncc->fields & MNCC_F_CCCAP)
303 sign.cccap() = MNCC__cccap(in_mncc->cccap.dtmf, in_mncc->cccap.pcp);
Harald Welted13700d2018-02-02 20:06:52 +0100304 if (in_mncc->fields & MNCC_F_KEYPAD) {
305 char kpd[2] = { (char) in_mncc->keypad, 0 };
306 sign.keypad() = CHARSTRING(kpd);
307 }
Harald Welte474fd7d2017-12-29 16:01:39 +0100308 if (in_mncc->fields & MNCC_F_SIGNAL)
309 sign.signal() = in_mncc->signal;
310
311 sign.clir__sup() = in_mncc->clir.sup;
312 sign.clir__inv() = in_mncc->clir.inv;
313 sign.more() = in_mncc->more;
314 sign.notify() = in_mncc->notify;
315 sign.imsi() = CHARSTRING(in_mncc->imsi);
316 sign.lchan__type() = in_mncc->lchan_type;
317 sign.lchan__mode() = in_mncc->lchan_mode;
318 u.signal() = sign;
319 break;
320 }
321 return MNCC__PDU(in_mncc->msg_type, u);
322}
323
324}