comparison mtctest/sig_handler.c @ 5:e7b192a5dee5

mtctest: initial import from old ThemWi
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 09 Jun 2024 00:58:38 +0000
parents
children 33d8b3177540
comparison
equal deleted inserted replaced
4:ce450869db09 5:e7b192a5dee5
1 /*
2 * In this module we handle all incoming messages from MNCC,
3 * printing all of them and generating protocol-required responses
4 * for some.
5 */
6
7 #include <sys/types.h>
8 #include <sys/time.h>
9 #include <sys/socket.h>
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <strings.h>
15 #include "../include/mncc.h"
16 #include "../include/gsm48_const.h"
17
18 extern int disconnect_mode;
19 extern struct sockaddr_storage dummy_rtp_endp;
20 extern struct timeval cur_event_time;
21
22 static void
23 print_bearer_cap(bcap)
24 struct gsm_mncc_bearer_cap *bcap;
25 {
26 int i, sv;
27
28 printf("Bearer cap: itcap=%d tmod=%d coding=%d rrq=%d\n",
29 bcap->transfer, bcap->mode, bcap->coding, bcap->radio);
30 printf(" speech: CTM=%d sv", bcap->speech_ctm);
31 for (i = 0; i < 8; i++) {
32 sv = bcap->speech_ver[i];
33 if (sv < 0)
34 break;
35 printf(" %d", sv);
36 }
37 putchar('\n');
38 printf(" data: ra=%d sig=%d async=%d nstop=%d ndata=%d\n",
39 bcap->data.rate_adaption, bcap->data.sig_access,
40 bcap->data.async, bcap->data.nr_stop_bits,
41 bcap->data.nr_data_bits);
42 printf(" urate=%d par=%d irate=%d transp=%d mtype=%d\n",
43 bcap->data.user_rate, bcap->data.parity,
44 bcap->data.interm_rate, bcap->data.transp,
45 bcap->data.modem_type);
46 }
47
48 static void
49 print_cc_cap(cc)
50 struct gsm_mncc_cccap *cc;
51 {
52 printf("CC capabilities: DTMF=%d PCP=%d\n", cc->dtmf, cc->pcp);
53 }
54
55 static void
56 print_cause(cause)
57 struct gsm_mncc_cause *cause;
58 {
59 int i;
60
61 printf("Cause: loc=%d coding=%d value=%d", cause->location,
62 cause->coding, cause->value);
63 if (cause->rec)
64 printf(" rec=0x%02X", cause->rec_val);
65 for (i = 0; i < cause->diag_len; i++) {
66 if (!(i & 15)) {
67 putchar('\n');
68 putchar(' ');
69 }
70 printf(" %02X", cause->diag[i] & 0xFF);
71 }
72 putchar('\n');
73 }
74
75 static void
76 print_progress(prog)
77 struct gsm_mncc_progress *prog;
78 {
79 printf("Progress: loc=%d coding=%d descr=0x%02X", prog->location,
80 prog->coding, prog->descr);
81 }
82
83 static void
84 print_useruser(uu)
85 struct gsm_mncc_useruser *uu;
86 {
87 printf("User-User IE: proto=0x%02X\n", uu->proto);
88 /* dump to be implemented if and when we actually get a UU somewhere */
89 }
90
91 static void
92 print_keypad(kp)
93 int kp;
94 {
95 if (kp >= '!' && kp <= '~')
96 printf("Keypad code: %c\n", kp);
97 else
98 printf("Keypad code: 0x%02X\n", kp);
99 }
100
101 static void
102 print_facility(fac)
103 struct gsm_mncc_facility *fac;
104 {
105 int i;
106
107 printf("Facility IE: %d byte(s)", fac->len);
108 for (i = 0; i < fac->len; i++) {
109 if (!(i & 15)) {
110 putchar('\n');
111 putchar(' ');
112 }
113 printf(" %02X", fac->info[i] & 0xFF);
114 }
115 putchar('\n');
116 }
117
118 static void
119 print_ssver(ssv)
120 struct gsm_mncc_ssversion *ssv;
121 {
122 int i;
123
124 printf("SS version IE: %d byte(s)", ssv->len);
125 for (i = 0; i < ssv->len; i++) {
126 if (!(i & 15)) {
127 putchar('\n');
128 putchar(' ');
129 }
130 printf(" %02X", ssv->info[i] & 0xFF);
131 }
132 putchar('\n');
133 }
134
135 static void
136 print_fields(msg)
137 struct gsm_mncc *msg;
138 {
139 if (msg->fields & MNCC_F_BEARER_CAP)
140 print_bearer_cap(&msg->bearer_cap);
141 if (msg->fields & MNCC_F_CCCAP)
142 print_cc_cap(&msg->cccap);
143 if (msg->fields & MNCC_F_CAUSE)
144 print_cause(&msg->cause);
145 if (msg->fields & MNCC_F_PROGRESS)
146 print_progress(&msg->progress);
147 if (msg->fields & MNCC_F_USERUSER)
148 print_useruser(&msg->useruser);
149 if (msg->more)
150 printf("More data flag set\n");
151 if (msg->fields & MNCC_F_KEYPAD)
152 print_keypad(msg->keypad);
153 if (msg->fields & MNCC_F_FACILITY)
154 print_facility(&msg->facility);
155 if (msg->fields & MNCC_F_SSVERSION)
156 print_ssver(&msg->ssversion);
157 }
158
159 static void
160 print_sdp(sdp)
161 char *sdp;
162 {
163 char *cp, *ep, *np;
164
165 for (cp = sdp; *cp; cp = np) {
166 ep = index(cp, '\n');
167 if (ep) {
168 *ep = '\0';
169 np = ep + 1;
170 } else
171 np = 0;
172 ep = index(cp, '\r');
173 if (ep)
174 *ep = '\0';
175 printf("%s %s\n", cp == sdp ? "SDP:" : " ", cp);
176 }
177 }
178
179 static void
180 send_connect_ack()
181 {
182 struct gsm_mncc ack;
183
184 printf("Sending connect ack\n");
185 bzero(&ack, sizeof(struct gsm_mncc));
186 ack.msg_type = MNCC_SETUP_COMPL_REQ;
187 ack.callref = 1;
188 send_mncc_to_gsm(&ack, sizeof(struct gsm_mncc));
189 }
190
191 static void
192 send_rtp_connect()
193 {
194 struct gsm_mncc_rtp rtp;
195
196 printf("Sending MNCC_RTP_CONNECT\n");
197 bzero(&rtp, sizeof(struct gsm_mncc_rtp));
198 rtp.msg_type = MNCC_RTP_CONNECT;
199 rtp.callref = 1;
200 bcopy(&dummy_rtp_endp, &rtp.addr, sizeof(struct sockaddr_storage));
201 send_mncc_to_gsm(&rtp, sizeof(struct gsm_mncc_rtp));
202 }
203
204 static void
205 handle_dtmf_time()
206 {
207 static struct timeval last_dtmf_time;
208 struct timeval delta;
209 unsigned ms;
210
211 if (timerisset(&last_dtmf_time) &&
212 timercmp(&cur_event_time, &last_dtmf_time, >)) {
213 timersub(&cur_event_time, &last_dtmf_time, &delta);
214 if (delta.tv_sec >= 2)
215 printf("Time since last DTMF event: %u s\n",
216 (unsigned) delta.tv_sec);
217 else {
218 ms = delta.tv_sec * 1000 + delta.tv_usec / 1000;
219 printf("Time since last DTMF event: %u ms\n", ms);
220 }
221 }
222 bcopy(&cur_event_time, &last_dtmf_time, sizeof(struct timeval));
223 }
224
225 static void
226 handle_signaling_msg(msg, msglen)
227 struct gsm_mncc *msg;
228 unsigned msglen;
229 {
230 if (msglen != sizeof(struct gsm_mncc)) {
231 fprintf(stderr,
232 "error: Rx MNCC message type 0x%x has wrong length\n",
233 msg->msg_type);
234 exit(1);
235 }
236 if (msg->callref != 1) {
237 fprintf(stderr,
238 "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n",
239 msg->msg_type, msg->callref);
240 exit(1);
241 }
242 switch (msg->msg_type) {
243 case MNCC_SETUP_CNF:
244 printf("MNCC_SETUP_CNF: call is answered\n");
245 print_fields(msg);
246 print_sdp(msg->sdp);
247 send_rtp_connect();
248 send_connect_ack();
249 return;
250 case MNCC_CALL_CONF_IND:
251 printf("MNCC_CALL_CONF_IND: call is confirmed\n");
252 print_fields(msg);
253 print_sdp(msg->sdp);
254 return;
255 case MNCC_ALERT_IND:
256 printf("MNCC_ALERT_IND: call is alerting\n");
257 print_fields(msg);
258 print_sdp(msg->sdp);
259 return;
260 case MNCC_NOTIFY_IND:
261 printf("NNCC_NOTIFY_IND: NOTIFY byte from MS: 0x%02X\n",
262 msg->notify);
263 return;
264 case MNCC_DISC_IND:
265 printf("MNCC_DISC_IND: MS initiates disconnect\n");
266 print_fields(msg);
267 disconnect_mode = 1;
268 printf("Responding with release request\n");
269 msg->msg_type = MNCC_REL_REQ;
270 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
271 return;
272 case MNCC_FACILITY_IND:
273 printf("MNCC_FACILITY_IND: call-related SS from MS\n");
274 print_fields(msg);
275 return;
276 case MNCC_START_DTMF_IND:
277 printf("MNCC_START_DTMF_IND: MS sending DTMF start\n");
278 print_fields(msg);
279 handle_dtmf_time();
280 if (msg->fields & MNCC_F_KEYPAD &&
281 is_valid_dtmf_digit(msg->keypad)) {
282 printf("Responding with ACK\n");
283 msg->msg_type = MNCC_START_DTMF_RSP;
284 } else {
285 printf("Responding with Reject\n");
286 msg->msg_type = MNCC_START_DTMF_REJ;
287 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
288 GSM48_CC_CAUSE_INVAL_MAND_INF);
289 }
290 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
291 return;
292 case MNCC_STOP_DTMF_IND:
293 printf("MNCC_STOP_DTMF_IND: MS sending DTMF stop\n");
294 handle_dtmf_time();
295 msg->msg_type = MNCC_STOP_DTMF_RSP;
296 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
297 return;
298 case MNCC_MODIFY_IND:
299 printf("MNCC_MODIFY_IND: MS requests call modification\n");
300 print_fields(msg);
301 msg->msg_type = MNCC_MODIFY_REJ;
302 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU,
303 GSM48_CC_CAUSE_SERV_OPT_UNIMPL);
304 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
305 return;
306 case MNCC_HOLD_IND:
307 printf("MNCC_HOLD_IND: MS requests call hold\n");
308 msg->msg_type = MNCC_HOLD_CNF;
309 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
310 return;
311 case MNCC_RETRIEVE_IND:
312 printf("MNCC_RETRIEVE_IND: MS requests call retrieve\n");
313 send_rtp_connect();
314 msg->msg_type = MNCC_RETRIEVE_CNF;
315 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
316 return;
317 case MNCC_USERINFO_IND:
318 printf("MNCC_USERINFO_IND: user-user info\n");
319 print_fields(msg);
320 return;
321 case MNCC_REL_IND:
322 printf("MNCC_REL_IND: final release\n");
323 print_fields(msg);
324 exit(0);
325 case MNCC_REL_CNF:
326 printf("MNCC_REL_CNF: final release in response to request\n");
327 print_fields(msg);
328 exit(0);
329 case MNCC_REJ_IND:
330 printf("MNCC_REJ_IND: MT call rejected\n");
331 print_fields(msg);
332 exit(0);
333 }
334 }
335
336 static void
337 handle_rtp_msg(msg, msglen)
338 struct gsm_mncc_rtp *msg;
339 unsigned msglen;
340 {
341 if (msglen != sizeof(struct gsm_mncc_rtp)) {
342 fprintf(stderr,
343 "error: Rx MNCC message type 0x%x has wrong length\n",
344 msg->msg_type);
345 exit(1);
346 }
347 if (msg->callref != 1) {
348 fprintf(stderr,
349 "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n",
350 msg->msg_type, msg->callref);
351 exit(1);
352 }
353 switch (msg->msg_type) {
354 case MNCC_RTP_CREATE:
355 printf("MNCC_RTP_CREATE: RTP info from MSC\n");
356 printf("payload_type=0x%x payload_msg_type=0x%x\n",
357 msg->payload_type, msg->payload_msg_type);
358 print_sdp(msg->sdp);
359 return;
360 case MNCC_RTP_CONNECT:
361 printf("MNCC_RTP_CONNECT: error response\n");
362 return;
363 case MNCC_RTP_FREE:
364 printf("MNCC_RTP_FREE: bogon\n");
365 return;
366 }
367 }
368
369 void
370 msg_from_mncc(msg, msglen)
371 union mncc_msg *msg;
372 unsigned msglen;
373 {
374 switch (msg->msg_type) {
375 case MNCC_SETUP_CNF:
376 case MNCC_CALL_CONF_IND:
377 case MNCC_ALERT_IND:
378 case MNCC_NOTIFY_IND:
379 case MNCC_DISC_IND:
380 case MNCC_FACILITY_IND:
381 case MNCC_START_DTMF_IND:
382 case MNCC_STOP_DTMF_IND:
383 case MNCC_MODIFY_IND:
384 case MNCC_HOLD_IND:
385 case MNCC_RETRIEVE_IND:
386 case MNCC_USERINFO_IND:
387 case MNCC_REL_IND:
388 case MNCC_REL_CNF:
389 case MNCC_REJ_IND:
390 handle_signaling_msg(msg, msglen);
391 return;
392 case MNCC_RTP_CREATE:
393 case MNCC_RTP_CONNECT:
394 case MNCC_RTP_FREE:
395 handle_rtp_msg(msg, msglen);
396 return;
397 default:
398 fprintf(stderr,
399 "error: received unexpected MNCC message type 0x%x\n",
400 msg->msg_type);
401 exit(1);
402 }
403 }