view smsc-daemon/gsup_rx.c @ 5:cef4677a4cf8

smsc-daemon: the starting program is called osmo-euse-demo
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Aug 2023 14:07:41 -0800
parents 8680979baeb1
children 81386a48c463
line wrap: on
line source

/*
 * This C module is part of proto-smsc-daemon concoction, a prototype/test
 * implementation of a GSUP-based GSM SMSC.  It is based on the osmo-euse-demo
 * program from OsmoHLR package.
 *
 * proto-smsc-daemon author: Mychaela N. Falconia <falcon@freecalypso.org>,
 * no copyright.
 *
 * osmo-euse-demo author: Harald Welte <laforge@gnumonks.org>, (C) 2018, AGPL3+
 */

#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>

#include <osmocom/core/msgb.h>
#include <osmocom/core/select.h>
#include <osmocom/core/application.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>

#include <osmocom/gsm/gsup.h>

#include <osmocom/gsupclient/gsup_client.h>

#include "logging.h"

extern void record_mo_sm(struct osmo_gsup_message *gmsg);

static void send_gsup_response(struct osmo_gsup_client *gsupc,
				struct osmo_gsup_message *orig_msg)
{
	struct osmo_gsup_message resp = {0};
	struct msgb *resp_msg;

	resp.message_type = OSMO_GSUP_TO_MSGT_RESULT(orig_msg->message_type);
	OSMO_STRLCPY_ARRAY(resp.imsi, orig_msg->imsi);
	resp.message_class = OSMO_GSUP_MESSAGE_CLASS_SMS;
	resp.sm_rp_mr = orig_msg->sm_rp_mr;
	resp.destination_name = orig_msg->source_name;
	resp.destination_name_len = orig_msg->source_name_len;

	resp_msg = osmo_gsup_client_msgb_alloc();
	OSMO_ASSERT(resp_msg);
	osmo_gsup_encode(resp_msg, &resp);
	osmo_gsup_client_send(gsupc, resp_msg);
}

static void handle_mo_forward_sm(struct osmo_gsup_client *gsupc,
				 struct osmo_gsup_message *gmsg)
{
	if (!gmsg->sm_rp_mr) {
		LOGP(DMAIN, LOGL_ERROR,
		     "error in MO-FORWARD-SM: missing SM-RP-MR\n");
		return;
	}
	if (!gmsg->sm_rp_da_type) {
		LOGP(DMAIN, LOGL_ERROR,
		     "error in MO-FORWARD-SM: missing SM-RP-DA\n");
		return;
	}
	if (!gmsg->sm_rp_oa_type) {
		LOGP(DMAIN, LOGL_ERROR,
		     "error in MO-FORWARD-SM: missing SM-RP-OA\n");
		return;
	}
	if (!gmsg->sm_rp_ui) {
		LOGP(DMAIN, LOGL_ERROR,
		     "error in MO-FORWARD-SM: missing SM-RP-UI\n");
		return;
	}
	record_mo_sm(gmsg);
	send_gsup_response(gsupc, gmsg);
}

static void handle_ready_for_sm(struct osmo_gsup_client *gsupc,
				struct osmo_gsup_message *gmsg)
{
	if (!gmsg->sm_rp_mr) {
		LOGP(DMAIN, LOGL_ERROR,
		     "error in READY-FOR-SM: missing SM-RP-MR\n");
		return;
	}
	send_gsup_response(gsupc, gmsg);
}

int gsupc_read_cb(struct osmo_gsup_client *gsupc, struct msgb *msg)
{
	struct osmo_gsup_message gsup_msg = {0};
	int rc;

	rc = osmo_gsup_decode(msgb_l2(msg), msgb_l2len(msg), &gsup_msg);
	if (rc < 0) {
		LOGP(DMAIN, LOGL_ERROR, "Error decoding GSUP: %s\n", msgb_hexdump(msg));
		return rc;
	}
	DEBUGP(DMAIN, "Rx GSUP %s: %s\n", osmo_gsup_message_type_name(gsup_msg.message_type),
		msgb_hexdump(msg));

	switch (gsup_msg.message_type) {
	case OSMO_GSUP_MSGT_MO_FORWARD_SM_REQUEST:
		handle_mo_forward_sm(gsupc, &gsup_msg);
		break;
	case OSMO_GSUP_MSGT_READY_FOR_SM_REQUEST:
		handle_ready_for_sm(gsupc, &gsup_msg);
		break;
	default:
		LOGP(DMAIN, LOGL_ERROR, "Unhandled GSUP message type %s\n",
			osmo_gsup_message_type_name(gsup_msg.message_type));
		break;
	}

	msgb_free(msg);
	return 0;
}