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