/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* Copyright (c) 2024-2025 Brett Sheffield <bacs@librecast.net> */

/*
 * testing lc_socketpair() - encryption tests
 */

#include "test.h"
#include <librecast_pvt.h>
#include <librecast/net.h>

int main(void)
{
	char name[] = "lc_socketpair() - symmetric encryption";
#ifdef HAVE_LIBSODIUM
	lc_ctx_t *lctx;
	lc_socket_t *sock[2];
	lc_channel_t *chan[2];
	unsigned char key[crypto_secretbox_KEYBYTES];
	char msg[1024];
	char buf[sizeof msg];
	ssize_t rc;

	test_name(name);

	lctx = lc_ctx_new();
	if (!test_assert(lctx != NULL, "lc_ctx_new()")) return test_status;

	/* generate and set key */
	lc_getrandom(key, sizeof key);
	if (!test_assert(lc_ctx_set_sym_key(lctx, key, sizeof key) == 0,
				"lc_ctx_set_sym_key()"))
		goto err_free_lctx;

	/* turn on encoding */
	if (!test_assert(lc_ctx_coding_set(lctx, LC_CODE_SYMM) == LC_CODE_SYMM,
				"lc_ctx_coding_set()"))
		goto err_free_lctx;

	/* create socketpair */
	if (!test_assert(lc_socketpair(lctx, sock) == 0, "lc_socketpair()"))
		goto err_free_lctx;

	/* create random data to send */
	lc_getrandom(msg, sizeof msg);

	chan[0] = lc_channel_random(lctx);
	if (!test_assert(chan[0] != NULL, "lc_channel_random()")) goto err_free_lctx;
	chan[1]= lc_channel_copy(lctx, chan[0]);
	if (!test_assert(chan[1] != NULL, "lc_channel_copy()")) goto err_free_lctx;

	if (!test_assert(lc_channel_bind(sock[0], chan[0]) == 0, "lc_channel_bind()"))
		goto err_free_lctx;
	if (!test_assert(lc_channel_bind(sock[1], chan[1]) == 0, "lc_channel_bind()"))
		goto err_free_lctx;

	/* JOIN channel - ensure channel is in OIL filter */
	lc_channel_join(chan[1]);

	rc = lc_channel_send(chan[0], msg, sizeof msg, 0);
	test_assert((size_t)rc == sizeof msg, "%zi (total) bytes sent", rc);

	rc = lc_channel_recv(chan[1], buf, sizeof buf, 0);
	if (rc) perror("lc_channel_recv");
	test_assert(rc == sizeof msg, "%zi (information) bytes decoded", rc);

	test_assert(!memcmp(msg, buf, sizeof msg), "msg received matches");

err_free_lctx:
	lc_ctx_free(lctx);
	return test_status;
#else
	return test_skip("%s - requires libsodium", name);
#endif
}
