diff --git a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java index 7f5cc856..4c952f37 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/PendingConnection.java @@ -1,6 +1,7 @@ package net.md_5.bungee.api.connection; import java.net.InetSocketAddress; +import net.md_5.bungee.api.config.ListenerInfo; /** * Represents a user attempting to log into the proxy. @@ -36,4 +37,11 @@ public interface PendingConnection extends Connection * @param reason the disconnect reason displayed to the player */ public void disconnect(String reason); + + /** + * Get the listener that accepted this connection. + * + * @return the accepting listener + */ + public ListenerInfo getListener(); } diff --git a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java index 59515a8b..b0e45598 100644 --- a/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java +++ b/api/src/main/java/net/md_5/bungee/api/connection/ProxiedPlayer.java @@ -55,4 +55,11 @@ public interface ProxiedPlayer extends Connection, CommandSender * @param data the data to send */ public void sendData(String channel, byte[] data); + + /** + * Get the pending connection that belongs to this player. + * + * @return the pending connection that this player used + */ + public PendingConnection getPendingConnection(); } diff --git a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java index a9b9d589..ded8ae36 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -87,7 +87,7 @@ public class BungeeCord extends ProxyServer public final PluginManager pluginManager = new PluginManager(); @Getter @Setter - private ReconnectHandler reconnectHandler; + private ReconnectHandler reconnectHandler = new YamlReconnectHandler(); @Getter @Setter private ConfigurationAdapter configurationAdapter = new YamlConfig(); diff --git a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java index 605f0e4b..611cc1c6 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java @@ -8,6 +8,7 @@ import java.net.Socket; import java.util.ArrayList; import java.util.List; import javax.crypto.SecretKey; +import lombok.Getter; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ListenerInfo; @@ -26,7 +27,8 @@ public class InitialHandler implements Runnable, PendingConnection { private final Socket socket; - private final ListenerInfo info; + @Getter + private final ListenerInfo listener; private PacketInputStream in; private OutputStream out; private Packet2Handshake handshake; @@ -34,7 +36,7 @@ public class InitialHandler implements Runnable, PendingConnection public InitialHandler(Socket socket, ListenerInfo info) throws IOException { this.socket = socket; - this.info = info; + this.listener = info; in = new PacketInputStream(socket.getInputStream()); out = socket.getOutputStream(); } @@ -77,7 +79,7 @@ public class InitialHandler implements Runnable, PendingConnection customPackets.add(custom); } - UserConnection userCon = new UserConnection(socket, info, in, out, handshake, customPackets); + UserConnection userCon = new UserConnection(socket, this, in, out, handshake, customPackets); String server = ProxyServer.getInstance().getReconnectHandler().getServer(userCon); ServerInfo s = BungeeCord.getInstance().config.getServers().get(server); userCon.connect(s); @@ -96,10 +98,10 @@ public class InitialHandler implements Runnable, PendingConnection String ping = (newPing) ? ChatColor.COLOR_CHAR + "1" + "\00" + BungeeCord.PROTOCOL_VERSION + "\00" + BungeeCord.GAME_VERSION - + "\00" + info.getMotd() + + "\00" + listener.getMotd() + "\00" + ProxyServer.getInstance().getPlayers().size() - + "\00" + info.getMaxPlayers() - : info.getMotd() + ChatColor.COLOR_CHAR + ProxyServer.getInstance().getPlayers().size() + ChatColor.COLOR_CHAR + info.getMaxPlayers(); + + "\00" + listener.getMaxPlayers() + : listener.getMotd() + ChatColor.COLOR_CHAR + ProxyServer.getInstance().getPlayers().size() + ChatColor.COLOR_CHAR + listener.getMaxPlayers(); throw new KickException(ping); default: if (id == 0xFA) diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java index 65d1c5d1..1a56ab2c 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -87,7 +87,7 @@ public class ServerConnection extends GenericConnection implements Server throw ex; } catch (Exception ex) { - InetSocketAddress def = BungeeCord.getInstance().config.getServers().get(user.info.getDefaultServer()).getAddress(); + InetSocketAddress def = BungeeCord.getInstance().config.getServers().get(user.getPendingConnection().getListener().getDefaultServer()).getAddress(); if (retry && !address.equals(def)) { return connect(user, name, def, handshake, false); diff --git a/proxy/src/main/java/net/md_5/bungee/UserConnection.java b/proxy/src/main/java/net/md_5/bungee/UserConnection.java index bb557304..d7bd7648 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -20,6 +20,7 @@ import lombok.Synchronized; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ListenerInfo; import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.api.connection.PendingConnection; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.event.ChatEvent; import net.md_5.bungee.api.event.PluginMessageEvent; @@ -32,7 +33,8 @@ public class UserConnection extends GenericConnection implements ProxiedPlayer public final Packet2Handshake handshake; public Queue packetQueue = new ConcurrentLinkedQueue<>(); public List loginPackets = new ArrayList<>(); -final ListenerInfo info; + @Getter + private final PendingConnection pendingConnection; @Getter private ServerConnection server; private UpstreamBridge upBridge; @@ -51,11 +53,11 @@ final ListenerInfo info; private final Map permissions = new HashMap<>(); private final Object permMutex = new Object(); - public UserConnection(Socket socket, ListenerInfo info, PacketInputStream in, OutputStream out, Packet2Handshake handshake, List loginPackets) + public UserConnection(Socket socket, PendingConnection pendingConnection, PacketInputStream in, OutputStream out, Packet2Handshake handshake, List loginPackets) { super(socket, in, out); - this.info = info; this.handshake = handshake; + this.pendingConnection = pendingConnection; name = handshake.username; displayName = handshake.username; this.loginPackets = loginPackets; diff --git a/proxy/src/main/java/net/md_5/bungee/YamlReconnectHandler.java b/proxy/src/main/java/net/md_5/bungee/YamlReconnectHandler.java new file mode 100644 index 00000000..6f1ced11 --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/YamlReconnectHandler.java @@ -0,0 +1,81 @@ +package net.md_5.bungee; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.ReconnectHandler; +import net.md_5.bungee.api.config.ListenerInfo; +import net.md_5.bungee.api.connection.ProxiedPlayer; +import org.yaml.snakeyaml.Yaml; + +public class YamlReconnectHandler implements ReconnectHandler +{ + + private final Yaml yaml = new Yaml(); + private final File file = new File("locations.yml"); + /*========================================================================*/ + private Map data; + + @SuppressWarnings("unchecked") + public YamlReconnectHandler() + { + try (FileReader rd = new FileReader(file)) + { + data = yaml.loadAs(rd, Map.class); + } catch (IOException ex) + { + ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not load reconnect locations", ex); + } + + if (data == null) + { + data = new ConcurrentHashMap<>(); + } else + { + data = new ConcurrentHashMap<>(data); + } + } + + @Override + public String getServer(ProxiedPlayer player) + { + ListenerInfo listener = player.getPendingConnection().getListener(); + if (listener.isForceDefault()) + { + return listener.getDefaultServer(); + } + + String server = data.get(key(player)); + return (server != null) ? server : listener.getDefaultServer(); + } + + @Override + public void setServer(ProxiedPlayer player) + { + data.put(key(player), player.getServer().getInfo().getName()); + } + + private String key(ProxiedPlayer player) + { + InetSocketAddress host = player.getPendingConnection().getVirtualHost(); + return player.getName() + ";" + host.getHostString() + ":" + host.getPort(); + } + + @Override + public void save() + { + try (FileWriter wr = new FileWriter(file)) + { + yaml.dump(data, wr); + } catch (IOException ex) + { + ProxyServer.getInstance().getLogger().log(Level.WARNING, "Could not save reconnect locations", ex); + } + } +}