Mirror von
https://github.com/PaperMC/Velocity.git
synchronisiert 2024-11-17 05:20:14 +01:00
Merge pull request #139 from VelocityPowered/reload-command
Reload command
Dieser Commit ist enthalten in:
Commit
a3bfa292c6
@ -0,0 +1,12 @@
|
|||||||
|
package com.velocitypowered.api.event.proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This event is fired when the proxy is reloaded by the user using {@code /velocity reload}.
|
||||||
|
*/
|
||||||
|
public class ProxyReloadEvent {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ProxyReloadEvent";
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ allprojects {
|
|||||||
junitVersion = '5.3.0-M1'
|
junitVersion = '5.3.0-M1'
|
||||||
slf4jVersion = '1.7.25'
|
slf4jVersion = '1.7.25'
|
||||||
log4jVersion = '2.11.1'
|
log4jVersion = '2.11.1'
|
||||||
nettyVersion = '4.1.30.Final'
|
nettyVersion = '4.1.32.Final'
|
||||||
guavaVersion = '25.1-jre'
|
guavaVersion = '25.1-jre'
|
||||||
checkerFrameworkVersion = '2.5.6'
|
checkerFrameworkVersion = '2.5.6'
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import com.google.gson.Gson;
|
|||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.velocitypowered.api.event.EventManager;
|
import com.velocitypowered.api.event.EventManager;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
|
||||||
|
import com.velocitypowered.api.event.proxy.ProxyReloadEvent;
|
||||||
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
|
||||||
import com.velocitypowered.api.plugin.PluginContainer;
|
import com.velocitypowered.api.plugin.PluginContainer;
|
||||||
import com.velocitypowered.api.plugin.PluginManager;
|
import com.velocitypowered.api.plugin.PluginManager;
|
||||||
@ -40,17 +41,20 @@ import com.velocitypowered.proxy.util.VelocityChannelRegistrar;
|
|||||||
import com.velocitypowered.proxy.util.ratelimit.Ratelimiter;
|
import com.velocitypowered.proxy.util.ratelimit.Ratelimiter;
|
||||||
import com.velocitypowered.proxy.util.ratelimit.Ratelimiters;
|
import com.velocitypowered.proxy.util.ratelimit.Ratelimiters;
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import net.kyori.text.Component;
|
import net.kyori.text.Component;
|
||||||
import net.kyori.text.TextComponent;
|
import net.kyori.text.TextComponent;
|
||||||
@ -70,26 +74,32 @@ public class VelocityServer implements ProxyServer {
|
|||||||
.registerTypeHierarchyAdapter(GameProfile.class, new GameProfileSerializer())
|
.registerTypeHierarchyAdapter(GameProfile.class, new GameProfileSerializer())
|
||||||
.create();
|
.create();
|
||||||
|
|
||||||
|
private final ConnectionManager cm;
|
||||||
private final ProxyOptions options;
|
private final ProxyOptions options;
|
||||||
private @MonotonicNonNull ConnectionManager cm;
|
|
||||||
private @MonotonicNonNull VelocityConfiguration configuration;
|
private @MonotonicNonNull VelocityConfiguration configuration;
|
||||||
private @MonotonicNonNull NettyHttpClient httpClient;
|
private @MonotonicNonNull NettyHttpClient httpClient;
|
||||||
private @MonotonicNonNull KeyPair serverKeyPair;
|
private @MonotonicNonNull KeyPair serverKeyPair;
|
||||||
private @MonotonicNonNull ServerMap servers;
|
private final ServerMap servers;
|
||||||
private final VelocityCommandManager commandManager = new VelocityCommandManager();
|
private final VelocityCommandManager commandManager = new VelocityCommandManager();
|
||||||
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
private final AtomicBoolean shutdownInProgress = new AtomicBoolean(false);
|
||||||
private boolean shutdown = false;
|
private boolean shutdown = false;
|
||||||
private @MonotonicNonNull VelocityPluginManager pluginManager;
|
private final VelocityPluginManager pluginManager;
|
||||||
|
|
||||||
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
private final Map<UUID, ConnectedPlayer> connectionsByUuid = new ConcurrentHashMap<>();
|
||||||
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
private final Map<String, ConnectedPlayer> connectionsByName = new ConcurrentHashMap<>();
|
||||||
private @MonotonicNonNull VelocityConsole console;
|
private final VelocityConsole console;
|
||||||
private @MonotonicNonNull Ratelimiter ipAttemptLimiter;
|
private @MonotonicNonNull Ratelimiter ipAttemptLimiter;
|
||||||
private @MonotonicNonNull VelocityEventManager eventManager;
|
private final VelocityEventManager eventManager;
|
||||||
private @MonotonicNonNull VelocityScheduler scheduler;
|
private final VelocityScheduler scheduler;
|
||||||
private final VelocityChannelRegistrar channelRegistrar = new VelocityChannelRegistrar();
|
private final VelocityChannelRegistrar channelRegistrar = new VelocityChannelRegistrar();
|
||||||
|
|
||||||
public VelocityServer(final ProxyOptions options) {
|
VelocityServer(final ProxyOptions options) {
|
||||||
|
pluginManager = new VelocityPluginManager(this);
|
||||||
|
eventManager = new VelocityEventManager(pluginManager);
|
||||||
|
scheduler = new VelocityScheduler(pluginManager);
|
||||||
|
console = new VelocityConsole(this);
|
||||||
|
cm = new ConnectionManager(this);
|
||||||
|
servers = new ServerMap(this);
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,12 +148,6 @@ public class VelocityServer implements ProxyServer {
|
|||||||
logger.info("Booting up {} {}...", getVersion().getName(), getVersion().getVersion());
|
logger.info("Booting up {} {}...", getVersion().getName(), getVersion().getVersion());
|
||||||
|
|
||||||
serverKeyPair = EncryptionUtils.createRsaKeyPair(1024);
|
serverKeyPair = EncryptionUtils.createRsaKeyPair(1024);
|
||||||
pluginManager = new VelocityPluginManager(this);
|
|
||||||
eventManager = new VelocityEventManager(pluginManager);
|
|
||||||
scheduler = new VelocityScheduler(pluginManager);
|
|
||||||
console = new VelocityConsole(this);
|
|
||||||
cm = new ConnectionManager(this);
|
|
||||||
servers = new ServerMap(this);
|
|
||||||
|
|
||||||
cm.logChannelInformation();
|
cm.logChannelInformation();
|
||||||
|
|
||||||
@ -233,9 +237,6 @@ public class VelocityServer implements ProxyServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Bootstrap initializeGenericBootstrap() {
|
public Bootstrap initializeGenericBootstrap() {
|
||||||
if (cm == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return this.cm.createWorker();
|
return this.cm.createWorker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,6 +244,87 @@ public class VelocityServer implements ProxyServer {
|
|||||||
return shutdown;
|
return shutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean reloadConfiguration() throws IOException {
|
||||||
|
Path configPath = Paths.get("velocity.toml");
|
||||||
|
VelocityConfiguration newConfiguration = VelocityConfiguration.read(configPath);
|
||||||
|
|
||||||
|
if (!newConfiguration.validate()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-register servers. If a server is being replaced, make sure to note what players need to
|
||||||
|
// move back to a fallback server.
|
||||||
|
Collection<ConnectedPlayer> evacuate = new ArrayList<>();
|
||||||
|
for (Map.Entry<String, String> entry : newConfiguration.getServers().entrySet()) {
|
||||||
|
ServerInfo newInfo =
|
||||||
|
new ServerInfo(entry.getKey(), AddressUtil.parseAddress(entry.getValue()));
|
||||||
|
Optional<RegisteredServer> rs = servers.getServer(entry.getKey());
|
||||||
|
if (!rs.isPresent()) {
|
||||||
|
servers.register(newInfo);
|
||||||
|
} else if (!rs.get().getServerInfo().equals(newInfo)) {
|
||||||
|
for (Player player : rs.get().getPlayersConnected()) {
|
||||||
|
if (!(player instanceof ConnectedPlayer)) {
|
||||||
|
throw new IllegalStateException("ConnectedPlayer not found for player " + player
|
||||||
|
+ " in server " + rs.get().getServerInfo().getName());
|
||||||
|
}
|
||||||
|
evacuate.add((ConnectedPlayer) player);
|
||||||
|
}
|
||||||
|
servers.unregister(rs.get().getServerInfo());
|
||||||
|
servers.register(newInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we had any players to evacuate, let's move them now. Wait until they are all moved off.
|
||||||
|
if (!evacuate.isEmpty()) {
|
||||||
|
CountDownLatch latch = new CountDownLatch(evacuate.size());
|
||||||
|
for (ConnectedPlayer player : evacuate) {
|
||||||
|
Optional<RegisteredServer> next = player.getNextServerToTry();
|
||||||
|
if (next.isPresent()) {
|
||||||
|
player.createConnectionRequest(next.get()).connectWithIndication()
|
||||||
|
.whenComplete((success, ex) -> {
|
||||||
|
if (ex != null || success == null || !success) {
|
||||||
|
player.disconnect(TextComponent.of("Your server has been changed, but we could "
|
||||||
|
+ "not move you to any fallback servers."));
|
||||||
|
}
|
||||||
|
latch.countDown();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
latch.countDown();
|
||||||
|
player.disconnect(TextComponent.of("Your server has been changed, but we could "
|
||||||
|
+ "not move you to any fallback servers."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
latch.await();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
logger.error("Interrupted whilst moving players", e);
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have a new bind address, bind to it
|
||||||
|
if (!configuration.getBind().equals(newConfiguration.getBind())) {
|
||||||
|
this.cm.bind(newConfiguration.getBind());
|
||||||
|
this.cm.close(configuration.getBind());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configuration.isQueryEnabled() && (!newConfiguration.isQueryEnabled()
|
||||||
|
|| newConfiguration.getQueryPort() != configuration.getQueryPort())) {
|
||||||
|
this.cm.close(new InetSocketAddress(
|
||||||
|
configuration.getBind().getHostString(), configuration.getQueryPort()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newConfiguration.isQueryEnabled()) {
|
||||||
|
this.cm.queryBind(newConfiguration.getBind().getHostString(),
|
||||||
|
newConfiguration.getQueryPort());
|
||||||
|
}
|
||||||
|
|
||||||
|
ipAttemptLimiter = Ratelimiters.createWithMilliseconds(newConfiguration.getLoginRatelimit());
|
||||||
|
this.configuration = newConfiguration;
|
||||||
|
eventManager.fireAndForget(new ProxyReloadEvent());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown(boolean explicitExit) {
|
public void shutdown(boolean explicitExit) {
|
||||||
if (eventManager == null || pluginManager == null || cm == null || scheduler == null) {
|
if (eventManager == null || pluginManager == null || cm == null || scheduler == null) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
@ -340,66 +422,41 @@ public class VelocityServer implements ProxyServer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<RegisteredServer> getServer(String name) {
|
public Optional<RegisteredServer> getServer(String name) {
|
||||||
Preconditions.checkNotNull(name, "name");
|
|
||||||
if (servers == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return servers.getServer(name);
|
return servers.getServer(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<RegisteredServer> getAllServers() {
|
public Collection<RegisteredServer> getAllServers() {
|
||||||
if (servers == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return servers.getAllServers();
|
return servers.getAllServers();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegisteredServer registerServer(ServerInfo server) {
|
public RegisteredServer registerServer(ServerInfo server) {
|
||||||
if (servers == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return servers.register(server);
|
return servers.register(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void unregisterServer(ServerInfo server) {
|
public void unregisterServer(ServerInfo server) {
|
||||||
if (servers == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
servers.unregister(server);
|
servers.unregister(server);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VelocityConsole getConsoleCommandSource() {
|
public VelocityConsole getConsoleCommandSource() {
|
||||||
if (console == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return console;
|
return console;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PluginManager getPluginManager() {
|
public PluginManager getPluginManager() {
|
||||||
if (pluginManager == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return pluginManager;
|
return pluginManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EventManager getEventManager() {
|
public EventManager getEventManager() {
|
||||||
if (eventManager == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return eventManager;
|
return eventManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public VelocityScheduler getScheduler() {
|
public VelocityScheduler getScheduler() {
|
||||||
if (scheduler == null) {
|
|
||||||
throw new IllegalStateException("Server did not initialize properly.");
|
|
||||||
}
|
|
||||||
return scheduler;
|
return scheduler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ import com.velocitypowered.api.plugin.PluginContainer;
|
|||||||
import com.velocitypowered.api.plugin.PluginDescription;
|
import com.velocitypowered.api.plugin.PluginDescription;
|
||||||
import com.velocitypowered.api.proxy.ProxyServer;
|
import com.velocitypowered.api.proxy.ProxyServer;
|
||||||
import com.velocitypowered.api.util.ProxyVersion;
|
import com.velocitypowered.api.util.ProxyVersion;
|
||||||
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@ -22,6 +24,8 @@ import net.kyori.text.event.HoverEvent;
|
|||||||
import net.kyori.text.event.HoverEvent.Action;
|
import net.kyori.text.event.HoverEvent.Action;
|
||||||
import net.kyori.text.format.TextColor;
|
import net.kyori.text.format.TextColor;
|
||||||
import net.kyori.text.format.TextDecoration;
|
import net.kyori.text.format.TextDecoration;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||||
|
|
||||||
public class VelocityCommand implements Command {
|
public class VelocityCommand implements Command {
|
||||||
@ -32,10 +36,11 @@ public class VelocityCommand implements Command {
|
|||||||
* Initializes the command object for /velocity.
|
* Initializes the command object for /velocity.
|
||||||
* @param server the Velocity server
|
* @param server the Velocity server
|
||||||
*/
|
*/
|
||||||
public VelocityCommand(ProxyServer server) {
|
public VelocityCommand(VelocityServer server) {
|
||||||
this.subcommands = ImmutableMap.<String, Command>builder()
|
this.subcommands = ImmutableMap.<String, Command>builder()
|
||||||
.put("version", new Info(server))
|
.put("version", new Info(server))
|
||||||
.put("plugins", new Plugins(server))
|
.put("plugins", new Plugins(server))
|
||||||
|
.put("reload", new Reload(server))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +108,39 @@ public class VelocityCommand implements Command {
|
|||||||
return command.hasPermission(source, actualArgs);
|
return command.hasPermission(source, actualArgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class Reload implements Command {
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(Reload.class);
|
||||||
|
private final VelocityServer server;
|
||||||
|
|
||||||
|
private Reload(VelocityServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(CommandSource source, String @NonNull [] args) {
|
||||||
|
try {
|
||||||
|
if (server.reloadConfiguration()) {
|
||||||
|
source.sendMessage(TextComponent.of("Configuration reloaded.", TextColor.GREEN));
|
||||||
|
} else {
|
||||||
|
source.sendMessage(TextComponent.of(
|
||||||
|
"Unable to reload your configuration. Check the console for more details.",
|
||||||
|
TextColor.RED));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unable to reload configuration", e);
|
||||||
|
source.sendMessage(TextComponent.of(
|
||||||
|
"Unable to reload your configuration. Check the console for more details.",
|
||||||
|
TextColor.RED));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasPermission(CommandSource source, String @NonNull [] args) {
|
||||||
|
return source.getPermissionValue("velocity.command.reload") == Tristate.TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class Info implements Command {
|
private static class Info implements Command {
|
||||||
|
|
||||||
private final ProxyServer server;
|
private final ProxyServer server;
|
||||||
|
@ -383,7 +383,7 @@ public class ConnectedPlayer implements MinecraftConnectionAssociation, Player {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<RegisteredServer> getNextServerToTry() {
|
public Optional<RegisteredServer> getNextServerToTry() {
|
||||||
if (serversToTry == null) {
|
if (serversToTry == null) {
|
||||||
String virtualHostStr = getVirtualHost().map(InetSocketAddress::getHostString).orElse("");
|
String virtualHostStr = getVirtualHost().map(InetSocketAddress::getHostString).orElse("");
|
||||||
serversToTry = server.getConfiguration().getForcedHosts()
|
serversToTry = server.getConfiguration().getForcedHosts()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.velocitypowered.proxy.network;
|
package com.velocitypowered.proxy.network;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
import com.velocitypowered.natives.util.Natives;
|
import com.velocitypowered.natives.util.Natives;
|
||||||
import com.velocitypowered.proxy.VelocityServer;
|
import com.velocitypowered.proxy.VelocityServer;
|
||||||
import com.velocitypowered.proxy.protocol.netty.GS4QueryHandler;
|
import com.velocitypowered.proxy.protocol.netty.GS4QueryHandler;
|
||||||
@ -11,7 +12,9 @@ import io.netty.channel.ChannelOption;
|
|||||||
import io.netty.channel.EventLoopGroup;
|
import io.netty.channel.EventLoopGroup;
|
||||||
import io.netty.channel.WriteBufferWaterMark;
|
import io.netty.channel.WriteBufferWaterMark;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
@ -21,7 +24,7 @@ public final class ConnectionManager {
|
|||||||
private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 16,
|
private static final WriteBufferWaterMark SERVER_WRITE_MARK = new WriteBufferWaterMark(1 << 16,
|
||||||
1 << 18);
|
1 << 18);
|
||||||
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
|
private static final Logger LOGGER = LogManager.getLogger(ConnectionManager.class);
|
||||||
private final Set<Channel> endpoints = new HashSet<>();
|
private final Map<InetSocketAddress, Channel> endpoints = new HashMap<>();
|
||||||
private final TransportType transportType;
|
private final TransportType transportType;
|
||||||
private final EventLoopGroup bossGroup;
|
private final EventLoopGroup bossGroup;
|
||||||
private final EventLoopGroup workerGroup;
|
private final EventLoopGroup workerGroup;
|
||||||
@ -55,7 +58,7 @@ public final class ConnectionManager {
|
|||||||
.addListener((ChannelFutureListener) future -> {
|
.addListener((ChannelFutureListener) future -> {
|
||||||
final Channel channel = future.channel();
|
final Channel channel = future.channel();
|
||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
this.endpoints.add(channel);
|
this.endpoints.put(address, channel);
|
||||||
LOGGER.info("Listening on {}", channel.localAddress());
|
LOGGER.info("Listening on {}", channel.localAddress());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("Can't bind to {}", address, future.cause());
|
LOGGER.error("Can't bind to {}", address, future.cause());
|
||||||
@ -64,16 +67,17 @@ public final class ConnectionManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void queryBind(final String hostname, final int port) {
|
public void queryBind(final String hostname, final int port) {
|
||||||
|
InetSocketAddress address = new InetSocketAddress(hostname, port);
|
||||||
final Bootstrap bootstrap = new Bootstrap()
|
final Bootstrap bootstrap = new Bootstrap()
|
||||||
.channel(this.transportType.datagramChannelClass)
|
.channel(this.transportType.datagramChannelClass)
|
||||||
.group(this.workerGroup)
|
.group(this.workerGroup)
|
||||||
.handler(new GS4QueryHandler(this.server))
|
.handler(new GS4QueryHandler(this.server))
|
||||||
.localAddress(hostname, port);
|
.localAddress(address);
|
||||||
bootstrap.bind()
|
bootstrap.bind()
|
||||||
.addListener((ChannelFutureListener) future -> {
|
.addListener((ChannelFutureListener) future -> {
|
||||||
final Channel channel = future.channel();
|
final Channel channel = future.channel();
|
||||||
if (future.isSuccess()) {
|
if (future.isSuccess()) {
|
||||||
this.endpoints.add(channel);
|
this.endpoints.put(address, channel);
|
||||||
LOGGER.info("Listening for GS4 query on {}", channel.localAddress());
|
LOGGER.info("Listening for GS4 query on {}", channel.localAddress());
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("Can't bind to {}", bootstrap.config().localAddress(), future.cause());
|
LOGGER.error("Can't bind to {}", bootstrap.config().localAddress(), future.cause());
|
||||||
@ -90,8 +94,15 @@ public final class ConnectionManager {
|
|||||||
this.server.getConfiguration().getConnectTimeout());
|
this.server.getConfiguration().getConnectTimeout());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close(InetSocketAddress oldBind) {
|
||||||
|
Channel serverChannel = endpoints.remove(oldBind);
|
||||||
|
Preconditions.checkState(serverChannel != null, "Endpoint %s not registered", oldBind);
|
||||||
|
LOGGER.info("Closing endpoint {}", serverChannel.localAddress());
|
||||||
|
serverChannel.close().syncUninterruptibly();
|
||||||
|
}
|
||||||
|
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
for (final Channel endpoint : this.endpoints) {
|
for (final Channel endpoint : this.endpoints.values()) {
|
||||||
try {
|
try {
|
||||||
LOGGER.info("Closing endpoint {}", endpoint.localAddress());
|
LOGGER.info("Closing endpoint {}", endpoint.localAddress());
|
||||||
endpoint.close().sync();
|
endpoint.close().sync();
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren