/*
 * 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;


// Useful addresses.
const Ipv6Address ipv6_ll_all_nodes = {
	.x = {0xFF, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
};


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(con, data, len);
}

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 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;
	return 0;
}

Ipv6UdpCon *new_ipv6_udp_con(NetDevice *dev, const Ipv6Address *remote_ip,
			     uint16_t port)
{
	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;

	return con;
}

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)
{
	return eth_recv(dev, data, len);
}

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);
