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