View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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  public class HeaderParser
26  {
27      private State state = State.VERSION;
28      private int cursor;
29      private int version;
30      private int type;
31      private int request;
32      private int length;
33      private int padding;
34  
35      public boolean parse(ByteBuffer buffer)
36      {
37          while (buffer.hasRemaining())
38          {
39              switch (state)
40              {
41                  case VERSION:
42                  {
43                      version = buffer.get() & 0xFF;
44                      state = State.TYPE;
45                      break;
46                  }
47                  case TYPE:
48                  {
49                      type = buffer.get() & 0xFF;
50                      state = State.REQUEST;
51                      break;
52                  }
53                  case REQUEST:
54                  {
55                      if (buffer.remaining() >= 2)
56                      {
57                          request = buffer.getShort() & 0xFF_FF;
58                          state = State.LENGTH;
59                      }
60                      else
61                      {
62                          state = State.REQUEST_BYTES;
63                          cursor = 0;
64                      }
65                      break;
66                  }
67                  case REQUEST_BYTES:
68                  {
69                      int halfShort = buffer.get() & 0xFF;
70                      request = (request << 8) + halfShort;
71                      if (++cursor == 2)
72                          state = State.LENGTH;
73                      break;
74                  }
75                  case LENGTH:
76                  {
77                      if (buffer.remaining() >= 2)
78                      {
79                          length = buffer.getShort() & 0xFF_FF;
80                          state = State.PADDING;
81                      }
82                      else
83                      {
84                          state = State.LENGTH_BYTES;
85                          cursor = 0;
86                      }
87                      break;
88                  }
89                  case LENGTH_BYTES:
90                  {
91                      int halfShort = buffer.get() & 0xFF;
92                      length = (length << 8) + halfShort;
93                      if (++cursor == 2)
94                          state = State.PADDING;
95                      break;
96                  }
97                  case PADDING:
98                  {
99                      padding = buffer.get() & 0xFF;
100                     state = State.RESERVED;
101                     break;
102                 }
103                 case RESERVED:
104                 {
105                     buffer.get();
106                     return true;
107                 }
108                 default:
109                 {
110                     throw new IllegalStateException();
111                 }
112             }
113         }
114         return false;
115     }
116 
117     public FCGI.FrameType getFrameType()
118     {
119         return FCGI.FrameType.from(type);
120     }
121 
122     public int getRequest()
123     {
124         return request;
125     }
126 
127     public int getContentLength()
128     {
129         return length;
130     }
131 
132     public int getPaddingLength()
133     {
134         return padding;
135     }
136 
137     protected void reset()
138     {
139         state = State.VERSION;
140         cursor = 0;
141         version = 0;
142         type = 0;
143         request = 0;
144         length = 0;
145         padding = 0;
146     }
147 
148     private enum State
149     {
150         VERSION, TYPE, REQUEST, REQUEST_BYTES, LENGTH, LENGTH_BYTES, PADDING, RESERVED
151     }
152 }