Rewrite login process in preparation for both forge and netty.

This commit is contained in:
md_5 2013-02-16 09:34:31 +11:00
parent 51e2570ddd
commit 05a6b566b2
4 changed files with 99 additions and 88 deletions

View File

@ -6,20 +6,13 @@ import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentLinkedQueue;
import lombok.Getter; import lombok.Getter;
import net.md_5.bungee.api.Callback; 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.ServerPing;
import net.md_5.bungee.api.config.ServerInfo; import net.md_5.bungee.api.config.ServerInfo;
import net.md_5.bungee.api.connection.Server; 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.DefinedPacket;
import net.md_5.bungee.packet.Packet1Login; 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.PacketFAPluginMessage;
import net.md_5.bungee.packet.PacketFFKick;
import net.md_5.bungee.packet.PacketStream; 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. * 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; 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<DefinedPacket> 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 @Override
public void sendData(String channel, byte[] data) public void sendData(String channel, byte[] data)
{ {

View File

@ -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 ) );
}
}
}
}

View File

@ -113,7 +113,7 @@ public class UserConnection extends GenericConnection implements ProxiedPlayer
stream.write( new Packet9Respawn( (byte) -1, (byte) 0, (byte) 0, (short) 256, "DEFAULT" ) ); 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 ) if ( server == null )
{ {
// Once again, first connection // Once again, first connection
@ -157,8 +157,7 @@ public class UserConnection extends GenericConnection implements ProxiedPlayer
destroySelf( ex.getMessage() ); destroySelf( ex.getMessage() );
} catch ( Exception ex ) } catch ( Exception ex )
{ {
ex.printStackTrace(); // TODO: Remove destroySelf( "Could not connect to server - " + Util.exception( ex ) );
destroySelf( "Could not connect to server - " + ex.getClass().getSimpleName() );
} }
} }

View File

@ -1,5 +1,6 @@
package net.md_5.bungee.packet; package net.md_5.bungee.packet;
import com.google.common.base.Preconditions;
import com.google.common.io.ByteArrayDataOutput; import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams; import com.google.common.io.ByteStreams;
import java.io.ByteArrayInputStream; 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; return ret;
} }
@ -227,6 +230,7 @@ public abstract class DefinedPacket implements DataOutput
classes[0xCD] = PacketCDClientStatus.class; classes[0xCD] = PacketCDClientStatus.class;
classes[0xFA] = PacketFAPluginMessage.class; classes[0xFA] = PacketFAPluginMessage.class;
classes[0xFC] = PacketFCEncryptionResponse.class; classes[0xFC] = PacketFCEncryptionResponse.class;
classes[0xFD] = PacketFDEncryptionRequest.class;
classes[0xFE] = PacketFEPing.class; classes[0xFE] = PacketFEPing.class;
classes[0xFF] = PacketFFKick.class; classes[0xFF] = PacketFFKick.class;
} }