/* 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()
{
	/* 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));
	}
}
