FreeCalypso > hg > themwi-system-sw
comparison mtctest/sig_handler.c @ 21:cc0e1c6e33c3
themwi-test-mtc utility written, compiles
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Tue, 28 Jun 2022 18:25:28 -0800 |
parents | |
children | e8e82a4bf12b |
comparison
equal
deleted
inserted
replaced
20:b13acb024fc6 | 21:cc0e1c6e33c3 |
---|---|
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/socket.h> | |
9 #include <stdio.h> | |
10 #include <stdint.h> | |
11 #include <stdlib.h> | |
12 #include <string.h> | |
13 #include <strings.h> | |
14 #include "../include/mncc.h" | |
15 #include "../include/gsm48_const.h" | |
16 | |
17 extern int disconnect_mode; | |
18 | |
19 static void | |
20 print_bearer_cap(bcap) | |
21 struct gsm_mncc_bearer_cap *bcap; | |
22 { | |
23 int i, sv; | |
24 | |
25 printf("Bearer cap: itcap=%d tmod=%d coding=%d rrq=%d\n", | |
26 bcap->transfer, bcap->mode, bcap->coding, bcap->radio); | |
27 printf(" speech: CTM=%d sv", bcap->speech_ctm); | |
28 for (i = 0; i < 8; i++) { | |
29 sv = bcap->speech_ver[i]; | |
30 if (sv < 0) | |
31 break; | |
32 printf(" %d", sv); | |
33 } | |
34 putchar('\n'); | |
35 printf(" data: ra=%d sig=%d async=%d nstop=%d ndata=%d\n", | |
36 bcap->data.rate_adaption, bcap->data.sig_access, | |
37 bcap->data.async, bcap->data.nr_stop_bits, | |
38 bcap->data.nr_data_bits); | |
39 printf(" urate=%d par=%d irate=%d transp=%d mtype=%d\n", | |
40 bcap->data.user_rate, bcap->data.parity, | |
41 bcap->data.interm_rate, bcap->data.transp, | |
42 bcap->data.modem_type); | |
43 } | |
44 | |
45 static void | |
46 print_cc_cap(cc) | |
47 struct gsm_mncc_cccap *cc; | |
48 { | |
49 printf("CC capabilities: DTMF=%d PCP=%d\n", cc->dtmf, cc->pcp); | |
50 } | |
51 | |
52 static void | |
53 print_cause(cause) | |
54 struct gsm_mncc_cause *cause; | |
55 { | |
56 int i; | |
57 | |
58 printf("Cause: loc=%d coding=%d value=%d", cause->location, | |
59 cause->coding, cause->value); | |
60 if (cause->rec) | |
61 printf(" rec=0x%02X", cause->rec_val); | |
62 for (i = 0; i < cause->diag_len; i++) { | |
63 if (!(i & 15)) { | |
64 putchar('\n'); | |
65 putchar(' '); | |
66 } | |
67 printf(" %02X", cause->diag[i] & 0xFF); | |
68 } | |
69 putchar('\n'); | |
70 } | |
71 | |
72 static void | |
73 print_progress(prog) | |
74 struct gsm_mncc_progress *prog; | |
75 { | |
76 printf("Progress: loc=%d coding=%d descr=0x%02X", prog->location, | |
77 prog->coding, prog->descr); | |
78 } | |
79 | |
80 static void | |
81 print_useruser(uu) | |
82 struct gsm_mncc_useruser *uu; | |
83 { | |
84 printf("User-User IE: proto=0x%02X\n", uu->proto); | |
85 /* dump to be implemented if and when we actually get a UU somewhere */ | |
86 } | |
87 | |
88 static void | |
89 print_keypad(kp) | |
90 int kp; | |
91 { | |
92 if (kp >= '!' && kp <= '~') | |
93 printf("Keypad code: %c\n", kp); | |
94 else | |
95 printf("Keypad code: 0x%02X\n", kp); | |
96 } | |
97 | |
98 static void | |
99 print_facility(fac) | |
100 struct gsm_mncc_facility *fac; | |
101 { | |
102 int i; | |
103 | |
104 printf("Facility IE: %d byte(s)", fac->len); | |
105 for (i = 0; i < fac->len; i++) { | |
106 if (!(i & 15)) { | |
107 putchar('\n'); | |
108 putchar(' '); | |
109 } | |
110 printf(" %02X", fac->info[i] & 0xFF); | |
111 } | |
112 putchar('\n'); | |
113 } | |
114 | |
115 static void | |
116 print_ssver(ssv) | |
117 struct gsm_mncc_ssversion *ssv; | |
118 { | |
119 int i; | |
120 | |
121 printf("SS version IE: %d byte(s)", ssv->len); | |
122 for (i = 0; i < ssv->len; i++) { | |
123 if (!(i & 15)) { | |
124 putchar('\n'); | |
125 putchar(' '); | |
126 } | |
127 printf(" %02X", ssv->info[i] & 0xFF); | |
128 } | |
129 putchar('\n'); | |
130 } | |
131 | |
132 static void | |
133 print_fields(msg) | |
134 struct gsm_mncc *msg; | |
135 { | |
136 if (msg->fields & MNCC_F_BEARER_CAP) | |
137 print_bearer_cap(&msg->bearer_cap); | |
138 if (msg->fields & MNCC_F_CCCAP) | |
139 print_cc_cap(&msg->cccap); | |
140 if (msg->fields & MNCC_F_CAUSE) | |
141 print_cause(&msg->cause); | |
142 if (msg->fields & MNCC_F_PROGRESS) | |
143 print_progress(&msg->progress); | |
144 if (msg->fields & MNCC_F_USERUSER) | |
145 print_useruser(&msg->useruser); | |
146 if (msg->more) | |
147 printf("More data flag set\n"); | |
148 if (msg->fields & MNCC_F_KEYPAD) | |
149 print_keypad(msg->keypad); | |
150 if (msg->fields & MNCC_F_FACILITY) | |
151 print_facility(&msg->facility); | |
152 if (msg->fields & MNCC_F_SSVERSION) | |
153 print_ssver(&msg->ssversion); | |
154 } | |
155 | |
156 static void | |
157 send_connect_ack() | |
158 { | |
159 struct gsm_mncc ack; | |
160 | |
161 printf("Sending connect ack\n"); | |
162 bzero(&ack, sizeof(struct gsm_mncc)); | |
163 ack.msg_type = MNCC_SETUP_COMPL_REQ; | |
164 ack.callref = 1; | |
165 send_mncc_to_gsm(&ack, sizeof(struct gsm_mncc)); | |
166 } | |
167 | |
168 static void | |
169 handle_signaling_msg(msg, msglen) | |
170 struct gsm_mncc *msg; | |
171 unsigned msglen; | |
172 { | |
173 if (msglen != sizeof(struct gsm_mncc)) { | |
174 fprintf(stderr, | |
175 "error: Rx MNCC message type 0x%x has wrong length\n", | |
176 msg->msg_type); | |
177 exit(1); | |
178 } | |
179 if (msg->callref != 1) { | |
180 fprintf(stderr, | |
181 "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n", | |
182 msg->msg_type, msg->callref); | |
183 exit(1); | |
184 } | |
185 switch (msg->msg_type) { | |
186 case MNCC_SETUP_CNF: | |
187 printf("MNCC_SETUP_CNF: call is answered\n"); | |
188 print_fields(msg); | |
189 send_connect_ack(); | |
190 return; | |
191 case MNCC_CALL_CONF_IND: | |
192 printf("MNCC_CALL_CONF_IND: call is confirmed\n"); | |
193 print_fields(msg); | |
194 return; | |
195 case MNCC_ALERT_IND: | |
196 printf("MNCC_ALERT_IND: call is alerting\n"); | |
197 print_fields(msg); | |
198 return; | |
199 case MNCC_NOTIFY_IND: | |
200 printf("NNCC_NOTIFY_IND: NOTIFY byte from MS: 0x%02X\n", | |
201 msg->notify); | |
202 return; | |
203 case MNCC_DISC_IND: | |
204 printf("MNCC_DISC_IND: MS initiates disconnect\n"); | |
205 print_fields(msg); | |
206 disconnect_mode = 1; | |
207 printf("Responding with release request\n"); | |
208 msg->msg_type = MNCC_REL_REQ; | |
209 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
210 return; | |
211 case MNCC_FACILITY_IND: | |
212 printf("MNCC_FACILITY_IND: call-related SS from MS\n"); | |
213 print_fields(msg); | |
214 return; | |
215 case MNCC_START_DTMF_IND: | |
216 printf("MNCC_START_DTMF_IND: MS sending DTMF start\n"); | |
217 print_fields(msg); | |
218 msg->msg_type = MNCC_START_DTMF_REJ; | |
219 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, | |
220 GSM48_CC_CAUSE_SERV_OPT_UNIMPL); | |
221 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
222 return; | |
223 case MNCC_STOP_DTMF_IND: | |
224 printf("MNCC_STOP_DTMF_IND: MS sending DTMF stop\n"); | |
225 msg->msg_type = MNCC_STOP_DTMF_RSP; | |
226 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
227 return; | |
228 case MNCC_MODIFY_IND: | |
229 printf("MNCC_MODIFY_IND: MS requests call modification\n"); | |
230 print_fields(msg); | |
231 msg->msg_type = MNCC_MODIFY_REJ; | |
232 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, | |
233 GSM48_CC_CAUSE_SERV_OPT_UNIMPL); | |
234 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
235 return; | |
236 case MNCC_HOLD_IND: | |
237 printf("MNCC_HOLD_IND: MS requests call hold\n"); | |
238 msg->msg_type = MNCC_HOLD_REJ; | |
239 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, | |
240 GSM48_CC_CAUSE_SERV_OPT_UNIMPL); | |
241 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
242 return; | |
243 case MNCC_RETRIEVE_IND: | |
244 printf("MNCC_RETRIEVE_IND: MS requests call retrieve\n"); | |
245 msg->msg_type = MNCC_RETRIEVE_REJ; | |
246 mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, | |
247 GSM48_CC_CAUSE_SERV_OPT_UNIMPL); | |
248 send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); | |
249 return; | |
250 case MNCC_USERINFO_IND: | |
251 printf("MNCC_USERINFO_IND: user-user info\n"); | |
252 print_fields(msg); | |
253 return; | |
254 case MNCC_REL_IND: | |
255 printf("MNCC_REL_IND: final release\n"); | |
256 print_fields(msg); | |
257 exit(0); | |
258 case MNCC_REL_CNF: | |
259 printf("MNCC_REL_CNF: final release in response to request\n"); | |
260 print_fields(msg); | |
261 exit(0); | |
262 case MNCC_REJ_IND: | |
263 printf("MNCC_REJ_IND: MT call rejected\n"); | |
264 print_fields(msg); | |
265 exit(0); | |
266 } | |
267 } | |
268 | |
269 static void | |
270 handle_rtp_create(msg, msglen) | |
271 struct gsm_mncc_rtp *msg; | |
272 unsigned msglen; | |
273 { | |
274 if (msglen != sizeof(struct gsm_mncc_rtp)) { | |
275 fprintf(stderr, | |
276 "error: Rx MNCC message type 0x%x has wrong length\n", | |
277 msg->msg_type); | |
278 exit(1); | |
279 } | |
280 if (msg->callref != 1) { | |
281 fprintf(stderr, | |
282 "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n", | |
283 msg->msg_type, msg->callref); | |
284 exit(1); | |
285 } | |
286 printf("MNCC_RTP_CREATE: RTP info from MSC\n"); | |
287 printf("payload_type=0x%x payload_msg_type=0x%x\n", msg->payload_type, | |
288 msg->payload_msg_type); | |
289 } | |
290 | |
291 void | |
292 msg_from_mncc(msg, msglen) | |
293 union mncc_msg *msg; | |
294 unsigned msglen; | |
295 { | |
296 switch (msg->msg_type) { | |
297 case MNCC_SETUP_CNF: | |
298 case MNCC_CALL_CONF_IND: | |
299 case MNCC_ALERT_IND: | |
300 case MNCC_NOTIFY_IND: | |
301 case MNCC_DISC_IND: | |
302 case MNCC_FACILITY_IND: | |
303 case MNCC_START_DTMF_IND: | |
304 case MNCC_STOP_DTMF_IND: | |
305 case MNCC_MODIFY_IND: | |
306 case MNCC_HOLD_IND: | |
307 case MNCC_RETRIEVE_IND: | |
308 case MNCC_USERINFO_IND: | |
309 case MNCC_REL_IND: | |
310 case MNCC_REL_CNF: | |
311 case MNCC_REJ_IND: | |
312 handle_signaling_msg(msg, msglen); | |
313 return; | |
314 case MNCC_RTP_CREATE: | |
315 handle_rtp_create(msg, msglen); | |
316 return; | |
317 default: | |
318 fprintf(stderr, | |
319 "error: received unexpected MNCC message type 0x%x\n", | |
320 msg->msg_type); | |
321 exit(1); | |
322 } | |
323 } |