/*
 * Copyright (c) 2015 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>

#include <linker/sections.h>
#include <toolchain.h>

#include <misc/printk.h>

#include <net/net_core.h>
#include <net/net_ip.h>
#include <net/net_pkt.h>

#include "zperf.h"
#include "zperf_internal.h"
#include "shell_utils.h"
#include "zperf_session.h"

/* To get net_sprint_ipv{4|6}_addr() */
#define NET_LOG_ENABLED 1
#include "net_private.h"

#define TAG CMD_STR_TCP_DOWNLOAD" "

#define TCP_RX_FIBER_STACK_SIZE 1024

static K_THREAD_STACK_DEFINE(zperf_tcp_rx_stack, TCP_RX_FIBER_STACK_SIZE);
static struct k_thread zperf_tcp_rx_thread_data;

#if defined(CONFIG_NET_IPV6)
static struct sockaddr_in6 *in6_addr_my;
#endif
#if defined(CONFIG_NET_IPV4)
static struct sockaddr_in *in4_addr_my;
#endif

static void tcp_received(struct net_context *context,
			 struct net_pkt *pkt,
			 int status,
			 void *user_data)
{
	struct session *session;
	u32_t time;

	if (!pkt) {
		return;
	}

	time = k_cycle_get_32();

	session = get_session(pkt, SESSION_TCP);
	if (!session) {
		printk(TAG "ERROR! cannot get a session!\n");
		return;
	}

	switch (session->state) {
	case STATE_NULL:
	case STATE_COMPLETED:
		printk(TAG "New session started\n");
		zperf_reset_session_stats(session);
		session->start_time =  sys_cycle_get_32();
		session->state = STATE_ONGOING;
		/* fall through */
	case STATE_ONGOING:
		session->counter++;

		if (pkt) {
			session->length += net_pkt_appdatalen(pkt);
		}

		if (!pkt && status == 0) { /* EOF */
			u32_t rate_in_kbps;
			u32_t duration = HW_CYCLES_TO_USEC(
				time_delta(session->start_time, time));

			session->state = STATE_COMPLETED;

			/* Compute baud rate */
			if (duration != 0) {
				rate_in_kbps = (u32_t)
					(((u64_t)session->length *
					  (u64_t)8 *
					  (u64_t)USEC_PER_SEC) /
					 ((u64_t)duration * 1024));
			} else {
				rate_in_kbps = 0;
			}

			printk(TAG "TCP session ended\n");

			printk(TAG " duration:\t\t");
			print_number(duration, TIME_US, TIME_US_UNIT);
			printk("\n");

			printk(TAG " rate:\t\t\t");
			print_number(rate_in_kbps, KBPS, KBPS_UNIT);
			printk("\n");
		}
		break;
	case STATE_LAST_PACKET_RECEIVED:
		break;
	default:
		printk(TAG "Error! Unsupported case\n");
	}

	net_pkt_unref(pkt);
}

static void tcp_accepted(struct net_context *context,
			 struct sockaddr *addr,
			 socklen_t addrlen,
			 int error,
			 void *user_data)
{
	int ret;

	ret = net_context_recv(context, tcp_received, K_NO_WAIT, user_data);
	if (ret < 0) {
		printk(TAG "Cannot receive TCP packet (family %d)",
			net_context_get_family(context));
	}
}

static void zperf_tcp_rx_thread(int port)
{
#if defined(CONFIG_NET_IPV4)
	struct net_context *context4 = NULL;
#endif
#if defined(CONFIG_NET_IPV6)
	struct net_context *context6 = NULL;
#endif
	int ret, fail = 0;

#if defined(CONFIG_NET_IPV4) && defined(MY_IP4ADDR)
	ret = net_context_get(AF_INET, SOCK_STREAM, IPPROTO_TCP, &context4);
	if (ret < 0) {
		printk(TAG "ERROR! Cannot get IPv4 TCP network context.\n");
		return;
	}

	ret = zperf_get_ipv4_addr(MY_IP4ADDR, &in4_addr_my->sin_addr, TAG);
	if (ret < 0) {
		printk(TAG "ERROR! Unable to set IPv4\n");
		return;
	}

	printk(TAG "Binding to %s\n",
	       net_sprint_ipv4_addr(&in4_addr_my->sin_addr));

	in4_addr_my->sin_port = htons(port);
#endif

#if defined(CONFIG_NET_IPV6) && defined(MY_IP6ADDR)
	ret = net_context_get(AF_INET6, SOCK_STREAM, IPPROTO_TCP, &context6);
	if (ret < 0) {
		printk(TAG "ERROR! Cannot get IPv6 TCP network context.\n");
		return;
	}

	ret = zperf_get_ipv6_addr(MY_IP6ADDR, MY_PREFIX_LEN_STR,
				  &in6_addr_my->sin6_addr, TAG);
	if (ret < 0) {
		printk(TAG "ERROR! Unable to set IPv6\n");
		return;
	}

	printk(TAG "Binding to %s\n",
	       net_sprint_ipv6_addr(&in6_addr_my->sin6_addr));

	in6_addr_my->sin6_port = htons(port);
#endif

#if defined(CONFIG_NET_IPV6)
	if (context6) {
		ret = net_context_bind(context6,
				       (struct sockaddr *)in6_addr_my,
				       sizeof(struct sockaddr_in6));
		if (ret < 0) {
			printk(TAG "Cannot bind IPv6 TCP port %d (%d)\n",
			       ntohs(in6_addr_my->sin6_port), ret);
			fail++;
		}

		ret = net_context_listen(context6, 0);
		if (ret < 0) {
			printk(TAG "Cannot listen IPv6 TCP (%d)", ret);
			return;
		}

		ret = net_context_accept(context6, tcp_accepted, K_NO_WAIT, NULL);
		if (ret < 0) {
			printk(TAG "Cannot receive IPv6 TCP packets (%d)", ret);
			return;
		}
	}
#endif

#if defined(CONFIG_NET_IPV4)
	if (context4) {
		ret = net_context_bind(context4,
				       (struct sockaddr *)in4_addr_my,
				       sizeof(struct sockaddr_in));
		if (ret < 0) {
			printk(TAG "Cannot bind IPv4 TCP port %d (%d)\n",
			       ntohs(in4_addr_my->sin_port), ret);
			fail++;
		}

		ret = net_context_listen(context4, 0);
		if (ret < 0) {
			printk(TAG "Cannot listen IPv4 TCP (%d)", ret);
			return;
		}

		ret = net_context_accept(context4, tcp_accepted, K_NO_WAIT, NULL);
		if (ret < 0) {
			printk(TAG "Cannot receive IPv4 TCP packets (%d)", ret);
			return;
		}
	}
#endif

	if (fail > 1) {
		return;
	}

	k_sleep(K_FOREVER);
}

void zperf_tcp_receiver_init(int port)
{
#if defined(CONFIG_NET_IPV6)
	in6_addr_my = zperf_get_sin6();
#endif
#if defined(CONFIG_NET_IPV4)
	in4_addr_my = zperf_get_sin();
#endif

	k_thread_create(&zperf_tcp_rx_thread_data, zperf_tcp_rx_stack,
			K_THREAD_STACK_SIZEOF(zperf_tcp_rx_stack),
			(k_thread_entry_t)zperf_tcp_rx_thread,
			INT_TO_POINTER(port), 0, 0,
			K_PRIO_COOP(7), 0, K_NO_WAIT);
}
