/* 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 <stdlib.h>
#include <unistd.h>

#include <osmocom/mslookup/mslookup.h>
#include <osmocom/mslookup/mdns.h>
#include <osmocom/hlr/logging.h>
#include <osmocom/hlr/hlr.h>
#include <osmocom/hlr/mslookup_server.h>
#include <osmocom/hlr/mslookup_server_mdns.h>

static void osmo_mslookup_server_mdns_tx(struct osmo_mslookup_server_mdns *server,
					 uint16_t packet_id,
					 const struct osmo_mslookup_query *query,
					 const struct osmo_mslookup_result *result)
{
	struct msgb *msg;
	const char *errmsg = NULL;
	void *ctx = talloc_named_const(server, 0, __func__);

	msg = osmo_mdns_result_encode(ctx, packet_id, query, result, server->domain_suffix);
	if (!msg)
		errmsg = "Error encoding mDNS answer packet";
	else if (osmo_mdns_sock_send(server->sock, msg))
		errmsg = "Error sending mDNS answer";
	if (errmsg)
		LOGP(DMSLOOKUP, LOGL_ERROR, "%s: mDNS: %s\n", osmo_mslookup_result_name_c(ctx, query, result), errmsg);
	talloc_free(ctx);
}

static void osmo_mslookup_server_mdns_handle_request(uint16_t packet_id,
						     struct osmo_mslookup_server_mdns *server,
						     const struct osmo_mslookup_query *query)
{
	struct osmo_mslookup_result result;

	mslookup_server_rx(query, &result);
	/* Error logging already happens in mslookup_server_rx() */
	if (result.rc != OSMO_MSLOOKUP_RC_RESULT)
		return;

	osmo_mslookup_server_mdns_tx(server, packet_id, query, &result);
}

static int osmo_mslookup_server_mdns_rx(struct osmo_fd *osmo_fd, unsigned int what)
{
	struct osmo_mslookup_server_mdns *server = osmo_fd->data;
	struct osmo_mslookup_query *query;
	uint16_t packet_id;
	int n;
	uint8_t buffer[1024];
	void *ctx;

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

	ctx = talloc_named_const(server, 0, __func__);
	query = osmo_mdns_query_decode(ctx, buffer, n, &packet_id, server->domain_suffix);
	if (!query) {
		talloc_free(ctx);
		return -1;
	}

	osmo_mslookup_id_name_buf((char *)buffer, sizeof(buffer), &query->id);
	LOGP(DMSLOOKUP, LOGL_DEBUG, "mDNS rx request: %s.%s\n", query->service, buffer);
	osmo_mslookup_server_mdns_handle_request(packet_id, server, query);
	talloc_free(ctx);
	return n;
}

struct osmo_mslookup_server_mdns *osmo_mslookup_server_mdns_start(void *ctx, const struct osmo_sockaddr_str *bind_addr,
								  const char *domain_suffix)
{
	struct osmo_mslookup_server_mdns *server = talloc_zero(ctx, struct osmo_mslookup_server_mdns);
	OSMO_ASSERT(server);
	*server = (struct osmo_mslookup_server_mdns){
		.bind_addr = *bind_addr,
		.domain_suffix = talloc_strdup(server, domain_suffix)
	};

	server->sock = osmo_mdns_sock_init(server,
					   bind_addr->ip, bind_addr->port,
					   osmo_mslookup_server_mdns_rx,
					   server, 0);
	if (!server->sock) {
		LOGP(DMSLOOKUP, LOGL_ERROR,
		     "mslookup mDNS server: error initializing multicast bind on " OSMO_SOCKADDR_STR_FMT "\n",
		     OSMO_SOCKADDR_STR_FMT_ARGS(bind_addr));
		talloc_free(server);
		return NULL;
	}

	return server;
}

void osmo_mslookup_server_mdns_stop(struct osmo_mslookup_server_mdns *server)
{
	if (!server)
		return;
	osmo_mdns_sock_cleanup(server->sock);
	talloc_free(server);
}

void mslookup_server_mdns_config_apply(void)
{
	/* Check whether to start/stop/restart mDNS server */
	bool should_run;
	bool should_stop;

	should_run = g_hlr->mslookup.allow_startup
		&& g_hlr->mslookup.server.enable && g_hlr->mslookup.server.mdns.enable;
	should_stop = g_hlr->mslookup.server.mdns.running
		&& (!should_run
		    || osmo_sockaddr_str_cmp(&g_hlr->mslookup.server.mdns.bind_addr,
					     &g_hlr->mslookup.server.mdns.running->bind_addr)
		    || strcmp(g_hlr->mslookup.server.mdns.domain_suffix,
			      g_hlr->mslookup.server.mdns.running->domain_suffix));

	if (should_stop) {
		osmo_mslookup_server_mdns_stop(g_hlr->mslookup.server.mdns.running);
		g_hlr->mslookup.server.mdns.running = NULL;
		LOGP(DMSLOOKUP, LOGL_NOTICE, "Stopped mslookup mDNS server\n");
	}

	if (should_run && !g_hlr->mslookup.server.mdns.running) {
		g_hlr->mslookup.server.mdns.running =
			osmo_mslookup_server_mdns_start(g_hlr, &g_hlr->mslookup.server.mdns.bind_addr,
							g_hlr->mslookup.server.mdns.domain_suffix);
		if (!g_hlr->mslookup.server.mdns.running)
			LOGP(DMSLOOKUP, LOGL_ERROR, "Failed to start mslookup mDNS server on " OSMO_SOCKADDR_STR_FMT "\n",
			     OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.bind_addr));
		else
			LOGP(DMSLOOKUP, LOGL_NOTICE, "Started mslookup mDNS server, receiving mDNS requests at multicast "
			     OSMO_SOCKADDR_STR_FMT "\n",
			     OSMO_SOCKADDR_STR_FMT_ARGS(&g_hlr->mslookup.server.mdns.running->bind_addr));
	}
}
