/*
 * Copyright (c) 2021 Nordic Semiconductor
 *
 * SPDX-License-Identifier: Apache-2.0
 */
#include "mesh_test.h"
#include "settings_test_backend.h"
#include "mesh/mesh.h"
#include "mesh/net.h"

#define LOG_MODULE_NAME test_rpc

#include <logging/log.h>
LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);

#define WAIT_TIME 60 /*seconds*/
#define TEST_DATA_WAITING_TIME 5 /* seconds */
#define TEST_DATA_SIZE 20

static const struct bt_mesh_test_cfg tx_cfg = {
	.addr = 0x0001,
	.dev_key = { 0x01 },
};
static const struct bt_mesh_test_cfg rx_cfg = {
	.addr = 0x0002,
	.dev_key = { 0x02 },
};

static uint8_t test_data[TEST_DATA_SIZE];
static uint8_t rx_cnt;
static bool is_tx_succeeded;

static void test_tx_init(void)
{
	bt_mesh_test_cfg_set(&tx_cfg, WAIT_TIME);
}

static void test_rx_init(void)
{
	bt_mesh_test_cfg_set(&rx_cfg, WAIT_TIME);
}

static void tx_started(uint16_t dur, int err, void *data)
{
	if (err) {
		FAIL("Couldn't start sending (err: %d)", err);
	}

	LOG_INF("Sending started");
}

static void tx_ended(int err, void *data)
{
	struct k_sem *sem = data;

	if (err) {
		is_tx_succeeded = false;
		LOG_INF("Sending failed (%d)", err);
	} else {
		is_tx_succeeded = true;
		LOG_INF("Sending succeeded");
	}

	k_sem_give(sem);
}

static void rx_ended(uint8_t *data, size_t len)
{
	memset(test_data, rx_cnt++, sizeof(test_data));

	if (memcmp(test_data, data, len)) {
		FAIL("Unexpected rx data");
	}

	LOG_INF("Receiving succeeded");
}

static void test_tx_immediate_replay_attack(void)
{
	settings_test_backend_clear();
	bt_mesh_test_setup();

	static const struct bt_mesh_send_cb send_cb = {
		.start = tx_started,
		.end = tx_ended,
	};
	struct k_sem sem;

	k_sem_init(&sem, 0, 1);

	uint32_t seq = bt_mesh.seq;

	for (int i = 0; i < 3; i++) {
		is_tx_succeeded = false;

		memset(test_data, i, sizeof(test_data));
		ASSERT_OK(bt_mesh_test_send_ra(rx_cfg.addr, test_data,
			sizeof(test_data), &send_cb, &sem));

		if (k_sem_take(&sem, K_SECONDS(TEST_DATA_WAITING_TIME))) {
			LOG_ERR("Send timed out");
		}

		ASSERT_TRUE(is_tx_succeeded);
	}

	bt_mesh.seq = seq;

	for (int i = 0; i < 3; i++) {
		is_tx_succeeded = true;

		memset(test_data, i, sizeof(test_data));
		ASSERT_OK(bt_mesh_test_send_ra(rx_cfg.addr, test_data,
			sizeof(test_data), &send_cb, &sem));

		if (k_sem_take(&sem, K_SECONDS(TEST_DATA_WAITING_TIME))) {
			LOG_ERR("Send timed out");
		}

		ASSERT_TRUE(!is_tx_succeeded);
	}

	PASS();
}

static void test_rx_immediate_replay_attack(void)
{
	settings_test_backend_clear();
	bt_mesh_test_setup();
	bt_mesh_test_ra_cb_setup(rx_ended);

	k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));

	ASSERT_TRUE(rx_cnt == 3, "Device didn't receive expected data");

	PASS();
}

static void test_tx_power_replay_attack(void)
{
	settings_test_backend_clear();
	bt_mesh_test_setup();

	static const struct bt_mesh_send_cb send_cb = {
		.start = tx_started,
		.end = tx_ended,
	};
	struct k_sem sem;

	k_sem_init(&sem, 0, 1);

	for (int i = 0; i < 3; i++) {
		is_tx_succeeded = true;

		memset(test_data, i, sizeof(test_data));
		ASSERT_OK(bt_mesh_test_send_ra(rx_cfg.addr, test_data,
			sizeof(test_data), &send_cb, &sem));

		if (k_sem_take(&sem, K_SECONDS(TEST_DATA_WAITING_TIME))) {
			LOG_ERR("Send timed out");
		}

		ASSERT_TRUE(!is_tx_succeeded);
	}

	for (int i = 0; i < 3; i++) {
		is_tx_succeeded = false;

		memset(test_data, i, sizeof(test_data));
		ASSERT_OK(bt_mesh_test_send_ra(rx_cfg.addr, test_data,
			sizeof(test_data), &send_cb, &sem));

		if (k_sem_take(&sem, K_SECONDS(TEST_DATA_WAITING_TIME))) {
			LOG_ERR("Send timed out");
		}

		ASSERT_TRUE(is_tx_succeeded);
	}

	PASS();
}

static void test_rx_power_replay_attack(void)
{
	bt_mesh_test_setup();
	bt_mesh_test_ra_cb_setup(rx_ended);

	k_sleep(K_SECONDS(6 * TEST_DATA_WAITING_TIME));

	ASSERT_TRUE(rx_cnt == 3, "Device didn't receive expected data");

	PASS();
}

#define TEST_CASE(role, name, description)                     \
	{                                                      \
		.test_id = "rpc_" #role "_" #name,             \
		.test_descr = description,                     \
		.test_post_init_f = test_##role##_init,        \
		.test_tick_f = bt_mesh_test_timeout,           \
		.test_main_f = test_##role##_##name,           \
	}

static const struct bst_test_instance test_rpc[] = {
	TEST_CASE(tx, immediate_replay_attack, "RPC: perform replay attack immediately"),
	TEST_CASE(tx, power_replay_attack,     "RPC: perform replay attack after power cycle"),

	TEST_CASE(rx, immediate_replay_attack, "RPC: device under immediate attack"),
	TEST_CASE(rx, power_replay_attack,     "RPC: device under power cycle reply attack"),
	BSTEST_END_MARKER
};

struct bst_test_list *test_rpc_install(struct bst_test_list *tests)
{
	tests = bst_add_tests(tests, test_rpc);
	return tests;
}
