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

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

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

#include <zephyr/kernel.h>
#include <zephyr/posix/unistd.h>
#include <zephyr/posix/poll.h>
#include <zephyr/posix/arpa/inet.h>
#include <zephyr/posix/sys/socket.h>
#include <zephyr/net/socket_service.h>

#define MY_PORT 4242

static char addr_str[INET6_ADDRSTRLEN];

static struct pollfd sockfd_udp[1] = {
	[0] = { .fd = -1 }, /* UDP socket */
};
static struct pollfd sockfd_tcp[1] = {
	[0] = { .fd = -1 }, /* TCP socket */
};

#define MAX_SERVICES 1

static void receive_data(bool is_udp, struct net_socket_service_event *pev,
			 char *buf, size_t buflen);

static void tcp_service_handler(struct k_work *work)
{
	struct net_socket_service_event *pev =
		CONTAINER_OF(work, struct net_socket_service_event, work);
	static char buf[1500];

	/* Note that in this application we receive / send data from
	 * system work queue. In proper application the socket reading and data
	 * sending should be done so that the system work queue is not blocked.
	 * It is possible to create a socket service that uses own work queue.
	 */
	receive_data(false, pev, buf, sizeof(buf));
}

static void udp_service_handler(struct k_work *work)
{
	struct net_socket_service_event *pev =
		CONTAINER_OF(work, struct net_socket_service_event, work);
	static char buf[1500];

	receive_data(true, pev, buf, sizeof(buf));
}

/* In this example we create two services, one with async behavior and one with
 * sync one. The async is for TCP and sync is for UDP (this is just an arbitrary
 * choice).
 * This is an artificial example, both UDP and TCP sockets could be served by the
 * same service.
 */
NET_SOCKET_SERVICE_SYNC_DEFINE_STATIC(service_udp, NULL, udp_service_handler, MAX_SERVICES);
NET_SOCKET_SERVICE_ASYNC_DEFINE_STATIC(service_tcp, NULL, tcp_service_handler, MAX_SERVICES);

static void receive_data(bool is_udp, struct net_socket_service_event *pev,
			 char *buf, size_t buflen)
{
	struct pollfd *pfd = &pev->event;
	int client = pfd->fd;
	struct sockaddr_in6 addr;
	socklen_t addrlen = sizeof(addr);
	int len, out_len;
	char *p;

	len = recvfrom(client, buf, buflen, 0,
		       (struct sockaddr *)&addr, &addrlen);
	if (len <= 0) {
		if (len < 0) {
			LOG_ERR("recv: %d", -errno);
		}

		/* If the TCP socket is closed, mark it as non pollable */
		if (!is_udp && sockfd_tcp[0].fd == client) {
			sockfd_tcp[0].fd = -1;

			/* Update the handler so that client connection is
			 * not monitored any more.
			 */
			(void)net_socket_service_register(&service_tcp, sockfd_tcp,
							  ARRAY_SIZE(sockfd_tcp), NULL);
			close(client);

			LOG_INF("Connection from %s closed", addr_str);
		}

		return;
	}

	p = buf;
	do {
		out_len = sendto(client, p, len, 0,
				 (struct sockaddr *)&addr, addrlen);
		if (out_len < 0) {
			LOG_ERR("sendto: %d", -errno);
			break;
		}

		p += out_len;
		len -= out_len;
	} while (len);
}

static int setup_tcp_socket(struct sockaddr_in6 *addr)
{
	socklen_t optlen = sizeof(int);
	int ret, sock, opt;

	sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
	if (sock < 0) {
		LOG_ERR("socket: %d", -errno);
		return -errno;
	}

	ret = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &optlen);
	if (ret == 0 && opt) {
		LOG_INF("IPV6_V6ONLY option is on, turning it off.");

		opt = 0;
		ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, optlen);
		if (ret < 0) {
			LOG_WRN("Cannot turn off IPV6_V6ONLY option");
		} else {
			LOG_INF("Sharing same socket between IPv6 and IPv4");
		}
	}

	if (bind(sock, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
		LOG_ERR("bind: %d", -errno);
		return -errno;
	}

	if (listen(sock, 5) < 0) {
		LOG_ERR("listen: %d", -errno);
		return -errno;
	}

	return sock;
}

static int setup_udp_socket(struct sockaddr_in6 *addr)
{
	socklen_t optlen = sizeof(int);
	int ret, sock, opt;

	sock = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
	if (sock < 0) {
		LOG_ERR("socket: %d", -errno);
		return -errno;
	}

	ret = getsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &optlen);
	if (ret == 0 && opt) {
		LOG_INF("IPV6_V6ONLY option is on, turning it off.");

		opt = 0;
		ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &opt, optlen);
		if (ret < 0) {
			LOG_WRN("Cannot turn off IPV6_V6ONLY option");
		} else {
			LOG_INF("Sharing same socket between IPv6 and IPv4");
		}
	}

	if (bind(sock, (struct sockaddr *)addr, sizeof(*addr)) < 0) {
		LOG_ERR("bind: %d", -errno);
		return -errno;
	}

	return sock;
}

int main(void)
{
	int tcp_sock, udp_sock, ret;
	struct sockaddr_in6 addr = {
		.sin6_family = AF_INET6,
		.sin6_addr = IN6ADDR_ANY_INIT,
		.sin6_port = htons(MY_PORT),
	};
	static int counter;

	tcp_sock = setup_tcp_socket(&addr);
	if (tcp_sock < 0) {
		return tcp_sock;
	}

	udp_sock = setup_udp_socket(&addr);
	if (udp_sock < 0) {
		return udp_sock;
	}

	sockfd_udp[0].fd = udp_sock;
	sockfd_udp[0].events = POLLIN;

	/* Register UDP socket to service handler */
	ret = net_socket_service_register(&service_udp, sockfd_udp,
					  ARRAY_SIZE(sockfd_udp), NULL);
	if (ret < 0) {
		LOG_ERR("Cannot register socket service handler (%d)", ret);
	}

	LOG_INF("Single-threaded TCP/UDP echo server waits "
		"for a connection on port %d", MY_PORT);

	while (1) {
		struct sockaddr_in6 client_addr;
		socklen_t client_addr_len = sizeof(client_addr);
		int client;

		client = accept(tcp_sock, (struct sockaddr *)&client_addr,
				&client_addr_len);
		if (client < 0) {
			LOG_ERR("accept: %d", -errno);
			continue;
		}

		inet_ntop(client_addr.sin6_family, &client_addr.sin6_addr,
			  addr_str, sizeof(addr_str));
		LOG_INF("Connection #%d from %s (%d)", counter++, addr_str, client);

		sockfd_tcp[0].fd = client;
		sockfd_tcp[0].events = POLLIN;

		/* Register all the sockets to service handler */
		ret = net_socket_service_register(&service_tcp, sockfd_tcp,
						  ARRAY_SIZE(sockfd_tcp), NULL);
		if (ret < 0) {
			LOG_ERR("Cannot register socket service handler (%d)",
				ret);
			break;
		}
	}

	(void)net_socket_service_unregister(&service_tcp);
	(void)net_socket_service_unregister(&service_udp);

	close(tcp_sock);
	close(udp_sock);

	return 0;
}
