diff mncc/mncc_recv.c @ 2:053f04687106

mncc: initial import from old ThemWi
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 08 Jun 2024 23:12:12 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mncc/mncc_recv.c	Sat Jun 08 23:12:12 2024 +0000
@@ -0,0 +1,198 @@
+/*
+ * 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"
+
+extern char *mncc_msg_name();
+
+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;
+	}
+	syslog(LOG_DEBUG, "Rx MNCC_SETUP_IND from GSM, callref=0x%x",
+		msg->callref);
+	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;
+	}
+	syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x",
+		mncc_msg_name(msg->msg_type), msg->callref);
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR, "%s from GSM: callref 0x%x not found",
+			mncc_msg_name(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;
+	}
+	syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x",
+		mncc_msg_name(msg->msg_type), msg->callref);
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR, "%s from GSM: callref 0x%x not found",
+			mncc_msg_name(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);
+		syslog(LOG_DEBUG,
+		"clearing socket call: GSM callref 0x%x, socket ref 0x%x",
+			call->callref, call->socket_ref);
+		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;
+	}
+	syslog(LOG_DEBUG, "Rx %s from GSM, callref=0x%x",
+		mncc_msg_name(msg->msg_type), msg->callref);
+	call = find_gsm_callref(msg->callref);
+	if (!call) {
+		syslog(LOG_ERR, "%s from GSM: callref 0x%x not found",
+			mncc_msg_name(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);
+	}
+}