FreeCalypso > hg > themwi-system-sw
view mtctest/sig_handler.c @ 128:5685412bd6aa
sip-in: pass DTMF start & stop to themwi-mgw
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 01 Oct 2022 23:07:01 -0800 |
parents | 64b9f0f90726 |
children | 0967f67c6ac3 |
line wrap: on
line source
/* * In this module we handle all incoming messages from MNCC, * printing all of them and generating protocol-required responses * for some. */ #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include "../include/mncc.h" #include "../include/gsm48_const.h" extern int disconnect_mode; extern struct sockaddr_storage dummy_rtp_endp; static void print_bearer_cap(bcap) struct gsm_mncc_bearer_cap *bcap; { int i, sv; printf("Bearer cap: itcap=%d tmod=%d coding=%d rrq=%d\n", bcap->transfer, bcap->mode, bcap->coding, bcap->radio); printf(" speech: CTM=%d sv", bcap->speech_ctm); for (i = 0; i < 8; i++) { sv = bcap->speech_ver[i]; if (sv < 0) break; printf(" %d", sv); } putchar('\n'); printf(" data: ra=%d sig=%d async=%d nstop=%d ndata=%d\n", bcap->data.rate_adaption, bcap->data.sig_access, bcap->data.async, bcap->data.nr_stop_bits, bcap->data.nr_data_bits); printf(" urate=%d par=%d irate=%d transp=%d mtype=%d\n", bcap->data.user_rate, bcap->data.parity, bcap->data.interm_rate, bcap->data.transp, bcap->data.modem_type); } static void print_cc_cap(cc) struct gsm_mncc_cccap *cc; { printf("CC capabilities: DTMF=%d PCP=%d\n", cc->dtmf, cc->pcp); } static void print_cause(cause) struct gsm_mncc_cause *cause; { int i; printf("Cause: loc=%d coding=%d value=%d", cause->location, cause->coding, cause->value); if (cause->rec) printf(" rec=0x%02X", cause->rec_val); for (i = 0; i < cause->diag_len; i++) { if (!(i & 15)) { putchar('\n'); putchar(' '); } printf(" %02X", cause->diag[i] & 0xFF); } putchar('\n'); } static void print_progress(prog) struct gsm_mncc_progress *prog; { printf("Progress: loc=%d coding=%d descr=0x%02X", prog->location, prog->coding, prog->descr); } static void print_useruser(uu) struct gsm_mncc_useruser *uu; { printf("User-User IE: proto=0x%02X\n", uu->proto); /* dump to be implemented if and when we actually get a UU somewhere */ } static void print_keypad(kp) int kp; { if (kp >= '!' && kp <= '~') printf("Keypad code: %c\n", kp); else printf("Keypad code: 0x%02X\n", kp); } static void print_facility(fac) struct gsm_mncc_facility *fac; { int i; printf("Facility IE: %d byte(s)", fac->len); for (i = 0; i < fac->len; i++) { if (!(i & 15)) { putchar('\n'); putchar(' '); } printf(" %02X", fac->info[i] & 0xFF); } putchar('\n'); } static void print_ssver(ssv) struct gsm_mncc_ssversion *ssv; { int i; printf("SS version IE: %d byte(s)", ssv->len); for (i = 0; i < ssv->len; i++) { if (!(i & 15)) { putchar('\n'); putchar(' '); } printf(" %02X", ssv->info[i] & 0xFF); } putchar('\n'); } static void print_fields(msg) struct gsm_mncc *msg; { if (msg->fields & MNCC_F_BEARER_CAP) print_bearer_cap(&msg->bearer_cap); if (msg->fields & MNCC_F_CCCAP) print_cc_cap(&msg->cccap); if (msg->fields & MNCC_F_CAUSE) print_cause(&msg->cause); if (msg->fields & MNCC_F_PROGRESS) print_progress(&msg->progress); if (msg->fields & MNCC_F_USERUSER) print_useruser(&msg->useruser); if (msg->more) printf("More data flag set\n"); if (msg->fields & MNCC_F_KEYPAD) print_keypad(msg->keypad); if (msg->fields & MNCC_F_FACILITY) print_facility(&msg->facility); if (msg->fields & MNCC_F_SSVERSION) print_ssver(&msg->ssversion); } static void send_connect_ack() { struct gsm_mncc ack; printf("Sending connect ack\n"); bzero(&ack, sizeof(struct gsm_mncc)); ack.msg_type = MNCC_SETUP_COMPL_REQ; ack.callref = 1; send_mncc_to_gsm(&ack, sizeof(struct gsm_mncc)); } static void handle_signaling_msg(msg, msglen) struct gsm_mncc *msg; unsigned msglen; { if (msglen != sizeof(struct gsm_mncc)) { fprintf(stderr, "error: Rx MNCC message type 0x%x has wrong length\n", msg->msg_type); exit(1); } if (msg->callref != 1) { fprintf(stderr, "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n", msg->msg_type, msg->callref); exit(1); } switch (msg->msg_type) { case MNCC_SETUP_CNF: printf("MNCC_SETUP_CNF: call is answered\n"); print_fields(msg); send_connect_ack(); return; case MNCC_CALL_CONF_IND: printf("MNCC_CALL_CONF_IND: call is confirmed\n"); print_fields(msg); return; case MNCC_ALERT_IND: printf("MNCC_ALERT_IND: call is alerting\n"); print_fields(msg); return; case MNCC_NOTIFY_IND: printf("NNCC_NOTIFY_IND: NOTIFY byte from MS: 0x%02X\n", msg->notify); return; case MNCC_DISC_IND: printf("MNCC_DISC_IND: MS initiates disconnect\n"); print_fields(msg); disconnect_mode = 1; printf("Responding with release request\n"); msg->msg_type = MNCC_REL_REQ; send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_FACILITY_IND: printf("MNCC_FACILITY_IND: call-related SS from MS\n"); print_fields(msg); return; case MNCC_START_DTMF_IND: printf("MNCC_START_DTMF_IND: MS sending DTMF start\n"); print_fields(msg); if (msg->fields & MNCC_F_KEYPAD && is_valid_dtmf_digit(msg->keypad)) { printf("Responding with ACK\n"); msg->msg_type = MNCC_START_DTMF_RSP; } else { printf("Responding with Reject\n"); msg->msg_type = MNCC_START_DTMF_REJ; mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_INVAL_MAND_INF); } send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_STOP_DTMF_IND: printf("MNCC_STOP_DTMF_IND: MS sending DTMF stop\n"); msg->msg_type = MNCC_STOP_DTMF_RSP; send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_MODIFY_IND: printf("MNCC_MODIFY_IND: MS requests call modification\n"); print_fields(msg); msg->msg_type = MNCC_MODIFY_REJ; mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_SERV_OPT_UNIMPL); send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_HOLD_IND: printf("MNCC_HOLD_IND: MS requests call hold\n"); msg->msg_type = MNCC_HOLD_REJ; mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_SERV_OPT_UNIMPL); send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_RETRIEVE_IND: printf("MNCC_RETRIEVE_IND: MS requests call retrieve\n"); msg->msg_type = MNCC_RETRIEVE_REJ; mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, GSM48_CC_CAUSE_SERV_OPT_UNIMPL); send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); return; case MNCC_USERINFO_IND: printf("MNCC_USERINFO_IND: user-user info\n"); print_fields(msg); return; case MNCC_REL_IND: printf("MNCC_REL_IND: final release\n"); print_fields(msg); exit(0); case MNCC_REL_CNF: printf("MNCC_REL_CNF: final release in response to request\n"); print_fields(msg); exit(0); case MNCC_REJ_IND: printf("MNCC_REJ_IND: MT call rejected\n"); print_fields(msg); exit(0); } } static void handle_rtp_create(msg, msglen) struct gsm_mncc_rtp *msg; unsigned msglen; { if (msglen != sizeof(struct gsm_mncc_rtp)) { fprintf(stderr, "error: Rx MNCC message type 0x%x has wrong length\n", msg->msg_type); exit(1); } if (msg->callref != 1) { fprintf(stderr, "error: Rx MNCC message type 0x%x has unexpected callref 0x%x\n", msg->msg_type, msg->callref); exit(1); } printf("MNCC_RTP_CREATE: RTP info from MSC\n"); printf("payload_type=0x%x payload_msg_type=0x%x\n", msg->payload_type, msg->payload_msg_type); printf("Responding with MNCC_RTP_CONNECT (dummy RTP endpoint)\n"); msg->msg_type = MNCC_RTP_CONNECT; bcopy(&dummy_rtp_endp, &msg->addr, sizeof(struct sockaddr_storage)); send_mncc_to_gsm(msg, sizeof(struct gsm_mncc_rtp)); } void msg_from_mncc(msg, msglen) union mncc_msg *msg; unsigned msglen; { switch (msg->msg_type) { case MNCC_SETUP_CNF: case MNCC_CALL_CONF_IND: case MNCC_ALERT_IND: case MNCC_NOTIFY_IND: case MNCC_DISC_IND: case MNCC_FACILITY_IND: case MNCC_START_DTMF_IND: case MNCC_STOP_DTMF_IND: case MNCC_MODIFY_IND: case MNCC_HOLD_IND: case MNCC_RETRIEVE_IND: case MNCC_USERINFO_IND: case MNCC_REL_IND: case MNCC_REL_CNF: case MNCC_REJ_IND: handle_signaling_msg(msg, msglen); return; case MNCC_RTP_CREATE: handle_rtp_create(msg, msglen); return; default: fprintf(stderr, "error: received unexpected MNCC message type 0x%x\n", msg->msg_type); exit(1); } }