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.frames.RstStreamFrame;
22
23 public class RstStreamBodyParser extends ControlFrameBodyParser
24 {
25 private final ControlFrameParser controlFrameParser;
26 private State state = State.STREAM_ID;
27 private int cursor;
28 private int streamId;
29 private int statusCode;
30
31 public RstStreamBodyParser(ControlFrameParser controlFrameParser)
32 {
33 this.controlFrameParser = controlFrameParser;
34 }
35
36 @Override
37 public boolean parse(ByteBuffer buffer)
38 {
39 while (buffer.hasRemaining())
40 {
41 switch (state)
42 {
43 case STREAM_ID:
44 {
45 if (buffer.remaining() >= 4)
46 {
47 streamId = buffer.getInt() & 0x7F_FF_FF_FF;
48 state = State.STATUS_CODE;
49 }
50 else
51 {
52 state = State.STREAM_ID_BYTES;
53 cursor = 4;
54 }
55 break;
56 }
57 case STREAM_ID_BYTES:
58 {
59 byte currByte = buffer.get();
60 --cursor;
61 streamId += (currByte & 0xFF) << 8 * cursor;
62 if (cursor == 0)
63 {
64 streamId &= 0x7F_FF_FF_FF;
65 state = State.STATUS_CODE;
66 }
67 break;
68 }
69 case STATUS_CODE:
70 {
71 if (buffer.remaining() >= 4)
72 {
73 statusCode = buffer.getInt();
74 onRstStream();
75 return true;
76 }
77 else
78 {
79 state = State.STATUS_CODE_BYTES;
80 cursor = 4;
81 }
82 break;
83 }
84 case STATUS_CODE_BYTES:
85 {
86 byte currByte = buffer.get();
87 --cursor;
88 statusCode += (currByte & 0xFF) << 8 * cursor;
89 if (cursor == 0)
90 {
91 onRstStream();
92 return true;
93 }
94 break;
95 }
96 default:
97 {
98 throw new IllegalStateException();
99 }
100 }
101 }
102 return false;
103 }
104
105 private void onRstStream()
106 {
107 // TODO: check that statusCode is not 0
108 RstStreamFrame frame = new RstStreamFrame(controlFrameParser.getVersion(), streamId, statusCode);
109 controlFrameParser.onControlFrame(frame);
110 reset();
111 }
112
113 private void reset()
114 {
115 state = State.STREAM_ID;
116 cursor = 0;
117 streamId = 0;
118 statusCode = 0;
119 }
120
121 private enum State
122 {
123 STREAM_ID, STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
124 }
125 }