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