view mncc/mncc_recv.c @ 124:7e04d28fae8b

sip-in: default use-100rel to no BulkVS servers act badly when we send a reliable 180 Ringing response to an incoming call, even though they advertise 100rel support in the Supported header in the INVITE packet, and we probably won't be implementing 100rel for outbound because doing per-the-spec PRACK as a UAC is just too burdensome. Therefore, we need to consider 100rel extension as not-really-supported in themwi-system-sw.
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 01 Oct 2022 15:54:50 -0800
parents 660126bd5f59
children
line wrap: on
line source

/*
 * 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);
	}
}