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.util.collection.CharObjectHashMap;
19
20 import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_LIST_SIZE;
21 import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_MAX_CONCURRENT_STREAMS;
22 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_CONCURRENT_STREAMS;
23 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_LOWER_BOUND;
24 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_FRAME_SIZE_UPPER_BOUND;
25 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_HEADER_LIST_SIZE;
26 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_HEADER_TABLE_SIZE;
27 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_INITIAL_WINDOW_SIZE;
28 import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_UNSIGNED_INT;
29 import static io.netty.handler.codec.http2.Http2CodecUtil.MIN_CONCURRENT_STREAMS;
30 import static io.netty.handler.codec.http2.Http2CodecUtil.MIN_HEADER_LIST_SIZE;
31 import static io.netty.handler.codec.http2.Http2CodecUtil.MIN_HEADER_TABLE_SIZE;
32 import static io.netty.handler.codec.http2.Http2CodecUtil.MIN_INITIAL_WINDOW_SIZE;
33 import static io.netty.handler.codec.http2.Http2CodecUtil.NUM_STANDARD_SETTINGS;
34 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_ENABLE_CONNECT_PROTOCOL;
35 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_ENABLE_PUSH;
36 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_HEADER_TABLE_SIZE;
37 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_INITIAL_WINDOW_SIZE;
38 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_MAX_CONCURRENT_STREAMS;
39 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_MAX_FRAME_SIZE;
40 import static io.netty.handler.codec.http2.Http2CodecUtil.SETTINGS_MAX_HEADER_LIST_SIZE;
41 import static io.netty.handler.codec.http2.Http2CodecUtil.isMaxFrameSizeValid;
42 import static io.netty.util.internal.ObjectUtil.checkNotNull;
43 import static java.lang.Integer.toHexString;
44
45
46
47
48
49
50 public final class Http2Settings extends CharObjectHashMap<Long> {
51
52
53
54
55 private static final int DEFAULT_CAPACITY = (int) (NUM_STANDARD_SETTINGS / DEFAULT_LOAD_FACTOR) + 1;
56 private static final Long FALSE = 0L;
57 private static final Long TRUE = 1L;
58
59 public Http2Settings() {
60 this(DEFAULT_CAPACITY);
61 }
62
63 public Http2Settings(int initialCapacity, float loadFactor) {
64 super(initialCapacity, loadFactor);
65 }
66
67 public Http2Settings(int initialCapacity) {
68 super(initialCapacity);
69 }
70
71
72
73
74
75
76
77 @Override
78 public Long put(char key, Long value) {
79 verifyStandardSetting(key, value);
80 return super.put(key, value);
81 }
82
83
84
85
86 public Long headerTableSize() {
87 return get(SETTINGS_HEADER_TABLE_SIZE);
88 }
89
90
91
92
93
94
95 public Http2Settings headerTableSize(long value) {
96 put(SETTINGS_HEADER_TABLE_SIZE, Long.valueOf(value));
97 return this;
98 }
99
100
101
102
103 public Boolean pushEnabled() {
104 Long value = get(SETTINGS_ENABLE_PUSH);
105 if (value == null) {
106 return null;
107 }
108 return TRUE.equals(value);
109 }
110
111
112
113
114 public Http2Settings pushEnabled(boolean enabled) {
115 put(SETTINGS_ENABLE_PUSH, enabled ? TRUE : FALSE);
116 return this;
117 }
118
119
120
121
122 public Long maxConcurrentStreams() {
123 return get(SETTINGS_MAX_CONCURRENT_STREAMS);
124 }
125
126
127
128
129
130
131 public Http2Settings maxConcurrentStreams(long value) {
132 put(SETTINGS_MAX_CONCURRENT_STREAMS, Long.valueOf(value));
133 return this;
134 }
135
136
137
138
139 public Integer initialWindowSize() {
140 return getIntValue(SETTINGS_INITIAL_WINDOW_SIZE);
141 }
142
143
144
145
146
147
148 public Http2Settings initialWindowSize(int value) {
149 put(SETTINGS_INITIAL_WINDOW_SIZE, Long.valueOf(value));
150 return this;
151 }
152
153
154
155
156 public Integer maxFrameSize() {
157 return getIntValue(SETTINGS_MAX_FRAME_SIZE);
158 }
159
160
161
162
163
164
165 public Http2Settings maxFrameSize(int value) {
166 put(SETTINGS_MAX_FRAME_SIZE, Long.valueOf(value));
167 return this;
168 }
169
170
171
172
173 public Long maxHeaderListSize() {
174 return get(SETTINGS_MAX_HEADER_LIST_SIZE);
175 }
176
177
178
179
180
181
182 public Http2Settings maxHeaderListSize(long value) {
183 put(SETTINGS_MAX_HEADER_LIST_SIZE, Long.valueOf(value));
184 return this;
185 }
186
187
188
189
190 public Boolean connectProtocolEnabled() {
191 Long value = get(SETTINGS_ENABLE_CONNECT_PROTOCOL);
192 if (value == null) {
193 return null;
194 }
195 return TRUE.equals(value);
196 }
197
198
199
200
201 public Http2Settings connectProtocolEnabled(boolean enabled) {
202 put(SETTINGS_ENABLE_CONNECT_PROTOCOL, enabled ? TRUE : FALSE);
203 return this;
204 }
205
206
207
208
209 public Http2Settings copyFrom(Http2Settings settings) {
210 clear();
211 putAll(settings);
212 return this;
213 }
214
215
216
217
218
219
220 public Integer getIntValue(char key) {
221 Long value = get(key);
222 if (value == null) {
223 return null;
224 }
225 return value.intValue();
226 }
227
228 private static void verifyStandardSetting(int key, Long value) {
229 checkNotNull(value, "value");
230 switch (key) {
231 case SETTINGS_HEADER_TABLE_SIZE:
232 if (value < MIN_HEADER_TABLE_SIZE || value > MAX_HEADER_TABLE_SIZE) {
233 throw new IllegalArgumentException("Setting HEADER_TABLE_SIZE is invalid: " + value +
234 ", expected [" + MIN_HEADER_TABLE_SIZE + ", " + MAX_HEADER_TABLE_SIZE + ']');
235 }
236 break;
237 case SETTINGS_ENABLE_PUSH:
238 if (value != 0L && value != 1L) {
239 throw new IllegalArgumentException("Setting ENABLE_PUSH is invalid: " + value +
240 ", expected [0, 1]");
241 }
242 break;
243 case SETTINGS_MAX_CONCURRENT_STREAMS:
244 if (value < MIN_CONCURRENT_STREAMS || value > MAX_CONCURRENT_STREAMS) {
245 throw new IllegalArgumentException("Setting MAX_CONCURRENT_STREAMS is invalid: " + value +
246 ", expected [" + MIN_CONCURRENT_STREAMS + ", " + MAX_CONCURRENT_STREAMS + ']');
247 }
248 break;
249 case SETTINGS_INITIAL_WINDOW_SIZE:
250 if (value < MIN_INITIAL_WINDOW_SIZE || value > MAX_INITIAL_WINDOW_SIZE) {
251 throw new IllegalArgumentException("Setting INITIAL_WINDOW_SIZE is invalid: " + value +
252 ", expected [" + MIN_INITIAL_WINDOW_SIZE + ", " + MAX_INITIAL_WINDOW_SIZE + ']');
253 }
254 break;
255 case SETTINGS_MAX_FRAME_SIZE:
256 if (!isMaxFrameSizeValid(value.intValue())) {
257 throw new IllegalArgumentException("Setting MAX_FRAME_SIZE is invalid: " + value +
258 ", expected [" + MAX_FRAME_SIZE_LOWER_BOUND + ", " + MAX_FRAME_SIZE_UPPER_BOUND + ']');
259 }
260 break;
261 case SETTINGS_MAX_HEADER_LIST_SIZE:
262 if (value < MIN_HEADER_LIST_SIZE || value > MAX_HEADER_LIST_SIZE) {
263 throw new IllegalArgumentException("Setting MAX_HEADER_LIST_SIZE is invalid: " + value +
264 ", expected [" + MIN_HEADER_LIST_SIZE + ", " + MAX_HEADER_LIST_SIZE + ']');
265 }
266 break;
267 case SETTINGS_ENABLE_CONNECT_PROTOCOL:
268 if (value != 0L && value != 1L) {
269 throw new IllegalArgumentException("Setting ENABLE_CONNECT_PROTOCOL is invalid: " + value +
270 ", expected [0, 1]");
271 }
272 break;
273 default:
274
275 if (value < 0 || value > MAX_UNSIGNED_INT) {
276 throw new IllegalArgumentException("Non-standard setting 0x" + toHexString(key) + " is invalid: " +
277 value + ", expected unsigned 32-bit value");
278 }
279 break;
280 }
281 }
282
283 @Override
284 protected String keyToString(char key) {
285 switch (key) {
286 case SETTINGS_HEADER_TABLE_SIZE:
287 return "HEADER_TABLE_SIZE";
288 case SETTINGS_ENABLE_PUSH:
289 return "ENABLE_PUSH";
290 case SETTINGS_MAX_CONCURRENT_STREAMS:
291 return "MAX_CONCURRENT_STREAMS";
292 case SETTINGS_INITIAL_WINDOW_SIZE:
293 return "INITIAL_WINDOW_SIZE";
294 case SETTINGS_MAX_FRAME_SIZE:
295 return "MAX_FRAME_SIZE";
296 case SETTINGS_MAX_HEADER_LIST_SIZE:
297 return "MAX_HEADER_LIST_SIZE";
298 case SETTINGS_ENABLE_CONNECT_PROTOCOL:
299 return "ENABLE_CONNECT_PROTOCOL";
300 default:
301
302 return "0x" + toHexString(key);
303 }
304 }
305
306 public static Http2Settings defaultSettings() {
307 return new Http2Settings().maxHeaderListSize(DEFAULT_HEADER_LIST_SIZE)
308 .maxConcurrentStreams(DEFAULT_MAX_CONCURRENT_STREAMS);
309 }
310 }