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