/* GSM silent call feature */

/*
 * (C) 2009 by Harald Welte <laforge@gnumonks.org>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <stdlib.h>
#include <unistd.h>
#include <errno.h>

#include <osmocom/core/msgb.h>
#include <osmocom/msc/signal.h>
#include <osmocom/msc/debug.h>
#include <osmocom/msc/gsm_data.h>
#include <osmocom/msc/gsm_subscriber.h>
#include <osmocom/msc/vlr.h>

/* paging of the requested subscriber has completed */
static int paging_cb_silent(unsigned int hooknum, unsigned int event,
			    struct msgb *msg, void *_conn, void *_data)
{
	struct ran_conn *conn = _conn;
	struct scall_signal_data sigdata;
	int rc = 0;

	if (hooknum != GSM_HOOK_RR_PAGING)
		return -EINVAL;

	DEBUGP(DLSMS, "paging_cb_silent: ");

	sigdata.conn = conn;
	sigdata.data = _data;

	switch (event) {
	case GSM_PAGING_SUCCEEDED:
#if BEFORE_MSCSPLIT
		/* Re-enable this log output once we can obtain this information via
		 * A-interface, see OS#2391. */
		DEBUGPC(DLSMS, "success, using Timeslot %u on ARFCN %u\n",
			conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
#endif
		conn->silent_call = 1;
		ran_conn_get(conn, RAN_CONN_USE_SILENT_CALL);
		/* increment lchan reference count */
		osmo_signal_dispatch(SS_SCALL, S_SCALL_SUCCESS, &sigdata);
		break;
	case GSM_PAGING_EXPIRED:
	case GSM_PAGING_BUSY:
		DEBUGP(DLSMS, "expired\n");
		osmo_signal_dispatch(SS_SCALL, S_SCALL_EXPIRED, &sigdata);
		break;
	default:
		rc = -EINVAL;
		break;
	}

	return rc;
}

#if 0
/* receive a layer 3 message from a silent call */
int silent_call_rx(struct ran_conn *conn, struct msgb *msg)
{
	/* FIXME: do something like sending it through a UDP port */
	LOGP(DLSMS, LOGL_NOTICE, "Discarding L3 message from a silent call.\n");
	return 0;
}

struct msg_match {
	uint8_t pdisc;
	uint8_t msg_type;
};

/* list of messages that are handled inside OpenBSC, even in a silent call */
static const struct msg_match silent_call_accept[] = {
	{ GSM48_PDISC_MM, GSM48_MT_MM_LOC_UPD_REQUEST },
	{ GSM48_PDISC_MM, GSM48_MT_MM_CM_SERV_REQ },
};

/* decide if we need to reroute a message as part of a silent call */
int silent_call_reroute(struct ran_conn *conn, struct msgb *msg)
{
	struct gsm48_hdr *gh = msgb_l3(msg);
	uint8_t pdisc = gsm48_hdr_pdisc(gh);
	uint8_t msg_type = gsm48_hdr_msg_type(gh);
	int i;

	/* if we're not part of a silent call, never reroute */
	if (!conn->silent_call)
		return 0;

	/* check if we are a special message that is handled in openbsc */
	for (i = 0; i < ARRAY_SIZE(silent_call_accept); i++) {
		if (silent_call_accept[i].pdisc == pdisc &&
		    silent_call_accept[i].msg_type == msg_type)
			return 0;
	}

	/* otherwise, reroute */
	LOGP(DLSMS, LOGL_INFO, "Rerouting L3 message from a silent call.\n");
	return 1;
}
#endif


/* initiate a silent call with a given subscriber */
int gsm_silent_call_start(struct vlr_subscr *vsub, void *data, int type)
{
	struct subscr_request *req;

	/* FIXME the VTY command allows selecting a silent call channel type.
	 * This doesn't apply to the situation after MSCSPLIT with an
	 * A-interface. */
	req = subscr_request_conn(vsub, paging_cb_silent, data,
				  "establish silent call");
	if (!req)
		return -ENODEV;
	return 0;
}

/* end a silent call with a given subscriber */
int gsm_silent_call_stop(struct vlr_subscr *vsub)
{
	struct ran_conn *conn;

	conn = connection_for_subscr(vsub);
	if (!conn) {
		LOGP(DMM, LOGL_ERROR, "%s: Cannot stop silent call, no connection for subscriber\n",
		     vlr_subscr_name(vsub));
		return -ENODEV;
	}

	/* did we actually establish a silent call for this guy? */
	if (!conn->silent_call) {
		LOGP(DMM, LOGL_ERROR, "%s: Cannot stop silent call, subscriber has no active silent call\n",
		     vlr_subscr_name(vsub));
		return -ENOENT;
	}

#if BEFORE_MSCSPLIT
	/* Re-enable this log output once we can obtain this information via
	 * A-interface, see OS#2391. */
	DEBUGPC(DLSMS, "Stopping silent call using Timeslot %u on ARFCN %u\n",
		conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
#endif

	conn->silent_call = 0;
	ran_conn_put(conn, RAN_CONN_USE_SILENT_CALL);

	return 0;
}
