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 }