view sip-in/mncc_handle.c @ 63:e5aee661e3b2

sip-in: beginning to handle incoming MNCC messages from themwi-mncc
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 18 Sep 2022 15:01:11 -0800
parents
children 7c0309df59f8
line wrap: on
line source

/*
 * In this module we implement our handling of call control messages
 * from OsmoMSC relayed to us via themwi-mncc.
 */

#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/mncc.h"
#include "../include/gsm48_const.h"
#include "call.h"

extern struct call *find_call_by_mncc_callref();

static void
handle_alerting(call, msg)
	struct call *call;
	struct gsm_mncc *msg;
{
	/* handling to be implemented */
}

static void
handle_answer(call, msg)
	struct call *call;
	struct gsm_mncc *msg;
{
	/* handling to be implemented */
}

static void
handle_disconnect_ind(call, msg)
	struct call *call;
	struct gsm_mncc *msg;
{
	/* handling to be implemented */
}

static void
handle_final_release(call, msg)
	struct call *call;
	struct gsm_mncc *msg;
{
	/* handling to be implemented */
}

static void
handle_signaling_msg(msg, msglen)
	struct gsm_mncc *msg;
	unsigned msglen;
{
	struct call *call;

	if (msglen != sizeof(struct gsm_mncc)) {
		syslog(LOG_CRIT,
			"FATAL: Rx MNCC message type 0x%x has wrong length",
			msg->msg_type);
		exit(1);
	}
	call = find_call_by_mncc_callref(msg->callref);
	if (!call) {
		syslog(LOG_CRIT,
		"error: Rx MNCC message type 0x%x has invalid callref 0x%x",
			msg->msg_type, msg->callref);
		exit(1);
	}
	switch (msg->msg_type) {
	case MNCC_SETUP_CNF:
		handle_answer(call, msg);
		return;
	case MNCC_ALERT_IND:
		handle_alerting(call, msg);
		return;
	case MNCC_DISC_IND:
		handle_disconnect_ind(call, msg);
		return;
	case MNCC_REL_IND:
	case MNCC_REL_CNF:
	case MNCC_REJ_IND:
		handle_final_release(call, msg);
		return;
	case MNCC_START_DTMF_IND:
		msg->msg_type = MNCC_START_DTMF_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));
		return;
	case MNCC_STOP_DTMF_IND:
		msg->msg_type = MNCC_STOP_DTMF_RSP;
		send_mncc_to_gsm(msg, sizeof(struct gsm_mncc));
		return;
	case MNCC_MODIFY_IND:
		msg->msg_type = MNCC_MODIFY_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));
		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));
		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));
		return;
	}
}

static void
handle_rtp_create(msg, msglen)
	struct gsm_mncc_rtp *msg;
	unsigned msglen;
{
	struct call *call;

	if (msglen != sizeof(struct gsm_mncc_rtp)) {
		syslog(LOG_CRIT,
			"FATAL: Rx MNCC message type 0x%x has wrong length",
			msg->msg_type);
		exit(1);
	}
	call = find_call_by_mncc_callref(msg->callref);
	if (!call) {
		syslog(LOG_CRIT,
		"error: Rx MNCC message type 0x%x has invalid callref 0x%x",
			msg->msg_type, msg->callref);
		exit(1);
	}
	/* handling to be implemented */
}

void
msg_from_mncc(msg, msglen)
	union mncc_msg *msg;
	unsigned msglen;
{
	switch (msg->msg_type) {
	case MNCC_SETUP_CNF:
	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_HOLD_IND:
	case MNCC_RETRIEVE_IND:
	case MNCC_USERINFO_IND:
	case MNCC_REL_IND:
	case MNCC_REL_CNF:
	case MNCC_REJ_IND:
		handle_signaling_msg(msg, msglen);
		return;
	case MNCC_RTP_CREATE:
		handle_rtp_create(msg, msglen);
		return;
	default:
		syslog(LOG_CRIT,
			"FATAL: received unexpected MNCC message type 0x%x",
			msg->msg_type);
		exit(1);
	}
}