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 import io.netty.util.internal.UnstableApi;
20
21 import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_HEADER_LIST_SIZE;
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_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 @UnstableApi
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 Http2Settings copyFrom(Http2Settings settings) {
191 clear();
192 putAll(settings);
193 return this;
194 }
195
196
197
198
199
200
201 public Integer getIntValue(char key) {
202 Long value = get(key);
203 if (value == null) {
204 return null;
205 }
206 return value.intValue();
207 }
208
209 private static void verifyStandardSetting(int key, Long value) {
210 checkNotNull(value, "value");
211 switch (key) {
212 case SETTINGS_HEADER_TABLE_SIZE:
213 if (value < MIN_HEADER_TABLE_SIZE || value > MAX_HEADER_TABLE_SIZE) {
214 throw new IllegalArgumentException("Setting HEADER_TABLE_SIZE is invalid: " + value +
215 ", expected [" + MIN_HEADER_TABLE_SIZE + ", " + MAX_HEADER_TABLE_SIZE + ']');
216 }
217 break;
218 case SETTINGS_ENABLE_PUSH:
219 if (value != 0L && value != 1L) {
220 throw new IllegalArgumentException("Setting ENABLE_PUSH is invalid: " + value +
221 ", expected [0, 1]");
222 }
223 break;
224 case SETTINGS_MAX_CONCURRENT_STREAMS:
225 if (value < MIN_CONCURRENT_STREAMS || value > MAX_CONCURRENT_STREAMS) {
226 throw new IllegalArgumentException("Setting MAX_CONCURRENT_STREAMS is invalid: " + value +
227 ", expected [" + MIN_CONCURRENT_STREAMS + ", " + MAX_CONCURRENT_STREAMS + ']');
228 }
229 break;
230 case SETTINGS_INITIAL_WINDOW_SIZE:
231 if (value < MIN_INITIAL_WINDOW_SIZE || value > MAX_INITIAL_WINDOW_SIZE) {
232 throw new IllegalArgumentException("Setting INITIAL_WINDOW_SIZE is invalid: " + value +
233 ", expected [" + MIN_INITIAL_WINDOW_SIZE + ", " + MAX_INITIAL_WINDOW_SIZE + ']');
234 }
235 break;
236 case SETTINGS_MAX_FRAME_SIZE:
237 if (!isMaxFrameSizeValid(value.intValue())) {
238 throw new IllegalArgumentException("Setting MAX_FRAME_SIZE is invalid: " + value +
239 ", expected [" + MAX_FRAME_SIZE_LOWER_BOUND + ", " + MAX_FRAME_SIZE_UPPER_BOUND + ']');
240 }
241 break;
242 case SETTINGS_MAX_HEADER_LIST_SIZE:
243 if (value < MIN_HEADER_LIST_SIZE || value > MAX_HEADER_LIST_SIZE) {
244 throw new IllegalArgumentException("Setting MAX_HEADER_LIST_SIZE is invalid: " + value +
245 ", expected [" + MIN_HEADER_LIST_SIZE + ", " + MAX_HEADER_LIST_SIZE + ']');
246 }
247 break;
248 default:
249
250 if (value < 0 || value > MAX_UNSIGNED_INT) {
251 throw new IllegalArgumentException("Non-standard setting 0x" + toHexString(key) + " is invalid: " +
252 value + ", expected unsigned 32-bit value");
253 }
254 break;
255 }
256 }
257
258 @Override
259 protected String keyToString(char key) {
260 switch (key) {
261 case SETTINGS_HEADER_TABLE_SIZE:
262 return "HEADER_TABLE_SIZE";
263 case SETTINGS_ENABLE_PUSH:
264 return "ENABLE_PUSH";
265 case SETTINGS_MAX_CONCURRENT_STREAMS:
266 return "MAX_CONCURRENT_STREAMS";
267 case SETTINGS_INITIAL_WINDOW_SIZE:
268 return "INITIAL_WINDOW_SIZE";
269 case SETTINGS_MAX_FRAME_SIZE:
270 return "MAX_FRAME_SIZE";
271 case SETTINGS_MAX_HEADER_LIST_SIZE:
272 return "MAX_HEADER_LIST_SIZE";
273 default:
274
275 return "0x" + toHexString(key);
276 }
277 }
278
279 public static Http2Settings defaultSettings() {
280 return new Http2Settings().maxHeaderListSize(DEFAULT_HEADER_LIST_SIZE);
281 }
282 }