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

#include <logging/log.h>
LOG_MODULE_REGISTER(net_pkt_sock_sample, LOG_LEVEL_DBG);

#include <zephyr.h>
#include <errno.h>
#include <stdio.h>

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

#define STACK_SIZE 1024
#define THREAD_PRIORITY K_PRIO_COOP(8)
#define RECV_BUFFER_SIZE 1280
#define RAW_WAIT K_SECONDS(5)

static struct packet_data packet;

static struct k_sem quit_lock;

struct packet_data {
	int sock;
	char recv_buffer[RECV_BUFFER_SIZE];
	struct k_delayed_work send;
};

static void process_packet(void);
static void send_packet(void);

K_THREAD_DEFINE(packet_thread_id, STACK_SIZE,
		process_packet, NULL, NULL, NULL,
		THREAD_PRIORITY, 0, K_FOREVER);

/* Generated by http://www.lipsum.com/
 * 2 paragraphs, 179 words, 1160 bytes of Lorem Ipsum
 */
const char lorem_ipsum[] =
	"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque "
	"sodales lorem lorem, sed congue enim vehicula a. Sed finibus diam sed "
	"odio ultrices pharetra. Nullam dictum arcu ultricies turpis congue, "
	"vel venenatis turpis venenatis. Nam tempus arcu eros, ac congue libero "
	"tristique congue. Proin velit lectus, euismod sit amet quam in, "
	"maximus condimentum urna. Cras vel erat luctus, mattis orci ut, varius "
	"urna. Nam eu lobortis velit."
	"\n"
	"Nullam sit amet diam vel odio sodales cursus vehicula eu arcu. Proin "
	"fringilla, enim nec consectetur mollis, lorem orci interdum nisi, "
	"vitae suscipit nisi mauris eu mi. Proin diam enim, mollis ac rhoncus "
	"vitae, placerat et eros. Suspendisse convallis, ipsum nec rhoncus "
	"aliquam, ex augue ultrices nisl, id aliquet mi diam quis ante. "
	"Pellentesque venenatis ornare ultrices. Quisque et porttitor lectus. "
	"Ut venenatis nunc et urna imperdiet porttitor non laoreet massa. Donec "
	"eleifend eros in mi sagittis egestas. Sed et mi nunc. Nunc vulputate, "
	"mauris non ullamcorper viverra, lorem nulla vulputate diam, et congue "
	"dui velit non erat. Duis interdum leo et ipsum tempor consequat. In "
	"faucibus enim quis purus vulputate nullam."
	"\n";

static void quit(void)
{
	k_sem_give(&quit_lock);
}

static int start_packet_socket(void)
{
	struct sockaddr_ll dst;
	int ret;

	packet.sock = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL);
	if (packet.sock < 0) {
		LOG_ERR("Failed to create RAW socket : %d", errno);
		return -errno;
	}

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

	ret = bind(packet.sock, (const struct sockaddr *)&dst,
		   sizeof(struct sockaddr_ll));
	if (ret < 0) {
		LOG_ERR("Failed to bind packet socket : %d", errno);
		return -errno;
	}

	return 0;
}

static void wait_send(struct k_work *work)
{
	/* Send a new packet at this point */
	send_packet();
}

static void send_packet(void)
{
	struct sockaddr_ll dst;
	u8_t send = 100U;
	int ret;

	dst.sll_ifindex = net_if_get_by_iface(net_if_get_default());

	/* Sending dummy data */
	ret = sendto(packet.sock, lorem_ipsum, send, 0,
		     (const struct sockaddr *)&dst,
		     sizeof(struct sockaddr_ll));
	if (ret < 0) {
		LOG_ERR("Failed to send, errno %d", errno);
	} else {
		LOG_DBG("Sent %d bytes", send);
	}

	k_delayed_work_submit(&packet.send, RAW_WAIT);
}

static int process_packet_socket(void)
{
	int ret = 0;
	int received;

	LOG_INF("Waiting for packets ...");

	send_packet();

	do {
		received = recv(packet.sock, packet.recv_buffer,
				    sizeof(packet.recv_buffer), 0);

		if (received < 0) {
			LOG_ERR("RAW : recv error %d", errno);
			ret = -errno;
			break;
		}

		LOG_DBG("Received %d bytes", received);

	} while (true);

	return ret;
}

static void process_packet(void)
{
	int ret;

	ret = start_packet_socket();
	if (ret < 0) {
		quit();
		return;
	}

	while (ret == 0) {
		ret = process_packet_socket();
		if (ret < 0) {
			quit();
			return;
		}
	}
}

void main(void)
{
	k_sem_init(&quit_lock, 0, UINT_MAX);
	k_delayed_work_init(&packet.send, wait_send);

	LOG_INF("Packet socket sample is running");

	k_thread_start(packet_thread_id);

	k_sem_take(&quit_lock, K_FOREVER);

	LOG_INF("Stopping...");

	k_thread_abort(packet_thread_id);

	k_delayed_work_cancel(&packet.send);

	if (packet.sock > 0) {
		(void)close(packet.sock);
	}
}
