View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 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.fcgi.parser;
20  
21  import java.nio.ByteBuffer;
22  
23  import org.eclipse.jetty.fcgi.FCGI;
24  
25  /**
26   * <p>Parser for the BEGIN_REQUEST frame body.</p>
27   * <pre>
28   * struct begin_request_body {
29   *     ushort role;
30   *     ubyte flags;
31   *     ubyte[5] reserved;
32   * }
33   * </pre>
34   */
35  public class BeginRequestContentParser extends ContentParser
36  {
37      private final ServerParser.Listener listener;
38      private State state = State.ROLE;
39      private int cursor;
40      private int role;
41      private int flags;
42  
43      public BeginRequestContentParser(HeaderParser headerParser, ServerParser.Listener listener)
44      {
45          super(headerParser);
46          this.listener = listener;
47      }
48  
49      @Override
50      public Result parse(ByteBuffer buffer)
51      {
52          while (buffer.hasRemaining())
53          {
54              switch (state)
55              {
56                  case ROLE:
57                  {
58                      if (buffer.remaining() >= 2)
59                      {
60                          role = buffer.getShort();
61                          state = State.FLAGS;
62                      }
63                      else
64                      {
65                          state = State.ROLE_BYTES;
66                          cursor = 0;
67                      }
68                      break;
69                  }
70                  case ROLE_BYTES:
71                  {
72                      int halfShort = buffer.get() & 0xFF;
73                      role = (role << 8) + halfShort;
74                      if (++cursor == 2)
75                          state = State.FLAGS;
76                      break;
77                  }
78                  case FLAGS:
79                  {
80                      flags = buffer.get() & 0xFF;
81                      state = State.RESERVED;
82                      break;
83                  }
84                  case RESERVED:
85                  {
86                      if (buffer.remaining() >= 5)
87                      {
88                          buffer.position(buffer.position() + 5);
89                          onStart();
90                          reset();
91                          return Result.COMPLETE;
92                      }
93                      else
94                      {
95                          state = State.RESERVED_BYTES;
96                          cursor = 0;
97                          break;
98                      }
99                  }
100                 case RESERVED_BYTES:
101                 {
102                     buffer.get();
103                     if (++cursor == 5)
104                     {
105                         onStart();
106                         reset();
107                         return Result.COMPLETE;
108                     }
109                     break;
110                 }
111                 default:
112                 {
113                     throw new IllegalStateException();
114                 }
115             }
116         }
117         return Result.PENDING;
118     }
119 
120     private void onStart()
121     {
122         listener.onStart(getRequest(), FCGI.Role.from(role), flags);
123     }
124 
125     private void reset()
126     {
127         state = State.ROLE;
128         cursor = 0;
129         role = 0;
130         flags = 0;
131     }
132 
133     private enum State
134     {
135         ROLE, ROLE_BYTES, FLAGS, RESERVED, RESERVED_BYTES
136     }
137 }