/*
 * 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 Ipv6LlAllNodes = {
	.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;
	ipv6_init(dev);
	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(NetDevice *dev, 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);
