1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http2;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufUtil;
20 import io.netty.channel.ChannelHandler;
21 import io.netty.channel.ChannelHandlerContext;
22 import io.netty.handler.codec.ByteToMessageDecoder;
23 import io.netty.handler.codec.http.HttpServerCodec;
24 import io.netty.handler.codec.http.HttpServerUpgradeHandler;
25
26 import java.util.List;
27
28 import static io.netty.buffer.Unpooled.unreleasableBuffer;
29 import static io.netty.handler.codec.http2.Http2CodecUtil.connectionPrefaceBuf;
30
31 import static io.netty.util.internal.ObjectUtil.checkNotNull;
32
33
34
35
36
37
38
39 public final class CleartextHttp2ServerUpgradeHandler extends ByteToMessageDecoder {
40 private static final ByteBuf CONNECTION_PREFACE = unreleasableBuffer(connectionPrefaceBuf()).asReadOnly();
41
42 private final HttpServerCodec httpServerCodec;
43 private final HttpServerUpgradeHandler httpServerUpgradeHandler;
44 private final ChannelHandler http2ServerHandler;
45
46
47
48
49
50
51
52
53
54
55 public CleartextHttp2ServerUpgradeHandler(HttpServerCodec httpServerCodec,
56 HttpServerUpgradeHandler httpServerUpgradeHandler,
57 ChannelHandler http2ServerHandler) {
58 this.httpServerCodec = checkNotNull(httpServerCodec, "httpServerCodec");
59 this.httpServerUpgradeHandler = checkNotNull(httpServerUpgradeHandler, "httpServerUpgradeHandler");
60 this.http2ServerHandler = checkNotNull(http2ServerHandler, "http2ServerHandler");
61 }
62
63 @Override
64 public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
65 ctx.pipeline()
66 .addAfter(ctx.name(), null, httpServerUpgradeHandler)
67 .addAfter(ctx.name(), null, httpServerCodec);
68 }
69
70
71
72
73
74 @Override
75 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
76 int prefaceLength = CONNECTION_PREFACE.readableBytes();
77 int bytesRead = Math.min(in.readableBytes(), prefaceLength);
78
79 if (!ByteBufUtil.equals(CONNECTION_PREFACE, CONNECTION_PREFACE.readerIndex(),
80 in, in.readerIndex(), bytesRead)) {
81 ctx.pipeline().remove(this);
82 } else if (bytesRead == prefaceLength) {
83
84
85 ctx.pipeline()
86 .remove(httpServerCodec)
87 .remove(httpServerUpgradeHandler);
88
89 ctx.pipeline().addAfter(ctx.name(), null, http2ServerHandler);
90 ctx.pipeline().remove(this);
91
92 ctx.fireUserEventTriggered(PriorKnowledgeUpgradeEvent.INSTANCE);
93 }
94 }
95
96
97
98
99 public static final class PriorKnowledgeUpgradeEvent {
100 private static final PriorKnowledgeUpgradeEvent INSTANCE = new PriorKnowledgeUpgradeEvent();
101
102 private PriorKnowledgeUpgradeEvent() {
103 }
104 }
105 }