FreeCalypso > hg > themwi-system-sw
view mtctest/sig_handler.c @ 124:7e04d28fae8b
sip-in: default use-100rel to no
BulkVS servers act badly when we send a reliable 180 Ringing response
to an incoming call, even though they advertise 100rel support in
the Supported header in the INVITE packet, and we probably won't be
implementing 100rel for outbound because doing per-the-spec PRACK
as a UAC is just too burdensome. Therefore, we need to consider
100rel extension as not-really-supported in themwi-system-sw.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 01 Oct 2022 15:54:50 -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); } }