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