/* Copyright 2019 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <osmocom/core/select.h>
#include <osmocom/core/application.h>
#include <osmocom/hlr/logging.h>
#include <osmocom/mslookup/mslookup.h>
#include <osmocom/mslookup/mslookup_client.h>
#include <osmocom/mslookup/mslookup_client_mdns.h>
#include <osmocom/mslookup/mdns.h>
#include <osmocom/mslookup/mdns_sock.h>

void *ctx = NULL;

#define TEST_IP OSMO_MSLOOKUP_MDNS_IP4
#define TEST_PORT OSMO_MSLOOKUP_MDNS_PORT
#define TEST_DOMAIN_SUFFIX "mslookup_client_mdns_test.dgsm.osmocom.org"

/*
 * Test server (emulates the mDNS server in OsmoHLR) and client
 */
struct osmo_mdns_sock *server_mc;


static void server_reply(struct osmo_mslookup_query *query, uint16_t packet_id)
{
	struct osmo_mslookup_result result = {0};
	struct msgb *msg;

	result.rc = OSMO_MSLOOKUP_RC_RESULT;
	result.age = 3;
	osmo_sockaddr_str_from_str(&result.host_v4, "42.42.42.42", 444);
	osmo_sockaddr_str_from_str(&result.host_v6, "1122:3344:5566:7788:99aa:bbcc:ddee:ff00", 666);

	msg = osmo_mdns_result_encode(ctx, packet_id, query, &result, TEST_DOMAIN_SUFFIX);
	OSMO_ASSERT(msg);
	OSMO_ASSERT(osmo_mdns_sock_send(server_mc, msg) == 0);
}

static int server_recv(struct osmo_fd *osmo_fd, unsigned int what)
{
	int n;
	uint8_t buffer[1024];
	uint16_t packet_id;
	struct osmo_mslookup_query *query;

	fprintf(stderr, "%s\n", __func__);

	/* Parse the message and print it */
	n = read(osmo_fd->fd, buffer, sizeof(buffer));
	OSMO_ASSERT(n >= 0);

	query = osmo_mdns_query_decode(ctx, buffer, n, &packet_id, TEST_DOMAIN_SUFFIX);
	if (!query)
		return -1; /* server receiving own answer is expected */

	fprintf(stderr, "received request\n");
	server_reply(query, packet_id);
	talloc_free(query);
	return n;
}

static void server_init()
{
	fprintf(stderr, "%s\n", __func__);
	server_mc = osmo_mdns_sock_init(ctx, TEST_IP, TEST_PORT, server_recv, NULL, 0);
	OSMO_ASSERT(server_mc);
}

static void server_stop()
{
	fprintf(stderr, "%s\n", __func__);
	OSMO_ASSERT(server_mc);
	osmo_mdns_sock_cleanup(server_mc);
	server_mc = NULL;
}

struct osmo_mslookup_client* client;
struct osmo_mslookup_client_method* client_method;

static void client_init()
{
	fprintf(stderr, "%s\n", __func__);
	client = osmo_mslookup_client_new(ctx);
	OSMO_ASSERT(client);
	client_method = osmo_mslookup_client_add_mdns(client, TEST_IP, TEST_PORT, 1337, TEST_DOMAIN_SUFFIX);
	OSMO_ASSERT(client_method);
}

static void client_recv(struct osmo_mslookup_client *client, uint32_t request_handle,
			const struct osmo_mslookup_query *query, const struct osmo_mslookup_result *result)
{
	char buf[256];
	fprintf(stderr, "%s\n", __func__);
	fprintf(stderr, "client_recv(): %s\n", osmo_mslookup_result_name_b(buf, sizeof(buf), query, result));

	osmo_mslookup_client_request_cancel(client, request_handle);
}

static void client_query()
{
	struct osmo_mslookup_id id = {.type = OSMO_MSLOOKUP_ID_IMSI,
				      .imsi = "123456789012345"};
	const struct osmo_mslookup_query query = {
		.service = "gsup.hlr",
		.id = id,
	};
	struct osmo_mslookup_query_handling handling = {
		.result_timeout_milliseconds = 2000,
		.result_cb = client_recv,
	};

	fprintf(stderr, "%s\n", __func__);
	osmo_mslookup_client_request(client, &query, &handling);
}

static void client_stop()
{
	fprintf(stderr, "%s\n", __func__);
	osmo_mslookup_client_free(client);
	client = NULL;
}
const struct timeval fake_time_start_time = { 0, 0 };

#define fake_time_passes(secs, usecs) do \
{ \
	struct timeval diff; \
	osmo_gettimeofday_override_add(secs, usecs); \
	osmo_clock_override_add(CLOCK_MONOTONIC, secs, usecs * 1000); \
	timersub(&osmo_gettimeofday_override_time, &fake_time_start_time, &diff); \
	LOGP(DMSLOOKUP, LOGL_DEBUG, "Total time passed: %d.%06d s\n", \
	       (int)diff.tv_sec, (int)diff.tv_usec); \
	osmo_timers_prepare(); \
	osmo_timers_update(); \
} while (0)

static void fake_time_start()
{
	struct timespec *clock_override;

	osmo_gettimeofday_override_time = fake_time_start_time;
	osmo_gettimeofday_override = true;
	clock_override = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
	OSMO_ASSERT(clock_override);
	clock_override->tv_sec = fake_time_start_time.tv_sec;
	clock_override->tv_nsec = fake_time_start_time.tv_usec * 1000;
	osmo_clock_override_enable(CLOCK_MONOTONIC, true);
	fake_time_passes(0, 0);
}
static void test_server_client()
{
	fprintf(stderr, "-- %s --\n", __func__);
	server_init();
	client_init();
	client_query();

	/* Let the server receive the query and indirectly call server_recv(). As side effect of using the same IP and
	 * port, the client will also receive its own question. The client will dismiss its own question, as it is just
	 * looking for answers. */
	OSMO_ASSERT(osmo_select_main_ctx(1) == 1);

	/* Let the mslookup client receive the answer (also same side effect as above). It does not call the callback
         * (client_recv()) just yet, because it is waiting for the best result within two seconds. */
	OSMO_ASSERT(osmo_select_main_ctx(1) == 1);

	/* Time flies by, client_recv() gets called. */
	fake_time_passes(5, 0);

	server_stop();
	client_stop();
}

bool is_multicast_enabled()
{
	bool ret = true;
	struct addrinfo *ai;
	int sock;
	struct addrinfo hints = {0};
	struct ip_mreq multicast_req = {0};
	in_addr_t iface = INADDR_ANY;

	hints.ai_family = PF_UNSPEC;
	hints.ai_socktype = SOCK_DGRAM;
	hints.ai_flags = (AI_PASSIVE | AI_NUMERICHOST);
	assert(getaddrinfo("239.192.23.42", "4266", &hints, &ai) == 0);

	sock = socket(ai->ai_family, ai->ai_socktype, 0);
	assert(sock != -1);
	assert(setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, (char*)&iface, sizeof(iface)) != -1);

	memcpy(&multicast_req.imr_multiaddr, &((struct sockaddr_in*)(ai->ai_addr))->sin_addr,
	       sizeof(multicast_req.imr_multiaddr));
	multicast_req.imr_interface.s_addr = htonl(INADDR_ANY);

	if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&multicast_req, sizeof(multicast_req)) == -1)
		ret = false;

	freeaddrinfo(ai);
	return ret;
}

/*
 * Run all tests
 */
int main()
{
	if (!is_multicast_enabled()) {
		fprintf(stderr, "ERROR: multicast is disabled! (OS#4361)");
		return 1;
	}

	talloc_enable_null_tracking();
	ctx = talloc_named_const(NULL, 0, "main");
	osmo_init_logging2(ctx, NULL);

	log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
	log_set_print_level(osmo_stderr_target, 0);
	log_set_print_category(osmo_stderr_target, 0);
	log_set_print_category_hex(osmo_stderr_target, 0);
	log_set_use_color(osmo_stderr_target, 0);
	log_set_category_filter(osmo_stderr_target, DMSLOOKUP, true, LOGL_DEBUG);

	fake_time_start();

	test_server_client();

	log_fini();

	OSMO_ASSERT(talloc_total_blocks(ctx) == 1);
	talloc_free(ctx);
	OSMO_ASSERT(talloc_total_blocks(NULL) == 1);
	talloc_disable_null_tracking();

	return 0;
}
