3
0
Mirror von https://github.com/PaperMC/Velocity.git synchronisiert 2024-11-17 05:20:14 +01:00

Merge pull request #123 from mikroskeem/feature/native-forced-hosts

[WIP] Forced hosts configuration support
Dieser Commit ist enthalten in:
Andrew Steinborn 2018-10-27 15:40:24 -04:00 committet von GitHub
Commit f8ad686625
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
4 geänderte Dateien mit 116 neuen und 5 gelöschten Zeilen

Datei anzeigen

@ -66,6 +66,12 @@ public interface ProxyConfig {
*/ */
List<String> getAttemptConnectionOrder(); List<String> getAttemptConnectionOrder();
/**
* Get forced servers mapped to given virtual host
* @return list of server names
*/
Map<String, List<String>> getForcedHosts();
/** /**
* Get the minimum compression threshold for packets * Get the minimum compression threshold for packets
* @return the compression threshold * @return the compression threshold

Datei anzeigen

@ -120,7 +120,7 @@ public class AnnotatedConfig {
if (field.getAnnotation(IsMap.class) != null) { // check if field is map if (field.getAnnotation(IsMap.class) != null) { // check if field is map
Map<String, ?> map = (Map<String, ?>) field.get(toSave); Map<String, ?> map = (Map<String, ?>) field.get(toSave);
for (Entry<String, ?> entry : map.entrySet()) { for (Entry<String, ?> entry : map.entrySet()) {
lines.add(entry.getKey() + " = " + toString(entry.getValue())); // Save a map data lines.add(safeKey(entry.getKey()) + " = " + toString(entry.getValue())); // Save a map data
} }
lines.add(""); //Add empty line lines.add(""); //Add empty line
continue; continue;
@ -165,6 +165,13 @@ public class AnnotatedConfig {
return value != null ? value.toString() : "null"; return value != null ? value.toString() : "null";
} }
private String safeKey(String key) {
if(key.contains(".") && !(key.indexOf('"') == 0 && key.lastIndexOf('"') == (key.length() - 1))) {
return '"' + key + '"';
}
return key;
}
/** /**
* Saves lines to file * Saves lines to file
* *

Datei anzeigen

@ -2,6 +2,7 @@ package com.velocitypowered.proxy.config;
import com.google.common.base.MoreObjects; import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableList;
import com.moandjiezana.toml.Toml; import com.moandjiezana.toml.Toml;
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;
@ -65,6 +66,9 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
@Table("[servers]") @Table("[servers]")
private final Servers servers; private final Servers servers;
@Table("[forced-hosts]")
private final ForcedHosts forcedHosts;
@Table("[advanced]") @Table("[advanced]")
private final Advanced advanced; private final Advanced advanced;
@ -76,15 +80,16 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
@Ignore @Ignore
private Favicon favicon; private Favicon favicon;
public VelocityConfiguration(Servers servers, Advanced advanced, Query query) { public VelocityConfiguration(Servers servers, ForcedHosts forcedHosts, Advanced advanced, Query query) {
this.servers = servers; this.servers = servers;
this.forcedHosts = forcedHosts;
this.advanced = advanced; this.advanced = advanced;
this.query = query; this.query = query;
} }
private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode, private VelocityConfiguration(String bind, String motd, int showMaxPlayers, boolean onlineMode,
boolean announceForge, PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret, boolean announceForge, PlayerInfoForwarding playerInfoForwardingMode, byte[] forwardingSecret,
Servers servers, Advanced advanced, Query query) { Servers servers, ForcedHosts forcedHosts, Advanced advanced, Query query) {
this.bind = bind; this.bind = bind;
this.motd = motd; this.motd = motd;
this.showMaxPlayers = showMaxPlayers; this.showMaxPlayers = showMaxPlayers;
@ -93,6 +98,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
this.playerInfoForwardingMode = playerInfoForwardingMode; this.playerInfoForwardingMode = playerInfoForwardingMode;
this.forwardingSecret = forwardingSecret; this.forwardingSecret = forwardingSecret;
this.servers = servers; this.servers = servers;
this.forcedHosts = forcedHosts;
this.advanced = advanced; this.advanced = advanced;
this.query = query; this.query = query;
} }
@ -153,6 +159,21 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
valid = false; valid = false;
} }
} }
for (Map.Entry<String, List<String>> entry : forcedHosts.getForcedHosts().entrySet()) {
if (entry.getValue().isEmpty()) {
logger.error("Forced host '{}' does not contain any servers", entry.getKey());
valid = false;
continue;
}
for (String server : entry.getValue()) {
if (!servers.getServers().containsKey(server)) {
logger.error("Server '{}' for forced host '{}' does not exist", server, entry.getKey());
valid = false;
}
}
}
} }
try { try {
@ -257,6 +278,10 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
return servers.getAttemptConnectionOrder(); return servers.getAttemptConnectionOrder();
} }
public Map<String, List<String>> getForcedHosts() {
return forcedHosts.getForcedHosts();
}
public int getCompressionThreshold() { public int getCompressionThreshold() {
return advanced.getCompressionThreshold(); return advanced.getCompressionThreshold();
} }
@ -301,6 +326,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
.add("forwardingSecret", forwardingSecret) .add("forwardingSecret", forwardingSecret)
.add("announceForge", announceForge) .add("announceForge", announceForge)
.add("servers", servers) .add("servers", servers)
.add("forcedHosts", forcedHosts)
.add("advanced", advanced) .add("advanced", advanced)
.add("query", query) .add("query", query)
.add("favicon", favicon) .add("favicon", favicon)
@ -311,7 +337,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
Toml toml; Toml toml;
if (!path.toFile().exists()) { if (!path.toFile().exists()) {
getLogger().info("No velocity.toml found, creating one for you..."); getLogger().info("No velocity.toml found, creating one for you...");
return new VelocityConfiguration(new Servers(), new Advanced(), new Query()); return new VelocityConfiguration(new Servers(), new ForcedHosts(), new Advanced(), new Query());
} else { } else {
try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) { try (Reader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8)) {
toml = new Toml().read(reader); toml = new Toml().read(reader);
@ -319,6 +345,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
} }
Servers servers = new Servers(toml.getTable("servers")); Servers servers = new Servers(toml.getTable("servers"));
ForcedHosts forcedHosts = new ForcedHosts(toml.getTable("forced-hosts"));
Advanced advanced = new Advanced(toml.getTable("advanced")); Advanced advanced = new Advanced(toml.getTable("advanced"));
Query query = new Query(toml.getTable("query")); Query query = new Query(toml.getTable("query"));
byte[] forwardingSecret = toml.getString("forwarding-secret", "5up3r53cr3t") byte[] forwardingSecret = toml.getString("forwarding-secret", "5up3r53cr3t")
@ -333,6 +360,7 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
PlayerInfoForwarding.valueOf(toml.getString("player-info-forwarding-mode", "MODERN").toUpperCase()), PlayerInfoForwarding.valueOf(toml.getString("player-info-forwarding-mode", "MODERN").toUpperCase()),
forwardingSecret, forwardingSecret,
servers, servers,
forcedHosts,
advanced, advanced,
query query
); );
@ -421,6 +449,61 @@ public class VelocityConfiguration extends AnnotatedConfig implements ProxyConfi
} }
private static class ForcedHosts {
@IsMap
@Comment("Configure your forced hosts here.")
private Map<String, List<String>> forcedHosts = ImmutableMap.of(
"lobby.example.com", ImmutableList.of("lobby"),
"factions.example.com", ImmutableList.of("factions"),
"minigames.example.com", ImmutableList.of("minigames")
);
private ForcedHosts() {}
private ForcedHosts(Toml toml) {
if (toml != null) {
Map<String, List<String>> forcedHosts = new HashMap<>();
for (Map.Entry<String, Object> entry : toml.entrySet()) {
if (entry.getValue() instanceof String) {
forcedHosts.put(stripQuotes(entry.getKey()), ImmutableList.of((String) entry.getValue()));
} else if (entry.getValue() instanceof List) {
forcedHosts.put(stripQuotes(entry.getKey()), 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;
}
private Map<String, List<String>> getForcedHosts() {
return forcedHosts;
}
private void setForcedHosts(Map<String, List<String>> forcedHosts) {
this.forcedHosts = forcedHosts;
}
private static String stripQuotes(String key) {
int lastIndex;
if (key.indexOf('"') == 0 && (lastIndex = key.lastIndexOf('"')) == (key.length() - 1)) {
return key.substring(1, lastIndex);
}
return key;
}
@Override
public String toString() {
return "ForcedHosts{" +
"forcedHosts=" + forcedHosts +
'}';
}
}
private static class Advanced { private static class Advanced {
@Comment({ @Comment({

Datei anzeigen

@ -42,12 +42,16 @@ import net.kyori.text.serializer.ComponentSerializers;
import net.kyori.text.serializer.PlainComponentSerializer; import net.kyori.text.serializer.PlainComponentSerializer;
import org.apache.logging.log4j.LogManager; 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.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; import org.checkerframework.checker.nullness.qual.Nullable;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionException;
@ -71,6 +75,9 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
private final VelocityTabList tabList; private final VelocityTabList tabList;
private final VelocityServer server; private final VelocityServer server;
@MonotonicNonNull
private List<String> serversToTry = null;
ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, InetSocketAddress virtualHost) { ConnectedPlayer(VelocityServer server, GameProfile profile, MinecraftConnection connection, InetSocketAddress virtualHost) {
this.server = server; this.server = server;
this.tabList = new VelocityTabList(connection); this.tabList = new VelocityTabList(connection);
@ -344,7 +351,15 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
} }
Optional<RegisteredServer> getNextServerToTry() { Optional<RegisteredServer> getNextServerToTry() {
List<String> serversToTry = server.getConfiguration().getAttemptConnectionOrder(); if (serversToTry == null) {
String virtualHost = getVirtualHost().map(InetSocketAddress::getHostString).orElse("");
serversToTry = server.getConfiguration().getForcedHosts().getOrDefault(virtualHost, Collections.emptyList());
}
if (serversToTry.isEmpty()) {
serversToTry = server.getConfiguration().getAttemptConnectionOrder();
}
if (tryIndex >= serversToTry.size()) { if (tryIndex >= serversToTry.size()) {
return Optional.empty(); return Optional.empty();
} }