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

#include <logging/log.h>
LOG_MODULE_REGISTER(log_backend_net, CONFIG_LOG_DEFAULT_LEVEL);

#include <logging/log_backend.h>
#include <logging/log_core.h>
#include <logging/log_output.h>
#include <logging/log_msg.h>
#include <net/net_pkt.h>
#include <net/net_context.h>

/* Set this to 1 if you want to see what is being sent to server */
#define DEBUG_PRINTING 0

#if DEBUG_PRINTING
#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
#else
#define DBG(fmt, ...)
#endif

#if defined(CONFIG_NET_IPV6) || CONFIG_NET_HOSTNAME_ENABLE
#define MAX_HOSTNAME_LEN NET_IPV6_ADDR_LEN
#else
#define MAX_HOSTNAME_LEN NET_IPV4_ADDR_LEN
#endif

static char dev_hostname[MAX_HOSTNAME_LEN + 1];

static uint8_t output_buf[CONFIG_LOG_BACKEND_NET_MAX_BUF_SIZE];
static bool net_init_done;
struct sockaddr server_addr;
static bool panic_mode;
static uint32_t log_format_current = CONFIG_LOG_BACKEND_NET_OUTPUT_DEFAULT;

const struct log_backend *log_backend_net_get(void);

NET_PKT_SLAB_DEFINE(syslog_tx_pkts, CONFIG_LOG_BACKEND_NET_MAX_BUF);
NET_PKT_DATA_POOL_DEFINE(syslog_tx_bufs,
			 ROUND_UP(CONFIG_LOG_BACKEND_NET_MAX_BUF_SIZE /
				  CONFIG_NET_BUF_DATA_SIZE, 1) *
			 CONFIG_LOG_BACKEND_NET_MAX_BUF);

static struct k_mem_slab *get_tx_slab(void)
{
	return &syslog_tx_pkts;
}

struct net_buf_pool *get_data_pool(void)
{
	return &syslog_tx_bufs;
}

static int line_out(uint8_t *data, size_t length, void *output_ctx)
{
	struct net_context *ctx = (struct net_context *)output_ctx;
	int ret = -ENOMEM;

	if (ctx == NULL) {
		return length;
	}

	ret = net_context_send(ctx, data, length, NULL, K_NO_WAIT, NULL);
	if (ret < 0) {
		goto fail;
	}

	DBG(data);
fail:
	return length;
}

LOG_OUTPUT_DEFINE(log_output_net, line_out, output_buf, sizeof(output_buf));

static int do_net_init(void)
{
	struct sockaddr *local_addr = NULL;
	struct sockaddr_in6 local_addr6 = {0};
	struct sockaddr_in local_addr4 = {0};
	socklen_t server_addr_len;
	struct net_context *ctx;
	int ret;

	if (IS_ENABLED(CONFIG_NET_IPV4) && server_addr.sa_family == AF_INET) {
		local_addr = (struct sockaddr *)&local_addr4;
		server_addr_len = sizeof(struct sockaddr_in);
		local_addr4.sin_port = 0U;
	}

	if (IS_ENABLED(CONFIG_NET_IPV6) && server_addr.sa_family == AF_INET6) {
		local_addr = (struct sockaddr *)&local_addr6;
		server_addr_len = sizeof(struct sockaddr_in6);
		local_addr6.sin6_port = 0U;
	}

	if (local_addr == NULL) {
		DBG("Server address unknown\n");
		return -EINVAL;
	}

	local_addr->sa_family = server_addr.sa_family;

	ret = net_context_get(server_addr.sa_family, SOCK_DGRAM, IPPROTO_UDP,
			      &ctx);
	if (ret < 0) {
		DBG("Cannot get context (%d)\n", ret);
		return ret;
	}

	if (IS_ENABLED(CONFIG_NET_HOSTNAME_ENABLE)) {
		(void)strncpy(dev_hostname, net_hostname_get(), MAX_HOSTNAME_LEN);

	} else if (IS_ENABLED(CONFIG_NET_IPV6) &&
		   server_addr.sa_family == AF_INET6) {
		const struct in6_addr *src;

		src = net_if_ipv6_select_src_addr(
			NULL, &net_sin6(&server_addr)->sin6_addr);
		if (src) {
			net_addr_ntop(AF_INET6, src, dev_hostname,
				      MAX_HOSTNAME_LEN);

			net_ipaddr_copy(&local_addr6.sin6_addr, src);
		} else {
			goto unknown;
		}

	} else if (IS_ENABLED(CONFIG_NET_IPV4) &&
		   server_addr.sa_family == AF_INET) {
		const struct in_addr *src;

		src = net_if_ipv4_select_src_addr(
				  NULL, &net_sin(&server_addr)->sin_addr);

		if (src) {
			net_addr_ntop(AF_INET, src, dev_hostname,
				      MAX_HOSTNAME_LEN);

			net_ipaddr_copy(&local_addr4.sin_addr, src);
		} else {
			goto unknown;
		}

	} else {
	unknown:
		DBG("Cannot setup local context\n");
		return -EINVAL;
	}

	ret = net_context_bind(ctx, local_addr, server_addr_len);
	if (ret < 0) {
		DBG("Cannot bind context (%d)\n", ret);
		return ret;
	}

	(void)net_context_connect(ctx, &server_addr, server_addr_len,
				  NULL, K_NO_WAIT, NULL);

	/* We do not care about return value for this UDP connect call that
	 * basically does nothing. Calling the connect is only useful so that
	 * we can see the syslog connection in net-shell.
	 */

	net_context_setup_pools(ctx, get_tx_slab, get_data_pool);

	log_output_ctx_set(&log_output_net, ctx);
	log_output_hostname_set(&log_output_net, dev_hostname);

	return 0;
}

static void send_output(const struct log_backend *const backend,
			struct log_msg *msg)
{
	if (panic_mode) {
		return;
	}

	if (!net_init_done && do_net_init() == 0) {
		net_init_done = true;
	}

	log_msg_get(msg);

	log_output_msg_process(&log_output_net, msg,
			       LOG_OUTPUT_FLAG_FORMAT_SYSLOG |
			       LOG_OUTPUT_FLAG_TIMESTAMP |
			(IS_ENABLED(CONFIG_LOG_BACKEND_NET_OUTPUT_SYST) ?
			LOG_OUTPUT_FLAG_FORMAT_SYST : 0));

	log_msg_put(msg);
}

static void process(const struct log_backend *const backend,
		    union log_msg2_generic *msg)
{
	uint32_t flags = LOG_OUTPUT_FLAG_FORMAT_SYSLOG | LOG_OUTPUT_FLAG_TIMESTAMP;

	if (panic_mode) {
		return;
	}

	if (!net_init_done && do_net_init() == 0) {
		net_init_done = true;
	}

	log_format_func_t log_output_func = log_format_func_t_get(log_format_current);

	log_output_func(&log_output_net, &msg->log, flags);
}

static int format_set(const struct log_backend *const backend, uint32_t log_type)
{
	log_format_current = log_type;
	return 0;
}

static void init_net(struct log_backend const *const backend)
{
	ARG_UNUSED(backend);
	int ret;

	net_sin(&server_addr)->sin_port = htons(514);

	ret = net_ipaddr_parse(CONFIG_LOG_BACKEND_NET_SERVER,
			       sizeof(CONFIG_LOG_BACKEND_NET_SERVER) - 1,
			       &server_addr);
	if (ret == 0) {
		LOG_ERR("Cannot configure syslog server address");
		return;
	}

	log_backend_deactivate(log_backend_net_get());
}

static void panic(struct log_backend const *const backend)
{
	panic_mode = true;
}

static void sync_string(const struct log_backend *const backend,
		     struct log_msg_ids src_level, uint32_t timestamp,
		     const char *fmt, va_list ap)
{
	uint32_t flags = LOG_OUTPUT_FLAG_LEVEL | LOG_OUTPUT_FLAG_FORMAT_SYSLOG |
		LOG_OUTPUT_FLAG_TIMESTAMP |
		(IS_ENABLED(CONFIG_LOG_BACKEND_NET_OUTPUT_SYST) ?
		LOG_OUTPUT_FLAG_FORMAT_SYST : 0);
	uint32_t key;

	if (!net_init_done && do_net_init() == 0) {
		net_init_done = true;
	}

	key = irq_lock();
	log_output_string(&log_output_net, src_level,
			  timestamp, fmt, ap, flags);
	irq_unlock(key);
}

const struct log_backend_api log_backend_net_api = {
	.panic = panic,
	.init = init_net,
	.process = IS_ENABLED(CONFIG_LOG2) ? process : NULL,
	.put = IS_ENABLED(CONFIG_LOG1_DEFERRED) ? send_output : NULL,
	.put_sync_string = IS_ENABLED(CONFIG_LOG1_IMMEDIATE) ?
							sync_string : NULL,
	/* Currently we do not send hexdumps over network to remote server
	 * if CONFIG_LOG_MODE_IMMEDIATE is used. This is just to save resources,
	 * this can be revisited if needed.
	 */
	.put_sync_hexdump = NULL,
	.format_set = IS_ENABLED(CONFIG_LOG1) ? NULL : format_set,
};

/* Note that the backend can be activated only after we have networking
 * subsystem ready so we must not start it immediately.
 */
LOG_BACKEND_DEFINE(log_backend_net, log_backend_net_api,
		   IS_ENABLED(CONFIG_LOG_BACKEND_NET_AUTOSTART));

const struct log_backend *log_backend_net_get(void)
{
	return &log_backend_net;
}
