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