]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp03/http/server2/request_parser.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / asio / example / cpp03 / http / server2 / request_parser.cpp
1 //
2 // request_parser.cpp
3 // ~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2019 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #include "request_parser.hpp"
12 #include "request.hpp"
13
14 namespace http {
15 namespace server2 {
16
17 request_parser::request_parser()
18 : state_(method_start)
19 {
20 }
21
22 void request_parser::reset()
23 {
24 state_ = method_start;
25 }
26
27 boost::tribool request_parser::consume(request& req, char input)
28 {
29 switch (state_)
30 {
31 case method_start:
32 if (!is_char(input) || is_ctl(input) || is_tspecial(input))
33 {
34 return false;
35 }
36 else
37 {
38 state_ = method;
39 req.method.push_back(input);
40 return boost::indeterminate;
41 }
42 case method:
43 if (input == ' ')
44 {
45 state_ = uri;
46 return boost::indeterminate;
47 }
48 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
49 {
50 return false;
51 }
52 else
53 {
54 req.method.push_back(input);
55 return boost::indeterminate;
56 }
57 case uri:
58 if (input == ' ')
59 {
60 state_ = http_version_h;
61 return boost::indeterminate;
62 }
63 else if (is_ctl(input))
64 {
65 return false;
66 }
67 else
68 {
69 req.uri.push_back(input);
70 return boost::indeterminate;
71 }
72 case http_version_h:
73 if (input == 'H')
74 {
75 state_ = http_version_t_1;
76 return boost::indeterminate;
77 }
78 else
79 {
80 return false;
81 }
82 case http_version_t_1:
83 if (input == 'T')
84 {
85 state_ = http_version_t_2;
86 return boost::indeterminate;
87 }
88 else
89 {
90 return false;
91 }
92 case http_version_t_2:
93 if (input == 'T')
94 {
95 state_ = http_version_p;
96 return boost::indeterminate;
97 }
98 else
99 {
100 return false;
101 }
102 case http_version_p:
103 if (input == 'P')
104 {
105 state_ = http_version_slash;
106 return boost::indeterminate;
107 }
108 else
109 {
110 return false;
111 }
112 case http_version_slash:
113 if (input == '/')
114 {
115 req.http_version_major = 0;
116 req.http_version_minor = 0;
117 state_ = http_version_major_start;
118 return boost::indeterminate;
119 }
120 else
121 {
122 return false;
123 }
124 case http_version_major_start:
125 if (is_digit(input))
126 {
127 req.http_version_major = req.http_version_major * 10 + input - '0';
128 state_ = http_version_major;
129 return boost::indeterminate;
130 }
131 else
132 {
133 return false;
134 }
135 case http_version_major:
136 if (input == '.')
137 {
138 state_ = http_version_minor_start;
139 return boost::indeterminate;
140 }
141 else if (is_digit(input))
142 {
143 req.http_version_major = req.http_version_major * 10 + input - '0';
144 return boost::indeterminate;
145 }
146 else
147 {
148 return false;
149 }
150 case http_version_minor_start:
151 if (is_digit(input))
152 {
153 req.http_version_minor = req.http_version_minor * 10 + input - '0';
154 state_ = http_version_minor;
155 return boost::indeterminate;
156 }
157 else
158 {
159 return false;
160 }
161 case http_version_minor:
162 if (input == '\r')
163 {
164 state_ = expecting_newline_1;
165 return boost::indeterminate;
166 }
167 else if (is_digit(input))
168 {
169 req.http_version_minor = req.http_version_minor * 10 + input - '0';
170 return boost::indeterminate;
171 }
172 else
173 {
174 return false;
175 }
176 case expecting_newline_1:
177 if (input == '\n')
178 {
179 state_ = header_line_start;
180 return boost::indeterminate;
181 }
182 else
183 {
184 return false;
185 }
186 case header_line_start:
187 if (input == '\r')
188 {
189 state_ = expecting_newline_3;
190 return boost::indeterminate;
191 }
192 else if (!req.headers.empty() && (input == ' ' || input == '\t'))
193 {
194 state_ = header_lws;
195 return boost::indeterminate;
196 }
197 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
198 {
199 return false;
200 }
201 else
202 {
203 req.headers.push_back(header());
204 req.headers.back().name.push_back(input);
205 state_ = header_name;
206 return boost::indeterminate;
207 }
208 case header_lws:
209 if (input == '\r')
210 {
211 state_ = expecting_newline_2;
212 return boost::indeterminate;
213 }
214 else if (input == ' ' || input == '\t')
215 {
216 return boost::indeterminate;
217 }
218 else if (is_ctl(input))
219 {
220 return false;
221 }
222 else
223 {
224 state_ = header_value;
225 req.headers.back().value.push_back(input);
226 return boost::indeterminate;
227 }
228 case header_name:
229 if (input == ':')
230 {
231 state_ = space_before_header_value;
232 return boost::indeterminate;
233 }
234 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
235 {
236 return false;
237 }
238 else
239 {
240 req.headers.back().name.push_back(input);
241 return boost::indeterminate;
242 }
243 case space_before_header_value:
244 if (input == ' ')
245 {
246 state_ = header_value;
247 return boost::indeterminate;
248 }
249 else
250 {
251 return false;
252 }
253 case header_value:
254 if (input == '\r')
255 {
256 state_ = expecting_newline_2;
257 return boost::indeterminate;
258 }
259 else if (is_ctl(input))
260 {
261 return false;
262 }
263 else
264 {
265 req.headers.back().value.push_back(input);
266 return boost::indeterminate;
267 }
268 case expecting_newline_2:
269 if (input == '\n')
270 {
271 state_ = header_line_start;
272 return boost::indeterminate;
273 }
274 else
275 {
276 return false;
277 }
278 case expecting_newline_3:
279 return (input == '\n');
280 default:
281 return false;
282 }
283 }
284
285 bool request_parser::is_char(int c)
286 {
287 return c >= 0 && c <= 127;
288 }
289
290 bool request_parser::is_ctl(int c)
291 {
292 return (c >= 0 && c <= 31) || (c == 127);
293 }
294
295 bool request_parser::is_tspecial(int c)
296 {
297 switch (c)
298 {
299 case '(': case ')': case '<': case '>': case '@':
300 case ',': case ';': case ':': case '\\': case '"':
301 case '/': case '[': case ']': case '?': case '=':
302 case '{': case '}': case ' ': case '\t':
303 return true;
304 default:
305 return false;
306 }
307 }
308
309 bool request_parser::is_digit(int c)
310 {
311 return c >= '0' && c <= '9';
312 }
313
314 } // namespace server2
315 } // namespace http