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 }