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