1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.spdy;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.Unpooled;
20 import io.netty.util.internal.ObjectUtil;
21
22 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_DATA_FLAG_FIN;
23 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_DATA_FRAME;
24 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_FLAG_FIN;
25 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_FLAG_UNIDIRECTIONAL;
26 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_GOAWAY_FRAME;
27 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADERS_FRAME;
28 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_FLAGS_OFFSET;
29 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_LENGTH_OFFSET;
30 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_SIZE;
31 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_HEADER_TYPE_OFFSET;
32 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_PING_FRAME;
33 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_RST_STREAM_FRAME;
34 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_CLEAR;
35 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_FRAME;
36 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_PERSISTED;
37 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SETTINGS_PERSIST_VALUE;
38 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SYN_REPLY_FRAME;
39 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_SYN_STREAM_FRAME;
40 import static io.netty.handler.codec.spdy.SpdyCodecUtil.SPDY_WINDOW_UPDATE_FRAME;
41 import static io.netty.handler.codec.spdy.SpdyCodecUtil.getSignedInt;
42 import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedInt;
43 import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedMedium;
44 import static io.netty.handler.codec.spdy.SpdyCodecUtil.getUnsignedShort;
45
46
47
48
49 public class SpdyFrameDecoder {
50
51 protected final SpdyFrameDecoderDelegate delegate;
52 protected final int spdyVersion;
53 private final int maxChunkSize;
54
55 private int frameType;
56 private State state;
57
58
59 private byte flags;
60 private int length;
61 private int streamId;
62
63 private int numSettings;
64
65 private enum State {
66 READ_COMMON_HEADER,
67 READ_DATA_FRAME,
68 READ_SYN_STREAM_FRAME,
69 READ_SYN_REPLY_FRAME,
70 READ_RST_STREAM_FRAME,
71 READ_SETTINGS_FRAME,
72 READ_SETTING,
73 READ_PING_FRAME,
74 READ_GOAWAY_FRAME,
75 READ_HEADERS_FRAME,
76 READ_WINDOW_UPDATE_FRAME,
77 READ_UNKNOWN_FRAME,
78 READ_HEADER_BLOCK,
79 DISCARD_FRAME,
80 FRAME_ERROR
81 }
82
83
84
85
86
87 public SpdyFrameDecoder(SpdyVersion spdyVersion, SpdyFrameDecoderDelegate delegate) {
88 this(spdyVersion, delegate, 8192);
89 }
90
91
92
93
94 public SpdyFrameDecoder(SpdyVersion spdyVersion, SpdyFrameDecoderDelegate delegate, int maxChunkSize) {
95 this.spdyVersion = ObjectUtil.checkNotNull(spdyVersion, "spdyVersion").version();
96 this.delegate = ObjectUtil.checkNotNull(delegate, "delegate");
97 this.maxChunkSize = ObjectUtil.checkPositive(maxChunkSize, "maxChunkSize");
98 state = State.READ_COMMON_HEADER;
99 }
100
101 public void decode(ByteBuf buffer) {
102 boolean last;
103 int statusCode;
104
105 while (true) {
106 switch(state) {
107 case READ_COMMON_HEADER:
108 if (buffer.readableBytes() < SPDY_HEADER_SIZE) {
109 return;
110 }
111
112 int frameOffset = buffer.readerIndex();
113 int flagsOffset = frameOffset + SPDY_HEADER_FLAGS_OFFSET;
114 int lengthOffset = frameOffset + SPDY_HEADER_LENGTH_OFFSET;
115 buffer.skipBytes(SPDY_HEADER_SIZE);
116
117 boolean control = (buffer.getByte(frameOffset) & 0x80) != 0;
118
119 int version;
120 if (control) {
121
122 version = getUnsignedShort(buffer, frameOffset) & 0x7FFF;
123 frameType = getUnsignedShort(buffer, frameOffset + SPDY_HEADER_TYPE_OFFSET);
124 streamId = 0;
125 } else {
126
127 version = spdyVersion;
128 frameType = SPDY_DATA_FRAME;
129 streamId = getUnsignedInt(buffer, frameOffset);
130 }
131
132 flags = buffer.getByte(flagsOffset);
133 length = getUnsignedMedium(buffer, lengthOffset);
134
135
136 if (version != spdyVersion) {
137 state = State.FRAME_ERROR;
138 delegate.readFrameError("Invalid SPDY Version");
139 } else if (!isValidFrameHeader(streamId, frameType, flags, length)) {
140 state = State.FRAME_ERROR;
141 delegate.readFrameError("Invalid Frame Error");
142 } else if (isValidUnknownFrameHeader(streamId, frameType, flags, length)) {
143 state = State.READ_UNKNOWN_FRAME;
144 } else {
145 state = getNextState(frameType, length);
146 }
147 break;
148
149 case READ_DATA_FRAME:
150 if (length == 0) {
151 state = State.READ_COMMON_HEADER;
152 delegate.readDataFrame(streamId, hasFlag(flags, SPDY_DATA_FLAG_FIN), Unpooled.buffer(0));
153 break;
154 }
155
156
157 int dataLength = Math.min(maxChunkSize, length);
158
159
160 if (buffer.readableBytes() < dataLength) {
161 return;
162 }
163
164 ByteBuf data = buffer.readRetainedSlice(dataLength);
165 length -= dataLength;
166
167 if (length == 0) {
168 state = State.READ_COMMON_HEADER;
169 }
170
171 last = length == 0 && hasFlag(flags, SPDY_DATA_FLAG_FIN);
172
173 delegate.readDataFrame(streamId, last, data);
174 break;
175
176 case READ_SYN_STREAM_FRAME:
177 if (buffer.readableBytes() < 10) {
178 return;
179 }
180
181 int offset = buffer.readerIndex();
182 streamId = getUnsignedInt(buffer, offset);
183 int associatedToStreamId = getUnsignedInt(buffer, offset + 4);
184 byte priority = (byte) (buffer.getByte(offset + 8) >> 5 & 0x07);
185 last = hasFlag(flags, SPDY_FLAG_FIN);
186 boolean unidirectional = hasFlag(flags, SPDY_FLAG_UNIDIRECTIONAL);
187 buffer.skipBytes(10);
188 length -= 10;
189
190 if (streamId == 0) {
191 state = State.FRAME_ERROR;
192 delegate.readFrameError("Invalid SYN_STREAM Frame");
193 } else {
194 state = State.READ_HEADER_BLOCK;
195 delegate.readSynStreamFrame(streamId, associatedToStreamId, priority, last, unidirectional);
196 }
197 break;
198
199 case READ_SYN_REPLY_FRAME:
200 if (buffer.readableBytes() < 4) {
201 return;
202 }
203
204 streamId = getUnsignedInt(buffer, buffer.readerIndex());
205 last = hasFlag(flags, SPDY_FLAG_FIN);
206
207 buffer.skipBytes(4);
208 length -= 4;
209
210 if (streamId == 0) {
211 state = State.FRAME_ERROR;
212 delegate.readFrameError("Invalid SYN_REPLY Frame");
213 } else {
214 state = State.READ_HEADER_BLOCK;
215 delegate.readSynReplyFrame(streamId, last);
216 }
217 break;
218
219 case READ_RST_STREAM_FRAME:
220 if (buffer.readableBytes() < 8) {
221 return;
222 }
223
224 streamId = getUnsignedInt(buffer, buffer.readerIndex());
225 statusCode = getSignedInt(buffer, buffer.readerIndex() + 4);
226 buffer.skipBytes(8);
227
228 if (streamId == 0 || statusCode == 0) {
229 state = State.FRAME_ERROR;
230 delegate.readFrameError("Invalid RST_STREAM Frame");
231 } else {
232 state = State.READ_COMMON_HEADER;
233 delegate.readRstStreamFrame(streamId, statusCode);
234 }
235 break;
236
237 case READ_SETTINGS_FRAME:
238 if (buffer.readableBytes() < 4) {
239 return;
240 }
241
242 boolean clear = hasFlag(flags, SPDY_SETTINGS_CLEAR);
243
244 numSettings = getUnsignedInt(buffer, buffer.readerIndex());
245 buffer.skipBytes(4);
246 length -= 4;
247
248
249 if ((length & 0x07) != 0 || length >> 3 != numSettings) {
250 state = State.FRAME_ERROR;
251 delegate.readFrameError("Invalid SETTINGS Frame");
252 } else {
253 state = State.READ_SETTING;
254 delegate.readSettingsFrame(clear);
255 }
256 break;
257
258 case READ_SETTING:
259 if (numSettings == 0) {
260 state = State.READ_COMMON_HEADER;
261 delegate.readSettingsEnd();
262 break;
263 }
264
265 if (buffer.readableBytes() < 8) {
266 return;
267 }
268
269 byte settingsFlags = buffer.getByte(buffer.readerIndex());
270 int id = getUnsignedMedium(buffer, buffer.readerIndex() + 1);
271 int value = getSignedInt(buffer, buffer.readerIndex() + 4);
272 boolean persistValue = hasFlag(settingsFlags, SPDY_SETTINGS_PERSIST_VALUE);
273 boolean persisted = hasFlag(settingsFlags, SPDY_SETTINGS_PERSISTED);
274 buffer.skipBytes(8);
275
276 --numSettings;
277
278 delegate.readSetting(id, value, persistValue, persisted);
279 break;
280
281 case READ_PING_FRAME:
282 if (buffer.readableBytes() < 4) {
283 return;
284 }
285
286 int pingId = getSignedInt(buffer, buffer.readerIndex());
287 buffer.skipBytes(4);
288
289 state = State.READ_COMMON_HEADER;
290 delegate.readPingFrame(pingId);
291 break;
292
293 case READ_GOAWAY_FRAME:
294 if (buffer.readableBytes() < 8) {
295 return;
296 }
297
298 int lastGoodStreamId = getUnsignedInt(buffer, buffer.readerIndex());
299 statusCode = getSignedInt(buffer, buffer.readerIndex() + 4);
300 buffer.skipBytes(8);
301
302 state = State.READ_COMMON_HEADER;
303 delegate.readGoAwayFrame(lastGoodStreamId, statusCode);
304 break;
305
306 case READ_HEADERS_FRAME:
307 if (buffer.readableBytes() < 4) {
308 return;
309 }
310
311 streamId = getUnsignedInt(buffer, buffer.readerIndex());
312 last = hasFlag(flags, SPDY_FLAG_FIN);
313
314 buffer.skipBytes(4);
315 length -= 4;
316
317 if (streamId == 0) {
318 state = State.FRAME_ERROR;
319 delegate.readFrameError("Invalid HEADERS Frame");
320 } else {
321 state = State.READ_HEADER_BLOCK;
322 delegate.readHeadersFrame(streamId, last);
323 }
324 break;
325
326 case READ_WINDOW_UPDATE_FRAME:
327 if (buffer.readableBytes() < 8) {
328 return;
329 }
330
331 streamId = getUnsignedInt(buffer, buffer.readerIndex());
332 int deltaWindowSize = getUnsignedInt(buffer, buffer.readerIndex() + 4);
333 buffer.skipBytes(8);
334
335 if (deltaWindowSize == 0) {
336 state = State.FRAME_ERROR;
337 delegate.readFrameError("Invalid WINDOW_UPDATE Frame");
338 } else {
339 state = State.READ_COMMON_HEADER;
340 delegate.readWindowUpdateFrame(streamId, deltaWindowSize);
341 }
342 break;
343
344 case READ_UNKNOWN_FRAME:
345 if (decodeUnknownFrame(frameType, flags, length, buffer)) {
346 state = State.READ_COMMON_HEADER;
347 break;
348 }
349 return;
350
351 case READ_HEADER_BLOCK:
352 if (length == 0) {
353 state = State.READ_COMMON_HEADER;
354 delegate.readHeaderBlockEnd();
355 break;
356 }
357
358 if (!buffer.isReadable()) {
359 return;
360 }
361
362 int compressedBytes = Math.min(buffer.readableBytes(), length);
363 ByteBuf headerBlock = buffer.readRetainedSlice(compressedBytes);
364 length -= compressedBytes;
365
366 delegate.readHeaderBlock(headerBlock);
367 break;
368
369 case DISCARD_FRAME:
370 int numBytes = Math.min(buffer.readableBytes(), length);
371 buffer.skipBytes(numBytes);
372 length -= numBytes;
373 if (length == 0) {
374 state = State.READ_COMMON_HEADER;
375 break;
376 }
377 return;
378
379 case FRAME_ERROR:
380 buffer.skipBytes(buffer.readableBytes());
381 return;
382
383 default:
384 throw new Error("Shouldn't reach here.");
385 }
386 }
387 }
388
389 private static boolean hasFlag(byte flags, byte flag) {
390 return (flags & flag) != 0;
391 }
392
393 private static State getNextState(int type, int length) {
394 switch (type) {
395 case SPDY_DATA_FRAME:
396 return State.READ_DATA_FRAME;
397
398 case SPDY_SYN_STREAM_FRAME:
399 return State.READ_SYN_STREAM_FRAME;
400
401 case SPDY_SYN_REPLY_FRAME:
402 return State.READ_SYN_REPLY_FRAME;
403
404 case SPDY_RST_STREAM_FRAME:
405 return State.READ_RST_STREAM_FRAME;
406
407 case SPDY_SETTINGS_FRAME:
408 return State.READ_SETTINGS_FRAME;
409
410 case SPDY_PING_FRAME:
411 return State.READ_PING_FRAME;
412
413 case SPDY_GOAWAY_FRAME:
414 return State.READ_GOAWAY_FRAME;
415
416 case SPDY_HEADERS_FRAME:
417 return State.READ_HEADERS_FRAME;
418
419 case SPDY_WINDOW_UPDATE_FRAME:
420 return State.READ_WINDOW_UPDATE_FRAME;
421
422 default:
423
424 if (length != 0) {
425 return State.DISCARD_FRAME;
426 } else {
427 return State.READ_COMMON_HEADER;
428 }
429 }
430 }
431
432
433
434
435 protected boolean decodeUnknownFrame(int frameType, byte flags, int length, ByteBuf buffer) {
436 if (length == 0) {
437 if (delegate instanceof SpdyFrameDecoderExtendedDelegate) {
438 ((SpdyFrameDecoderExtendedDelegate) delegate).readUnknownFrame(frameType, flags, Unpooled.EMPTY_BUFFER);
439 }
440 return true;
441 }
442 if (buffer.readableBytes() < length) {
443 return false;
444 }
445 if (delegate instanceof SpdyFrameDecoderExtendedDelegate) {
446 ByteBuf data = buffer.readRetainedSlice(length);
447 ((SpdyFrameDecoderExtendedDelegate) delegate).readUnknownFrame(frameType, flags, data);
448 } else {
449 buffer.skipBytes(length);
450 }
451 return true;
452 }
453
454
455
456
457
458 protected boolean isValidUnknownFrameHeader(int streamId, int type, byte flags, int length) {
459 return false;
460 }
461
462 private static boolean isValidFrameHeader(int streamId, int type, byte flags, int length) {
463 switch (type) {
464 case SPDY_DATA_FRAME:
465 return streamId != 0;
466
467 case SPDY_SYN_STREAM_FRAME:
468 return length >= 10;
469
470 case SPDY_SYN_REPLY_FRAME:
471 return length >= 4;
472
473 case SPDY_RST_STREAM_FRAME:
474 return flags == 0 && length == 8;
475
476 case SPDY_SETTINGS_FRAME:
477 return length >= 4;
478
479 case SPDY_PING_FRAME:
480 return length == 4;
481
482 case SPDY_GOAWAY_FRAME:
483 return length == 8;
484
485 case SPDY_HEADERS_FRAME:
486 return length >= 4;
487
488 case SPDY_WINDOW_UPDATE_FRAME:
489 return length == 8;
490
491 default:
492 return true;
493 }
494 }
495 }