# HG changeset patch # User Mychaela Falconia # Date 1664694421 28800 # Node ID 5685412bd6aad9ccc35c5c82ba54f87353e949d1 # Parent f062c32a5116d579c2aba3ebb555d84415df3fa7 sip-in: pass DTMF start & stop to themwi-mgw diff -r f062c32a5116 -r 5685412bd6aa sip-in/call.h --- a/sip-in/call.h Sat Oct 01 20:31:15 2022 -0800 +++ b/sip-in/call.h Sat Oct 01 23:07:01 2022 -0800 @@ -42,6 +42,8 @@ char invite_fail[80]; unsigned sip_tx_count; time_t sip_clear_time; + int dtmf_digit; + int dtmf_pending_stop; }; #define OVERALL_STATE_CRCX 1 @@ -75,3 +77,4 @@ #define MGW_STATE_CONNECTING 2 #define MGW_STATE_COMPLETE 3 #define MGW_STATE_DELETING 4 +#define MGW_STATE_DTMF_OP 5 diff -r f062c32a5116 -r 5685412bd6aa sip-in/disconnect.c --- a/sip-in/disconnect.c Sat Oct 01 20:31:15 2022 -0800 +++ b/sip-in/disconnect.c Sat Oct 01 23:07:01 2022 -0800 @@ -44,6 +44,7 @@ case MGW_STATE_NO_EXIST: case MGW_STATE_CONNECTING: case MGW_STATE_DELETING: + case MGW_STATE_DTMF_OP: return; case MGW_STATE_ALLOCATED: case MGW_STATE_COMPLETE: diff -r f062c32a5116 -r 5685412bd6aa sip-in/mgw_ops.c --- a/sip-in/mgw_ops.c Sat Oct 01 20:31:15 2022 -0800 +++ b/sip-in/mgw_ops.c Sat Oct 01 23:07:01 2022 -0800 @@ -102,6 +102,39 @@ call->mgw_xact_id = req.transact_ref; } +void +tmgw_send_dtmf_start(call) + struct call *call; +{ + struct tmgw_ctrl_req req; + + bzero(&req, sizeof req); + req.opcode = TMGW_CTRL_OP_DTMF_START; + req.transact_ref = get_new_tmgw_xact_id(); + req.ep_id = call->mgw_ep_id; + req.fwd_mode = call->dtmf_digit; + send_req_to_tmgw(&req); + call->mgw_state = MGW_STATE_DTMF_OP; + call->mgw_xact = TMGW_CTRL_OP_DTMF_START; + call->mgw_xact_id = req.transact_ref; +} + +void +tmgw_send_dtmf_stop(call) + struct call *call; +{ + struct tmgw_ctrl_req req; + + bzero(&req, sizeof req); + req.opcode = TMGW_CTRL_OP_DTMF_STOP; + req.transact_ref = get_new_tmgw_xact_id(); + req.ep_id = call->mgw_ep_id; + send_req_to_tmgw(&req); + call->mgw_state = MGW_STATE_DTMF_OP; + call->mgw_xact = TMGW_CTRL_OP_DTMF_STOP; + call->mgw_xact_id = req.transact_ref; +} + static void handle_crcx_fail(call, msg) struct call *call; @@ -227,6 +260,39 @@ transition_dead_sip(call); } +static void +dtmf_start_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (call->overall_state == OVERALL_STATE_TEARDOWN) { + tmgw_send_dlcx(call); + return; + } + if (msg->res == TMGW_RESP_OK) + mncc_dtmf_start_ok(call); + else + mncc_dtmf_start_err(call); + if (call->dtmf_pending_stop) + tmgw_send_dtmf_stop(call); + else + call->mgw_state = MGW_STATE_COMPLETE; +} + +static void +dtmf_stop_response(call, msg) + struct call *call; + struct tmgw_ctrl_resp *msg; +{ + if (call->overall_state == OVERALL_STATE_TEARDOWN) { + tmgw_send_dlcx(call); + return; + } + mncc_dtmf_stop_ok(call); + call->mgw_state = MGW_STATE_COMPLETE; + call->dtmf_pending_stop = 0; +} + void process_tmgw_response(msg) struct tmgw_ctrl_resp *msg; @@ -253,6 +319,12 @@ case TMGW_CTRL_OP_DLCX: dlcx_response(call, msg); return; + case TMGW_CTRL_OP_DTMF_START: + dtmf_start_response(call, msg); + return; + case TMGW_CTRL_OP_DTMF_STOP: + dtmf_stop_response(call, msg); + return; default: syslog(LOG_CRIT, "FATAL: invalid opcode 0x%x in call->msg_xact", opc); diff -r f062c32a5116 -r 5685412bd6aa sip-in/mncc_handle.c --- a/sip-in/mncc_handle.c Sat Oct 01 20:31:15 2022 -0800 +++ b/sip-in/mncc_handle.c Sat Oct 01 23:07:01 2022 -0800 @@ -39,6 +39,46 @@ call->overall_state = OVERALL_STATE_CONNECTED; } +void +mncc_dtmf_start_ok(call) + struct call *call; +{ + struct gsm_mncc msg; + + bzero(&msg, sizeof(struct gsm_mncc)); + msg.msg_type = MNCC_START_DTMF_RSP; + msg.callref = call->mncc_callref; + msg.fields |= MNCC_F_KEYPAD; + msg.keypad = call->dtmf_digit; + send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); +} + +void +mncc_dtmf_start_err(call) + struct call *call; +{ + struct gsm_mncc msg; + + bzero(&msg, sizeof(struct gsm_mncc)); + msg.msg_type = MNCC_START_DTMF_REJ; + msg.callref = call->mncc_callref; + mncc_set_cause(&msg, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_PROTO_ERR); + send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); +} + +void +mncc_dtmf_stop_ok(call) + struct call *call; +{ + struct gsm_mncc msg; + + bzero(&msg, sizeof(struct gsm_mncc)); + msg.msg_type = MNCC_STOP_DTMF_RSP; + msg.callref = call->mncc_callref; + send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc)); +} + static void handle_alerting(call, msg) struct call *call; @@ -122,6 +162,43 @@ } static void +handle_dtmf_start(call, msg) + struct call *call; + struct gsm_mncc *msg; +{ + if (!(msg->fields & MNCC_F_KEYPAD) || + !is_valid_dtmf_digit(msg->keypad)) { + 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; + } + if (call->overall_state != OVERALL_STATE_CONNECTED || + call->mgw_state != MGW_STATE_COMPLETE) { + msg->msg_type = MNCC_START_DTMF_REJ; + mncc_set_cause(msg, GSM48_CAUSE_LOC_PRN_S_LU, + GSM48_CC_CAUSE_MSGTYPE_INCOMPAT); + send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); + return; + } + call->dtmf_digit = msg->keypad; + tmgw_send_dtmf_start(call); +} + +static void +handle_dtmf_stop(call, msg) + struct call *call; + struct gsm_mncc *msg; +{ + if (call->overall_state == OVERALL_STATE_CONNECTED && + call->mgw_state == MGW_STATE_COMPLETE) + tmgw_send_dtmf_stop(call); + else + call->dtmf_pending_stop = 1; +} + +static void handle_signaling_msg(msg, msglen) struct gsm_mncc *msg; unsigned msglen; @@ -157,14 +234,10 @@ handle_final_release(call, msg); return; case MNCC_START_DTMF_IND: - msg->msg_type = MNCC_START_DTMF_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)); + handle_dtmf_start(call, msg); return; case MNCC_STOP_DTMF_IND: - msg->msg_type = MNCC_STOP_DTMF_RSP; - send_mncc_to_gsm(msg, sizeof(struct gsm_mncc)); + handle_dtmf_stop(call, msg); return; case MNCC_MODIFY_IND: msg->msg_type = MNCC_MODIFY_REJ;