#3737: Use composite buffers where possible
This commit is contained in:
@@ -2,18 +2,23 @@ package net.md_5.bungee.compress;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import io.netty.handler.codec.MessageToMessageEncoder;
|
||||
import java.util.List;
|
||||
import java.util.zip.Deflater;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.md_5.bungee.jni.zlib.BungeeZlib;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
|
||||
public class PacketCompressor extends MessageToByteEncoder<ByteBuf>
|
||||
public class PacketCompressor extends MessageToMessageEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Getter
|
||||
private final BungeeZlib zlib = CompressFactory.zlib.newInstance();
|
||||
@Setter
|
||||
private int threshold = 256;
|
||||
@Setter
|
||||
private boolean compose = true;
|
||||
|
||||
@Override
|
||||
public void handlerAdded(ChannelHandlerContext ctx) throws Exception
|
||||
@@ -28,18 +33,25 @@ public class PacketCompressor extends MessageToByteEncoder<ByteBuf>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception
|
||||
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception
|
||||
{
|
||||
int origSize = msg.readableBytes();
|
||||
if ( origSize < threshold )
|
||||
{
|
||||
DefinedPacket.writeVarInt( 0, out );
|
||||
out.writeBytes( msg );
|
||||
if ( compose )
|
||||
{
|
||||
// create a virtual buffer to avoid copying of data
|
||||
out.add( ctx.alloc().compositeDirectBuffer( 2 ).addComponents( true, ctx.alloc().directBuffer( 1 ).writeByte( 0 ), msg.retain() ) );
|
||||
} else
|
||||
{
|
||||
out.add( ctx.alloc().directBuffer( origSize + 1 ).writeByte( 0 ).writeBytes( msg ) );
|
||||
}
|
||||
} else
|
||||
{
|
||||
DefinedPacket.writeVarInt( origSize, out );
|
||||
|
||||
zlib.process( msg, out );
|
||||
ByteBuf buf = ctx.alloc().directBuffer( BungeeZlib.OUTPUT_BUFFER_SIZE );
|
||||
DefinedPacket.writeVarInt( origSize, buf );
|
||||
zlib.process( msg, buf );
|
||||
out.add( buf );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -508,6 +508,8 @@ public class InitialHandler extends PacketHandler implements PendingConnection
|
||||
ch.addBefore( PipelineUtils.FRAME_DECODER, PipelineUtils.DECRYPT_HANDLER, new CipherDecoder( decrypt ) );
|
||||
BungeeCipher encrypt = EncryptionUtil.getCipher( true, sharedKey );
|
||||
ch.addBefore( PipelineUtils.FRAME_PREPENDER, PipelineUtils.ENCRYPT_HANDLER, new CipherEncoder( encrypt ) );
|
||||
// disable use of composite buffers if we use natives
|
||||
ch.updateComposite();
|
||||
|
||||
String encName = URLEncoder.encode( InitialHandler.this.getName(), "UTF-8" );
|
||||
|
||||
|
@@ -7,15 +7,19 @@ import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.compress.PacketCompressor;
|
||||
import net.md_5.bungee.compress.PacketDecompressor;
|
||||
import net.md_5.bungee.netty.cipher.CipherEncoder;
|
||||
import net.md_5.bungee.protocol.DefinedPacket;
|
||||
import net.md_5.bungee.protocol.MinecraftDecoder;
|
||||
import net.md_5.bungee.protocol.MinecraftEncoder;
|
||||
import net.md_5.bungee.protocol.PacketWrapper;
|
||||
import net.md_5.bungee.protocol.Protocol;
|
||||
import net.md_5.bungee.protocol.Varint21LengthFieldPrepender;
|
||||
import net.md_5.bungee.protocol.packet.Kick;
|
||||
|
||||
public class ChannelWrapper
|
||||
@@ -187,5 +191,36 @@ public class ChannelWrapper
|
||||
{
|
||||
ch.pipeline().remove( "decompress" );
|
||||
}
|
||||
// disable use of composite buffers if we use natives
|
||||
updateComposite();
|
||||
}
|
||||
|
||||
/*
|
||||
* Should be called on encryption add and on compressor add or remove
|
||||
*/
|
||||
public void updateComposite()
|
||||
{
|
||||
CipherEncoder cipherEncoder = ch.pipeline().get( CipherEncoder.class );
|
||||
PacketCompressor packetCompressor = ch.pipeline().get( PacketCompressor.class );
|
||||
Varint21LengthFieldPrepender prepender = ch.pipeline().get( Varint21LengthFieldPrepender.class );
|
||||
boolean compressorCompose = cipherEncoder == null || cipherEncoder.getCipher().allowComposite();
|
||||
boolean prependerCompose = compressorCompose && ( packetCompressor == null || packetCompressor.getZlib().allowComposite() );
|
||||
|
||||
if ( prepender != null )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.FINE, "set prepender compose to {0} for {1}", new Object[]
|
||||
{
|
||||
prependerCompose, ch
|
||||
} );
|
||||
prepender.setCompose( prependerCompose );
|
||||
}
|
||||
if ( packetCompressor != null )
|
||||
{
|
||||
ProxyServer.getInstance().getLogger().log( Level.FINE, "set packetCompressor compose to {0} for {1}", new Object[]
|
||||
{
|
||||
compressorCompose, ch
|
||||
} );
|
||||
packetCompressor.setCompose( compressorCompose );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -93,7 +93,6 @@ public class PipelineUtils
|
||||
public static final Base BASE = new Base( false );
|
||||
public static final Base BASE_SERVERSIDE = new Base( true );
|
||||
private static final KickStringWriter legacyKicker = new KickStringWriter();
|
||||
private static final Varint21LengthFieldPrepender framePrepender = new Varint21LengthFieldPrepender();
|
||||
private static final Varint21LengthFieldExtraBufPrepender serverFramePrepender = new Varint21LengthFieldExtraBufPrepender();
|
||||
public static final String TIMEOUT_HANDLER = "timeout";
|
||||
public static final String PACKET_DECODER = "packet-decoder";
|
||||
@@ -202,7 +201,7 @@ public class PipelineUtils
|
||||
ch.pipeline().addLast( TIMEOUT_HANDLER, new ReadTimeoutHandler( BungeeCord.getInstance().config.getTimeout(), TimeUnit.MILLISECONDS ) );
|
||||
// No encryption bungee -> server, therefore use extra buffer to avoid copying everything for length prepending
|
||||
// Not used bungee -> client as header would need to be encrypted separately through expensive JNI call
|
||||
ch.pipeline().addLast( FRAME_PREPENDER, ( toServer ) ? serverFramePrepender : framePrepender );
|
||||
ch.pipeline().addLast( FRAME_PREPENDER, ( toServer ) ? serverFramePrepender : new Varint21LengthFieldPrepender() );
|
||||
|
||||
ch.pipeline().addLast( BOSS_HANDLER, new HandlerBoss() );
|
||||
}
|
||||
|
@@ -3,6 +3,7 @@ package net.md_5.bungee.netty.cipher;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
|
||||
@@ -10,6 +11,7 @@ import net.md_5.bungee.jni.cipher.BungeeCipher;
|
||||
public class CipherEncoder extends MessageToByteEncoder<ByteBuf>
|
||||
{
|
||||
|
||||
@Getter
|
||||
private final BungeeCipher cipher;
|
||||
|
||||
@Override
|
||||
|
Reference in New Issue
Block a user