ClearTextHttp2ServerUpgradeHandler can be merged with inner PriorKnowledgeHandler (#10008)

Motivation:

ClearTextHttp2ServerUpgradeHandler is currently more complex then needed. We can simplify it by directly implement the prior-knowledge logic as part of the handler.

Modifications:

Merge inner PriorKnowledgeHandler logic into ClearTextHttp2ServerUpgradeHandler by extending ByteToMessageDecoder directly

Result:

Cleaner code and less pipeline operations
This commit is contained in:
Norman Maurer 2020-02-08 08:49:55 +01:00 committed by GitHub
parent 2a5118f824
commit e7f291629b

View File

@ -18,7 +18,6 @@ package io.netty.handler.codec.http2;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil; import io.netty.buffer.ByteBufUtil;
import io.netty.channel.ChannelHandler; import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder; import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.codec.http.HttpServerCodec;
@ -39,7 +38,7 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
* prior knowledge or not. * prior knowledge or not.
*/ */
@UnstableApi @UnstableApi
public final class CleartextHttp2ServerUpgradeHandler extends ChannelHandlerAdapter { public final class CleartextHttp2ServerUpgradeHandler extends ByteToMessageDecoder {
private static final ByteBuf CONNECTION_PREFACE = unreleasableBuffer(connectionPrefaceBuf()); private static final ByteBuf CONNECTION_PREFACE = unreleasableBuffer(connectionPrefaceBuf());
private final HttpServerCodec httpServerCodec; private final HttpServerCodec httpServerCodec;
@ -66,36 +65,33 @@ public final class CleartextHttp2ServerUpgradeHandler extends ChannelHandlerAdap
@Override @Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception { public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
ctx.pipeline() ctx.pipeline()
.addBefore(ctx.name(), null, new PriorKnowledgeHandler()) .addAfter(ctx.name(), null, httpServerUpgradeHandler)
.addBefore(ctx.name(), null, httpServerCodec) .addAfter(ctx.name(), null, httpServerCodec);
.replace(this, null, httpServerUpgradeHandler);
} }
/** /**
* Peek inbound message to determine current connection wants to start HTTP/2 * Peek inbound message to determine current connection wants to start HTTP/2
* by HTTP upgrade or prior knowledge * by HTTP upgrade or prior knowledge
*/ */
private final class PriorKnowledgeHandler extends ByteToMessageDecoder { @Override
@Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { int prefaceLength = CONNECTION_PREFACE.readableBytes();
int prefaceLength = CONNECTION_PREFACE.readableBytes(); int bytesRead = Math.min(in.readableBytes(), prefaceLength);
int bytesRead = Math.min(in.readableBytes(), prefaceLength);
if (!ByteBufUtil.equals(CONNECTION_PREFACE, CONNECTION_PREFACE.readerIndex(), if (!ByteBufUtil.equals(CONNECTION_PREFACE, CONNECTION_PREFACE.readerIndex(),
in, in.readerIndex(), bytesRead)) { in, in.readerIndex(), bytesRead)) {
ctx.pipeline().remove(this); ctx.pipeline().remove(this);
} else if (bytesRead == prefaceLength) { } else if (bytesRead == prefaceLength) {
// Full h2 preface match, removed source codec, using http2 codec to handle // Full h2 preface match, removed source codec, using http2 codec to handle
// following network traffic // following network traffic
ctx.pipeline() ctx.pipeline()
.remove(httpServerCodec) .remove(httpServerCodec)
.remove(httpServerUpgradeHandler); .remove(httpServerUpgradeHandler);
ctx.pipeline().addAfter(ctx.name(), null, http2ServerHandler); ctx.pipeline().addAfter(ctx.name(), null, http2ServerHandler);
ctx.pipeline().remove(this); ctx.pipeline().remove(this);
ctx.fireUserEventTriggered(PriorKnowledgeUpgradeEvent.INSTANCE); ctx.fireUserEventTriggered(PriorKnowledgeUpgradeEvent.INSTANCE);
}
} }
} }