diff sip-in/mgw_ops.c @ 60:02761f1ae5e5

sip-in INVITE processing: got as far as CRCX completion
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 11 Sep 2022 15:42:54 -0800
parents
children e12036337412
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sip-in/mgw_ops.c	Sun Sep 11 15:42:54 2022 -0800
@@ -0,0 +1,204 @@
+/*
+ * In this module we implement all transactions from themwi-sip-in
+ * toward themwi-mgw.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <syslog.h>
+#include "../include/tmgw_ctrl.h"
+#include "../include/tmgw_const.h"
+#include "call.h"
+
+extern struct call *call_list;
+
+struct call *
+find_call_with_mgw_xact(xact_id)
+	uint32_t xact_id;
+{
+	struct call *call;
+
+	for (call = call_list; call; call = call->next)
+		if (call->mgw_xact && call->mgw_xact_id == xact_id)
+			return call;
+	return 0;
+}
+
+uint32_t
+get_new_tmgw_xact_id()
+{
+	static uint32_t next_xact_id;
+
+	for (;;) {
+		next_xact_id++;
+		if (!find_call_with_mgw_xact(next_xact_id))
+			return next_xact_id;
+	}
+}
+
+void
+tmgw_send_crcx(call)
+	struct call *call;
+{
+	struct tmgw_ctrl_req req;
+
+	bzero(&req, sizeof req);
+	req.opcode = TMGW_CTRL_OP_CRCX;
+	req.transact_ref = get_new_tmgw_xact_id();
+	req.ep_id = TMGW_EP_TYPE_GATEWAY;
+	req.setup_mask = TMGW_CTRL_MASK_PSTN_CONN;
+	bcopy(&call->pstn_rtp_remote, &req.pstn_addr,
+		sizeof(struct sockaddr_in));
+	req.pstn_payload_type =
+		call->use_pcma ? PSTN_CODEC_PCMA : PSTN_CODEC_PCMU;
+	send_req_to_tmgw(&req);
+	call->mgw_xact = TMGW_CTRL_OP_CRCX;
+	call->mgw_xact_id = req.transact_ref;
+}
+
+void
+tmgw_send_mdcx_gsm_rtp(call)
+	struct call *call;
+{
+	struct tmgw_ctrl_req req;
+
+	bzero(&req, sizeof req);
+	req.opcode = TMGW_CTRL_OP_MDCX;
+	req.transact_ref = get_new_tmgw_xact_id();
+	req.ep_id = call->mgw_ep_id;;
+	req.setup_mask = TMGW_CTRL_MASK_GSM_CONN;
+	bcopy(&call->gsm_rtp_osmo, &req.gsm_addr,
+		sizeof(struct sockaddr_storage));
+	req.gsm_payload_type = call->gsm_payload_type;
+	req.gsm_payload_msg_type = call->gsm_payload_msg_type;
+	send_req_to_tmgw(&req);
+	call->mgw_state = MGW_STATE_CONNECTING;
+	call->mgw_xact = TMGW_CTRL_OP_MDCX;
+	call->mgw_xact_id = req.transact_ref;
+}
+
+void
+tmgw_send_dlcx(call)
+	struct call *call;
+{
+	struct tmgw_ctrl_req req;
+
+	bzero(&req, sizeof req);
+	req.opcode = TMGW_CTRL_OP_DLCX;
+	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_DELETING;
+	call->mgw_xact = TMGW_CTRL_OP_DLCX;
+	call->mgw_xact_id = req.transact_ref;
+}
+
+static void
+handle_crcx_fail(call, msg)
+	struct call *call;
+	struct tmgw_ctrl_resp *msg;
+{
+	call->overall_state = OVERALL_STATE_TEARDOWN;
+	strcpy(call->invite_fail, "503 Gateway resource allocation failure");
+	signal_invite_error(call);
+}
+
+static void
+crcx_response(call, msg)
+	struct call *call;
+	struct tmgw_ctrl_resp *msg;
+{
+	if (msg->res == TMGW_RESP_OK) {
+		call->mgw_state = MGW_STATE_ALLOCATED;
+		call->mgw_ep_id = msg->ep_id;
+		bcopy(&msg->gsm_addr, &call->gsm_rtp_tmgw,
+			sizeof(struct sockaddr_storage));
+		bcopy(&msg->pstn_addr, &call->pstn_rtp_local,
+			sizeof(struct sockaddr_in));
+		switch (call->overall_state) {
+		case OVERALL_STATE_CRCX:
+			/* proceed_with_call_setup(call); */
+			return;
+		case OVERALL_STATE_TEARDOWN:
+			tmgw_send_dlcx(call);
+			return;
+		default:
+		bad_state:
+			syslog(LOG_CRIT,
+			"FATAL: invalid overall state 0x%x on CRCX response",
+				call->overall_state);
+			exit(1);
+		}
+	} else {
+		switch (call->overall_state) {
+		case OVERALL_STATE_CRCX:
+			handle_crcx_fail(call, msg);
+			return;
+		case OVERALL_STATE_TEARDOWN:
+			return;
+		default:
+			goto bad_state;
+		}
+	}
+}
+
+static void
+mdcx_response(call, msg)
+	struct call *call;
+	struct tmgw_ctrl_resp *msg;
+{
+	/* will be handled later */
+}
+
+static void
+dlcx_response(call, msg)
+	struct call *call;
+	struct tmgw_ctrl_resp *msg;
+{
+	if (msg->res != TMGW_RESP_OK) {
+		syslog(LOG_CRIT, "FATAL: TMGW DLCX failed with code 0x%x",
+			msg->res);
+		exit(1);
+	}
+	call->mgw_state = MGW_STATE_NO_EXIST;
+	/* TODO: transition from TEARDOWN to DEAD_SIP */
+}
+
+void
+process_tmgw_response(msg)
+	struct tmgw_ctrl_resp *msg;
+{
+	struct call *call;
+	unsigned opc;
+
+	call = find_call_with_mgw_xact(msg->transact_ref);
+	if (!call) {
+		syslog(LOG_CRIT,
+		"FATAL: response from TMGW xact 0x%x does not match any call",
+			msg->transact_ref);
+		exit(1);
+	}
+	opc = call->mgw_xact;
+	call->mgw_xact = 0;
+	switch (opc) {
+	case TMGW_CTRL_OP_CRCX:
+		crcx_response(call, msg);
+		return;
+	case TMGW_CTRL_OP_MDCX:
+		mdcx_response(call, msg);
+		return;
+	case TMGW_CTRL_OP_DLCX:
+		dlcx_response(call, msg);
+		return;
+	default:
+		syslog(LOG_CRIT,
+			"FATAL: invalid opcode 0x%x in call->msg_xact", opc);
+		exit(1);
+	}
+}