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