From 2c9ba58d3142243b439dd83b254b1e6eba94d52c Mon Sep 17 00:00:00 2001
From: David Härdeman <david@hardeman.nu>
Date: Sun, 5 Jul 2020 19:04:13 +0200
Subject: Add per-server announce setting

---
 minecctl/minecctl.c            | 17 +++++++++++++++++
 minecproxy/main.c              |  6 +++---
 minecproxy/server.c            |  6 +++++-
 shared/config-parser.c         | 17 +++++++++++++++++
 shared/config-parser.h         |  8 ++++++++
 shared/server-config-options.h |  6 ++++++
 6 files changed, 56 insertions(+), 4 deletions(-)

diff --git a/minecctl/minecctl.c b/minecctl/minecctl.c
index 1752e25..dd4e9e8 100644
--- a/minecctl/minecctl.c
+++ b/minecctl/minecctl.c
@@ -47,6 +47,23 @@ static void dump_server(struct server *server)
 	}
 
 	info("│   │ pretty_name      : %s", server->scfg.pretty_name);
+
+	switch (server->scfg.announce) {
+	case SERVER_ANNOUNCE_ALWAYS:
+		info("│   │ announce         : always");
+		break;
+	case SERVER_ANNOUNCE_NEVER:
+		info("│   │ announce         : never");
+		break;
+	case SERVER_ANNOUNCE_WHEN_RUNNING:
+		info("│   │ announce         : when-running");
+		break;
+	case SERVER_ANNOUNCE_UNDEFINED:
+		_fallthrough_;
+	default:
+		info("│   │ announce         : <undefined>");
+	}
+
 	info("│   │ announce_port    : %" PRIu16, server->scfg.announce_port);
 	info("│   │ idle_timeout     : %u", server->scfg.idle_timeout);
 
diff --git a/minecproxy/main.c b/minecproxy/main.c
index 54a0d7b..6ec92ba 100644
--- a/minecproxy/main.c
+++ b/minecproxy/main.c
@@ -187,7 +187,7 @@ enum mcfg_keys {
 	MCFG_KEY_INVALID = 0,
 	MCFG_KEY_IGMP,
 	MCFG_KEY_IGMP_IFACE,
-	MCFG_KEY_ANN_INTERVAL,
+	MCFG_KEY_ANNOUNCE_INTERVAL,
 	MCFG_KEY_PROXY_CONN_INTERVAL,
 	MCFG_KEY_PROXY_CONN_ATTEMPTS,
 	MCFG_KEY_SOCKET_DEFER,
@@ -210,7 +210,7 @@ struct cfg_key_value_map mcfg_key_map[] = {
 	},
 	{
 		.key_name = "announce_interval",
-		.key_value = MCFG_KEY_ANN_INTERVAL,
+		.key_value = MCFG_KEY_ANNOUNCE_INTERVAL,
 		.value_type = CFG_VAL_TYPE_UINT16,
 	},
 	{
@@ -332,7 +332,7 @@ static void cfg_read()
 
 			break;
 
-		case MCFG_KEY_ANN_INTERVAL:
+		case MCFG_KEY_ANNOUNCE_INTERVAL:
 			cfg->announce_interval = value.uint16;
 			break;
 
diff --git a/minecproxy/server.c b/minecproxy/server.c
index 84a50ee..85019b4 100644
--- a/minecproxy/server.c
+++ b/minecproxy/server.c
@@ -91,6 +91,7 @@ void server_delete_by_filename(const char *filename)
 	}
 }
 
+/* FIXME: Share with minecctl */
 static void server_dump(struct server *server)
 {
 	struct server_local *local;
@@ -400,7 +401,10 @@ bool server_announce(struct server *server, int fd)
 	assert_return(server && fd >= 0, false);
 
 	if (server->state == SERVER_STATE_INIT ||
-	    server->state == SERVER_STATE_DEAD)
+	    server->state == SERVER_STATE_DEAD ||
+	    server->scfg.announce == SERVER_ANNOUNCE_NEVER ||
+	    (server->scfg.announce == SERVER_ANNOUNCE_WHEN_RUNNING &&
+	     server->state != SERVER_STATE_RUNNING))
 		return false;
 
 	debug(DBG_ANN, "announcing server: %s", server->name);
diff --git a/shared/config-parser.c b/shared/config-parser.c
index 3309b96..6b91f3f 100644
--- a/shared/config-parser.c
+++ b/shared/config-parser.c
@@ -216,6 +216,9 @@ bool scfg_validate(struct server_config *scfg, const char **error)
 
 	switch (scfg->type) {
 	case SERVER_TYPE_ANNOUNCE:
+		if (scfg->announce == SERVER_ANNOUNCE_NEVER)
+			ERROR("announce policy never with an announce server");
+	
 		if (scfg->announce_port == 0)
 			ERROR("missing announce port");
 
@@ -365,6 +368,19 @@ bool scfg_parse(struct server_config *scfg, char *buf, bool async,
 				ERROR("strdup failure");
 			break;
 
+		case SCFG_KEY_ANNOUNCE:
+			if (scfg->announce != SERVER_ANNOUNCE_UNDEFINED)
+				ERROR("announce policy defined multiple times");
+			else if (streq(value.str, "always"))
+				scfg->announce = SERVER_ANNOUNCE_ALWAYS;
+			else if (streq(value.str, "never"))
+				scfg->announce = SERVER_ANNOUNCE_NEVER;
+			else if (streq(value.str, "when-running"))
+				scfg->announce = SERVER_ANNOUNCE_WHEN_RUNNING;
+			else
+				ERROR("unknown announce policy");
+			break;
+
 		case SCFG_KEY_PORT:
 			if (scfg->announce_port != 0)
 				ERROR("port defined multiple times");
@@ -526,6 +542,7 @@ bool scfg_init(struct server_config *scfg, const char *filename)
 
 	scfg->type = SERVER_TYPE_UNDEFINED;
 	scfg->pretty_name = NULL;
+	scfg->announce = SERVER_ANNOUNCE_UNDEFINED;
 	scfg->announce_port = 0;
 	scfg->idle_timeout = 0;
 	scfg->stop_method = SERVER_STOP_METHOD_UNDEFINED;
diff --git a/shared/config-parser.h b/shared/config-parser.h
index e1d73d2..4e3cbca 100644
--- a/shared/config-parser.h
+++ b/shared/config-parser.h
@@ -26,10 +26,18 @@ enum server_start_method {
 	SERVER_START_METHOD_EXEC,
 };
 
+enum server_announce {
+	SERVER_ANNOUNCE_UNDEFINED,
+	SERVER_ANNOUNCE_ALWAYS,
+	SERVER_ANNOUNCE_NEVER,
+	SERVER_ANNOUNCE_WHEN_RUNNING,
+};
+
 struct server_config {
 	char *filename;
 	enum server_type type;
 	char *pretty_name;
+	enum server_announce announce;
 	uint16_t announce_port;
 	unsigned idle_timeout;
 	enum server_stop_method stop_method;
diff --git a/shared/server-config-options.h b/shared/server-config-options.h
index 5600e52..78f9598 100644
--- a/shared/server-config-options.h
+++ b/shared/server-config-options.h
@@ -7,6 +7,7 @@ enum scfg_keys {
 	SCFG_KEY_INVALID = 0,
 	SCFG_KEY_TYPE,
 	SCFG_KEY_NAME,
+	SCFG_KEY_ANNOUNCE,
 	SCFG_KEY_PORT,
 	SCFG_KEY_LOCAL,
 	SCFG_KEY_REMOTE,
@@ -31,6 +32,11 @@ struct cfg_key_value_map scfg_key_map[] = {
 		.key_value = SCFG_KEY_NAME,
 		.value_type = CFG_VAL_TYPE_STRING,
 	},
+	{
+		.key_name = "announce",
+		.key_value = SCFG_KEY_ANNOUNCE,
+		.value_type = CFG_VAL_TYPE_STRING,
+	},
 	{
 		.key_name = "port",
 		.key_value = SCFG_KEY_PORT,
-- 
cgit v1.2.3