Complete issue #190 - unthread the login event for maximum efficiency.

This commit is contained in:
md_5 2013-04-26 17:00:09 +10:00
parent a63739277b
commit 93ea108acb
3 changed files with 78 additions and 80 deletions

View File

@ -289,9 +289,7 @@ public class PluginManager
long start = System.nanoTime(); long start = System.nanoTime();
eventBus.post( event ); eventBus.post( event );
event.postCall(); event.postCall();
// TODO: No exceptions!
if ( !( event instanceof LoginEvent ) )
{
long elapsed = start - System.nanoTime(); long elapsed = start - System.nanoTime();
if ( elapsed > 250000 ) if ( elapsed > 250000 )
{ {
@ -300,7 +298,6 @@ public class PluginManager
event, elapsed event, elapsed
} ); } );
} }
}
return event; return event;
} }

View File

@ -1,5 +1,6 @@
package net.md_5.bungee; package net.md_5.bungee;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException; import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.Key; import java.security.Key;
@ -59,7 +60,7 @@ public class EncryptionUtil
return new SecretKeySpec( secret, "AES" ); return new SecretKeySpec( secret, "AES" );
} }
public static Cipher getCipher(int opMode, Key shared) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException public static Cipher getCipher(int opMode, Key shared) throws GeneralSecurityException
{ {
Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" ); Cipher cip = Cipher.getInstance( "AES/CFB8/NoPadding" );
cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) ); cip.init( opMode, shared, new IvParameterSpec( shared.getEncoded() ) );

View File

@ -1,6 +1,8 @@
package net.md_5.bungee.connection; package net.md_5.bungee.connection;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import com.ning.http.client.AsyncCompletionHandler;
import com.ning.http.client.Response;
import io.netty.channel.Channel; import io.netty.channel.Channel;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -9,6 +11,7 @@ import java.math.BigInteger;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URL; import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -57,6 +60,7 @@ public class InitialHandler extends PacketHandler implements PendingConnection
private PacketFDEncryptionRequest request; private PacketFDEncryptionRequest request;
private List<PacketFAPluginMessage> loginMessages = new ArrayList<>(); private List<PacketFAPluginMessage> loginMessages = new ArrayList<>();
private State thisState = State.HANDSHAKE; private State thisState = State.HANDSHAKE;
private SecretKey sharedKey;
private boolean disconnected; private boolean disconnected;
private enum State private enum State
@ -129,26 +133,15 @@ public class InitialHandler extends PacketHandler implements PendingConnection
{ {
Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" ); Preconditions.checkState( thisState == State.ENCRYPT, "Not expecting ENCRYPT" );
// TODO: This is shit sharedKey = EncryptionUtil.getSecret( encryptResponse, request );
new Thread( "Login Verifier - " + getName() )
{
@Override
public void run()
{
try
{
SecretKey shared = EncryptionUtil.getSecret( encryptResponse, request );
if ( BungeeCord.getInstance().config.isOnlineMode() ) if ( BungeeCord.getInstance().config.isOnlineMode() )
{
String reply = null;
try
{ {
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" ); String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
MessageDigest sha = MessageDigest.getInstance( "SHA-1" ); MessageDigest sha = MessageDigest.getInstance( "SHA-1" );
for ( byte[] bit : new byte[][] for ( byte[] bit : new byte[][]
{ {
request.serverId.getBytes( "ISO_8859_1" ), shared.getEncoded(), EncryptionUtil.keys.getPublic().getEncoded() request.serverId.getBytes( "ISO_8859_1" ), sharedKey.getEncoded(), EncryptionUtil.keys.getPublic().getEncoded()
} ) } )
{ {
sha.update( bit ); sha.update( bit );
@ -156,20 +149,35 @@ public class InitialHandler extends PacketHandler implements PendingConnection
String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" ); String encodedHash = URLEncoder.encode( new BigInteger( sha.digest() ).toString( 16 ), "UTF-8" );
String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash; String authURL = "http://session.minecraft.net/game/checkserver.jsp?user=" + encName + "&serverId=" + encodedHash;
bungee.getHttpClient().prepareGet( authURL ).execute( new AsyncCompletionHandler<Response>()
try ( BufferedReader in = new BufferedReader( new InputStreamReader( new URL( authURL ).openStream() ) ) )
{ {
reply = in.readLine(); @Override
} public Response onCompleted(Response response) throws Exception
} catch ( IOException ex )
{ {
} if ( "YES".equals( response.getResponseBody() ) )
{
if ( !"YES".equals( reply ) ) finish();
} else
{ {
disconnect( "Not authenticated with Minecraft.net" ); disconnect( "Not authenticated with Minecraft.net" );
} }
return response;
}
@Override
public void onThrowable(Throwable t)
{
disconnect( "Error occured while contacting login servers, are they down?" + Util.exception( t ) );
}
} );
} else
{
finish();
}
}
private void finish() throws GeneralSecurityException
{
// Check for multiple connections // Check for multiple connections
ProxiedPlayer old = bungee.getPlayer( handshake.username ); ProxiedPlayer old = bungee.getPlayer( handshake.username );
if ( old != null ) if ( old != null )
@ -177,8 +185,6 @@ public class InitialHandler extends PacketHandler implements PendingConnection
old.disconnect( "You are already connected to the server" ); old.disconnect( "You are already connected to the server" );
} }
}
// fire login event // fire login event
LoginEvent event = new LoginEvent( InitialHandler.this ); LoginEvent event = new LoginEvent( InitialHandler.this );
if ( bungee.getPluginManager().callEvent( event ).isCancelled() ) if ( bungee.getPluginManager().callEvent( event ).isCancelled() )
@ -190,18 +196,12 @@ public class InitialHandler extends PacketHandler implements PendingConnection
return; return;
} }
Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, shared ); Cipher encrypt = EncryptionUtil.getCipher( Cipher.ENCRYPT_MODE, sharedKey );
Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, shared ); Cipher decrypt = EncryptionUtil.getCipher( Cipher.DECRYPT_MODE, sharedKey );
ch.write( new PacketFCEncryptionResponse() ); ch.write( new PacketFCEncryptionResponse() );
ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) ); ch.pipeline().addBefore( "decoder", "cipher", new CipherCodec( encrypt, decrypt ) );
thisState = InitialHandler.State.LOGIN; thisState = InitialHandler.State.LOGIN;
} catch ( Throwable t )
{
disconnect( "[Report to md_5 / Server Owner] " + Util.exception( t ) );
}
}
}.start();
} }
@Override @Override