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 eaa81183..62fc3507 100644 --- a/proxy/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnection.java @@ -6,20 +6,13 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; import lombok.Getter; import net.md_5.bungee.api.Callback; -import net.md_5.bungee.api.ChatColor; -import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.ServerPing; import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.connection.Server; -import net.md_5.bungee.api.event.ServerConnectedEvent; 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.PacketFFKick; import net.md_5.bungee.packet.PacketStream; -import net.md_5.mendax.PacketDefinitions; /** * Class representing a connection from the proxy to the server; ie upstream. @@ -39,84 +32,6 @@ public class ServerConnection extends GenericConnection implements Server this.loginPacket = loginPacket; } - public static ServerConnection connect(UserConnection user, ServerInfo info, Packet2Handshake handshake, boolean retry) - { - try - { - Socket socket = new Socket(); - socket.connect( info.getAddress(), BungeeCord.getInstance().config.getTimeout() ); - BungeeCord.getInstance().setSocketOptions( socket ); - - PacketStream stream = new PacketStream( socket.getInputStream(), socket.getOutputStream(), user.stream.getProtocol() ); - - if ( user.forgeLogin != null ) - { - stream.write( user.forgeLogin ); - } - - stream.write( handshake ); - stream.write( PacketCDClientStatus.CLIENT_LOGIN ); - stream.readPacket(); - - byte[] loginResponse = null; - boolean forgeIHateYou = false; - loop: - while ( true ) - { - loginResponse = stream.readPacket(); - int id = Util.getId( loginResponse ); - switch ( id ) - { - case 0x01: - break loop; - case 0xFA: - if ( !forgeIHateYou ) - { - for ( PacketFAPluginMessage message : user.loginMessages ) - { - stream.write( message ); - } - forgeIHateYou = true; - } - break; - case 0xFF: - throw new KickException( "[Kicked] " + new PacketFFKick( loginResponse ).message ); - default: - throw new IllegalArgumentException( "Unknown login packet " + Util.hex( id ) ); - } - } - Packet1Login login = new Packet1Login( loginResponse ); - - ServerConnection server = new ServerConnection( socket, info, stream, login ); - ServerConnectedEvent event = new ServerConnectedEvent( user, server ); - ProxyServer.getInstance().getPluginManager().callEvent( event ); - - stream.write( BungeeCord.getInstance().registerChannels() ); - - Queue packetQueue = ( (BungeeServerInfo) info ).getPacketQueue(); - while ( !packetQueue.isEmpty() ) - { - stream.write( packetQueue.poll() ); - } - - return server; - } catch ( KickException ex ) - { - throw ex; - } catch ( Exception ex ) - { - ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); - if ( retry && !info.equals( def ) ) - { - user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); - return connect( user, def, handshake, false ); - } else - { - throw new RuntimeException( "Could not connect to target server " + Util.exception( ex ) ); - } - } - } - @Override public void sendData(String channel, byte[] data) { diff --git a/proxy/src/main/java/net/md_5/bungee/ServerConnector.java b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java new file mode 100644 index 00000000..5526dc3a --- /dev/null +++ b/proxy/src/main/java/net/md_5/bungee/ServerConnector.java @@ -0,0 +1,93 @@ +package net.md_5.bungee; + +import com.google.common.base.Preconditions; +import java.io.IOException; +import java.net.Socket; +import net.md_5.bungee.api.ChatColor; +import net.md_5.bungee.api.ProxyServer; +import net.md_5.bungee.api.config.ServerInfo; +import net.md_5.bungee.packet.DefinedPacket; +import net.md_5.bungee.packet.Packet1Login; +import net.md_5.bungee.packet.PacketCDClientStatus; +import net.md_5.bungee.packet.PacketFDEncryptionRequest; +import net.md_5.bungee.packet.PacketHandler; +import net.md_5.bungee.packet.PacketStream; + +public class ServerConnector extends PacketHandler +{ + + private final PacketStream stream; + private Packet1Login loginPacket; + private State thisState = State.ENCRYPT_REQUEST; + + public ServerConnector(PacketStream stream) + { + this.stream = stream; + } + + private enum State + { + + ENCRYPT_REQUEST, LOGIN, FINISHED; + } + + @Override + public void handle(Packet1Login login) throws Exception + { + Preconditions.checkState( thisState == State.LOGIN, "Not exepcting LOGIN" ); + loginPacket = login; + thisState = State.FINISHED; + } + + @Override + public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception + { + Preconditions.checkState( thisState == State.ENCRYPT_REQUEST, "Not expecting ENCRYPT_REQUEST" ); + thisState = State.LOGIN; + } + + public static ServerConnection connect(UserConnection user, ServerInfo server, boolean retry) + { + Socket socket = null; + try + { + socket = new Socket(); + socket.connect( server.getAddress(), BungeeCord.getInstance().config.getTimeout() ); + BungeeCord.getInstance().setSocketOptions( socket ); + PacketStream stream = new PacketStream( socket.getInputStream(), socket.getOutputStream(), user.stream.getProtocol() ); + + ServerConnector connector = new ServerConnector( stream ); + stream.write( user.handshake ); + stream.write( PacketCDClientStatus.CLIENT_LOGIN ); + + while ( connector.thisState != State.FINISHED ) + { + byte[] buf = stream.readPacket(); + DefinedPacket packet = DefinedPacket.packet( buf ); + packet.handle( connector ); + } + + return new ServerConnection( socket, server, stream, connector.loginPacket ); + } catch ( Exception ex ) + { + if ( socket != null ) + { + try + { + socket.close(); + } catch ( IOException ioe ) + { + } + } + ServerInfo def = ProxyServer.getInstance().getServers().get( user.getPendingConnection().getListener().getDefaultServer() ); + if ( retry && !server.equals( def ) ) + { + user.sendMessage( ChatColor.RED + "Could not connect to target server, you have been moved to the default server" ); + return connect( user, def, false ); + } else + { + throw new RuntimeException( "Could not connect to target server " + Util.exception( ex ) ); + } + } + } +} 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 36575972..4caee0de 100644 --- a/proxy/src/main/java/net/md_5/bungee/UserConnection.java +++ b/proxy/src/main/java/net/md_5/bungee/UserConnection.java @@ -113,7 +113,7 @@ public class UserConnection extends GenericConnection implements ProxiedPlayer stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); } - ServerConnection newServer = ServerConnection.connect( this, target, handshake, true ); + ServerConnection newServer = ServerConnector.connect( this, target, true ); if ( server == null ) { // Once again, first connection @@ -157,8 +157,7 @@ public class UserConnection extends GenericConnection implements ProxiedPlayer destroySelf( ex.getMessage() ); } catch ( Exception ex ) { - ex.printStackTrace(); // TODO: Remove - destroySelf( "Could not connect to server - " + ex.getClass().getSimpleName() ); + destroySelf( "Could not connect to server - " + Util.exception( ex ) ); } } diff --git a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java index 27843c4f..ac14eb5f 100644 --- a/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java +++ b/proxy/src/main/java/net/md_5/bungee/packet/DefinedPacket.java @@ -1,5 +1,6 @@ package net.md_5.bungee.packet; +import com.google.common.base.Preconditions; import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteStreams; import java.io.ByteArrayInputStream; @@ -213,6 +214,8 @@ public abstract class DefinedPacket implements DataOutput { } } + + Preconditions.checkState( ret != null, "Don't know how to deal with packet ID {0}", Util.hex( id ) ); return ret; } @@ -227,6 +230,7 @@ public abstract class DefinedPacket implements DataOutput classes[0xCD] = PacketCDClientStatus.class; classes[0xFA] = PacketFAPluginMessage.class; classes[0xFC] = PacketFCEncryptionResponse.class; + classes[0xFD] = PacketFDEncryptionRequest.class; classes[0xFE] = PacketFEPing.class; classes[0xFF] = PacketFFKick.class; }