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 } |
