View Javadoc

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