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.api.SPDY;
19  import org.eclipse.jetty.spdy.frames.GoAwayFrame;
20  
21  public class GoAwayBodyParser extends ControlFrameBodyParser
22  {
23      private final ControlFrameParser controlFrameParser;
24      private State state = State.LAST_GOOD_STREAM_ID;
25      private int cursor;
26      private int lastStreamId;
27      private int statusCode;
28  
29      public GoAwayBodyParser(ControlFrameParser controlFrameParser)
30      {
31          this.controlFrameParser = controlFrameParser;
32      }
33  
34      @Override
35      public boolean parse(ByteBuffer buffer)
36      {
37          while (buffer.hasRemaining())
38          {
39              switch (state)
40              {
41                  case LAST_GOOD_STREAM_ID:
42                  {
43                      if (buffer.remaining() >= 4)
44                      {
45                          lastStreamId = buffer.getInt() & 0x7F_FF_FF_FF;
46                          switch (controlFrameParser.getVersion())
47                          {
48                              case SPDY.V2:
49                              {
50                                  onGoAway();
51                                  return true;
52                              }
53                              case SPDY.V3:
54                              {
55                                  state = State.STATUS_CODE;
56                                  break;
57                              }
58                              default:
59                              {
60                                  throw new IllegalStateException();
61                              }
62                          }
63                      }
64                      else
65                      {
66                          state = State.LAST_GOOD_STREAM_ID_BYTES;
67                          cursor = 4;
68                      }
69                      break;
70                  }
71                  case LAST_GOOD_STREAM_ID_BYTES:
72                  {
73                      byte currByte = buffer.get();
74                      --cursor;
75                      lastStreamId += (currByte & 0xFF) << 8 * cursor;
76                      if (cursor == 0)
77                      {
78                          lastStreamId &= 0x7F_FF_FF_FF;
79                          switch (controlFrameParser.getVersion())
80                          {
81                              case SPDY.V2:
82                              {
83                                  onGoAway();
84                                  return true;
85                              }
86                              case SPDY.V3:
87                              {
88                                  state = State.STATUS_CODE;
89                                  break;
90                              }
91                              default:
92                              {
93                                  throw new IllegalStateException();
94                              }
95                          }
96                      }
97                      break;
98                  }
99                  case STATUS_CODE:
100                 {
101                     if (buffer.remaining() >= 4)
102                     {
103                         statusCode = buffer.getInt();
104                         onGoAway();
105                         return true;
106                     }
107                     else
108                     {
109                         state = State.STATUS_CODE_BYTES;
110                         cursor = 4;
111                     }
112                     break;
113                 }
114                 case STATUS_CODE_BYTES:
115                 {
116                     byte currByte = buffer.get();
117                     --cursor;
118                     statusCode += (currByte & 0xFF) << 8 * cursor;
119                     if (cursor == 0)
120                     {
121                         onGoAway();
122                         return true;
123                     }
124                     break;
125                 }
126                 default:
127                 {
128                     throw new IllegalStateException();
129                 }
130             }
131         }
132         return false;
133     }
134 
135     private void onGoAway()
136     {
137         GoAwayFrame frame = new GoAwayFrame(controlFrameParser.getVersion(), lastStreamId, statusCode);
138         controlFrameParser.onControlFrame(frame);
139         reset();
140     }
141 
142     private void reset()
143     {
144         state = State.LAST_GOOD_STREAM_ID;
145         cursor = 0;
146         lastStreamId = 0;
147         statusCode = 0;
148     }
149 
150     private enum State
151     {
152         LAST_GOOD_STREAM_ID, LAST_GOOD_STREAM_ID_BYTES, STATUS_CODE, STATUS_CODE_BYTES
153     }
154 }