diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnection.java b/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnection.java index 2e0435b..d090a47 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnection.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnection.java @@ -18,14 +18,7 @@ public class ServerConnection implements Server private final BungeeServerInfo info; private boolean isObsolete; - private Unsafe unsafe = new Unsafe() - { - @Override - public void sendPacket(DefinedPacket packet) - { - ch.write( packet ); - } - }; + private final Connection.Unsafe unsafe; @Override public void sendData(String channel, byte[] data) @@ -34,20 +27,15 @@ public class ServerConnection implements Server } @Override - public synchronized void disconnect(String reason) - { - if ( !ch.isClosed() ) - { - // TODO: Can we just use a future here? - unsafe().sendPacket( new PacketFFKick( reason ) ); - ch.getHandle().eventLoop().schedule( new Runnable() - { + public synchronized void disconnect(final String reason) { + if (this.ch != null && !this.ch.isClosed()) { + this.unsafe().sendPacket(new PacketFFKick(reason)); + this.ch.getHandle().eventLoop().schedule((Runnable) new Runnable() { @Override - public void run() - { - ch.getHandle().close(); + public void run() { + ServerConnection.this.ch.getHandle().close(); } - }, 100, TimeUnit.MILLISECONDS ); + }, 100L, TimeUnit.MILLISECONDS); } } diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnector.java b/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnector.java index 8b6fdcd..e599489 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnector.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/ServerConnector.java @@ -10,6 +10,8 @@ import java.util.Objects; import java.util.Queue; import javax.crypto.Cipher; import javax.crypto.SecretKey; + +import io.netty.channel.ChannelHandler; import net.md_5.bungee.api.ChatColor; import net.md_5.bungee.api.ProxyServer; import net.md_5.bungee.api.config.ServerInfo; @@ -51,6 +53,8 @@ public class ServerConnector extends PacketHandler private SecretKey secretkey; private boolean sentMessages; + private boolean protocolSupport = BungeeCord.getInstance().config.getProtocolSupport(); + public ServerConnector(ProxyServer bungee, UserConnection user, BungeeServerInfo target){ this.bungee = bungee; this.user = user; @@ -79,177 +83,135 @@ public class ServerConnector extends PacketHandler @Override public void connected(ChannelWrapper channel) throws Exception { + System.out.println("[ServerConnector] - connected"); this.ch = channel; - - ByteArrayDataOutput out = ByteStreams.newDataOutput(); - out.writeUTF( "Login" ); - out.writeUTF( user.getAddress().getHostString() ); - out.writeInt( user.getAddress().getPort() ); - channel.write( new PacketFAPluginMessage( "BungeeCord", out.toByteArray() ) ); - - channel.write( user.getPendingConnection().getHandshake() ); - - // Skip encryption if we are not using Forge - if ( user.getPendingConnection().getForgeLogin() == null ) - { - channel.write( PacketConstants.CLIENT_LOGIN ); + channel.write(this.user.getPendingConnection().getHandshake()); + if (!protocolSupport) { + final ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("Login"); + out.writeUTF(this.user.getAddress().getHostString()); + out.writeInt(this.user.getAddress().getPort()); + channel.write(new PacketFAPluginMessage("BungeeCord", out.toByteArray())); + if (this.user.getPendingConnection().getForgeLogin() == null) { + channel.write(PacketConstants.CLIENT_LOGIN); + } } } @Override public void disconnected(ChannelWrapper channel) throws Exception { - user.getPendingConnects().remove( target ); + user.getPendingConnects().remove(this.target); } @Override - public void handle(Packet1Login login) throws Exception - { - Preconditions.checkState( thisState == State.LOGIN, "Not exepcting LOGIN" ); - - ServerConnection server = new ServerConnection( ch, target ); - ServerConnectedEvent event = new ServerConnectedEvent( user, server ); - bungee.getPluginManager().callEvent( event ); - - ch.write( BungeeCord.getInstance().registerChannels() ); - Queue packetQueue = target.getPacketQueue(); - synchronized ( packetQueue ) - { - while ( !packetQueue.isEmpty() ) - { - ch.write( packetQueue.poll() ); + public void handle(final Packet1Login login) throws Exception { + System.out.println("[ServerConnector] - Handling LOGIN"); + Preconditions.checkState(this.thisState == State.LOGIN || this.thisState == State.ENCRYPT_REQUEST, (Object)"Not expecting LOGIN/ENCRYPT_REQUEST"); + if (this.thisState == State.ENCRYPT_REQUEST) { + this.thisState = State.LOGIN; + } + final ServerConnection server = new ServerConnection(this.ch, this.target); + final ServerConnectedEvent event = new ServerConnectedEvent(this.user, server); + this.bungee.getPluginManager().callEvent(event); + this.ch.write(BungeeCord.getInstance().registerChannels()); + final Queue packetQueue = this.target.getPacketQueue(); + synchronized (packetQueue) { + while (!packetQueue.isEmpty()) { + this.ch.write(packetQueue.poll()); } } - - for ( PacketFAPluginMessage message : user.getPendingConnection().getRegisterMessages() ) - { - ch.write( message ); + for (final PacketFAPluginMessage message : this.user.getPendingConnection().getRegisterMessages()) { + this.ch.write(message); } - if ( !sentMessages ) - { - for ( PacketFAPluginMessage message : user.getPendingConnection().getLoginMessages() ) - { - ch.write( message ); + if (!this.sentMessages) { + for (final PacketFAPluginMessage message : this.user.getPendingConnection().getLoginMessages()) { + this.ch.write(message); } } - - if ( user.getSettings() != null ) - { - ch.write( user.getSettings() ); + if (this.user.getSettings() != null) { + this.ch.write(this.user.getSettings()); } - - synchronized ( user.getSwitchMutex() ) - { - if ( user.getServer() == null ) - { - // Once again, first connection - user.setClientEntityId( login.getEntityId() ); - user.setServerEntityId( login.getEntityId() ); - - // Set tab list size, this sucks balls, TODO: what shall we do about packet mutability + synchronized (this.user.getSwitchMutex()) { + if (this.user.getServer() == null) { + this.user.setClientEntityId(login.getEntityId()); + this.user.setServerEntityId(login.getEntityId()); Packet1Login modLogin; - if ( ch.getHandle().pipeline().get( PacketDecoder.class ).getProtocol() == Forge.getInstance() ) - { - modLogin = new Forge1Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(), - (byte) user.getPendingConnection().getListener().getTabListSize() ); - } else - { - modLogin = new Packet1Login( login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte) login.getDimension(), login.getDifficulty(), login.getUnused(), - (byte) user.getPendingConnection().getListener().getTabListSize() ); + if (((PacketDecoder)this.ch.getHandle().pipeline().get((Class)PacketDecoder.class)).getProtocol() == Forge.getInstance()) { + modLogin = new Forge1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize()); } - user.unsafe().sendPacket( modLogin ); - - MinecraftOutput out = new MinecraftOutput(); - out.writeStringUTF8WithoutLengthHeaderBecauseDinnerboneStuffedUpTheMCBrandPacket( ProxyServer.getInstance().getName() + " (" + ProxyServer.getInstance().getVersion() + ")" ); - user.unsafe().sendPacket( new PacketFAPluginMessage( "MC|Brand", out.toArray() ) ); - } else - { - user.getTabList().onServerChange(); - - Scoreboard serverScoreboard = user.getServerSentScoreboard(); - for ( Objective objective : serverScoreboard.getObjectives() ) - { - user.unsafe().sendPacket( new PacketCEScoreboardObjective( objective.getName(), objective.getValue(), (byte) 1 ) ); + else { + modLogin = new Packet1Login(login.getEntityId(), login.getLevelType(), login.getGameMode(), (byte)login.getDimension(), login.getDifficulty(), login.getUnused(), (byte)this.user.getPendingConnection().getListener().getTabListSize()); } - for ( Team team : serverScoreboard.getTeams() ) - { - user.unsafe().sendPacket( new PacketD1Team( team.getName() ) ); + this.user.unsafe().sendPacket(modLogin); + } + else { + this.user.getTabList().onServerChange(); + final Scoreboard serverScoreboard = this.user.getServerSentScoreboard(); + for (final Objective objective : serverScoreboard.getObjectives()) { + this.user.unsafe().sendPacket(new PacketCEScoreboardObjective(objective.getName(), objective.getValue(), (byte)1)); + } + for (final Team team : serverScoreboard.getTeams()) { + this.user.unsafe().sendPacket(new PacketD1Team(team.getName())); } serverScoreboard.clear(); - - user.sendDimensionSwitch(); - - user.setServerEntityId( login.getEntityId() ); - user.unsafe().sendPacket( new Packet9Respawn( login.getDimension(), login.getDifficulty(), login.getGameMode(), (short) 256, login.getLevelType() ) ); - - // Remove from old servers - user.getServer().setObsolete( true ); - user.getServer().disconnect( "Quitting" ); + this.user.sendDimensionSwitch(); + this.user.setServerEntityId(login.getEntityId()); + this.user.unsafe().sendPacket(new Packet9Respawn(login.getDimension(), login.getDifficulty(), login.getGameMode(), (short)256, login.getLevelType())); + this.user.getServer().setObsolete(true); + this.user.getServer().disconnect("Quitting"); } - - // TODO: Fix this? - if ( !user.isActive() ) - { - server.disconnect( "Quitting" ); - // Silly server admins see stack trace and die - bungee.getLogger().warning( "No client connected for pending server!" ); + if (!this.user.isActive()) { + server.disconnect("Quitting"); + this.bungee.getLogger().warning("No client connected for pending server!"); return; } - - // Add to new server - // TODO: Move this to the connected() method of DownstreamBridge - target.addPlayer( user ); - user.getPendingConnects().remove( target ); - - user.setServer( server ); - ch.getHandle().pipeline().get( HandlerBoss.class ).setHandler( new DownstreamBridge( bungee, user, server ) ); + this.target.addPlayer(this.user); + this.user.getPendingConnects().remove(this.target); + this.user.setServer(server); + ((HandlerBoss)this.ch.getHandle().pipeline().get((Class)HandlerBoss.class)).setHandler(new DownstreamBridge(this.bungee, this.user, server)); } - - bungee.getPluginManager().callEvent( new ServerSwitchEvent( user ) ); - - thisState = State.FINISHED; - + this.bungee.getPluginManager().callEvent(new ServerSwitchEvent(this.user)); + this.thisState = State.FINISHED; throw new CancelSendSignal(); } @Override - public void handle(PacketFDEncryptionRequest encryptRequest) throws Exception - { - Preconditions.checkState( thisState == State.ENCRYPT_REQUEST, "Not expecting ENCRYPT_REQUEST" ); - - // Only need to handle this if we want to use encryption - if ( user.getPendingConnection().getForgeLogin() != null ) - { - PublicKey publickey = EncryptionUtil.getPubkey( encryptRequest ); + public void handle(final PacketFDEncryptionRequest encryptRequest) throws Exception { + Preconditions.checkState(this.thisState == State.ENCRYPT_REQUEST, (Object)"Not expecting ENCRYPT_REQUEST"); + if (protocolSupport) { + final ByteArrayDataOutput out = ByteStreams.newDataOutput(); + out.writeUTF("Login"); + out.writeUTF(this.user.getAddress().getHostString()); + out.writeInt(this.user.getAddress().getPort()); + this.user.unsafe().sendPacket(new PacketFAPluginMessage("BungeeCord", out.toByteArray())); + if (this.user.getPendingConnection().getForgeLogin() == null) { + this.user.unsafe().sendPacket(PacketConstants.CLIENT_LOGIN); + } + } + if (this.user.getPendingConnection().getForgeLogin() != null) { + final PublicKey publickey = EncryptionUtil.getPubkey(encryptRequest); this.secretkey = EncryptionUtil.getSecret(); - - byte[] shared = EncryptionUtil.encrypt( publickey, secretkey.getEncoded() ); - byte[] token = EncryptionUtil.encrypt( publickey, encryptRequest.getVerifyToken() ); - - ch.write( new PacketFCEncryptionResponse( shared, token ) ); - - Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, secretkey ); - ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) ); - - thisState = State.ENCRYPT_RESPONSE; - } else - { - thisState = State.LOGIN; + final byte[] shared = EncryptionUtil.encrypt(publickey, this.secretkey.getEncoded()); + final byte[] token = EncryptionUtil.encrypt(publickey, encryptRequest.getVerifyToken()); + this.ch.write(new PacketFCEncryptionResponse(shared, token)); + final Cipher encrypt = EncryptionUtil.getCipher(1, this.secretkey); + this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.ENCRYPT_HANDLER, (ChannelHandler)new CipherEncoder(encrypt)); + this.thisState = State.ENCRYPT_RESPONSE; + } + else { + this.thisState = State.LOGIN; } } @Override - public void handle(PacketFCEncryptionResponse encryptResponse) throws Exception - { - Preconditions.checkState( thisState == State.ENCRYPT_RESPONSE, "Not expecting ENCRYPT_RESPONSE" ); - - Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, secretkey ); - ch.addBefore( PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) ); - - ch.write( user.getPendingConnection().getForgeLogin() ); - - ch.write( PacketConstants.CLIENT_LOGIN ); - thisState = State.LOGIN; + public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception { + Preconditions.checkState(this.thisState == State.ENCRYPT_RESPONSE, (Object)"Not expecting ENCRYPT_RESPONSE"); + final Cipher decrypt = EncryptionUtil.getCipher(2, this.secretkey); + this.ch.getHandle().pipeline().addBefore(PipelineUtils.PACKET_DECODE_HANDLER, PipelineUtils.DECRYPT_HANDLER, (ChannelHandler)new CipherDecoder(decrypt)); + this.ch.write(this.user.getPendingConnection().getForgeLogin()); + this.ch.write(PacketConstants.CLIENT_LOGIN); + this.thisState = State.LOGIN; } @Override diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/UserConnection.java b/eaglerbungee/src/main/java/net/md_5/bungee/UserConnection.java index e265079..791db9a 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/UserConnection.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/UserConnection.java @@ -177,14 +177,7 @@ public final class UserConnection implements ProxiedPlayer return displayName; } - private Unsafe unsafe = new Unsafe() - { - @Override - public void sendPacket(DefinedPacket packet) - { - ch.write( packet ); - } - }; + private final Connection.Unsafe unsafe; @ConstructorProperties({ "bungee", "ch", "name", "pendingConnection" }) public UserConnection(final ProxyServer bungee, final ChannelWrapper ch, final String name, final InitialHandler pendingConnection) { diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java b/eaglerbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java index cdc44cb..d4c7df6 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/connection/InitialHandler.java @@ -111,7 +111,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection { boolean skipEncryption = false; if (handshake.getProcolVersion() == 78) { skipEncryption = true; - this.handshake.swapProtocol((byte) 78); + System.out.println("Skipping encryption..."); + //this.handshake.swapProtocol((byte) 78); }else if(handshake.getProcolVersion() > 78) { this.disconnect("this server does not support microsoft accounts"); return; @@ -212,6 +213,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { @Override public void handle(final PacketFCEncryptionResponse encryptResponse) throws Exception { + System.out.println("Handle PacketFCEncryptionResponse"); Preconditions.checkState(this.thisState == State.ENCRYPT, (Object) "Not expecting ENCRYPT"); this.sharedKey = EncryptionUtil.getSecret(encryptResponse, this.request); final Cipher decrypt = EncryptionUtil.getCipher(2, this.sharedKey); @@ -220,6 +222,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { } private void finish() throws GeneralSecurityException { + System.out.println("Finish"); final ProxiedPlayer old = this.bungee.getPlayer(this.handshake.getUsername()); if (old != null) { old.disconnect(this.bungee.getTranslation("already_connected")); @@ -254,6 +257,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection { @Override public void handle(final PacketCDClientStatus clientStatus) throws Exception { + System.out.println("[InitialHandler] - PacketCDClientStatus"); Preconditions.checkState(this.thisState == State.LOGIN, (Object) "Not expecting LOGIN"); final UserConnection userCon = new UserConnection(this.bungee, this.ch, this.getName(), this); InetAddress ins = WebSocketProxy.localToRemote.get(this.ch.getHandle().remoteAddress()); diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java b/eaglerbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java index 14d5415..671bd03 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/connection/UpstreamBridge.java @@ -61,14 +61,14 @@ public class UpstreamBridge extends PacketHandler public void handle(final byte[] buf) throws Exception { EntityMap.rewrite(Unpooled.wrappedBuffer(buf), this.con.getClientEntityId(), this.con.getServerEntityId()); if (this.con.getServer() != null && this.con.getServer().getCh() != null) { - this.con.getServer().getCh().write(buf); // Change to buf if its a problem + this.con.getServer().getCh().write(buf); } } @Override public void handle(Packet0KeepAlive alive) throws Exception { - if ( alive.getRandomId() == con.getSentPingId() ) + if (alive.getRandomId() == con.getSentPingId()) { int newPing = (int) ( System.currentTimeMillis() - con.getSentPingTime() ); con.getTabList().onPingChange( newPing ); diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java b/eaglerbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java index 13efd7b..57fe7d5 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/eaglercraft/WebSocketListener.java @@ -177,7 +177,6 @@ public class WebSocketListener extends WebSocketServer { @Override public void onMessage(WebSocket arg0, ByteBuffer arg1) { - System.out.println("[WebsocketListener] - onMessage called"); Object o = arg0.getAttachment(); if(o == null || (o instanceof PendingSocket)) { InetAddress realAddr; @@ -210,7 +209,6 @@ public class WebSocketListener extends WebSocketServer { } if(o != null) { if(o instanceof WebSocketProxy) { - System.out.println("Instance of WebSocketProxy, sending packet"); ((WebSocketProxy)o).sendPacket(arg1); }else { System.out.println("Closing websocket"); diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java b/eaglerbungee/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java index 85daacc..8314450 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/netty/ChannelWrapper.java @@ -1,28 +1,23 @@ +// +// Decompiled by Procyon v0.5.36 +// + package net.md_5.bungee.netty; -import com.google.common.base.Preconditions; import io.netty.channel.Channel; -import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandlerContext; -public class ChannelWrapper -{ - +public class ChannelWrapper { private final Channel ch; - - public boolean isClosed() { - return closed; - } - private volatile boolean closed; - public ChannelWrapper(ChannelHandlerContext ctx) - { + public ChannelWrapper(final ChannelHandlerContext ctx) { this.ch = ctx.channel(); } - public synchronized void write(final Object packet) { + public synchronized void write(final Object packet) { // This is a problem, the packets ARE being sent but arent coming to client if (!this.closed) { + System.out.println("[ChannelWrapper] - trying to send packet"); this.ch.write(packet); } } @@ -34,15 +29,11 @@ public class ChannelWrapper } } - public void addBefore(String baseName, String name, ChannelHandler handler) - { - Preconditions.checkState( ch.eventLoop().inEventLoop(), "cannot add handler outside of event loop" ); - //ch.pipeline().flush(); - ch.pipeline().addBefore( baseName, name, handler ); + public Channel getHandle() { + return this.ch; } - public Channel getHandle() - { - return ch; + public boolean isClosed() { + return this.closed; } } diff --git a/eaglerbungee/src/main/java/net/md_5/bungee/netty/HandlerBoss.java b/eaglerbungee/src/main/java/net/md_5/bungee/netty/HandlerBoss.java index d87be82..b8e8aeb 100644 --- a/eaglerbungee/src/main/java/net/md_5/bungee/netty/HandlerBoss.java +++ b/eaglerbungee/src/main/java/net/md_5/bungee/netty/HandlerBoss.java @@ -47,6 +47,7 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter { } public void messageReceived(final ChannelHandlerContext ctx, final MessageList msgs) throws Exception { + System.out.println("[HandlerBoss] - Message (packet?) received"); for (final Object msg : msgs) { if (this.handler != null && ctx.channel().isActive()) { if (msg instanceof PacketWrapper) { @@ -64,6 +65,9 @@ public class HandlerBoss extends ChannelInboundHandlerAdapter { this.handler.handle((byte[]) msg); } } + else { + System.out.println("Handler null or channel down"); + } } }