changeset 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 f062c32a5116
children b7cd66acb123
files sip-in/call.h sip-in/disconnect.c sip-in/mgw_ops.c sip-in/mncc_handle.c
diffstat 4 files changed, 155 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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:
--- 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);
--- 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;