11
|
1 module dreactor.protocol.http11_parser;
|
|
2
|
|
3 //#line 1 "http11_parser.rl"
|
|
4 /**
|
|
5 * Copyright (c) 2005 Zed A. Shaw,
|
|
6 * Modified for D by Rick Richardson, 2008
|
|
7 * You can redistribute it and/or modify it under the same terms as Ruby.
|
|
8 */
|
|
9
|
|
10
|
|
11 alias void delegate (Object data, char[] buf) element_cb;
|
|
12 alias void delegate (Object data, char[] field, char[] value) field_cb;
|
|
13
|
|
14 class Http11Parser
|
|
15 {
|
|
16 private
|
|
17 int cs;
|
|
18 size_t body_start;
|
|
19 int content_len;
|
|
20 size_t nread;
|
|
21 size_t mark;
|
|
22 size_t field_start;
|
|
23 size_t field_len;
|
|
24 size_t query_start;
|
|
25
|
|
26 Object data;
|
|
27
|
|
28 field_cb http_field;
|
|
29 element_cb request_method;
|
|
30 element_cb request_uri;
|
|
31 element_cb fragment;
|
|
32 element_cb request_path;
|
|
33 element_cb query_string;
|
|
34 element_cb http_version;
|
|
35 element_cb header_done;
|
|
36
|
|
37 /*
|
|
38 * capitalizes all lower-case ASCII characters,
|
|
39 * converts dashes to underscores.
|
|
40 */
|
|
41 private void snake_upcase_char(char *c)
|
|
42 {
|
|
43 if (*c >= 'a' && *c <= 'z')
|
|
44 *c &= ~0x20;
|
|
45 else if (*c == '-')
|
|
46 *c = '_';
|
|
47 }
|
|
48
|
|
49 //#define LEN(AT, FPC) (FPC - buffer - parser->AT)
|
|
50 private size_t LEN(char[] buffer, size_t at, char* fpc)
|
|
51 {
|
|
52 return (fpc - buffer.ptr - at);
|
|
53 }
|
|
54
|
|
55 //#define MARK(M,FPC) (parser->M = (FPC) - buffer)
|
|
56 private void MARK(char[] buffer, size_t* item, char* fpc)
|
|
57 {
|
|
58 *item = fpc - buffer.ptr;
|
|
59 }
|
|
60
|
|
61 /** Machine **/
|
|
62
|
|
63 //#line 126 "http11_parser.rl"
|
|
64
|
|
65
|
|
66 /** Data **/
|
|
67
|
|
68 //#line 70 "http11_parser.d"
|
|
69 static byte[] _http_parser_actions = [
|
|
70 0, 1, 0, 1, 2, 1, 3, 1,
|
|
71 4, 1, 5, 1, 6, 1, 7, 1,
|
|
72 8, 1, 9, 1, 11, 1, 12, 1,
|
|
73 13, 2, 1, 2, 2, 10, 7, 2,
|
|
74 12, 7, 3, 9, 10, 7
|
|
75 ];
|
|
76
|
|
77 static short[] _http_parser_key_offsets = [
|
|
78 0, 0, 8, 17, 27, 29, 30, 31,
|
|
79 32, 33, 34, 36, 39, 41, 44, 45,
|
|
80 61, 62, 78, 80, 81, 90, 99, 105,
|
|
81 111, 121, 130, 136, 142, 153, 159, 165,
|
|
82 175, 181, 187, 196, 205, 211, 217, 226,
|
|
83 235, 244, 253, 262, 271, 280, 289, 298,
|
|
84 307, 316, 325, 334, 343, 352, 361, 370,
|
|
85 379, 380
|
|
86 ];
|
|
87
|
|
88 static char[] _http_parser_trans_keys = [
|
|
89 36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u,
|
|
90 32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u,
|
|
91 90u, 42u, 43u, 47u, 58u, 45u, 57u, 65u,
|
|
92 90u, 97u, 122u, 32u, 35u, 72u, 84u, 84u,
|
|
93 80u, 47u, 48u, 57u, 46u, 48u, 57u, 48u,
|
|
94 57u, 13u, 48u, 57u, 10u, 13u, 33u, 124u,
|
|
95 126u, 35u, 39u, 42u, 43u, 45u, 46u, 48u,
|
|
96 57u, 65u, 90u, 94u, 122u, 10u, 33u, 58u,
|
|
97 124u, 126u, 35u, 39u, 42u, 43u, 45u, 46u,
|
|
98 48u, 57u, 65u, 90u, 94u, 122u, 13u, 32u,
|
|
99 13u, 32u, 37u, 60u, 62u, 127u, 0u, 31u,
|
|
100 34u, 35u, 32u, 37u, 60u, 62u, 127u, 0u,
|
|
101 31u, 34u, 35u, 48u, 57u, 65u, 70u, 97u,
|
|
102 102u, 48u, 57u, 65u, 70u, 97u, 102u, 43u,
|
|
103 58u, 45u, 46u, 48u, 57u, 65u, 90u, 97u,
|
|
104 122u, 32u, 34u, 35u, 37u, 60u, 62u, 127u,
|
|
105 0u, 31u, 48u, 57u, 65u, 70u, 97u, 102u,
|
|
106 48u, 57u, 65u, 70u, 97u, 102u, 32u, 34u,
|
|
107 35u, 37u, 59u, 60u, 62u, 63u, 127u, 0u,
|
|
108 31u, 48u, 57u, 65u, 70u, 97u, 102u, 48u,
|
|
109 57u, 65u, 70u, 97u, 102u, 32u, 34u, 35u,
|
|
110 37u, 60u, 62u, 63u, 127u, 0u, 31u, 48u,
|
|
111 57u, 65u, 70u, 97u, 102u, 48u, 57u, 65u,
|
|
112 70u, 97u, 102u, 32u, 34u, 35u, 37u, 60u,
|
|
113 62u, 127u, 0u, 31u, 32u, 34u, 35u, 37u,
|
|
114 60u, 62u, 127u, 0u, 31u, 48u, 57u, 65u,
|
|
115 70u, 97u, 102u, 48u, 57u, 65u, 70u, 97u,
|
|
116 102u, 32u, 36u, 95u, 45u, 46u, 48u, 57u,
|
|
117 65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u,
|
|
118 57u, 65u, 90u, 32u, 36u, 95u, 45u, 46u,
|
|
119 48u, 57u, 65u, 90u, 32u, 36u, 95u, 45u,
|
|
120 46u, 48u, 57u, 65u, 90u, 32u, 36u, 95u,
|
|
121 45u, 46u, 48u, 57u, 65u, 90u, 32u, 36u,
|
|
122 95u, 45u, 46u, 48u, 57u, 65u, 90u, 32u,
|
|
123 36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u,
|
|
124 32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u,
|
|
125 90u, 32u, 36u, 95u, 45u, 46u, 48u, 57u,
|
|
126 65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u,
|
|
127 57u, 65u, 90u, 32u, 36u, 95u, 45u, 46u,
|
|
128 48u, 57u, 65u, 90u, 32u, 36u, 95u, 45u,
|
|
129 46u, 48u, 57u, 65u, 90u, 32u, 36u, 95u,
|
|
130 45u, 46u, 48u, 57u, 65u, 90u, 32u, 36u,
|
|
131 95u, 45u, 46u, 48u, 57u, 65u, 90u, 32u,
|
|
132 36u, 95u, 45u, 46u, 48u, 57u, 65u, 90u,
|
|
133 32u, 36u, 95u, 45u, 46u, 48u, 57u, 65u,
|
|
134 90u, 32u, 36u, 95u, 45u, 46u, 48u, 57u,
|
|
135 65u, 90u, 32u, 36u, 95u, 45u, 46u, 48u,
|
|
136 57u, 65u, 90u, 32u, 0
|
|
137 ];
|
|
138
|
|
139 static byte[] _http_parser_single_lengths = [
|
|
140 0, 2, 3, 4, 2, 1, 1, 1,
|
|
141 1, 1, 0, 1, 0, 1, 1, 4,
|
|
142 1, 4, 2, 1, 5, 5, 0, 0,
|
|
143 2, 7, 0, 0, 9, 0, 0, 8,
|
|
144 0, 0, 7, 7, 0, 0, 3, 3,
|
|
145 3, 3, 3, 3, 3, 3, 3, 3,
|
|
146 3, 3, 3, 3, 3, 3, 3, 3,
|
|
147 1, 0
|
|
148 ];
|
|
149
|
|
150 static byte[] _http_parser_range_lengths = [
|
|
151 0, 3, 3, 3, 0, 0, 0, 0,
|
|
152 0, 0, 1, 1, 1, 1, 0, 6,
|
|
153 0, 6, 0, 0, 2, 2, 3, 3,
|
|
154 4, 1, 3, 3, 1, 3, 3, 1,
|
|
155 3, 3, 1, 1, 3, 3, 3, 3,
|
|
156 3, 3, 3, 3, 3, 3, 3, 3,
|
|
157 3, 3, 3, 3, 3, 3, 3, 3,
|
|
158 0, 0
|
|
159 ];
|
|
160
|
|
161 static short[] _http_parser_index_offsets = [
|
|
162 0, 0, 6, 13, 21, 24, 26, 28,
|
|
163 30, 32, 34, 36, 39, 41, 44, 46,
|
|
164 57, 59, 70, 73, 75, 83, 91, 95,
|
|
165 99, 106, 115, 119, 123, 134, 138, 142,
|
|
166 152, 156, 160, 169, 178, 182, 186, 193,
|
|
167 200, 207, 214, 221, 228, 235, 242, 249,
|
|
168 256, 263, 270, 277, 284, 291, 298, 305,
|
|
169 312, 314
|
|
170 ];
|
|
171
|
|
172 static byte[] _http_parser_indicies = [
|
|
173 0, 0, 0, 0, 0, 1, 2, 3,
|
|
174 3, 3, 3, 3, 1, 4, 5, 6,
|
|
175 7, 5, 5, 5, 1, 8, 9, 1,
|
|
176 10, 1, 11, 1, 12, 1, 13, 1,
|
|
177 14, 1, 15, 1, 16, 15, 1, 17,
|
|
178 1, 18, 17, 1, 19, 1, 20, 21,
|
|
179 21, 21, 21, 21, 21, 21, 21, 21,
|
|
180 1, 22, 1, 23, 24, 23, 23, 23,
|
|
181 23, 23, 23, 23, 23, 1, 26, 27,
|
|
182 25, 26, 28, 29, 31, 1, 1, 1,
|
|
183 1, 1, 30, 29, 33, 1, 1, 1,
|
|
184 1, 1, 32, 34, 34, 34, 1, 32,
|
|
185 32, 32, 1, 35, 36, 35, 35, 35,
|
|
186 35, 1, 8, 1, 9, 37, 1, 1,
|
|
187 1, 1, 36, 38, 38, 38, 1, 36,
|
|
188 36, 36, 1, 39, 1, 41, 42, 43,
|
|
189 1, 1, 44, 1, 1, 40, 45, 45,
|
|
190 45, 1, 40, 40, 40, 1, 8, 1,
|
|
191 9, 47, 1, 1, 48, 1, 1, 46,
|
|
192 49, 49, 49, 1, 46, 46, 46, 1,
|
|
193 50, 1, 52, 53, 1, 1, 1, 1,
|
|
194 51, 54, 1, 56, 57, 1, 1, 1,
|
|
195 1, 55, 58, 58, 58, 1, 55, 55,
|
|
196 55, 1, 2, 59, 59, 59, 59, 59,
|
|
197 1, 2, 60, 60, 60, 60, 60, 1,
|
|
198 2, 61, 61, 61, 61, 61, 1, 2,
|
|
199 62, 62, 62, 62, 62, 1, 2, 63,
|
|
200 63, 63, 63, 63, 1, 2, 64, 64,
|
|
201 64, 64, 64, 1, 2, 65, 65, 65,
|
|
202 65, 65, 1, 2, 66, 66, 66, 66,
|
|
203 66, 1, 2, 67, 67, 67, 67, 67,
|
|
204 1, 2, 68, 68, 68, 68, 68, 1,
|
|
205 2, 69, 69, 69, 69, 69, 1, 2,
|
|
206 70, 70, 70, 70, 70, 1, 2, 71,
|
|
207 71, 71, 71, 71, 1, 2, 72, 72,
|
|
208 72, 72, 72, 1, 2, 73, 73, 73,
|
|
209 73, 73, 1, 2, 74, 74, 74, 74,
|
|
210 74, 1, 2, 75, 75, 75, 75, 75,
|
|
211 1, 2, 76, 76, 76, 76, 76, 1,
|
|
212 2, 1, 1, 0
|
|
213 ];
|
|
214
|
|
215 static byte[] _http_parser_trans_targs_wi = [
|
|
216 2, 0, 3, 38, 4, 24, 28, 25,
|
|
217 5, 20, 6, 7, 8, 9, 10, 11,
|
|
218 12, 13, 14, 15, 16, 17, 57, 17,
|
|
219 18, 19, 14, 18, 19, 5, 21, 22,
|
|
220 21, 22, 23, 24, 25, 26, 27, 5,
|
|
221 28, 20, 29, 31, 34, 30, 31, 32,
|
|
222 34, 33, 5, 35, 20, 36, 5, 35,
|
|
223 20, 36, 37, 39, 40, 41, 42, 43,
|
|
224 44, 45, 46, 47, 48, 49, 50, 51,
|
|
225 52, 53, 54, 55, 56
|
|
226 ];
|
|
227
|
|
228 static byte[] _http_parser_trans_actions_wi = [
|
|
229 1, 0, 11, 0, 1, 1, 1, 1,
|
|
230 13, 13, 1, 0, 0, 0, 0, 0,
|
|
231 0, 0, 19, 0, 0, 25, 23, 3,
|
|
232 5, 7, 9, 7, 0, 15, 1, 1,
|
|
233 0, 0, 0, 0, 0, 0, 0, 31,
|
|
234 0, 31, 0, 21, 21, 0, 0, 0,
|
|
235 0, 0, 34, 17, 34, 17, 28, 0,
|
|
236 28, 0, 0, 0, 0, 0, 0, 0,
|
|
237 0, 0, 0, 0, 0, 0, 0, 0,
|
|
238 0, 0, 0, 0, 0
|
|
239 ];
|
|
240
|
|
241 static int http_parser_start = 1;
|
|
242 static int http_parser_first_final = 57;
|
|
243 static int http_parser_error = 0;
|
|
244
|
|
245 static int http_parser_en_main = 1;
|
|
246
|
|
247 //#line 130 "http11_parser.rl"
|
|
248
|
|
249 this ()
|
|
250 {
|
|
251 cs = 0;
|
|
252
|
|
253 //#line 255 "http11_parser.d"
|
|
254 {
|
|
255 cs = http_parser_start;
|
|
256 }
|
|
257 //#line 135 "http11_parser.rl"
|
|
258
|
|
259 body_start = 0;
|
|
260 content_len = 0;
|
|
261 mark = 0;
|
|
262 nread = 0;
|
|
263 field_len = 0;
|
|
264 field_start = 0;
|
|
265 }
|
|
266
|
|
267
|
|
268 /** exec **/
|
|
269 public size_t execute(char[] buffer, size_t off = 0) {
|
|
270 char* p, pe;
|
|
271 int len = buffer.length;
|
|
272
|
|
273 assert(off <= len && "offset past end of buffer");
|
|
274
|
|
275 p = buffer.ptr+off;
|
|
276 pe = buffer.ptr+len;
|
|
277
|
|
278 /* assert(*pe == '\0' && "pointer does not end on NUL"); */
|
|
279 assert(pe - p == len - off && "pointers aren't same distance");
|
|
280
|
|
281
|
|
282 //#line 284 "http11_parser.d"
|
|
283 {
|
|
284 int _klen;
|
|
285 uint _trans;
|
|
286 byte* _acts;
|
|
287 uint _nacts;
|
|
288 char* _keys;
|
|
289
|
|
290 if ( p == pe )
|
|
291 goto _out;
|
|
292 if ( cs == 0 )
|
|
293 goto _out;
|
|
294 _resume:
|
|
295 _keys = &_http_parser_trans_keys[_http_parser_key_offsets[cs]];
|
|
296 _trans = _http_parser_index_offsets[cs];
|
|
297
|
|
298 _klen = _http_parser_single_lengths[cs];
|
|
299 if ( _klen > 0 ) {
|
|
300 char* _lower = _keys;
|
|
301 char* _mid;
|
|
302 char* _upper = _keys + _klen - 1;
|
|
303 while (1) {
|
|
304 if ( _upper < _lower )
|
|
305 break;
|
|
306
|
|
307 _mid = _lower + ((_upper-_lower) >> 1);
|
|
308 if ( (*p) < *_mid )
|
|
309 _upper = _mid - 1;
|
|
310 else if ( (*p) > *_mid )
|
|
311 _lower = _mid + 1;
|
|
312 else {
|
|
313 _trans += (_mid - _keys);
|
|
314 goto _match;
|
|
315 }
|
|
316 }
|
|
317 _keys += _klen;
|
|
318 _trans += _klen;
|
|
319 }
|
|
320
|
|
321 _klen = _http_parser_range_lengths[cs];
|
|
322 if ( _klen > 0 ) {
|
|
323 char* _lower = _keys;
|
|
324 char* _mid;
|
|
325 char* _upper = _keys + (_klen<<1) - 2;
|
|
326 while (1) {
|
|
327 if ( _upper < _lower )
|
|
328 break;
|
|
329
|
|
330 _mid = _lower + (((_upper-_lower) >> 1) & ~1);
|
|
331 if ( (*p) < _mid[0] )
|
|
332 _upper = _mid - 2;
|
|
333 else if ( (*p) > _mid[1] )
|
|
334 _lower = _mid + 2;
|
|
335 else {
|
|
336 _trans += ((_mid - _keys)>>1);
|
|
337 goto _match;
|
|
338 }
|
|
339 }
|
|
340 _trans += _klen;
|
|
341 }
|
|
342
|
|
343 _match:
|
|
344 _trans = _http_parser_indicies[_trans];
|
|
345 cs = _http_parser_trans_targs_wi[_trans];
|
|
346
|
|
347 if ( _http_parser_trans_actions_wi[_trans] == 0 )
|
|
348 goto _again;
|
|
349
|
|
350 _acts = &_http_parser_actions[_http_parser_trans_actions_wi[_trans]];
|
|
351 _nacts = cast(uint) *_acts++;
|
|
352 while ( _nacts-- > 0 )
|
|
353 {
|
|
354 switch ( *_acts++ )
|
|
355 {
|
|
356 case 0:
|
|
357 //#line 67 "http11_parser.rl"
|
|
358 {buffer.MARK(&mark, p); }
|
|
359 break;
|
|
360 case 1:
|
|
361 //#line 70 "http11_parser.rl"
|
|
362 { buffer.MARK(&field_start, p); }
|
|
363 break;
|
|
364 case 2:
|
|
365 //#line 71 "http11_parser.rl"
|
|
366 { snake_upcase_char(cast(char *)p); }
|
|
367 break;
|
|
368 case 3:
|
|
369 //#line 72 "http11_parser.rl"
|
|
370 {
|
|
371 field_len = buffer.LEN(field_start, p);
|
|
372 }
|
|
373 break;
|
|
374 case 4:
|
|
375 //#line 76 "http11_parser.rl"
|
|
376 { buffer.MARK(&mark, p); }
|
|
377 break;
|
|
378 case 5:
|
|
379 //#line 77 "http11_parser.rl"
|
|
380 {
|
|
381 if(http_field)
|
|
382 http_field(data,
|
|
383 buffer[field_start .. field_start+field_len],
|
|
384 buffer[mark .. $]);
|
|
385 }
|
|
386 break;
|
|
387 case 6:
|
|
388 //#line 85 "http11_parser.rl"
|
|
389 {
|
|
390 if(request_method)
|
|
391 request_method(data, buffer[mark .. $]);
|
|
392 }
|
|
393 break;
|
|
394 case 7:
|
|
395 //#line 90 "http11_parser.rl"
|
|
396 {
|
|
397 if(request_uri)
|
|
398 request_uri(data, buffer[mark .. $]);
|
|
399 }
|
|
400 break;
|
|
401 case 8:
|
|
402 //#line 95 "http11_parser.rl"
|
|
403 {
|
|
404 if(fragment)
|
|
405 fragment(data, buffer[mark .. $]);
|
|
406 }
|
|
407 break;
|
|
408 case 9:
|
|
409 //#line 100 "http11_parser.rl"
|
|
410 {buffer.MARK(&query_start, p); }
|
|
411 break;
|
|
412 case 10:
|
|
413 //#line 102 "http11_parser.rl"
|
|
414 {
|
|
415 if(query_string)
|
|
416 query_string(data, buffer[query_start .. $]);
|
|
417 }
|
|
418 break;
|
|
419 case 11:
|
|
420 //#line 107 "http11_parser.rl"
|
|
421 {
|
|
422 if(http_version)
|
|
423 http_version(data, buffer[mark .. $]);
|
|
424 }
|
|
425 break;
|
|
426 case 12:
|
|
427 //#line 112 "http11_parser.rl"
|
|
428 {
|
|
429 if(request_path)
|
|
430 request_path(data, buffer[mark .. $]);
|
|
431 }
|
|
432 break;
|
|
433 case 13:
|
|
434 //#line 117 "http11_parser.rl"
|
|
435 {
|
|
436 body_start = p - buffer.ptr + 1;
|
|
437 if(header_done)
|
|
438 header_done(data, p[1 .. (pe - p - 1)]);
|
|
439 if (true) goto _out;
|
|
440 }
|
|
441 break;
|
|
442 //#line 446 "http11_parser.d"
|
|
443 default: break;
|
|
444 }
|
|
445 }
|
|
446
|
|
447 _again:
|
|
448 if ( cs == 0 )
|
|
449 goto _out;
|
|
450 if ( ++p != pe )
|
|
451 goto _resume;
|
|
452 _out: {}
|
|
453 }
|
|
454 //#line 159 "http11_parser.rl"
|
|
455
|
|
456 //parser->cs = cs;
|
|
457 nread += p - (buffer.ptr + off);
|
|
458
|
|
459 assert(p <= pe && "buffer overflow after parsing execute");
|
|
460 assert(nread <= len && "nread longer than length");
|
|
461 assert(body_start <= len && "body starts after buffer end");
|
|
462 assert(mark < len && "mark is after buffer end");
|
|
463 assert(field_len <= len && "field has length longer than whole buffer");
|
|
464 assert(field_start < len && "field starts after buffer end");
|
|
465
|
|
466 return(nread);
|
|
467 }
|
|
468
|
|
469 public int finish()
|
|
470 {
|
|
471 if (has_error() ) {
|
|
472 return -1;
|
|
473 } else if (is_finished() ) {
|
|
474 return 1;
|
|
475 } else {
|
|
476 return 0;
|
|
477 }
|
|
478 }
|
|
479
|
|
480 public bool has_error() {
|
|
481 return cs == http_parser_error;
|
|
482 }
|
|
483
|
|
484 public bool is_finished() {
|
|
485 return cs >= http_parser_first_final;
|
|
486 }
|
|
487
|
|
488 public void setData(Object d)
|
|
489 {
|
|
490 data = d;
|
|
491 }
|
|
492 }
|