View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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  public class EndRequestContentParser extends ContentParser
24  {
25      private final Parser.Listener listener;
26      private State state = State.APPLICATION;
27      private int cursor;
28      private int application;
29      private int protocol;
30  
31      public EndRequestContentParser(HeaderParser headerParser, Parser.Listener listener)
32      {
33          super(headerParser);
34          this.listener = listener;
35      }
36  
37      @Override
38      public Result parse(ByteBuffer buffer)
39      {
40          while (buffer.hasRemaining())
41          {
42              switch (state)
43              {
44                  case APPLICATION:
45                  {
46                      if (buffer.remaining() >= 4)
47                      {
48                          application = buffer.getInt();
49                          state = State.PROTOCOL;
50                      }
51                      else
52                      {
53                          state = State.APPLICATION_BYTES;
54                          cursor = 0;
55                      }
56                      break;
57                  }
58                  case APPLICATION_BYTES:
59                  {
60                      int quarterInt = buffer.get() & 0xFF;
61                      application = (application << 8) + quarterInt;
62                      if (++cursor == 4)
63                          state = State.PROTOCOL;
64                      break;
65                  }
66                  case PROTOCOL:
67                  {
68                      protocol = buffer.get() & 0xFF;
69                      state = State.RESERVED;
70                      break;
71                  }
72                  case RESERVED:
73                  {
74                      if (buffer.remaining() >= 3)
75                      {
76                          buffer.position(buffer.position() + 3);
77                          onEnd();
78                          reset();
79                          return Result.COMPLETE;
80                      }
81                      else
82                      {
83                          state = State.APPLICATION_BYTES;
84                          cursor = 0;
85                          break;
86                      }
87                  }
88                  case RESERVED_BYTES:
89                  {
90                      buffer.get();
91                      if (++cursor == 0)
92                      {
93                          onEnd();
94                          reset();
95                          return Result.COMPLETE;
96                      }
97                      break;
98                  }
99                  default:
100                 {
101                     throw new IllegalStateException();
102                 }
103             }
104         }
105         return Result.PENDING;
106     }
107 
108     private void onEnd()
109     {
110         if (application != 0)
111             listener.onFailure(getRequest(), new Exception("FastCGI application returned code " + application));
112         else if (protocol != 0)
113             listener.onFailure(getRequest(), new Exception("FastCGI server returned code " + protocol));
114         else
115             listener.onEnd(getRequest());
116     }
117 
118     private void reset()
119     {
120         state = State.APPLICATION;
121         cursor = 0;
122         application = 0;
123         protocol = 0;
124     }
125 
126     private enum State
127     {
128         APPLICATION, APPLICATION_BYTES, PROTOCOL, RESERVED, RESERVED_BYTES
129     }
130 }