/*
 * Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <logging/log.h>
LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);

#include <zephyr.h>
#include <linker/sections.h>
#include <ztest.h>
#include <random/rand32.h>

#include <fcntl.h>

#include <net/ethernet.h>
#include <net/dummy.h>
#include <net/net_if.h>
#include <net/socket.h>

struct fake_dev_context {
	uint8_t mac_addr[sizeof(struct net_eth_addr)];
	struct net_if *iface;
};

static const char testing_data[] = "Tappara";

static int fake_dev_send(const struct device *dev, struct net_pkt *pkt)
{
	struct net_pkt *recv_pkt;
	int ret;

	ARG_UNUSED(dev);
	ARG_UNUSED(pkt);

	/* Loopback the data back to stack: */
	NET_DBG("Dummy device: Loopbacking data (%d bytes) to iface %d\n", net_pkt_get_len(pkt),
	    net_if_get_by_iface(net_pkt_iface(pkt)));

	recv_pkt = net_pkt_clone(pkt, K_NO_WAIT);

	k_sleep(K_MSEC(10)); /* Let the receiver run */

	ret = net_recv_data(net_pkt_iface(recv_pkt), recv_pkt);
	zassert_equal(ret, 0, "Cannot receive data (%d)", ret);
	return 0;
}

static uint8_t *fake_dev_get_mac(struct fake_dev_context *ctx)
{
	if (ctx->mac_addr[2] == 0x00) {
		/* 00-00-5E-00-53-xx Documentation RFC 7042 */
		ctx->mac_addr[0] = 0x00;
		ctx->mac_addr[1] = 0x00;
		ctx->mac_addr[2] = 0x5E;
		ctx->mac_addr[3] = 0x00;
		ctx->mac_addr[4] = 0x53;
		ctx->mac_addr[5] = sys_rand32_get();
	}

	return ctx->mac_addr;
}

static void fake_dev_iface_init(struct net_if *iface)
{
	const struct device *dev = net_if_get_device(iface);
	struct fake_dev_context *ctx = dev->data;
	uint8_t *mac = fake_dev_get_mac(ctx);

	net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);

	ctx->iface = iface;
}

int fake_dev_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	return 0;
}

struct fake_dev_context fake_dev_context_data;

static struct dummy_api fake_dev_if_api = {
	.iface_api.init = fake_dev_iface_init,
	.send = fake_dev_send,
};

#define _ETH_L2_LAYER DUMMY_L2
#define _ETH_L2_CTX_TYPE NET_L2_GET_CTX_TYPE(DUMMY_L2)

NET_DEVICE_INIT(fake_dev, "fake_dev", fake_dev_init, NULL, &fake_dev_context_data, NULL,
		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, &fake_dev_if_api, _ETH_L2_LAYER,
		_ETH_L2_CTX_TYPE, 127);

void test_setup(void)
{
	struct net_if *iface;
	struct in_addr in4addr_my = { { { 192, 168, 0, 2 } } };
	struct net_if_addr *ifaddr;

	iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
	zassert_not_null(iface, "Could not get dummy iface");

	net_if_up(iface);

	ifaddr = net_if_ipv4_addr_add(iface, &in4addr_my, NET_ADDR_MANUAL, 0);
	zassert_not_null(ifaddr, "Could not add iface address");
}

void test_sckt_raw_packet_raw_ip(void)
{
	/* A test case for testing socket combo: AF_PACKET & SOCK_RAW & IPPROTO_RAW: */
	struct net_if *iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
	int recv_data_len, ret;
	struct sockaddr_ll dst = { 0 };
	char receive_buffer[128];
	int sock;

	sock = socket(AF_PACKET, SOCK_RAW, IPPROTO_RAW);
	zassert_true(sock >= 0, "Could not create a socket");

	dst.sll_ifindex = net_if_get_by_iface(iface);
	dst.sll_family = AF_PACKET;

	ret = bind(sock, (const struct sockaddr *)&dst, sizeof(struct sockaddr_ll));
	zassert_true(ret >= 0, "Could not bind the socket");

	/* Let's send some data: */
	ret = sendto(sock, testing_data, ARRAY_SIZE(testing_data), 0, (const struct sockaddr *)&dst,
		     sizeof(struct sockaddr_ll));
	zassert_true(ret > 0, "Could not send data");

	/* Receive the same data back: */
	recv_data_len = recv(sock, receive_buffer, sizeof(receive_buffer), 0);
	zassert_true(recv_data_len == ARRAY_SIZE(testing_data), "Expected data not received");

	NET_DBG("Received successfully data %s", log_strdup(receive_buffer));

	close(sock);
}

void test_main(void)
{
	ztest_test_suite(test_sckt_packet_raw_ip,
			 ztest_unit_test(test_setup),
			 ztest_unit_test(test_sckt_raw_packet_raw_ip));
	ztest_run_test_suite(test_sckt_packet_raw_ip);
}
