Mercurial > projects > dreactor
comparison dreactor/protocol/http11_parser.d @ 11:5836613d16ac
reorg! reorg!
author | rick@minifunk |
---|---|
date | Tue, 12 Aug 2008 16:59:56 -0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
10:e75a2e506b1d | 11:5836613d16ac |
---|---|
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 } |