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