Refactor native code and implement our own JNI wrapper around zlib.
The previous native cipher code has been refactored so that it may be loaded and used slightly more generically, allowing more native components to be easily added as time goes on. I have also written a new native code compression module, which wraps around zlib in the same manner that Inflater / Deflater does, however it operates directly on the memory addresses of it's input / output buffers which means that we can save one, or maybe even two copies. To support this, the VarInt decoder has been adjusted to always use a native buffer.
This commit is contained in:
@@ -68,6 +68,7 @@ import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
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.compress.CompressFactory;
|
||||
import net.md_5.bungee.conf.YamlConfig;
|
||||
import net.md_5.bungee.forge.ForgeConstants;
|
||||
import net.md_5.bungee.log.LoggingOutputStream;
|
||||
@@ -198,13 +199,20 @@ public class BungeeCord extends ProxyServer
|
||||
System.setErr( new PrintStream( new LoggingOutputStream( logger, Level.SEVERE ), true ) );
|
||||
System.setOut( new PrintStream( new LoggingOutputStream( logger, Level.INFO ), true ) );
|
||||
|
||||
if ( NativeCipher.load() )
|
||||
if ( EncryptionUtil.nativeFactory.load() )
|
||||
{
|
||||
logger.info( "Using OpenSSL based native cipher." );
|
||||
} else
|
||||
{
|
||||
logger.info( "Using standard Java JCE cipher. To enable the OpenSSL based native cipher, please make sure you are using 64 bit Ubuntu or Debian with libssl installed." );
|
||||
}
|
||||
if ( CompressFactory.zlib.load() )
|
||||
{
|
||||
logger.info( "Using native code compressor" );
|
||||
} else
|
||||
{
|
||||
logger.info( "Using standard Java compressor. To enable zero copy compression, run on 64 bit Linux" );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -14,6 +14,10 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import lombok.Getter;
|
||||
import net.md_5.bungee.jni.NativeCode;
|
||||
import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
import net.md_5.bungee.jni.cipher.JavaCipher;
|
||||
import net.md_5.bungee.jni.cipher.NativeCipher;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionResponse;
|
||||
import net.md_5.bungee.protocol.packet.EncryptionRequest;
|
||||
|
||||
@@ -27,6 +31,7 @@ public class EncryptionUtil
|
||||
public static final KeyPair keys;
|
||||
@Getter
|
||||
private static final SecretKey secret = new SecretKeySpec( new byte[ 16 ], "AES" );
|
||||
public static final NativeCode<BungeeCipher> nativeFactory = new NativeCode( "native-cipher", JavaCipher.class, NativeCipher.class );
|
||||
|
||||
static
|
||||
{
|
||||
@@ -65,14 +70,7 @@ public class EncryptionUtil
|
||||
|
||||
public static BungeeCipher getCipher(boolean forEncryption, SecretKey shared) throws GeneralSecurityException
|
||||
{
|
||||
BungeeCipher cipher;
|
||||
if ( NativeCipher.isLoaded() )
|
||||
{
|
||||
cipher = new NativeCipher();
|
||||
} else
|
||||
{
|
||||
cipher = new FallbackCipher();
|
||||
}
|
||||
BungeeCipher cipher = nativeFactory.newInstance();
|
||||
|
||||
cipher.init( forEncryption, shared );
|
||||
return cipher;
|
||||
|
@@ -0,0 +1,12 @@
|
||||
package net.md_5.bungee.compress;
|
||||
|
||||
import net.md_5.bungee.jni.NativeCode;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.jni.zlib.JavaZlib;
|
||||
import net.md_5.bungee.jni.zlib.NativeZlib;
|
||||
|
||||
public class CompressFactory
|
||||
{
|
||||
|
||||
public static final NativeCode<BungeeZlib> zlib = new NativeCode( "native-compress", JavaZlib.class, NativeZlib.class );
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
package net.md_5.bungee.compress;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import java.util.zip.Deflater;
|
||||
import lombok.Setter;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
|
||||
public class PacketCompressor extends MessageToByteEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
private final BungeeZlib zlib = CompressFactory.zlib.newInstance();
|
||||
@Setter
|
||||
private int threshold = 256;
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.init( true, Deflater.DEFAULT_COMPRESSION );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception
|
||||
{
|
||||
int origSize = msg.readableBytes();
|
||||
if ( origSize < threshold )
|
||||
{
|
||||
DefinedPacket.writeVarInt( 0, out );
|
||||
out.writeBytes( msg );
|
||||
} else
|
||||
{
|
||||
DefinedPacket.writeVarInt( origSize, out );
|
||||
|
||||
zlib.process( msg, out );
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,47 @@
|
||||
package net.md_5.bungee.compress;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
import java.util.List;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
|
||||
public class PacketDecompressor extends ByteToMessageDecoder
|
||||
{
|
||||
|
||||
private final BungeeZlib zlib = CompressFactory.zlib.newInstance();
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.init( false, 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception
|
||||
{
|
||||
zlib.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception
|
||||
{
|
||||
if ( in.readableBytes() == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int size = DefinedPacket.readVarInt( in );
|
||||
if ( size == 0 )
|
||||
{
|
||||
out.add( in.readBytes( in.readableBytes() ) );
|
||||
} else
|
||||
{
|
||||
ByteBuf decompressed = ctx.alloc().directBuffer();
|
||||
zlib.process( in, decompressed );
|
||||
|
||||
out.add( decompressed );
|
||||
}
|
||||
}
|
||||
}
|
@@ -48,6 +48,7 @@ import net.md_5.bungee.protocol.packet.Kick;
|
||||
import net.md_5.bungee.api.AbstractReconnectHandler;
|
||||
import net.md_5.bungee.api.event.PlayerHandshakeEvent;
|
||||
import net.md_5.bungee.api.event.PreLoginEvent;
|
||||
import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.ProtocolConstants;
|
||||
import net.md_5.bungee.protocol.packet.LegacyHandshake;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
package net.md_5.bungee.netty;
|
||||
|
||||
import net.md_5.bungee.protocol.PacketCompressor;
|
||||
import net.md_5.bungee.protocol.PacketDecompressor;
|
||||
import net.md_5.bungee.compress.PacketCompressor;
|
||||
import net.md_5.bungee.compress.PacketDecompressor;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.netty.channel.Channel;
|
||||
|
@@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.BungeeCipher;
|
||||
import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
import java.util.List;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
|
@@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.BungeeCipher;
|
||||
import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class CipherEncoder extends MessageToByteEncoder<ByteBuf>
|
||||
|
Reference in New Issue
Block a user