/*
 * 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 <endian.h>
#include <string.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/ipv4/ipv4.h"
#include "net/ipv4/uip/arp.h"
#include "net/ipv4/uip/udp/packet.h"
#include "net/ipv4/uip/uip.h"
#include "net/net.h"


ListNode ipv4_udp_connections;


static int ipv4_udp_con_init(Ipv4UdpCon *con)
{
	con->uip_con = uip_udp_new(&con->remote_ip, htonw(con->port));
	if (!con->uip_con) {
		printf("Failed to set up UDP connection.\n");
		return 1;
	}
	list_insert_after(&con->list_node, &ipv4_udp_connections);
	return 0;
}

static int ipv4_udp_bind(NetConOps *me, uint16_t port)
{
	Ipv4UdpCon *con = container_of(me, Ipv4UdpCon, ops);
	if (!con->uip_con && ipv4_udp_con_init(con))
		return 1;
	uip_udp_bind(con->uip_con, htonw(port));
	return 0;
}

static int ipv4_udp_incoming(NetConOps *me, size_t *size)
{
	Ipv4UdpCon *con = container_of(me, Ipv4UdpCon, ops);
	if (!con->uip_con && ipv4_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 ipv4_udp_send(NetConOps *me, const void *data, size_t len)
{
	Ipv4UdpCon *con = container_of(me, Ipv4UdpCon, ops);
	if (!con->uip_con && ipv4_udp_con_init(con))
		return 1;

	uip_udp_packet_send(con->dev, con->uip_con, data, len);
	return 0;
}

static int ipv4_udp_receive(NetConOps *me, void *data, size_t *len,
			    size_t max_len)
{
	Ipv4UdpCon *con = container_of(me, Ipv4UdpCon, ops);
	if (!con->uip_con && ipv4_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;
	if (data)
		memcpy(data, con->incoming, size);
	con->incoming_count = 0;
	return 0;
}

static int ipv4_udp_close(NetConOps *me)
{
	Ipv4UdpCon *con = container_of(me, Ipv4UdpCon, ops);
	if (!con->uip_con && ipv4_udp_con_init(con))
		return 1;
	list_remove(&con->list_node);
	uip_udp_remove(con->uip_con);
	con->uip_con = NULL;
	return 0;
}

Ipv4UdpCon *new_ipv4_udp_con(NetDevice *dev, uip_ipaddr_t remote_ip,
			     uint16_t port)
{
	Ipv4UdpCon *con = xzalloc(sizeof(*con));

	con->ops.bind = &ipv4_udp_bind;
	con->ops.incoming = &ipv4_udp_incoming;
	con->ops.send = &ipv4_udp_send;
	con->ops.receive = &ipv4_udp_receive;
	con->ops.close = &ipv4_udp_close;

	con->remote_ip = remote_ip;
	con->port = port;
	con->dev = dev;

	return con;
}


void ipv4_uip_udp_callback(void)
{
	// Extract the destination port.
	size_t header_size = sizeof(EtherHdr) + sizeof(struct uip_udpip_hdr);
	if (uip_len < header_size)
		return;
	struct uip_udpip_hdr *hdr = (void *)&uip_buf[sizeof(EtherHdr)];

	// Figure out who's data this is.
	Ipv4UdpCon *con;
	list_for_each(con, ipv4_udp_connections, list_node) {
		if (con->uip_con->lport == hdr->destport) {
			con->uip_con->rport = hdr->srcport;
			if (con->incoming_count) {
				printf("Already have data. Dropping.\n");
				return;
			}
			if (uip_datalen() > sizeof(con->incoming)) {
				printf("Too much data. Dropping.\n");
				return;
			}
			con->incoming_count = uip_datalen();
			memcpy(con->incoming, &uip_buf[header_size],
			       con->incoming_count);
			return;
		}
	}
}

void ipv4_uip_tcp_callback(void)
{
	die("TCP connections aren't supported.\n");
}

int ipv4_ipv4_process(EthTypeOps *me, NetDevice *dev, void *data, size_t len)
{
	assert(len <= CONFIG_UIP_BUFSIZE);
	memcpy(uip_buf, data, len);
	uip_len = len;

	uip_arp_ipin();
	uip_input();
	if (uip_len > 0) {
		uip_arp_out();
		dev->send(dev, uip_buf, uip_len);
	}

	return 0;
}

static EthTypeOps ipv4_ipv4_type = {
	.type = EthType_Ipv4,
	.process = &ipv4_ipv4_process,
};

int ipv4_arp_process(EthTypeOps *me, NetDevice *dev, void *data, size_t len)
{
	assert(len <= CONFIG_UIP_BUFSIZE);
	memcpy(uip_buf, data, len);
	uip_len = len;

	uip_arp_arpin();
	if (uip_len > 0)
		dev->send(dev, uip_buf, uip_len);

	return 0;
}

static EthTypeOps ipv4_arp_type = {
	.type = EthType_Arp,
	.process = &ipv4_arp_process,
};

static int ipv4_install_eth_types(void)
{
	list_insert_after(&ipv4_ipv4_type.list_node, &net_eth_types);
	list_insert_after(&ipv4_arp_type.list_node, &net_eth_types);
	return 0;
}

INIT_FUNC(ipv4_install_eth_types);
