]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/asio/example/cpp11/http/server/request_parser.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / asio / example / cpp11 / http / server / request_parser.cpp
1 //
2 // request_parser.cpp
3 // ~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2017 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 server {
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 request_parser::result_type 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 bad;
35 }
36 else
37 {
38 state_ = method;
39 req.method.push_back(input);
40 return indeterminate;
41 }
42 case method:
43 if (input == ' ')
44 {
45 state_ = uri;
46 return indeterminate;
47 }
48 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
49 {
50 return bad;
51 }
52 else
53 {
54 req.method.push_back(input);
55 return indeterminate;
56 }
57 case uri:
58 if (input == ' ')
59 {
60 state_ = http_version_h;
61 return indeterminate;
62 }
63 else if (is_ctl(input))
64 {
65 return bad;
66 }
67 else
68 {
69 req.uri.push_back(input);
70 return indeterminate;
71 }
72 case http_version_h:
73 if (input == 'H')
74 {
75 state_ = http_version_t_1;
76 return indeterminate;
77 }
78 else
79 {
80 return bad;
81 }
82 case http_version_t_1:
83 if (input == 'T')
84 {
85 state_ = http_version_t_2;
86 return indeterminate;
87 }
88 else
89 {
90 return bad;
91 }
92 case http_version_t_2:
93 if (input == 'T')
94 {
95 state_ = http_version_p;
96 return indeterminate;
97 }
98 else
99 {
100 return bad;
101 }
102 case http_version_p:
103 if (input == 'P')
104 {
105 state_ = http_version_slash;
106 return indeterminate;
107 }
108 else
109 {
110 return bad;
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 indeterminate;
119 }
120 else
121 {
122 return bad;
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 indeterminate;
130 }
131 else
132 {
133 return bad;
134 }
135 case http_version_major:
136 if (input == '.')
137 {
138 state_ = http_version_minor_start;
139 return indeterminate;
140 }
141 else if (is_digit(input))
142 {
143 req.http_version_major = req.http_version_major * 10 + input - '0';
144 return indeterminate;
145 }
146 else
147 {
148 return bad;
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 indeterminate;
156 }
157 else
158 {
159 return bad;
160 }
161 case http_version_minor:
162 if (input == '\r')
163 {
164 state_ = expecting_newline_1;
165 return indeterminate;
166 }
167 else if (is_digit(input))
168 {
169 req.http_version_minor = req.http_version_minor * 10 + input - '0';
170 return indeterminate;
171 }
172 else
173 {
174 return bad;
175 }
176 case expecting_newline_1:
177 if (input == '\n')
178 {
179 state_ = header_line_start;
180 return indeterminate;
181 }
182 else
183 {
184 return bad;
185 }
186 case header_line_start:
187 if (input == '\r')
188 {
189 state_ = expecting_newline_3;
190 return indeterminate;
191 }
192 else if (!req.headers.empty() && (input == ' ' || input == '\t'))
193 {
194 state_ = header_lws;
195 return indeterminate;
196 }
197 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
198 {
199 return bad;
200 }
201 else
202 {
203 req.headers.push_back(header());
204 req.headers.back().name.push_back(input);
205 state_ = header_name;
206 return indeterminate;
207 }
208 case header_lws:
209 if (input == '\r')
210 {
211 state_ = expecting_newline_2;
212 return indeterminate;
213 }
214 else if (input == ' ' || input == '\t')
215 {
216 return indeterminate;
217 }
218 else if (is_ctl(input))
219 {
220 return bad;
221 }
222 else
223 {
224 state_ = header_value;
225 req.headers.back().value.push_back(input);
226 return indeterminate;
227 }
228 case header_name:
229 if (input == ':')
230 {
231 state_ = space_before_header_value;
232 return indeterminate;
233 }
234 else if (!is_char(input) || is_ctl(input) || is_tspecial(input))
235 {
236 return bad;
237 }
238 else
239 {
240 req.headers.back().name.push_back(input);
241 return indeterminate;
242 }
243 case space_before_header_value:
244 if (input == ' ')
245 {
246 state_ = header_value;
247 return indeterminate;
248 }
249 else
250 {
251 return bad;
252 }
253 case header_value:
254 if (input == '\r')
255 {
256 state_ = expecting_newline_2;
257 return indeterminate;
258 }
259 else if (is_ctl(input))
260 {
261 return bad;
262 }
263 else
264 {
265 req.headers.back().value.push_back(input);
266 return indeterminate;
267 }
268 case expecting_newline_2:
269 if (input == '\n')
270 {
271 state_ = header_line_start;
272 return indeterminate;
273 }
274 else
275 {
276 return bad;
277 }
278 case expecting_newline_3:
279 return (input == '\n') ? good : bad;
280 default:
281 return bad;
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 server
315 } // namespace http