/*
 * Copyright 2016 Google Inc.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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 <assert.h>
#include <stdio.h>

#include "base/container_of.h"
#include "base/die.h"
#include "base/init_funcs.h"
#include "base/list.h"
#include "base/xalloc.h"
#include "net/ethernet.h"
#include "net/ipv6/inet6.h"
#include "net/ipv6/ipv6.h"
#include "net/net.h"


ListNode ipv6_udp_connections;


static int ipv6_udp_con_init(Ipv6UdpCon *con)
{
	NetDevice *dev = con->dev;
	const MacAddress *mac = dev->get_mac(dev);
	ipv6_init(mac);
	list_insert_after(&con->list_node, &ipv6_udp_connections);
	con->initialized = 1;
	return 0;
}

static int ipv6_udp_bind(NetConOps *me, uint16_t port)
{
	Ipv6UdpCon *con = container_of(me, Ipv6UdpCon, ops);
	if (!con->initialized && ipv6_udp_con_init(con))
		return 1;
	con->source_port = port;
	return 0;
}

static int ipv6_udp_incoming(NetConOps *me, size_t *size)
{
	Ipv6UdpCon *con = container_of(me, Ipv6UdpCon, ops);
	if (!con->initialized && ipv6_udp_con_init(con))
		return 1;

	*size = con->incoming_count;

	// Poke the device to receive any data it has.
	if (!*size) {
		net_service_dev(con->dev);
		*size = con->incoming_count;
	}

	return 0;
}

static int ipv6_udp_send(NetConOps *me, const void *data, size_t len)
{
	Ipv6UdpCon *con = container_of(me, Ipv6UdpCon, ops);
	if (!con->initialized && ipv6_udp_con_init(con))
		return 1;

	return udpv6_send(data, len, &con->dest_ip, con->dest_port,
			  con->source_port);
}

static int ipv6_udp_receive(NetConOps *me, void *data, size_t *len,
			    size_t max_len)
{
	Ipv6UdpCon *con = container_of(me, Ipv6UdpCon, ops);
	if (!con->initialized && ipv6_udp_con_init(con))
		return 1;

	size_t size;
	if (me->incoming(me, &size))
		return 1;

	if (!size) {
		printf("No data to receive.\n");
		return 1;
	} else if (size > max_len) {
		printf("Insufficient space: putting %zd bytes in %zd bytes.\n",
		       size, max_len);
		return 1;
	}

	*len = size;
	con->incoming_count = 0;
	if (data)
		memcpy(data, con->incoming, size);
	return 0;
}

static Ipv6UdpCon *ipv6_singleton;

static int ipv6_udp_close(NetConOps *me)
{
	Ipv6UdpCon *con = container_of(me, Ipv6UdpCon, ops);
	if (!con->initialized && ipv6_udp_con_init(con))
		return 1;
	list_remove(&con->list_node);
	con->initialized = 0;
	ipv6_singleton = NULL;
	return 0;
}

Ipv6UdpCon *new_ipv6_udp_con(NetDevice *dev, const Ipv6Address *remote_ip,
			     uint16_t port)
{
	if (ipv6_singleton)
		die("Only one ipv6 connection at a time.\n");

	Ipv6UdpCon *con = xzalloc(sizeof(*con));

	con->ops.bind = &ipv6_udp_bind;
	con->ops.incoming = &ipv6_udp_incoming;
	con->ops.send = &ipv6_udp_send;
	con->ops.receive = &ipv6_udp_receive;
	con->ops.close = &ipv6_udp_close;

	memcpy(&con->dest_ip, remote_ip, sizeof(con->dest_ip));
	con->dest_port = port;
	con->dev = dev;

	ipv6_singleton = con;

	return con;
}

static uint8_t ipv6_eth_buf[Ipv6IncomingBufferSize];
static int ipv6_eth_buf_in_use;

void *eth_get_buffer(size_t len)
{
	if (len > Ipv6IncomingBufferSize)
		return NULL;
	if (ipv6_eth_buf_in_use)
		return NULL;
	ipv6_eth_buf_in_use = 1;
	return ipv6_eth_buf;
}

void eth_put_buffer(void *ptr)
{
	assert(ipv6_eth_buf_in_use);
	assert(ptr == ipv6_eth_buf);
	ipv6_eth_buf_in_use = 0;
}

int eth_send(void *data, size_t len)
{
	assert(ipv6_singleton);
	NetDevice *dev = ipv6_singleton->dev;
	int ret = dev->send(dev, data, len);
	ipv6_eth_buf_in_use = 0;
	return ret;
}

int eth_add_mcast_filter(const MacAddress *addr)
{
	return 0;
}

void udpv6_recv(void *data, size_t len,
	        const Ipv6Address *daddr, uint16_t dport,
	       const Ipv6Address *saddr, uint16_t sport)
{
	// Figure out who's data this is.
	Ipv6UdpCon *con;
	list_for_each(con, ipv6_udp_connections, list_node) {
		if (con->source_port == dport) {
			con->dest_port = sport;
			memcpy(&con->dest_ip, saddr, sizeof(con->dest_ip));
			if (con->incoming_count) {
				printf("Already have data. Dropping.\n");
				return;
			}
			if (len > sizeof(con->incoming)) {
				printf("Too much data. Dropping.\n");
				return;
			}
			con->incoming_count = len;
			memcpy(con->incoming, data, con->incoming_count);
			return;
		}
	}
}

static int ipv6_process(EthTypeOps *me, NetDevice *dev, void *data, size_t len)
{
	eth_recv(data, len);
	return 0;
}

static EthTypeOps ipv6_type = {
	.type = EthType_Ipv6,
	.process = &ipv6_process,
};

static int ipv6_install_eth_types(void)
{
	list_insert_after(&ipv6_type.list_node, &net_eth_types);
	return 0;
}

INIT_FUNC(ipv6_install_eth_types);
