View Javadoc

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 }