diff --git a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java index dd51cdd9c..8baf0de79 100644 --- a/api/src/main/java/net/md_5/bungee/api/ProxyServer.java +++ b/api/src/main/java/net/md_5/bungee/api/ProxyServer.java @@ -113,6 +113,20 @@ public abstract class ProxyServer */ public abstract void setTabListHandler(TabListHandler handler); + /** + * Get the currently in use reconnect handler. + * + * @return the in use reconnect handler + */ + public abstract ReconnectHandler getReconnectHandler(); + + /** + * Sets the reconnect handler to be used for subsequent connections. + * + * @param handler the new handler + */ + public abstract void setReconnectHandler(ReconnectHandler handler); + /** * Gracefully mark this instance for shutdown. */ 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 4163239a9..7f5cc8568 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 @@ -28,4 +28,12 @@ public interface PendingConnection extends Connection * @return request virtual host or null if invalid / not specified. */ public InetSocketAddress getVirtualHost(); + + /** + * Completely kick this user from the proxy and all of its child + * connections. + * + * @param reason the disconnect reason displayed to the player + */ + public void disconnect(String reason); } 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 e34097866..c61ad882b 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 @@ -49,14 +49,6 @@ public interface ProxiedPlayer extends Connection, CommandSender */ public int getPing(); - /** - * Completely kick this user from the proxy and all of its child - * connections. - * - * @param reason the disconnect reason displayed to the player - */ - public void disconnect(String reason); - /** * Send a plugin message to this player. * 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 999af46bd..c8fde24b9 100644 --- a/proxy/src/main/java/net/md_5/bungee/BungeeCord.java +++ b/proxy/src/main/java/net/md_5/bungee/BungeeCord.java @@ -9,24 +9,26 @@ import java.net.Socket; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Queue; import java.util.Timer; +import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import lombok.Getter; +import lombok.Setter; import static net.md_5.bungee.Logger.$; import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.ReconnectHandler; import net.md_5.bungee.api.TabListHandler; import net.md_5.bungee.api.config.ConfigurationAdapter; import net.md_5.bungee.api.connection.ProxiedPlayer; import net.md_5.bungee.api.connection.Server; +import net.md_5.bungee.api.plugin.Plugin; import net.md_5.bungee.api.plugin.PluginManager; import net.md_5.bungee.command.*; import net.md_5.bungee.packet.DefinedPacket; -import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.tablist.GlobalPingTabList; import net.md_5.bungee.tablist.GlobalTabList; import net.md_5.bungee.tablist.ServerUniqueTabList; @@ -65,10 +67,6 @@ public class BungeeCord extends ProxyServer * Server socket listener. */ private ListenThread listener; - /** - * Current version. - */ - public static String version = (BungeeCord.class.getPackage().getImplementationVersion() == null) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion(); /** * Fully qualified connections. */ @@ -77,16 +75,17 @@ public class BungeeCord extends ProxyServer /** * Tab list handler */ + @Getter + @Setter public TabListHandler tabListHandler; - /** - * Registered Global Plugin Channels - */ - public Queue globalPluginChannels = new ConcurrentLinkedQueue<>(); /** * Plugin manager. */ @Getter public final PluginManager pluginManager = new PluginManager(); + @Getter + @Setter + private ReconnectHandler reconnectHandler; { @@ -163,14 +162,18 @@ public class BungeeCord extends ProxyServer break; } - // Add RubberBand to the global plugin channel list - globalPluginChannels.add("RubberBand"); - InetSocketAddress addr = Util.getAddr(config.bindHost); listener = new ListenThread(addr); listener.start(); - saveThread.start(); + saveThread.scheduleAtFixedRate(new TimerTask() + { + @Override + public void run() + { + getReconnectHandler().save(); + } + }, 0, TimeUnit.MINUTES.toMillis(5)); $().info("Listening on " + addr); if (config.metricsEnabled) @@ -186,8 +189,11 @@ public class BungeeCord extends ProxyServer public void stop() { this.isRunning = false; - $().info("Disabling plugin"); - pluginManager.onDisable(); + $().info("Disabling plugins"); + for (Plugin plugin : pluginManager.getPlugins()) + { + plugin.onDisable(); + } $().info("Closing listen thread"); try @@ -209,13 +215,7 @@ public class BungeeCord extends ProxyServer } $().info("Saving reconnect locations"); - saveThread.interrupt(); - try - { - saveThread.join(); - } catch (InterruptedException ex) - { - } + saveThread.cancel(); $().info("Thank you and goodbye"); System.exit(0); @@ -248,71 +248,6 @@ public class BungeeCord extends ProxyServer } } - /** - * Broadcasts a plugin message to all servers with currently connected - * players. - * - * @param channel name - * @param message to send - */ - public void broadcastPluginMessage(String channel, String message) - { - broadcastPluginMessage(channel, message, null); - } - - /** - * Broadcasts a plugin message to all servers with currently connected - * players. - * - * @param channel name - * @param message to send - * @param server the message was sent from originally - */ - public void broadcastPluginMessage(String channel, String message, String sourceServer) - { - for (String server : connectionsByServer.keySet()) - { - if (sourceServer == null || !sourceServer.equals(server)) - { - List conns = BungeeCord.instance.connectionsByServer.get(server); - if (conns != null && conns.size() > 0) - { - UserConnection user = conns.get(0); - user.sendPluginMessage(channel, message.getBytes()); - } - } - } - } - - /** - * Send a plugin message to a specific server if it has currently connected - * players. - * - * @param channel name - * @param message to send - * @param server the message is to be sent to - */ - public void sendPluginMessage(String channel, String message, String targetServer) - { - List conns = connectionsByServer.get(targetServer); - if (conns != null && conns.size() > 0) - { - UserConnection user = conns.get(0); - user.sendPluginMessage(channel, message.getBytes()); - } - } - - /** - * Register a plugin channel for all users - * - * @param channel name - */ - public void registerPluginChannel(String channel) - { - globalPluginChannels.add(channel); - broadcast(new PacketFAPluginMessage("REGISTER", channel.getBytes())); - } - @Override public String getName() { @@ -322,7 +257,7 @@ public class BungeeCord extends ProxyServer @Override public String getVersion() { - return version; + return (BungeeCord.class.getPackage().getImplementationVersion() == null) ? "unknown" : BungeeCord.class.getPackage().getImplementationVersion(); } @Override @@ -332,15 +267,16 @@ public class BungeeCord extends ProxyServer } @Override + @SuppressWarnings("unchecked") // TODO: Abstract more public Collection getPlayers() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return (Collection) connections.values(); } @Override public ProxiedPlayer getPlayer(String name) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return connections.get(name); } @Override 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 b2fe6660c..8211eeda9 100644 --- a/proxy/src/main/java/net/md_5/bungee/InitialHandler.java +++ b/proxy/src/main/java/net/md_5/bungee/InitialHandler.java @@ -2,26 +2,30 @@ package net.md_5.bungee; import java.io.IOException; import java.io.OutputStream; +import java.net.InetSocketAddress; import java.net.Socket; import java.util.ArrayList; import java.util.List; import javax.crypto.SecretKey; import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.connection.PendingConnection; +import net.md_5.bungee.api.event.LoginEvent; import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.PacketFCEncryptionResponse; import net.md_5.bungee.packet.PacketFDEncryptionRequest; import net.md_5.bungee.packet.PacketFFKick; import net.md_5.bungee.packet.PacketInputStream; -import net.md_5.bungee.plugin.LoginEvent; import org.bouncycastle.crypto.io.CipherInputStream; import org.bouncycastle.crypto.io.CipherOutputStream; -public class InitialHandler implements Runnable +public class InitialHandler implements Runnable, PendingConnection { private final Socket socket; private PacketInputStream in; private OutputStream out; + private Packet2Handshake handshake; public InitialHandler(Socket socket) throws IOException { @@ -40,15 +44,7 @@ public class InitialHandler implements Runnable switch (id) { case 0x02: - Packet2Handshake handshake = new Packet2Handshake(packet); - // fire connect event - LoginEvent event = new LoginEvent(handshake.username, socket.getInetAddress(), handshake.host); - BungeeCord.instance.pluginManager.onHandshake(event); - if (event.isCancelled()) - { - throw new KickException(event.getCancelReason()); - } - + handshake = new Packet2Handshake(packet); PacketFDEncryptionRequest request = EncryptionUtil.encryptRequest(); out.write(request.getPacket()); PacketFCEncryptionResponse response = new PacketFCEncryptionResponse(in.readPacket()); @@ -59,8 +55,8 @@ public class InitialHandler implements Runnable throw new KickException("Not authenticated with minecraft.net"); } - // fire post auth event - BungeeCord.instance.pluginManager.onLogin(event); + // fire login event + LoginEvent event = new LoginEvent(this); if (event.isCancelled()) { throw new KickException(event.getCancelReason()); @@ -77,8 +73,6 @@ public class InitialHandler implements Runnable } UserConnection userCon = new UserConnection(socket, in, out, handshake, customPackets); - String server = (BungeeCord.instance.config.forceDefaultServer) ? BungeeCord.instance.config.defaultServerName : BungeeCord.instance.config.getServer(handshake.username, handshake.host); - userCon.connect(server); break; case 0xFE: socket.setSoTimeout(100); @@ -90,14 +84,14 @@ public class InitialHandler implements Runnable } catch (IOException ex) { } - Configuration conf = BungeeCord.instance.config; + Configuration conf = BungeeCord.getInstance().config; String ping = (newPing) ? ChatColor.COLOR_CHAR + "1" + "\00" + BungeeCord.PROTOCOL_VERSION + "\00" + BungeeCord.GAME_VERSION + "\00" + conf.motd - + "\00" + BungeeCord.instance.connections.size() + + "\00" + ProxyServer.getInstance().getPlayers().size() + "\00" + conf.maxPlayers - : conf.motd + ChatColor.COLOR_CHAR + BungeeCord.instance.connections.size() + ChatColor.COLOR_CHAR + conf.maxPlayers; + : conf.motd + ChatColor.COLOR_CHAR + ProxyServer.getInstance().getPlayers().size() + ChatColor.COLOR_CHAR + conf.maxPlayers; throw new KickException(ping); default: if (id == 0xFA) @@ -110,18 +104,19 @@ public class InitialHandler implements Runnable } } catch (KickException ex) { - kick(ex.getMessage()); + disconnect(ex.getMessage()); } catch (Exception ex) { - kick("[Proxy Error] " + Util.exception(ex)); + disconnect("[Proxy Error] " + Util.exception(ex)); } } - private void kick(String message) + @Override + public void disconnect(String reason) { try { - out.write(new PacketFFKick(message).getPacket()); + out.write(new PacketFFKick(reason).getPacket()); } catch (IOException ioe) { } finally @@ -135,4 +130,28 @@ public class InitialHandler implements Runnable } } } + + @Override + public String getName() + { + return (handshake == null) ? null : handshake.username; + } + + @Override + public byte getVersion() + { + return (handshake == null) ? -1 : handshake.procolVersion; + } + + @Override + public InetSocketAddress getVirtualHost() + { + return (handshake == null) ? null : new InetSocketAddress(handshake.host, handshake.port); + } + + @Override + public InetSocketAddress getAddress() + { + return (InetSocketAddress) socket.getRemoteSocketAddress(); + } } 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 b1afe67bc..d70964073 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -17,7 +17,6 @@ import net.md_5.bungee.packet.DefinedPacket; import net.md_5.bungee.packet.Packet1Login; import net.md_5.bungee.packet.Packet2Handshake; import net.md_5.bungee.packet.PacketCDClientStatus; -import net.md_5.bungee.packet.PacketFAPluginMessage; import net.md_5.bungee.packet.PacketFCEncryptionResponse; import net.md_5.bungee.packet.PacketFDEncryptionRequest; import net.md_5.bungee.packet.PacketFFKick; @@ -84,13 +83,6 @@ public class ServerConnection extends GenericConnection implements Server } Packet1Login login = new Packet1Login(loginResponse); - // Register all global plugin message channels - // TODO: Allow player-specific plugin message channels for full mod support - for (String channel : BungeeCord.getInstance().globalPluginChannels) - { - out.write(new PacketFAPluginMessage("REGISTER", channel.getBytes()).getPacket()); - } - return new ServerConnection(name, socket, in, out, login); } catch (KickException ex) { diff --git a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java index 490e81b95..439a9a20a 100644 --- a/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java +++ b/proxy/src/main/java/net/md_5/bungee/command/CommandBungee.java @@ -1,8 +1,8 @@ package net.md_5.bungee.command; -import net.md_5.bungee.BungeeCord; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.CommandSender; +import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.plugin.Command; public class CommandBungee extends Command @@ -16,6 +16,6 @@ public class CommandBungee extends Command @Override public void execute(CommandSender sender, String[] args) { - sender.sendMessage(ChatColor.BLUE + "This server is running BungeeCord version " + BungeeCord.version + " by md_5"); + sender.sendMessage(ChatColor.BLUE + "This server is running BungeeCord version " + ProxyServer.getInstance().getVersion() + " by md_5"); } }