diff mncc/mncc_recv.c @ 15:ccc5ab6d8388

first version of themwi-mncc for ThemWi2
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 26 Jun 2022 16:31:47 -0800
parents
children 660126bd5f59
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mncc/mncc_recv.c	Sun Jun 26 16:31:47 2022 -0800
@@ -0,0 +1,188 @@
+/*
+ * In this module we implement initial handling of MNCC messages
+ * coming from OsmoMSC, dispatching them further as appropriate.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <syslog.h>
+#include "../include/mncc.h"
+#include "struct.h"
+#include "gsm_call.h"
+
+static void
+report_runt(msg)
+	union mncc_msg *msg;
+{
+	syslog(LOG_CRIT, "MNCC message type 0x%x from GSM is too short!",
+		msg->msg_type);
+}
+
+static void
+handle_setup_ind(msg, msglen)
+	struct gsm_mncc *msg;
+	unsigned msglen;
+{
+	struct gsm_call *call;
+
+	if (msglen < sizeof(struct gsm_mncc)) {
+		report_runt(msg);
+		return;
+	}
+	call = find_gsm_callref(msg->callref);
+	if (call) {
+		syslog(LOG_ERR, "duplicate MNCC_SETUP_IND for callref 0x%x",
+			msg->callref);
+		/* drop it like OsmoMSC's mncc_builtin does */
+		return;
+	}
+	/* further processing */
+	process_mo_call_setup(msg);
+}
+
+static void
+handle_signaling_msg(msg, msglen)
+	struct gsm_mncc *msg;
+	unsigned msglen;
+{
+	struct gsm_call *call;
+
+	if (msglen < sizeof(struct gsm_mncc)) {
+		report_runt(msg);
+		return;
+	}
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR,
+			"MNCC message type 0x%x: callref 0x%x not found",
+			msg->msg_type, msg->callref);
+		/* drop it like OsmoMSC's mncc_builtin does */
+		return;
+	}
+	if (msg->msg_type == MNCC_SETUP_CNF)
+		preen_connected_number(msg);
+	/* dispatch according to internal switch or socket */
+	if (call->socket)
+		mncc_signal_to_socket(call, msg);
+	else
+		internal_switch_mncc(call, msg);
+}
+
+static void
+handle_release_msg(msg, msglen)
+	struct gsm_mncc *msg;
+	unsigned msglen;
+{
+	struct gsm_call *call;
+
+	if (msglen < sizeof(struct gsm_mncc)) {
+		report_runt(msg);
+		return;
+	}
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR,
+			"MNCC message type 0x%x: callref 0x%x not found",
+			msg->msg_type, msg->callref);
+		/* drop it like OsmoMSC's mncc_builtin does */
+		return;
+	}
+	/* dispatch according to internal switch or socket */
+	if (call->socket) {
+		mncc_signal_to_socket(call, msg);
+		extsock_dec_refcount(call->socket);
+		call->gc_flag = 1;
+	} else
+		internal_switch_mncc(call, msg);
+}
+
+static void
+handle_rtp_msg(msg, msglen)
+	struct gsm_mncc_rtp *msg;
+	unsigned msglen;
+{
+	struct gsm_call *call;
+
+	if (msglen < sizeof(struct gsm_mncc_rtp)) {
+		report_runt(msg);
+		return;
+	}
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR,
+			"MNCC message type 0x%x: callref 0x%x not found",
+			msg->msg_type, msg->callref);
+		/* drop it like OsmoMSC's mncc_builtin does */
+		return;
+	}
+	/* only for socket connections - no RTP handling for internal */
+	if (call->socket)
+		mncc_rtp_to_socket(call, msg);
+}
+
+static void
+handle_mncc_hello(msg, msglen)
+	struct gsm_mncc_hello *msg;
+	unsigned msglen;
+{
+	if (msglen < sizeof(struct gsm_mncc_hello)) {
+		syslog(LOG_CRIT, "MNCC_SOCKET_HELLO message is too short!");
+		exit(1);
+	}
+	if (msg->version != MNCC_SOCK_VERSION) {
+		syslog(LOG_CRIT, "MNCC hello error: version number mismatch");
+		exit(1);
+	}
+	if (msg->mncc_size != sizeof(struct gsm_mncc)) {
+		syslog(LOG_CRIT, "MNCC hello error: mncc_size mismatch");
+		exit(1);
+	}
+}
+
+void
+mncc_msg_from_gsm(msg, msglen)
+	union mncc_msg *msg;
+	unsigned msglen;
+{
+	switch (msg->msg_type) {
+	case MNCC_SETUP_IND:
+		handle_setup_ind(msg, msglen);
+		return;
+	case MNCC_SETUP_CNF:
+	case MNCC_SETUP_COMPL_IND:
+	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_MODIFY_CNF:
+	case MNCC_MODIFY_REJ:
+	case MNCC_HOLD_IND:
+	case MNCC_RETRIEVE_IND:
+	case MNCC_USERINFO_IND:
+		handle_signaling_msg(msg, msglen);
+		return;
+	case MNCC_REL_IND:
+	case MNCC_REL_CNF:
+	case MNCC_REJ_IND:
+		handle_release_msg(msg, msglen);
+		return;
+	case MNCC_RTP_CREATE:
+	case MNCC_RTP_CONNECT:
+	case MNCC_RTP_FREE:
+		handle_rtp_msg(msg, msglen);
+		return;
+	case MNCC_SOCKET_HELLO:
+		handle_mncc_hello(msg, msglen);
+		return;
+	default:
+		syslog(LOG_CRIT, "unknown MNCC message type 0x%x from GSM",
+			msg->msg_type);
+	}
+}