Seperate out night-config toml loading logic

This commit is contained in:
Shane Freeder
2024-11-07 15:45:26 +00:00
parent 08a42b3723
commit c40181fcf9
4 changed files with 355 additions and 223 deletions

View File

@@ -45,6 +45,7 @@ import com.velocitypowered.proxy.command.builtin.SendCommand;
import com.velocitypowered.proxy.command.builtin.ServerCommand; import com.velocitypowered.proxy.command.builtin.ServerCommand;
import com.velocitypowered.proxy.command.builtin.ShutdownCommand; import com.velocitypowered.proxy.command.builtin.ShutdownCommand;
import com.velocitypowered.proxy.command.builtin.VelocityCommand; import com.velocitypowered.proxy.command.builtin.VelocityCommand;
import com.velocitypowered.proxy.config.LegacyConfigurationLoader;
import com.velocitypowered.proxy.config.VelocityConfiguration; import com.velocitypowered.proxy.config.VelocityConfiguration;
import com.velocitypowered.proxy.connection.client.ConnectedPlayer; import com.velocitypowered.proxy.connection.client.ConnectedPlayer;
import com.velocitypowered.proxy.connection.player.resourcepack.VelocityResourcePackInfo; import com.velocitypowered.proxy.connection.player.resourcepack.VelocityResourcePackInfo;
@@ -383,7 +384,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
private void doStartupConfigLoad() { private void doStartupConfigLoad() {
try { try {
Path configPath = Path.of("velocity.toml"); Path configPath = Path.of("velocity.toml");
configuration = VelocityConfiguration.read(configPath); configuration = LegacyConfigurationLoader.read(configPath);
if (!configuration.validate()) { if (!configuration.validate()) {
logger.error("Your configuration is invalid. Velocity will not start up until the errors " logger.error("Your configuration is invalid. Velocity will not start up until the errors "
@@ -461,7 +462,7 @@ public class VelocityServer implements ProxyServer, ForwardingAudience {
*/ */
public boolean reloadConfiguration() throws IOException { public boolean reloadConfiguration() throws IOException {
Path configPath = Path.of("velocity.toml"); Path configPath = Path.of("velocity.toml");
VelocityConfiguration newConfiguration = VelocityConfiguration.read(configPath); VelocityConfiguration newConfiguration = LegacyConfigurationLoader.read(configPath);
if (!newConfiguration.validate()) { if (!newConfiguration.validate()) {
return false; return false;

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.config;
/**
* Velocity Configurate Loader entry utils.
*/
public class ConfigurationLoader {
private ConfigurationLoader() {
}
/**
* performs legacy configuration migration if needed.
*
* @return {@code true} if a migration was performed, {@code false} otherwise
*/
public static boolean migrateIfNeeded() {
return false;
}
/**
* loads the velocity configuration.
*
* @return the loaded configuration
*/
public static VelocityConfiguration loadConfiguration() {
return null;
}
}

View File

@@ -0,0 +1,258 @@
/*
* Copyright (C) 2024 Velocity Contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.velocitypowered.proxy.config;
import static com.velocitypowered.proxy.config.VelocityConfiguration.Servers.cleanServerName;
import static com.velocitypowered.proxy.config.VelocityConfiguration.generateRandomString;
import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.velocitypowered.proxy.config.migration.ConfigurationMigration;
import com.velocitypowered.proxy.config.migration.ForwardingMigration;
import com.velocitypowered.proxy.config.migration.KeyAuthenticationMigration;
import com.velocitypowered.proxy.config.migration.MotdMigration;
import com.velocitypowered.proxy.config.migration.TransferIntegrationMigration;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* Legacy configuration loader for Velocity.
*/
public class LegacyConfigurationLoader {
private static final Logger logger = LogManager.getLogger(LegacyConfigurationLoader.class);
/**
* Reads the Velocity configuration from {@code path}.
*
* @param path the path to read from
* @return the deserialized Velocity configuration
* @throws IOException if we could not read from the {@code path}.
*/
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
justification = "I looked carefully and there's no way SpotBugs is right.")
public static VelocityConfiguration read(Path path) throws IOException {
URL defaultConfigLocation = VelocityConfiguration.class.getClassLoader()
.getResource("default-velocity.toml");
if (defaultConfigLocation == null) {
throw new RuntimeException("Default configuration file does not exist.");
}
// Create the forwarding-secret file on first-time startup if it doesn't exist
final Path defaultForwardingSecretPath = Path.of("forwarding.secret");
if (Files.notExists(path) && Files.notExists(defaultForwardingSecretPath)) {
Files.writeString(defaultForwardingSecretPath, generateRandomString(12));
}
try (final CommentedFileConfig config = CommentedFileConfig.builder(path)
.defaultData(defaultConfigLocation)
.autosave()
.preserveInsertionOrder()
.sync()
.build()
) {
config.load();
final ConfigurationMigration[] migrations = {
new ForwardingMigration(),
new KeyAuthenticationMigration(),
new MotdMigration(),
new TransferIntegrationMigration()
};
for (final ConfigurationMigration migration : migrations) {
if (migration.shouldMigrate(config)) {
migration.migrate(config, logger);
}
}
String forwardingSecretString = System.getenv().getOrDefault(
"VELOCITY_FORWARDING_SECRET", "");
if (forwardingSecretString.isEmpty()) {
final String forwardSecretFile = config.get("forwarding-secret-file");
final Path secretPath = forwardSecretFile == null
? defaultForwardingSecretPath
: Path.of(forwardSecretFile);
if (Files.exists(secretPath)) {
if (Files.isRegularFile(secretPath)) {
forwardingSecretString = String.join("", Files.readAllLines(secretPath));
} else {
throw new RuntimeException(
"The file " + forwardSecretFile + " is not a valid file or it is a directory.");
}
} else {
throw new RuntimeException("The forwarding-secret-file does not exist.");
}
}
final byte[] forwardingSecret = forwardingSecretString.getBytes(StandardCharsets.UTF_8);
final String motd = config.getOrElse("motd", "<#09add3>A Velocity Server");
// Read the rest of the config
final CommentedConfig serversConfig = config.get("servers");
final CommentedConfig forcedHostsConfig = config.get("forced-hosts");
final CommentedConfig advancedConfig = config.get("advanced");
final CommentedConfig queryConfig = config.get("query");
final CommentedConfig metricsConfig = config.get("metrics");
final PlayerInfoForwarding forwardingMode = config.getEnumOrElse(
"player-info-forwarding-mode", PlayerInfoForwarding.NONE);
final PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
PingPassthroughMode.DISABLED);
final String bind = config.getOrElse("bind", "0.0.0.0:25565");
final int maxPlayers = config.getIntOrElse("show-max-players", 500);
final boolean onlineMode = config.getOrElse("online-mode", true);
final boolean forceKeyAuthentication = config.getOrElse("force-key-authentication", true);
final boolean announceForge = config.getOrElse("announce-forge", true);
final boolean preventClientProxyConnections = config.getOrElse(
"prevent-client-proxy-connections", false);
final boolean kickExisting = config.getOrElse("kick-existing-players", false);
final boolean enablePlayerAddressLogging = config.getOrElse(
"enable-player-address-logging", true);
// Throw an exception if the forwarding-secret file is empty and the proxy is using a
// forwarding mode that requires it.
if (forwardingSecret.length == 0
&& (forwardingMode == PlayerInfoForwarding.MODERN
|| forwardingMode == PlayerInfoForwarding.BUNGEEGUARD)) {
throw new RuntimeException("The forwarding-secret file must not be empty.");
}
return new VelocityConfiguration(
bind,
motd,
maxPlayers,
onlineMode,
preventClientProxyConnections,
announceForge,
forwardingMode,
forwardingSecret,
kickExisting,
pingPassthroughMode,
enablePlayerAddressLogging,
readServers(serversConfig),
readForcedHosts(forcedHostsConfig),
readAdvanced(advancedConfig),
readQuery(queryConfig),
readMetrics(metricsConfig),
forceKeyAuthentication
);
}
}
private static VelocityConfiguration.Servers readServers(CommentedConfig config) {
if (config != null) {
Map<String, String> servers = new HashMap<>();
for (UnmodifiableConfig.Entry entry : config.entrySet()) {
if (entry.getValue() instanceof String) {
servers.put(cleanServerName(entry.getKey()), entry.getValue());
} else {
if (!entry.getKey().equalsIgnoreCase("try")) {
throw new IllegalArgumentException(
"Server entry " + entry.getKey() + " is not a string!");
}
}
}
return new VelocityConfiguration.Servers(ImmutableMap.copyOf(servers),
config.getOrElse("try", ImmutableList.of("lobby")));
}
return new VelocityConfiguration.Servers();
}
private static VelocityConfiguration.ForcedHosts readForcedHosts(CommentedConfig config) {
if (config != null) {
Map<String, List<String>> forcedHosts = new HashMap<>();
for (UnmodifiableConfig.Entry entry : config.entrySet()) {
if (entry.getValue() instanceof String) {
forcedHosts.put(entry.getKey().toLowerCase(Locale.ROOT),
ImmutableList.of(entry.getValue()));
} else if (entry.getValue() instanceof List) {
forcedHosts.put(entry.getKey().toLowerCase(Locale.ROOT),
ImmutableList.copyOf((List<String>) entry.getValue()));
} else {
throw new IllegalStateException(
"Invalid value of type " + entry.getValue().getClass() + " in forced hosts!");
}
}
return new VelocityConfiguration.ForcedHosts(forcedHosts);
}
return new VelocityConfiguration.ForcedHosts();
}
private static VelocityConfiguration.Advanced readAdvanced(CommentedConfig config) {
if (config != null) {
int compressionThreshold = config.getIntOrElse("compression-threshold", 256);
int compressionLevel = config.getIntOrElse("compression-level", -1);
int loginRatelimit = config.getIntOrElse("login-ratelimit", 3000);
int connectionTimeout = config.getIntOrElse("connection-timeout", 5000);
int readTimeout = config.getIntOrElse("read-timeout", 30000);
boolean proxyProtocol = false;
if (config.contains("haproxy-protocol")) {
proxyProtocol = config.getOrElse("haproxy-protocol", false);
} else {
proxyProtocol = config.getOrElse("proxy-protocol", false);
}
boolean tcpFastOpen = config.getOrElse("tcp-fast-open", false);
boolean bungeePluginMessageChannel = config.getOrElse("bungee-plugin-message-channel", true);
boolean showPingRequests = config.getOrElse("show-ping-requests", false);
boolean failoverOnUnexpectedServerDisconnect = config
.getOrElse("failover-on-unexpected-server-disconnect", true);
boolean announceProxyCommands = config.getOrElse("announce-proxy-commands", true);
boolean logCommandExecutions = config.getOrElse("log-command-executions", false);
boolean logPlayerConnections = config.getOrElse("log-player-connections", true);
boolean acceptTransfers = config.getOrElse("accepts-transfers", false);
return new VelocityConfiguration.Advanced(compressionThreshold, compressionLevel,
loginRatelimit, connectionTimeout, readTimeout, proxyProtocol, tcpFastOpen,
bungeePluginMessageChannel, showPingRequests, failoverOnUnexpectedServerDisconnect,
announceProxyCommands, logCommandExecutions, logPlayerConnections, acceptTransfers);
}
return new VelocityConfiguration.Advanced();
}
private static VelocityConfiguration.Query readQuery(CommentedConfig config) {
if (config != null) {
boolean queryEnabled = config.getOrElse("enabled", false);
int queryPort = config.getIntOrElse("port", 25565);
String queryMap = config.getOrElse("map", "Velocity");
boolean showPlugins = config.getOrElse("show-plugins", false);
return new VelocityConfiguration.Query(queryEnabled, queryPort, queryMap, showPlugins);
}
return new VelocityConfiguration.Query();
}
private static VelocityConfiguration.Metrics readMetrics(CommentedConfig config) {
if (config != null) {
boolean enabled = config.getOrElse("enabled", true);
return new VelocityConfiguration.Metrics(enabled);
}
return new VelocityConfiguration.Metrics();
}
}

View File

@@ -17,32 +17,19 @@
package com.velocitypowered.proxy.config; package com.velocitypowered.proxy.config;
import com.electronwill.nightconfig.core.CommentedConfig;
import com.electronwill.nightconfig.core.UnmodifiableConfig;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.gson.annotations.Expose; import com.google.gson.annotations.Expose;
import com.velocitypowered.api.proxy.config.ProxyConfig; import com.velocitypowered.api.proxy.config.ProxyConfig;
import com.velocitypowered.api.util.Favicon; import com.velocitypowered.api.util.Favicon;
import com.velocitypowered.proxy.config.migration.ConfigurationMigration;
import com.velocitypowered.proxy.config.migration.ForwardingMigration;
import com.velocitypowered.proxy.config.migration.KeyAuthenticationMigration;
import com.velocitypowered.proxy.config.migration.MotdMigration;
import com.velocitypowered.proxy.config.migration.TransferIntegrationMigration;
import com.velocitypowered.proxy.util.AddressUtil; import com.velocitypowered.proxy.util.AddressUtil;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Random; import java.util.Random;
@@ -51,10 +38,12 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
/** /**
* Velocity's configuration. * Velocity's configuration.
*/ */
@ConfigSerializable
public class VelocityConfiguration implements ProxyConfig { public class VelocityConfiguration implements ProxyConfig {
private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class); private static final Logger logger = LogManager.getLogger(VelocityConfiguration.class);
@@ -101,12 +90,14 @@ public class VelocityConfiguration implements ProxyConfig {
this.metrics = metrics; this.metrics = metrics;
} }
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode, VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
boolean preventClientProxyConnections, boolean announceForge, boolean preventClientProxyConnections, boolean announceForge,
PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret, PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret,
boolean onlineModeKickExistingPlayers, PingPassthroughMode pingPassthrough, boolean onlineModeKickExistingPlayers, PingPassthroughMode pingPassthrough,
boolean enablePlayerAddressLogging, Servers servers, ForcedHosts forcedHosts, boolean enablePlayerAddressLogging, Servers servers,
Advanced advanced, Query query, Metrics metrics, boolean forceKeyAuthentication) { ForcedHosts forcedHosts,
Advanced advanced, Query query, Metrics metrics,
boolean forceKeyAuthentication) {
this.bind = bind; this.bind = bind;
this.motd = motd; this.motd = motd;
this.showMaxPlayers = showMaxPlayers; this.showMaxPlayers = showMaxPlayers;
@@ -427,123 +418,6 @@ public class VelocityConfiguration implements ProxyConfig {
.toString(); .toString();
} }
/**
* Reads the Velocity configuration from {@code path}.
*
* @param path the path to read from
* @return the deserialized Velocity configuration
* @throws IOException if we could not read from the {@code path}.
*/
@SuppressFBWarnings(value = "RCN_REDUNDANT_NULLCHECK_WOULD_HAVE_BEEN_A_NPE",
justification = "I looked carefully and there's no way SpotBugs is right.")
public static VelocityConfiguration read(Path path) throws IOException {
URL defaultConfigLocation = VelocityConfiguration.class.getClassLoader()
.getResource("default-velocity.toml");
if (defaultConfigLocation == null) {
throw new RuntimeException("Default configuration file does not exist.");
}
// Create the forwarding-secret file on first-time startup if it doesn't exist
final Path defaultForwardingSecretPath = Path.of("forwarding.secret");
if (Files.notExists(path) && Files.notExists(defaultForwardingSecretPath)) {
Files.writeString(defaultForwardingSecretPath, generateRandomString(12));
}
try (final CommentedFileConfig config = CommentedFileConfig.builder(path)
.defaultData(defaultConfigLocation)
.autosave()
.preserveInsertionOrder()
.sync()
.build()
) {
config.load();
final ConfigurationMigration[] migrations = {
new ForwardingMigration(),
new KeyAuthenticationMigration(),
new MotdMigration(),
new TransferIntegrationMigration()
};
for (final ConfigurationMigration migration : migrations) {
if (migration.shouldMigrate(config)) {
migration.migrate(config, logger);
}
}
String forwardingSecretString = System.getenv().getOrDefault(
"VELOCITY_FORWARDING_SECRET", "");
if (forwardingSecretString.isEmpty()) {
final String forwardSecretFile = config.get("forwarding-secret-file");
final Path secretPath = forwardSecretFile == null
? defaultForwardingSecretPath
: Path.of(forwardSecretFile);
if (Files.exists(secretPath)) {
if (Files.isRegularFile(secretPath)) {
forwardingSecretString = String.join("", Files.readAllLines(secretPath));
} else {
throw new RuntimeException(
"The file " + forwardSecretFile + " is not a valid file or it is a directory.");
}
} else {
throw new RuntimeException("The forwarding-secret-file does not exist.");
}
}
final byte[] forwardingSecret = forwardingSecretString.getBytes(StandardCharsets.UTF_8);
final String motd = config.getOrElse("motd", "<#09add3>A Velocity Server");
// Read the rest of the config
final CommentedConfig serversConfig = config.get("servers");
final CommentedConfig forcedHostsConfig = config.get("forced-hosts");
final CommentedConfig advancedConfig = config.get("advanced");
final CommentedConfig queryConfig = config.get("query");
final CommentedConfig metricsConfig = config.get("metrics");
final PlayerInfoForwarding forwardingMode = config.getEnumOrElse(
"player-info-forwarding-mode", PlayerInfoForwarding.NONE);
final PingPassthroughMode pingPassthroughMode = config.getEnumOrElse("ping-passthrough",
PingPassthroughMode.DISABLED);
final String bind = config.getOrElse("bind", "0.0.0.0:25565");
final int maxPlayers = config.getIntOrElse("show-max-players", 500);
final boolean onlineMode = config.getOrElse("online-mode", true);
final boolean forceKeyAuthentication = config.getOrElse("force-key-authentication", true);
final boolean announceForge = config.getOrElse("announce-forge", true);
final boolean preventClientProxyConnections = config.getOrElse(
"prevent-client-proxy-connections", false);
final boolean kickExisting = config.getOrElse("kick-existing-players", false);
final boolean enablePlayerAddressLogging = config.getOrElse(
"enable-player-address-logging", true);
// Throw an exception if the forwarding-secret file is empty and the proxy is using a
// forwarding mode that requires it.
if (forwardingSecret.length == 0
&& (forwardingMode == PlayerInfoForwarding.MODERN
|| forwardingMode == PlayerInfoForwarding.BUNGEEGUARD)) {
throw new RuntimeException("The forwarding-secret file must not be empty.");
}
return new VelocityConfiguration(
bind,
motd,
maxPlayers,
onlineMode,
preventClientProxyConnections,
announceForge,
forwardingMode,
forwardingSecret,
kickExisting,
pingPassthroughMode,
enablePlayerAddressLogging,
new Servers(serversConfig),
new ForcedHosts(forcedHostsConfig),
new Advanced(advancedConfig),
new Query(queryConfig),
new Metrics(metricsConfig),
forceKeyAuthentication
);
}
}
/** /**
* Generates a Random String. * Generates a Random String.
* *
@@ -564,7 +438,7 @@ public class VelocityConfiguration implements ProxyConfig {
return onlineModeKickExistingPlayers; return onlineModeKickExistingPlayers;
} }
private static class Servers { static class Servers {
private Map<String, String> servers = ImmutableMap.of( private Map<String, String> servers = ImmutableMap.of(
"lobby", "127.0.0.1:30066", "lobby", "127.0.0.1:30066",
@@ -573,28 +447,10 @@ public class VelocityConfiguration implements ProxyConfig {
); );
private List<String> attemptConnectionOrder = ImmutableList.of("lobby"); private List<String> attemptConnectionOrder = ImmutableList.of("lobby");
private Servers() { Servers() {
} }
private Servers(CommentedConfig config) { Servers(Map<String, String> servers, List<String> attemptConnectionOrder) {
if (config != null) {
Map<String, String> servers = new HashMap<>();
for (UnmodifiableConfig.Entry entry : config.entrySet()) {
if (entry.getValue() instanceof String) {
servers.put(cleanServerName(entry.getKey()), entry.getValue());
} else {
if (!entry.getKey().equalsIgnoreCase("try")) {
throw new IllegalArgumentException(
"Server entry " + entry.getKey() + " is not a string!");
}
}
}
this.servers = ImmutableMap.copyOf(servers);
this.attemptConnectionOrder = config.getOrElse("try", attemptConnectionOrder);
}
}
private Servers(Map<String, String> servers, List<String> attemptConnectionOrder) {
this.servers = servers; this.servers = servers;
this.attemptConnectionOrder = attemptConnectionOrder; this.attemptConnectionOrder = attemptConnectionOrder;
} }
@@ -623,7 +479,7 @@ public class VelocityConfiguration implements ProxyConfig {
* @param name the server name to clean * @param name the server name to clean
* @return the cleaned server name * @return the cleaned server name
*/ */
private String cleanServerName(String name) { static String cleanServerName(String name) {
return name.replace("\"", ""); return name.replace("\"", "");
} }
@@ -636,7 +492,7 @@ public class VelocityConfiguration implements ProxyConfig {
} }
} }
private static class ForcedHosts { static class ForcedHosts {
private Map<String, List<String>> forcedHosts = ImmutableMap.of( private Map<String, List<String>> forcedHosts = ImmutableMap.of(
"lobby.example.com", ImmutableList.of("lobby"), "lobby.example.com", ImmutableList.of("lobby"),
@@ -644,29 +500,10 @@ public class VelocityConfiguration implements ProxyConfig {
"minigames.example.com", ImmutableList.of("minigames") "minigames.example.com", ImmutableList.of("minigames")
); );
private ForcedHosts() { ForcedHosts() {
} }
private ForcedHosts(CommentedConfig config) { ForcedHosts(Map<String, List<String>> forcedHosts) {
if (config != null) {
Map<String, List<String>> forcedHosts = new HashMap<>();
for (UnmodifiableConfig.Entry entry : config.entrySet()) {
if (entry.getValue() instanceof String) {
forcedHosts.put(entry.getKey().toLowerCase(Locale.ROOT),
ImmutableList.of(entry.getValue()));
} else if (entry.getValue() instanceof List) {
forcedHosts.put(entry.getKey().toLowerCase(Locale.ROOT),
ImmutableList.copyOf((List<String>) entry.getValue()));
} else {
throw new IllegalStateException(
"Invalid value of type " + entry.getValue().getClass() + " in forced hosts!");
}
}
this.forcedHosts = ImmutableMap.copyOf(forcedHosts);
}
}
private ForcedHosts(Map<String, List<String>> forcedHosts) {
this.forcedHosts = forcedHosts; this.forcedHosts = forcedHosts;
} }
@@ -686,7 +523,7 @@ public class VelocityConfiguration implements ProxyConfig {
} }
} }
private static class Advanced { static class Advanced {
@Expose @Expose
private int compressionThreshold = 256; private int compressionThreshold = 256;
@@ -717,33 +554,31 @@ public class VelocityConfiguration implements ProxyConfig {
@Expose @Expose
private boolean acceptTransfers = false; private boolean acceptTransfers = false;
private Advanced() { Advanced() {
} }
private Advanced(CommentedConfig config) { Advanced(int compressionThreshold, int compressionLevel, int loginRatelimit,
if (config != null) { int connectionTimeout, int readTimeout, boolean proxyProtocol, boolean tcpFastOpen,
this.compressionThreshold = config.getIntOrElse("compression-threshold", 256); boolean bungeePluginMessageChannel, boolean showPingRequests,
this.compressionLevel = config.getIntOrElse("compression-level", -1); boolean failoverOnUnexpectedServerDisconnect, boolean announceProxyCommands,
this.loginRatelimit = config.getIntOrElse("login-ratelimit", 3000); boolean logCommandExecutions, boolean logPlayerConnections, boolean acceptTransfers) {
this.connectionTimeout = config.getIntOrElse("connection-timeout", 5000); this.compressionThreshold = compressionThreshold;
this.readTimeout = config.getIntOrElse("read-timeout", 30000); this.compressionLevel = compressionLevel;
if (config.contains("haproxy-protocol")) { this.loginRatelimit = loginRatelimit;
this.proxyProtocol = config.getOrElse("haproxy-protocol", false); this.connectionTimeout = connectionTimeout;
} else { this.readTimeout = readTimeout;
this.proxyProtocol = config.getOrElse("proxy-protocol", false); this.proxyProtocol = proxyProtocol;
} this.tcpFastOpen = tcpFastOpen;
this.tcpFastOpen = config.getOrElse("tcp-fast-open", false); this.bungeePluginMessageChannel = bungeePluginMessageChannel;
this.bungeePluginMessageChannel = config.getOrElse("bungee-plugin-message-channel", true); this.showPingRequests = showPingRequests;
this.showPingRequests = config.getOrElse("show-ping-requests", false); this.failoverOnUnexpectedServerDisconnect = failoverOnUnexpectedServerDisconnect;
this.failoverOnUnexpectedServerDisconnect = config this.announceProxyCommands = announceProxyCommands;
.getOrElse("failover-on-unexpected-server-disconnect", true); this.logCommandExecutions = logCommandExecutions;
this.announceProxyCommands = config.getOrElse("announce-proxy-commands", true); this.logPlayerConnections = logPlayerConnections;
this.logCommandExecutions = config.getOrElse("log-command-executions", false); this.acceptTransfers = acceptTransfers;
this.logPlayerConnections = config.getOrElse("log-player-connections", true);
this.acceptTransfers = config.getOrElse("accepts-transfers", false);
}
} }
public int getCompressionThreshold() { public int getCompressionThreshold() {
return compressionThreshold; return compressionThreshold;
} }
@@ -825,7 +660,7 @@ public class VelocityConfiguration implements ProxyConfig {
} }
} }
private static class Query { static class Query {
@Expose @Expose
private boolean queryEnabled = false; private boolean queryEnabled = false;
@@ -836,25 +671,16 @@ public class VelocityConfiguration implements ProxyConfig {
@Expose @Expose
private boolean showPlugins = false; private boolean showPlugins = false;
private Query() { Query() {
} }
private Query(boolean queryEnabled, int queryPort, String queryMap, boolean showPlugins) { Query(boolean queryEnabled, int queryPort, String queryMap, boolean showPlugins) {
this.queryEnabled = queryEnabled; this.queryEnabled = queryEnabled;
this.queryPort = queryPort; this.queryPort = queryPort;
this.queryMap = queryMap; this.queryMap = queryMap;
this.showPlugins = showPlugins; this.showPlugins = showPlugins;
} }
private Query(CommentedConfig config) {
if (config != null) {
this.queryEnabled = config.getOrElse("enabled", false);
this.queryPort = config.getIntOrElse("port", 25565);
this.queryMap = config.getOrElse("map", "Velocity");
this.showPlugins = config.getOrElse("show-plugins", false);
}
}
public boolean isQueryEnabled() { public boolean isQueryEnabled() {
return queryEnabled; return queryEnabled;
} }
@@ -889,10 +715,11 @@ public class VelocityConfiguration implements ProxyConfig {
private boolean enabled = true; private boolean enabled = true;
private Metrics(CommentedConfig toml) { Metrics() {
if (toml != null) {
this.enabled = toml.getOrElse("enabled", true);
} }
Metrics(boolean enabled) {
this.enabled = enabled;
} }
public boolean isEnabled() { public boolean isEnabled() {