1 /*
2 * Copyright (c) 2012 the original author or authors.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.eclipse.jetty.spdy.parser;
18
19 import java.nio.ByteBuffer;
20
21 import org.eclipse.jetty.spdy.api.SPDY;
22 import org.eclipse.jetty.spdy.frames.GoAwayFrame;
23
24 public class GoAwayBodyParser extends ControlFrameBodyParser
25 {
26 private final ControlFrameParser controlFrameParser;
27 private State state = State.LAST_STREAM_ID;
28 private int cursor;
29 private int lastStreamId;
30 private int statusCode;
31
32 public GoAwayBodyParser(ControlFrameParser controlFrameParser)
33 {
34 this.controlFrameParser = controlFrameParser;
35 }
36
37 @Override
38 public boolean parse(ByteBuffer buffer)
39 {
40 while (buffer.hasRemaining())
41 {
42 switch (state)
43 {
44 case LAST_STREAM_ID:
45 {
46 if (buffer.remaining() >= 4)
47 {
48 lastStreamId = buffer.getInt() & 0x7F_FF_FF_FF;
49 switch (controlFrameParser.getVersion())
50 {
51 case SPDY.V2:
52 {
53 onGoAway();
54 return true;
55 }
56 case SPDY.V3:
57 {
58 state = State.STATUS_CODE;
59 break;
60 }
61 default:
62 {
63 throw new IllegalStateException();
64 }
65 }
66 }
67 else
68 {
69 state = State.LAST_STREAM_ID_BYTES;
70 cursor = 4;
71 }
72 break;
73 }
74 case LAST_STREAM_ID_BYTES:
75 {
76 byte currByte = buffer.get();
77 --cursor;
78 lastStreamId += (currByte & 0xFF) << 8 * cursor;
79 if (cursor == 0)
80 {
81 lastStreamId &= 0x7F_FF_FF_FF;
82 switch (controlFrameParser.getVersion())
83 {
84 case SPDY.V2:
85 {
86 onGoAway();
87 return true;
88 }
89 case SPDY.V3:
90 {
91 state = State.STATUS_CODE;
92 break;
93 }
94 default:
95 {
96 throw new IllegalStateException();
97 }
98 }
99 }
100 break;
101 }
102 case STATUS_CODE:
103 {
104 if (buffer.remaining() >= 4)
105 {
106 statusCode = buffer.getInt();
107 onGoAway();
108 return true;
109 }
110 else
111 {
112 state = State.STATUS_CODE_BYTES;
113 cursor = 4;
114 }
115 break;
116 }
117 case STATUS_CODE_BYTES:
118 {
119 byte currByte = buffer.get();
120 --cursor;
121 statusCode += (currByte & 0xFF) << 8 * cursor;
122 if (cursor == 0)
123 {
124 onGoAway();
125 return true;
126 }
127 break;
128 }
129 default:
130 {
131 throw new IllegalStateException();
132 }
133 }
134 }
135 return false;
136 }
137
138 private void onGoAway()
139 {
140 GoAwayFrame frame = new GoAwayFrame(controlFrameParser.getVersion(), lastStreamId, statusCode);
141 controlFrameParser.onControlFrame(frame);
142 reset();
143 }
144
145 private void reset()
146 {
147 state = State.LAST_STREAM_ID;
148 cursor = 0;
149 lastStreamId = 0;
150 statusCode = 0;
151 }
152
153 private enum State
154 {
155 LAST_STREAM_ID, LAST_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
156 }
157 }