1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.spdy.parser;
15
16 import java.nio.ByteBuffer;
17
18 import org.eclipse.jetty.spdy.api.SPDY;
19 import org.eclipse.jetty.spdy.frames.GoAwayFrame;
20
21 public class GoAwayBodyParser extends ControlFrameBodyParser
22 {
23 private final ControlFrameParser controlFrameParser;
24 private State state = State.LAST_GOOD_STREAM_ID;
25 private int cursor;
26 private int lastStreamId;
27 private int statusCode;
28
29 public GoAwayBodyParser(ControlFrameParser controlFrameParser)
30 {
31 this.controlFrameParser = controlFrameParser;
32 }
33
34 @Override
35 public boolean parse(ByteBuffer buffer)
36 {
37 while (buffer.hasRemaining())
38 {
39 switch (state)
40 {
41 case LAST_GOOD_STREAM_ID:
42 {
43 if (buffer.remaining() >= 4)
44 {
45 lastStreamId = buffer.getInt() & 0x7F_FF_FF_FF;
46 switch (controlFrameParser.getVersion())
47 {
48 case SPDY.V2:
49 {
50 onGoAway();
51 return true;
52 }
53 case SPDY.V3:
54 {
55 state = State.STATUS_CODE;
56 break;
57 }
58 default:
59 {
60 throw new IllegalStateException();
61 }
62 }
63 }
64 else
65 {
66 state = State.LAST_GOOD_STREAM_ID_BYTES;
67 cursor = 4;
68 }
69 break;
70 }
71 case LAST_GOOD_STREAM_ID_BYTES:
72 {
73 byte currByte = buffer.get();
74 --cursor;
75 lastStreamId += (currByte & 0xFF) << 8 * cursor;
76 if (cursor == 0)
77 {
78 lastStreamId &= 0x7F_FF_FF_FF;
79 switch (controlFrameParser.getVersion())
80 {
81 case SPDY.V2:
82 {
83 onGoAway();
84 return true;
85 }
86 case SPDY.V3:
87 {
88 state = State.STATUS_CODE;
89 break;
90 }
91 default:
92 {
93 throw new IllegalStateException();
94 }
95 }
96 }
97 break;
98 }
99 case STATUS_CODE:
100 {
101 if (buffer.remaining() >= 4)
102 {
103 statusCode = buffer.getInt();
104 onGoAway();
105 return true;
106 }
107 else
108 {
109 state = State.STATUS_CODE_BYTES;
110 cursor = 4;
111 }
112 break;
113 }
114 case STATUS_CODE_BYTES:
115 {
116 byte currByte = buffer.get();
117 --cursor;
118 statusCode += (currByte & 0xFF) << 8 * cursor;
119 if (cursor == 0)
120 {
121 onGoAway();
122 return true;
123 }
124 break;
125 }
126 default:
127 {
128 throw new IllegalStateException();
129 }
130 }
131 }
132 return false;
133 }
134
135 private void onGoAway()
136 {
137 GoAwayFrame frame = new GoAwayFrame(controlFrameParser.getVersion(), lastStreamId, statusCode);
138 controlFrameParser.onControlFrame(frame);
139 reset();
140 }
141
142 private void reset()
143 {
144 state = State.LAST_GOOD_STREAM_ID;
145 cursor = 0;
146 lastStreamId = 0;
147 statusCode = 0;
148 }
149
150 private enum State
151 {
152 LAST_GOOD_STREAM_ID, LAST_GOOD_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
153 }
154 }