#line 1 "http11_parser.rl" /** * Copyright (c) 2005 Zed A. Shaw * You can redistribute it and/or modify it under the same terms as Ruby. */ #include "http11_parser.h" #include #include #include #include #include #define LEN(AT, FPC) (FPC - buffer - parser->AT) #define MARK(M,FPC) (parser->M = (FPC) - buffer) #define PTR_TO(F) (buffer + parser->F) #define L(M) fprintf(stderr, "" # M "\n"); /** machine **/ #line 95 "http11_parser.rl" /** Data **/ #line 29 "http11_parser.c" static const char _httpclient_parser_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 7, 1, 8, 1, 10, 2, 0, 5, 2, 2, 3, 2, 3, 4, 2, 4, 10, 2, 6, 0, 2, 8, 10, 2, 9, 10, 2, 10, 9, 3, 2, 3, 4, 3, 4, 9, 10, 3, 4, 10, 9, 3, 6, 0, 5, 3, 8, 10, 9, 4, 2, 3, 4, 10, 5, 2, 3, 4, 9, 10, 5, 2, 3, 4, 10, 9 }; static const short _httpclient_parser_key_offsets[] = { 0, 0, 11, 12, 24, 29, 30, 31, 43, 58, 80, 95, 116, 131, 153, 168, 189, 204, 223, 238, 256, 257, 258, 259, 260, 262, 265, 267, 270, 272, 274, 276, 279, 281, 298, 314, 317, 319, 320, 322 }; static const char _httpclient_parser_trans_keys[] = { 10, 13, 48, 59, 72, 49, 57, 65, 70, 97, 102, 10, 10, 13, 32, 59, 9, 12, 48, 57, 65, 70, 97, 102, 10, 13, 32, 9, 12, 10, 10, 10, 13, 32, 59, 9, 12, 48, 57, 65, 70, 97, 102, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 32, 33, 59, 61, 124, 126, 9, 12, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 32, 33, 59, 124, 126, 9, 12, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 32, 33, 59, 61, 124, 126, 9, 12, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 32, 33, 59, 124, 126, 9, 12, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 33, 59, 61, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 33, 59, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 84, 84, 80, 47, 48, 57, 46, 48, 57, 48, 57, 32, 48, 57, 48, 57, 48, 57, 48, 57, 10, 13, 32, 10, 13, 10, 13, 33, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 33, 58, 124, 126, 35, 39, 42, 43, 45, 46, 48, 57, 65, 90, 94, 122, 10, 13, 32, 10, 13, 10, 10, 13, 0 }; static const char _httpclient_parser_single_lengths[] = { 0, 5, 1, 4, 3, 1, 1, 4, 3, 8, 3, 7, 3, 8, 3, 7, 3, 7, 3, 6, 1, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 3, 2, 5, 4, 3, 2, 1, 2, 0 }; static const char _httpclient_parser_range_lengths[] = { 0, 3, 0, 4, 1, 0, 0, 4, 6, 7, 6, 7, 6, 7, 6, 7, 6, 6, 6, 6, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 6, 6, 0, 0, 0, 0, 0 }; static const short _httpclient_parser_index_offsets[] = { 0, 0, 9, 11, 20, 25, 27, 29, 38, 48, 64, 74, 89, 99, 115, 125, 140, 150, 164, 174, 187, 189, 191, 193, 195, 197, 200, 202, 205, 207, 209, 211, 215, 218, 230, 241, 245, 248, 250, 253 }; static const char _httpclient_parser_indicies[] = { 0, 2, 3, 5, 6, 4, 4, 4, 1, 0, 1, 8, 9, 7, 11, 7, 10, 10, 10, 1, 13, 14, 12, 12, 1, 13, 1, 15, 1, 16, 17, 7, 18, 7, 10, 10, 10, 1, 19, 19, 19, 19, 19, 19, 19, 19, 19, 1, 21, 22, 20, 23, 24, 25, 23, 23, 20, 23, 23, 23, 23, 23, 23, 1, 26, 26, 26, 26, 26, 26, 26, 26, 26, 1, 28, 29, 27, 30, 31, 30, 30, 27, 30, 30, 30, 30, 30, 30, 1, 32, 32, 32, 32, 32, 32, 32, 32, 32, 1, 33, 34, 20, 35, 36, 37, 35, 35, 20, 35, 35, 35, 35, 35, 35, 1, 38, 38, 38, 38, 38, 38, 38, 38, 38, 1, 39, 40, 27, 41, 42, 41, 41, 27, 41, 41, 41, 41, 41, 41, 1, 43, 43, 43, 43, 43, 43, 43, 43, 43, 1, 44, 45, 46, 47, 48, 46, 46, 46, 46, 46, 46, 46, 46, 1, 49, 49, 49, 49, 49, 49, 49, 49, 49, 1, 50, 51, 52, 53, 52, 52, 52, 52, 52, 52, 52, 52, 1, 54, 1, 55, 1, 56, 1, 57, 1, 58, 1, 59, 58, 1, 60, 1, 61, 60, 1, 62, 1, 63, 1, 64, 1, 66, 67, 68, 65, 70, 71, 69, 13, 14, 72, 72, 72, 72, 72, 72, 72, 72, 72, 1, 73, 74, 73, 73, 73, 73, 73, 73, 73, 73, 1, 76, 77, 78, 75, 80, 81, 79, 82, 1, 84, 85, 83, 1, 0 }; static const char _httpclient_parser_trans_targs[] = { 39, 0, 2, 3, 7, 16, 20, 4, 39, 6, 7, 12, 4, 39, 5, 39, 39, 5, 8, 9, 4, 39, 5, 9, 8, 10, 11, 4, 39, 5, 11, 8, 13, 39, 6, 13, 12, 14, 15, 39, 6, 15, 12, 17, 39, 2, 17, 16, 18, 19, 39, 2, 19, 16, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 37, 38, 32, 33, 37, 34, 34, 35, 36, 33, 37, 35, 36, 33, 37, 33, 32, 33, 37 }; static const char _httpclient_parser_trans_actions[] = { 37, 0, 0, 1, 1, 0, 1, 15, 59, 15, 0, 15, 0, 17, 0, 40, 34, 15, 15, 3, 43, 63, 43, 0, 43, 22, 7, 9, 28, 9, 0, 9, 3, 74, 43, 0, 43, 22, 7, 51, 9, 0, 9, 3, 68, 43, 0, 43, 22, 7, 47, 9, 0, 9, 0, 0, 0, 0, 0, 0, 0, 13, 1, 0, 0, 31, 55, 55, 31, 0, 11, 11, 3, 0, 5, 7, 25, 25, 7, 0, 9, 9, 0, 1, 19, 19 }; static const int httpclient_parser_start = 1; static const int httpclient_parser_first_final = 39; static const int httpclient_parser_error = 0; static const int httpclient_parser_en_main = 1; #line 99 "http11_parser.rl" int httpclient_parser_init(httpclient_parser *parser) { int cs = 0; #line 195 "http11_parser.c" { cs = httpclient_parser_start; } #line 103 "http11_parser.rl" parser->cs = cs; parser->body_start = 0; parser->content_len = 0; parser->mark = 0; parser->nread = 0; parser->field_len = 0; parser->field_start = 0; return(1); } /** exec **/ size_t httpclient_parser_execute(httpclient_parser *parser, const char *buffer, size_t len, size_t off) { const char *p, *pe; int cs = parser->cs; assert(off <= len && "offset past end of buffer"); p = buffer+off; pe = buffer+len; assert(*pe == '\0' && "pointer does not end on NUL"); assert(pe - p == len - off && "pointers aren't same distance"); #line 228 "http11_parser.c" { int _klen; unsigned int _trans; const char *_acts; unsigned int _nacts; const char *_keys; if ( p == pe ) goto _test_eof; if ( cs == 0 ) goto _out; _resume: _keys = _httpclient_parser_trans_keys + _httpclient_parser_key_offsets[cs]; _trans = _httpclient_parser_index_offsets[cs]; _klen = _httpclient_parser_single_lengths[cs]; if ( _klen > 0 ) { const char *_lower = _keys; const char *_mid; const char *_upper = _keys + _klen - 1; while (1) { if ( _upper < _lower ) break; _mid = _lower + ((_upper-_lower) >> 1); if ( (*p) < *_mid ) _upper = _mid - 1; else if ( (*p) > *_mid ) _lower = _mid + 1; else { _trans += (_mid - _keys); goto _match; } } _keys += _klen; _trans += _klen; } _klen = _httpclient_parser_range_lengths[cs]; if ( _klen > 0 ) { const char *_lower = _keys; const char *_mid; const char *_upper = _keys + (_klen<<1) - 2; while (1) { if ( _upper < _lower ) break; _mid = _lower + (((_upper-_lower) >> 1) & ~1); if ( (*p) < _mid[0] ) _upper = _mid - 2; else if ( (*p) > _mid[1] ) _lower = _mid + 2; else { _trans += ((_mid - _keys)>>1); goto _match; } } _trans += _klen; } _match: _trans = _httpclient_parser_indicies[_trans]; cs = _httpclient_parser_trans_targs[_trans]; if ( _httpclient_parser_trans_actions[_trans] == 0 ) goto _again; _acts = _httpclient_parser_actions + _httpclient_parser_trans_actions[_trans]; _nacts = (unsigned int) *_acts++; while ( _nacts-- > 0 ) { switch ( *_acts++ ) { case 0: #line 23 "http11_parser.rl" {MARK(mark, p); } break; case 1: #line 25 "http11_parser.rl" { MARK(field_start, p); } break; case 2: #line 27 "http11_parser.rl" { parser->field_len = LEN(field_start, p); } break; case 3: #line 31 "http11_parser.rl" { MARK(mark, p); } break; case 4: #line 33 "http11_parser.rl" { parser->http_field(parser->data, PTR_TO(field_start), parser->field_len, PTR_TO(mark), LEN(mark, p)); } break; case 5: #line 37 "http11_parser.rl" { parser->reason_phrase(parser->data, PTR_TO(mark), LEN(mark, p)); } break; case 6: #line 41 "http11_parser.rl" { parser->status_code(parser->data, PTR_TO(mark), LEN(mark, p)); } break; case 7: #line 45 "http11_parser.rl" { parser->http_version(parser->data, PTR_TO(mark), LEN(mark, p)); } break; case 8: #line 49 "http11_parser.rl" { parser->chunk_size(parser->data, PTR_TO(mark), LEN(mark, p)); } break; case 9: #line 53 "http11_parser.rl" { parser->last_chunk(parser->data, NULL, 0); } break; case 10: #line 57 "http11_parser.rl" { parser->body_start = p - buffer + 1; if(parser->header_done != NULL) parser->header_done(parser->data, p + 1, pe - p - 1); {p++; goto _out; } } break; #line 365 "http11_parser.c" } } _again: if ( cs == 0 ) goto _out; if ( ++p != pe ) goto _resume; _test_eof: {} _out: {} } #line 130 "http11_parser.rl" parser->cs = cs; parser->nread += p - (buffer + off); assert(p <= pe && "buffer overflow after parsing execute"); assert(parser->nread <= len && "nread longer than length"); assert(parser->body_start <= len && "body starts after buffer end"); assert(parser->mark < len && "mark is after buffer end"); assert(parser->field_len <= len && "field has length longer than whole buffer"); assert(parser->field_start < len && "field starts after buffer end"); if(parser->body_start) { /* final \r\n combo encountered so stop right here */ parser->nread = parser->body_start; } return(parser->nread); } int httpclient_parser_finish(httpclient_parser *parser) { int cs = parser->cs; parser->cs = cs; if (httpclient_parser_has_error(parser) ) { return -1; } else if (httpclient_parser_is_finished(parser) ) { return 1; } else { return 0; } } int httpclient_parser_has_error(httpclient_parser *parser) { return parser->cs == httpclient_parser_error; } int httpclient_parser_is_finished(httpclient_parser *parser) { return parser->cs == httpclient_parser_first_final; }