/* Copied from tbf.cpp
 *
 * Copyright (C) 2012 Ivan Klyuchnikov
 * Copyright (C) 2012 Andreas Eversberg <jolly@eversberg.eu>
 * Copyright (C) 2013 by Holger Hans Peter Freyther
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <bts.h>

#include <stdio.h>

extern "C" {
#include <osmocom/core/msgb.h>
}

#include "pcu_utils.h"

/* reset LLC frame */
void gprs_llc::reset()
{
	m_index = 0;
	m_length = 0;

	memset(frame, 0x42, sizeof(frame));
}

void gprs_llc::reset_frame_space()
{
	m_index = 0;
}

/* Put an Unconfirmed Information (UI) Dummy command, see GSM 44.064, 6.4.2.2 */
void gprs_llc::put_dummy_frame(size_t req_len)
{
	/* The shortest dummy command (the spec requests at least 6 octets) */
	static const uint8_t llc_dummy_command[] = {
		0x43, 0xc0, 0x01, 0x2b, 0x2b, 0x2b
	};
	static const size_t max_dummy_command_len = 79;

	put_frame(llc_dummy_command, sizeof(llc_dummy_command));

	if (req_len > max_dummy_command_len)
		req_len = max_dummy_command_len;

	/* Add further stuffing, if the requested length exceeds the minimum
	 * dummy command length */
	while (m_length < req_len)
		frame[m_length++] = 0x2b;
}

void gprs_llc::put_frame(const uint8_t *data, size_t len)
{
	/* only put frames when we are empty */
	OSMO_ASSERT(m_index == 0 && m_length == 0);
	append_frame(data, len);
}

void gprs_llc::append_frame(const uint8_t *data, size_t len)
{
	/* TODO: bounds check */
	memcpy(frame + m_length, data, len);
	m_length += len;
}

void gprs_llc::init()
{
	reset();
}

bool gprs_llc::is_user_data_frame(uint8_t *data, size_t len)
{
	if (len < 2)
		return false;

	if ((data[0] & 0x0f) == 1 /* GPRS_SAPI_GMM */)
		return false;

	if ((data[0] & 0xe0) != 0xc0 /* LLC UI */)
		/* It is not an LLC UI frame, see TS 44.064, 6.3 */
		return false;

	return true;
}

void llc_queue_init(struct gprs_llc_queue *q)
{
	INIT_LLIST_HEAD(&q->m_queue);
	q->m_queue_size = 0;
	q->m_queue_octets = 0;
	q->m_avg_queue_delay = 0;
}


void gprs_llc_queue::enqueue(struct msgb *llc_msg, const struct timespec *expire_time)
{
	MetaInfo *meta_storage;

	osmo_static_assert(sizeof(*meta_storage) <= sizeof(llc_msg->cb), info_does_not_fit);

	m_queue_size += 1;
	m_queue_octets += msgb_length(llc_msg);

	meta_storage = (MetaInfo *)&llc_msg->cb[0];
	osmo_clock_gettime(CLOCK_MONOTONIC, &meta_storage->recv_time);
	meta_storage->expire_time = *expire_time;

	msgb_enqueue(&m_queue, llc_msg);
}

void llc_queue_clear(struct gprs_llc_queue *q, struct gprs_rlcmac_bts *bts)
{
	struct msgb *msg;

	while ((msg = msgb_dequeue(&q->m_queue))) {
		if (bts)
			bts_do_rate_ctr_inc(bts, CTR_LLC_FRAME_DROPPED);
		msgb_free(msg);
	}

	q->m_queue_size = 0;
	q->m_queue_octets = 0;
}

void llc_queue_move_and_merge(struct gprs_llc_queue *q, struct gprs_llc_queue *o)
{
	struct msgb *msg, *msg1 = NULL, *msg2 = NULL;
	struct llist_head new_queue;
	size_t queue_size = 0;
	size_t queue_octets = 0;
	INIT_LLIST_HEAD(&new_queue);

	while (1) {
		if (msg1 == NULL)
			msg1 = msgb_dequeue(&q->m_queue);

		if (msg2 == NULL)
			msg2 = msgb_dequeue(&o->m_queue);

		if (msg1 == NULL && msg2 == NULL)
			break;

		if (msg1 == NULL) {
			msg = msg2;
			msg2 = NULL;
		} else if (msg2 == NULL) {
			msg = msg1;
			msg1 = NULL;
		} else {
			const MetaInfo *mi1 = (MetaInfo *)&msg1->cb[0];
			const MetaInfo *mi2 = (MetaInfo *)&msg2->cb[0];

			if (timespeccmp(&mi2->recv_time, &mi1->recv_time, >)) {
				msg = msg1;
				msg1 = NULL;
			} else {
				msg = msg2;
				msg2 = NULL;
			}
		}

		msgb_enqueue(&new_queue, msg);
		queue_size += 1;
		queue_octets += msgb_length(msg);
	}

	OSMO_ASSERT(llist_empty(&q->m_queue));
	OSMO_ASSERT(llist_empty(&o->m_queue));

	o->m_queue_size = 0;
	o->m_queue_octets = 0;

	llist_splice_init(&new_queue, &q->m_queue);
	q->m_queue_size = queue_size;
	q->m_queue_octets = queue_octets;
}

#define ALPHA 0.5f

struct msgb *gprs_llc_queue::dequeue(const MetaInfo **info)
{
	struct msgb *msg;
	struct timespec *tv, tv_now, tv_result;
	uint32_t lifetime;
	const MetaInfo *meta_storage;

	msg = msgb_dequeue(&m_queue);
	if (!msg)
		return NULL;

	meta_storage = (MetaInfo *)&msg->cb[0];

	if (info)
		*info = meta_storage;

	m_queue_size -= 1;
	m_queue_octets -= msgb_length(msg);

	/* take the second time */
	osmo_clock_gettime(CLOCK_MONOTONIC, &tv_now);
	tv = (struct timespec *)&msg->data[sizeof(*tv)];
	timespecsub(&tv_now, &meta_storage->recv_time, &tv_result);

	lifetime = tv_result.tv_sec*1000 + tv_result.tv_nsec/1000000;
	m_avg_queue_delay = m_avg_queue_delay * ALPHA + lifetime * (1-ALPHA);

	return msg;
}

void gprs_llc_queue::calc_pdu_lifetime(struct gprs_rlcmac_bts *bts, const uint16_t pdu_delay_csec, struct timespec *tv)
{
	uint16_t delay_csec;
	if (bts->pcu->vty.force_llc_lifetime)
		delay_csec = bts->pcu->vty.force_llc_lifetime;
	else
		delay_csec = pdu_delay_csec;

	/* keep timestamp at 0 for infinite delay */
	if (delay_csec == 0xffff) {
		memset(tv, 0, sizeof(*tv));
		return;
	}

	/* calculate timestamp of timeout */
	struct timespec now, csec;
	osmo_clock_gettime(CLOCK_MONOTONIC, &now);
	csecs_to_timespec(delay_csec, &csec);

	timespecadd(&now, &csec, tv);
}

bool gprs_llc_queue::is_frame_expired(const struct timespec *tv_now,
	const struct timespec *tv)
{
	/* Timeout is infinite */
	if (tv->tv_sec == 0 && tv->tv_nsec == 0)
		return false;

	return timespeccmp(tv_now, tv, >);
}
