1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http3;
17
18 import io.netty.channel.Channel;
19 import io.netty.channel.ChannelHandler;
20 import io.netty.handler.codec.quic.QuicChannel;
21 import io.netty.handler.codec.quic.QuicClientCodecBuilder;
22 import io.netty.handler.codec.quic.QuicCodecBuilder;
23 import io.netty.handler.codec.quic.QuicServerCodecBuilder;
24 import io.netty.handler.codec.quic.QuicStreamChannel;
25 import io.netty.handler.codec.quic.QuicStreamChannelBootstrap;
26 import io.netty.handler.codec.quic.QuicStreamType;
27 import io.netty.util.AttributeKey;
28 import io.netty.util.concurrent.Future;
29 import org.jetbrains.annotations.Nullable;
30
31
32
33
34 public final class Http3 {
35
36 private Http3() { }
37
38 private static final String[] H3_PROTOS = new String[] {
39 "h3-29",
40 "h3-30",
41 "h3-31",
42 "h3-32",
43 "h3"
44 };
45
46 private static final AttributeKey<QuicStreamChannel> HTTP3_CONTROL_STREAM_KEY =
47 AttributeKey.valueOf(Http3.class, "HTTP3ControlStream");
48
49 private static final AttributeKey<QpackAttributes> QPACK_ATTRIBUTES_KEY =
50 AttributeKey.valueOf(Http3.class, "QpackAttributes");
51
52
53
54
55
56
57 @Nullable
58 public static QuicStreamChannel getLocalControlStream(Channel channel) {
59 return channel.attr(HTTP3_CONTROL_STREAM_KEY).get();
60 }
61
62
63
64
65
66
67
68
69
70
71 static long maxPushIdReceived(QuicChannel channel) {
72 final Http3ConnectionHandler connectionHandler = Http3CodecUtils.getConnectionHandlerOrClose(channel);
73 if (connectionHandler == null) {
74 throw new IllegalStateException("Connection handler not found.");
75 }
76 return connectionHandler.localControlStreamHandler.maxPushIdReceived();
77 }
78
79 static void setLocalControlStream(Channel channel, QuicStreamChannel controlStreamChannel) {
80 channel.attr(HTTP3_CONTROL_STREAM_KEY).set(controlStreamChannel);
81 }
82
83 @Nullable
84 static QpackAttributes getQpackAttributes(Channel channel) {
85 return channel.attr(QPACK_ATTRIBUTES_KEY).get();
86 }
87
88 static void setQpackAttributes(Channel channel, QpackAttributes attributes) {
89 channel.attr(QPACK_ATTRIBUTES_KEY).set(attributes);
90 }
91
92
93
94
95
96
97
98
99
100
101
102
103 public static Future<QuicStreamChannel> newRequestStream(QuicChannel channel, ChannelHandler handler) {
104 return channel.createStream(QuicStreamType.BIDIRECTIONAL, requestStreamInitializer(handler));
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118 public static QuicStreamChannelBootstrap newRequestStreamBootstrap(QuicChannel channel, ChannelHandler handler) {
119 return channel.newStreamBootstrap().handler(requestStreamInitializer(handler))
120 .type(QuicStreamType.BIDIRECTIONAL);
121 }
122
123
124
125
126
127
128 public static String[] supportedApplicationProtocols() {
129 return H3_PROTOS.clone();
130 }
131
132
133
134
135
136
137 public static final int MIN_INITIAL_MAX_STREAMS_UNIDIRECTIONAL = 3;
138
139
140
141
142
143 public static final int MIN_INITIAL_MAX_STREAM_DATA_UNIDIRECTIONAL = 1024;
144
145
146
147
148
149
150 public static QuicServerCodecBuilder newQuicServerCodecBuilder() {
151 return configure(new QuicServerCodecBuilder());
152 }
153
154
155
156
157
158
159 public static QuicClientCodecBuilder newQuicClientCodecBuilder() {
160 return configure(new QuicClientCodecBuilder());
161 }
162
163 private static <T extends QuicCodecBuilder<T>> T configure(T builder) {
164 return builder.initialMaxStreamsUnidirectional(MIN_INITIAL_MAX_STREAMS_UNIDIRECTIONAL)
165 .initialMaxStreamDataUnidirectional(MIN_INITIAL_MAX_STREAM_DATA_UNIDIRECTIONAL);
166 }
167
168 private static Http3RequestStreamInitializer requestStreamInitializer(ChannelHandler handler) {
169 if (handler instanceof Http3RequestStreamInitializer) {
170 return (Http3RequestStreamInitializer) handler;
171 }
172 return new Http3RequestStreamInitializer() {
173 @Override
174 protected void initRequestStream(QuicStreamChannel ch) {
175 ch.pipeline().addLast(handler);
176 }
177 };
178 }
179 }