View Javadoc

1   //========================================================================
2   //Copyright 2011-2012 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //All rights reserved. This program and the accompanying materials
5   //are made available under the terms of the Eclipse Public License v1.0
6   //and Apache License v2.0 which accompanies this distribution.
7   //The Eclipse Public License is available at
8   //http://www.eclipse.org/legal/epl-v10.html
9   //The Apache License v2.0 is available at
10  //http://www.opensource.org/licenses/apache2.0.php
11  //You may elect to redistribute this code under either of these licenses.
12  //========================================================================
13  
14  package org.eclipse.jetty.spdy.parser;
15  
16  import java.nio.ByteBuffer;
17  
18  import org.eclipse.jetty.spdy.frames.RstStreamFrame;
19  
20  public class RstStreamBodyParser extends ControlFrameBodyParser
21  {
22      private final ControlFrameParser controlFrameParser;
23      private State state = State.STREAM_ID;
24      private int cursor;
25      private int streamId;
26      private int statusCode;
27  
28      public RstStreamBodyParser(ControlFrameParser controlFrameParser)
29      {
30          this.controlFrameParser = controlFrameParser;
31      }
32  
33      @Override
34      public boolean parse(ByteBuffer buffer)
35      {
36          while (buffer.hasRemaining())
37          {
38              switch (state)
39              {
40                  case STREAM_ID:
41                  {
42                      if (buffer.remaining() >= 4)
43                      {
44                          streamId = buffer.getInt() & 0x7F_FF_FF_FF;
45                          state = State.STATUS_CODE;
46                      }
47                      else
48                      {
49                          state = State.STREAM_ID_BYTES;
50                          cursor = 4;
51                      }
52                      break;
53                  }
54                  case STREAM_ID_BYTES:
55                  {
56                      byte currByte = buffer.get();
57                      --cursor;
58                      streamId += (currByte & 0xFF) << 8 * cursor;
59                      if (cursor == 0)
60                      {
61                          streamId &= 0x7F_FF_FF_FF;
62                          state = State.STATUS_CODE;
63                      }
64                      break;
65                  }
66                  case STATUS_CODE:
67                  {
68                      if (buffer.remaining() >= 4)
69                      {
70                          statusCode = buffer.getInt();
71                          onRstStream();
72                          return true;
73                      }
74                      else
75                      {
76                          state = State.STATUS_CODE_BYTES;
77                          cursor = 4;
78                      }
79                      break;
80                  }
81                  case STATUS_CODE_BYTES:
82                  {
83                      byte currByte = buffer.get();
84                      --cursor;
85                      statusCode += (currByte & 0xFF) << 8 * cursor;
86                      if (cursor == 0)
87                      {
88                          onRstStream();
89                          return true;
90                      }
91                      break;
92                  }
93                  default:
94                  {
95                      throw new IllegalStateException();
96                  }
97              }
98          }
99          return false;
100     }
101 
102     private void onRstStream()
103     {
104         // TODO: check that statusCode is not 0
105         RstStreamFrame frame = new RstStreamFrame(controlFrameParser.getVersion(), streamId, statusCode);
106         controlFrameParser.onControlFrame(frame);
107         reset();
108     }
109 
110     private void reset()
111     {
112         state = State.STREAM_ID;
113         cursor = 0;
114         streamId = 0;
115         statusCode = 0;
116     }
117 
118     private enum State
119     {
120         STREAM_ID, STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
121     }
122 }