/* Interaction with the SCCP subsystem */
/*
 * (C) 2009-2010 by Holger Hans Peter Freyther <zecke@selfish.org>
 * (C) 2009-2010 by On-Waves
 * 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 <openbsc/gsm_data.h>
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_bsc_grace.h>
#include <openbsc/osmo_msc_data.h>
#include <openbsc/debug.h>
#include <openbsc/ipaccess.h>
#include <openbsc/signal.h>

#include <osmocore/gsm0808.h>
#include <osmocore/talloc.h>
#include <osmocore/protocol/gsm_08_08.h>

#include <osmocom/sccp/sccp.h>

/* SCCP helper */
#define SCCP_IT_TIMER 60

static LLIST_HEAD(active_connections);

static void free_queued(struct osmo_bsc_sccp_con *conn)
{
	struct msgb *msg;

	while (!llist_empty(&conn->sccp_queue)) {
		/* this is not allowed to fail */
		msg = msgb_dequeue(&conn->sccp_queue);
		msgb_free(msg);
	}

	conn->sccp_queue_size = 0;
}

static void send_queued(struct osmo_bsc_sccp_con *conn)
{
	struct msgb *msg;

	while (!llist_empty(&conn->sccp_queue)) {
		/* this is not allowed to fail */
		msg = msgb_dequeue(&conn->sccp_queue);
		sccp_connection_write(conn->sccp, msg);
		msgb_free(msg);
		conn->sccp_queue_size -= 1;
	}
}

static void msc_outgoing_sccp_data(struct sccp_connection *conn,
				   struct msgb *msg, unsigned int len)
{
	struct osmo_bsc_sccp_con *bsc_con =
			(struct osmo_bsc_sccp_con *) conn->data_ctx;

	bsc_handle_dt1(bsc_con, msg, len);
}

static void msc_outgoing_sccp_state(struct sccp_connection *conn, int old_state)
{
	struct osmo_bsc_sccp_con *con_data;

	if (conn->connection_state >= SCCP_CONNECTION_STATE_RELEASE_COMPLETE) {
		con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;
		if(con_data->conn) {
			LOGP(DMSC, LOGL_ERROR,
				"ERROR: The lchan is still associated\n.");
			gsm0808_clear(con_data->conn);
			subscr_con_free(con_data->conn);
			con_data->conn = NULL;
		}

		con_data->sccp = NULL;
		free_queued(con_data);
		sccp_connection_free(conn);
		bsc_delete_connection(con_data);
	} else if (conn->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED) {
		LOGP(DMSC, LOGL_DEBUG, "Connection established: %p\n", conn);
		con_data = (struct osmo_bsc_sccp_con *) conn->data_ctx;

		bsc_del_timer(&con_data->sccp_cc_timeout);
		bsc_schedule_timer(&con_data->sccp_it_timeout, SCCP_IT_TIMER, 0);

		send_queued(con_data);
	}
}

static void bsc_sccp_force_free(struct osmo_bsc_sccp_con *data)
{
	if (data->conn) {
		gsm0808_clear(data->conn);
		subscr_con_free(data->conn);
		data->conn = NULL;
	}

	free_queued(data);
	sccp_connection_force_free(data->sccp);
	data->sccp = NULL;
	bsc_delete_connection(data);
}

static void sccp_it_timeout(void *_data)
{
	struct osmo_bsc_sccp_con *data =
		(struct osmo_bsc_sccp_con *) _data;

	sccp_connection_send_it(data->sccp);
	bsc_schedule_timer(&data->sccp_it_timeout, SCCP_IT_TIMER, 0);
}

static void sccp_cc_timeout(void *_data)
{
	struct osmo_bsc_sccp_con *data =
		(struct osmo_bsc_sccp_con *) _data;

	if (data->sccp->connection_state >= SCCP_CONNECTION_STATE_ESTABLISHED)
		return;

	LOGP(DMSC, LOGL_ERROR, "The connection was never established.\n");
	bsc_sccp_force_free(data);
}

static void msc_sccp_write_ipa(struct sccp_connection *conn, struct msgb *msg, void *data)
{
	struct gsm_network *net = (struct gsm_network *) data;
	msc_queue_write(net->msc_data->msc_con, msg, IPAC_PROTO_SCCP);
}

static int msc_sccp_accept(struct sccp_connection *connection, void *data)
{
	LOGP(DMSC, LOGL_DEBUG, "Rejecting incoming SCCP connection.\n");
	return -1;
}

static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
{
	struct gsm_network *net = (struct gsm_network *) data;
	return bsc_handle_udt(net, net->msc_data->msc_con, msgb, length);
}

int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
	struct sccp_connection *sccp = conn->sccp;

	if (sccp->connection_state > SCCP_CONNECTION_STATE_ESTABLISHED) {
		LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
		msgb_free(msg);
	} else if (sccp->connection_state == SCCP_CONNECTION_STATE_ESTABLISHED
		   && conn->sccp_queue_size == 0) {
		sccp_connection_write(sccp, msg);
		msgb_free(msg);
	} else if (conn->sccp_queue_size > 10) {
		LOGP(DMSC, LOGL_ERROR, "Connection closing, dropping packet on: %p\n", sccp);
		msgb_free(msg);
	} else {
		LOGP(DMSC, LOGL_DEBUG, "Queueing packet on %p. Queue size: %d\n", sccp, conn->sccp_queue_size);
		conn->sccp_queue_size += 1;
		msgb_enqueue(&conn->sccp_queue, msg);
	}

	return 0;
}

int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
{
	struct gsm_network *net;
	struct osmo_bsc_sccp_con *bsc_con;
	struct sccp_connection *sccp;

	net = conn->bts->network;
	if (!net->msc_data->msc_con->is_authenticated) {
		LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
		return -1;
	}

	if (!bsc_grace_allow_new_connection(net)) {
		LOGP(DMSC, LOGL_NOTICE, "BSC in grace period. No new connections.\n");
		return -1;
	}

	sccp = sccp_connection_socket();
	if (!sccp) {
		LOGP(DMSC, LOGL_ERROR, "Failed to allocate memory.\n");
		return -ENOMEM;
	}

	bsc_con = talloc_zero(conn->bts, struct osmo_bsc_sccp_con);
	if (!bsc_con) {
		LOGP(DMSC, LOGL_ERROR, "Failed to allocate.\n");
		sccp_connection_free(sccp);
		return -1;
	}

	/* callbacks */
	sccp->state_cb = msc_outgoing_sccp_state;
	sccp->data_cb = msc_outgoing_sccp_data;
	sccp->data_ctx = bsc_con;

	/* prepare the timers */
	bsc_con->sccp_it_timeout.cb = sccp_it_timeout;
	bsc_con->sccp_it_timeout.data = bsc_con;
	bsc_con->sccp_cc_timeout.cb = sccp_cc_timeout;
	bsc_con->sccp_cc_timeout.data = bsc_con;

	INIT_LLIST_HEAD(&bsc_con->sccp_queue);

	bsc_con->sccp = sccp;
	bsc_con->msc_con = net->msc_data->msc_con;
	bsc_con->conn = conn;
	llist_add(&bsc_con->entry, &active_connections);
	conn->sccp_con = bsc_con;
	return 0;
}

int bsc_open_connection(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
	bsc_schedule_timer(&conn->sccp_cc_timeout, 10, 0);
	sccp_connection_connect(conn->sccp, &sccp_ssn_bssap, msg);
	msgb_free(msg);
	return 0;
}

int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp)
{
	if (!sccp)
		return 0;

	if (sccp->conn)
		LOGP(DMSC, LOGL_ERROR, "Should have been cleared.\n");

	llist_del(&sccp->entry);
	bsc_del_timer(&sccp->sccp_it_timeout);
	bsc_del_timer(&sccp->sccp_cc_timeout);
	talloc_free(sccp);
	return 0;
}

static void bsc_close_connections(struct bsc_msc_connection *msc_con)
{
	struct osmo_bsc_sccp_con *con, *tmp;

	llist_for_each_entry_safe(con, tmp, &active_connections, entry)
		bsc_sccp_force_free(con);
}

static int handle_msc_signal(unsigned int subsys, unsigned int signal,
			     void *handler_data, void *signal_data)
{
	struct osmo_msc_data *data;

	if (subsys != SS_MSC)
		return 0;

	data = (struct osmo_msc_data *) signal_data;
	if (signal == S_MSC_LOST)
		bsc_close_connections(data->msc_con);

	return 0;
}

int osmo_bsc_sccp_init(struct gsm_network *gsmnet)
{
	sccp_set_log_area(DSCCP);
	sccp_system_init(msc_sccp_write_ipa, gsmnet);
	sccp_connection_set_incoming(&sccp_ssn_bssap, msc_sccp_accept, NULL);
	sccp_set_read(&sccp_ssn_bssap, msc_sccp_read, gsmnet);

	register_signal_handler(SS_MSC, handle_msc_signal, gsmnet);

	return 0;
}
