diff sip-in/mncc_handle.c @ 141:e499e8db8b82

sip-in: handle call hold and retrieve
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 08 Oct 2022 13:28:30 -0800
parents 01fe81914bd6
children 99fd4ae573ae
line wrap: on
line diff
--- a/sip-in/mncc_handle.c	Sat Oct 08 11:48:26 2022 -0800
+++ b/sip-in/mncc_handle.c	Sat Oct 08 13:28:30 2022 -0800
@@ -79,6 +79,30 @@
 	send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc));
 }
 
+void
+mncc_send_hold_ack(call)
+	struct call *call;
+{
+	struct gsm_mncc msg;
+
+	bzero(&msg, sizeof(struct gsm_mncc));
+	msg.msg_type = MNCC_HOLD_CNF;
+	msg.callref = call->mncc_callref;
+	send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc));
+}
+
+void
+mncc_send_retrieve_ack(call)
+	struct call *call;
+{
+	struct gsm_mncc msg;
+
+	bzero(&msg, sizeof(struct gsm_mncc));
+	msg.msg_type = MNCC_RETRIEVE_CNF;
+	msg.callref = call->mncc_callref;
+	send_mncc_to_gsm(&msg, sizeof(struct gsm_mncc));
+}
+
 static void
 send_rtp_connect(call)
 	struct call *call;
@@ -205,11 +229,50 @@
 	struct call *call;
 	struct gsm_mncc *msg;
 {
-	if (call->overall_state == OVERALL_STATE_CONNECTED &&
-	    call->mgw_state == MGW_STATE_COMPLETE)
+	if (call->overall_state != OVERALL_STATE_CONNECTED)
+		return;
+	if (call->mgw_state == MGW_STATE_COMPLETE)
 		tmgw_send_dtmf_stop(call);
-	else
+	else if (call->mgw_state == MGW_STATE_DTMF_OP)
 		call->dtmf_pending_stop = 1;
+	else {
+		/* dummy OK response */
+		msg->msg_type = MNCC_STOP_DTMF_RSP;
+		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
+	}
+}
+
+static void
+handle_call_hold(call, msg)
+	struct call *call;
+	struct gsm_mncc *msg;
+{
+	if (call->overall_state != OVERALL_STATE_CONNECTED ||
+	    call->mgw_state != MGW_STATE_COMPLETE) {
+		msg->msg_type = MNCC_HOLD_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;
+	}
+	tmgw_send_mdcx_hold(call);
+}
+
+static void
+handle_call_retrieve(call, msg)
+	struct call *call;
+	struct gsm_mncc *msg;
+{
+	if (call->overall_state != OVERALL_STATE_CONNECTED ||
+	    call->mgw_state != MGW_STATE_HELD) {
+		msg->msg_type = MNCC_RETRIEVE_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;
+	}
+	send_rtp_connect(call);
+	tmgw_send_mdcx_retrieve(call);
 }
 
 static void
@@ -260,16 +323,10 @@
 		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
 		return;
 	case MNCC_HOLD_IND:
-		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));
+		handle_call_hold(call, msg);
 		return;
 	case MNCC_RETRIEVE_IND:
-		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));
+		handle_call_retrieve(call, msg);
 		return;
 	}
 }