Commit 6f90f78bc0f6f503d2ac749dc5be7c01162efb1d

Authored by Josh Klontz
1 parent 2d6ccbf1

removed http-parser

3rdparty/http-parser-2.1/.gitignore deleted
1 -/out/  
2 -core  
3 -tags  
4 -*.o  
5 -test  
6 -test_g  
7 -test_fast  
8 -url_parser  
9 -parsertrace  
10 -parsertrace_g  
11 -*.mk  
12 -*.Makefile  
13 -*.so  
14 -*.a  
3rdparty/http-parser-2.1/.mailmap deleted
1 -# update AUTHORS with:  
2 -# git log --all --reverse --format='%aN <%aE>' | perl -ne 'BEGIN{print "# Authors ordered by first contribution.\n"} print unless $h{$_}; $h{$_} = 1' > AUTHORS  
3 -Ryan Dahl <ry@tinyclouds.org>  
4 -Salman Haq <salman.haq@asti-usa.com>  
5 -Simon Zimmermann <simonz05@gmail.com>  
6 -Thomas LE ROUX <thomas@november-eleven.fr> LE ROUX Thomas <thomas@procheo.fr>  
7 -Thomas LE ROUX <thomas@november-eleven.fr> Thomas LE ROUX <thomas@procheo.fr>  
3rdparty/http-parser-2.1/.travis.yml deleted
1 -language: c  
2 -  
3 -compiler:  
4 - - clang  
5 - - gcc  
6 -  
7 -script:  
8 - - "make"  
9 -  
10 -notifications:  
11 - email: false  
12 - irc:  
13 - - "irc.freenode.net#libuv"  
3rdparty/http-parser-2.1/AUTHORS deleted
1 -# Authors ordered by first contribution.  
2 -Ryan Dahl <ry@tinyclouds.org>  
3 -Jeremy Hinegardner <jeremy@hinegardner.org>  
4 -Sergey Shepelev <temotor@gmail.com>  
5 -Joe Damato <ice799@gmail.com>  
6 -tomika <tomika_nospam@freemail.hu>  
7 -Phoenix Sol <phoenix@burninglabs.com>  
8 -Cliff Frey <cliff@meraki.com>  
9 -Ewen Cheslack-Postava <ewencp@cs.stanford.edu>  
10 -Santiago Gala <sgala@apache.org>  
11 -Tim Becker <tim.becker@syngenio.de>  
12 -Jeff Terrace <jterrace@gmail.com>  
13 -Ben Noordhuis <info@bnoordhuis.nl>  
14 -Nathan Rajlich <nathan@tootallnate.net>  
15 -Mark Nottingham <mnot@mnot.net>  
16 -Aman Gupta <aman@tmm1.net>  
17 -Tim Becker <tim.becker@kuriositaet.de>  
18 -Sean Cunningham <sean.cunningham@mandiant.com>  
19 -Peter Griess <pg@std.in>  
20 -Salman Haq <salman.haq@asti-usa.com>  
21 -Cliff Frey <clifffrey@gmail.com>  
22 -Jon Kolb <jon@b0g.us>  
23 -Fouad Mardini <f.mardini@gmail.com>  
24 -Paul Querna <pquerna@apache.org>  
25 -Felix Geisendörfer <felix@debuggable.com>  
26 -koichik <koichik@improvement.jp>  
27 -Andre Caron <andre.l.caron@gmail.com>  
28 -Ivo Raisr <ivosh@ivosh.net>  
29 -James McLaughlin <jamie@lacewing-project.org>  
30 -David Gwynne <loki@animata.net>  
31 -Thomas LE ROUX <thomas@november-eleven.fr>  
32 -Randy Rizun <rrizun@ortivawireless.com>  
33 -Andre Louis Caron <andre.louis.caron@usherbrooke.ca>  
34 -Simon Zimmermann <simonz05@gmail.com>  
35 -Erik Dubbelboer <erik@dubbelboer.com>  
36 -Martell Malone <martellmalone@gmail.com>  
37 -Bertrand Paquet <bpaquet@octo.com>  
38 -BogDan Vatra <bogdan@kde.org>  
39 -Peter Faiman <peter@thepicard.org>  
40 -Corey Richardson <corey@octayn.net>  
41 -Tóth Tamás <tomika_nospam@freemail.hu>  
3rdparty/http-parser-2.1/CONTRIBUTIONS deleted
1 -Contributors must agree to the Contributor License Agreement before patches  
2 -can be accepted.  
3 -  
4 -http://spreadsheets2.google.com/viewform?hl=en&formkey=dDJXOGUwbzlYaWM4cHN1MERwQS1CSnc6MQ  
3rdparty/http-parser-2.1/LICENSE-MIT deleted
1 -http_parser.c is based on src/http/ngx_http_parse.c from NGINX copyright  
2 -Igor Sysoev.  
3 -  
4 -Additional changes are licensed under the same terms as NGINX and  
5 -copyright Joyent, Inc. and other Node contributors. All rights reserved.  
6 -  
7 -Permission is hereby granted, free of charge, to any person obtaining a copy  
8 -of this software and associated documentation files (the "Software"), to  
9 -deal in the Software without restriction, including without limitation the  
10 -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
11 -sell copies of the Software, and to permit persons to whom the Software is  
12 -furnished to do so, subject to the following conditions:  
13 -  
14 -The above copyright notice and this permission notice shall be included in  
15 -all copies or substantial portions of the Software.  
16 -  
17 -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
18 -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
19 -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
20 -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
21 -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
22 -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS  
23 -IN THE SOFTWARE.  
3rdparty/http-parser-2.1/Makefile deleted
1 -CC?=gcc  
2 -AR?=ar  
3 -  
4 -CPPFLAGS += -I.  
5 -CPPFLAGS_DEBUG = $(CPPFLAGS) -DHTTP_PARSER_STRICT=1  
6 -CPPFLAGS_DEBUG += $(CPPFLAGS_DEBUG_EXTRA)  
7 -CPPFLAGS_FAST = $(CPPFLAGS) -DHTTP_PARSER_STRICT=0  
8 -CPPFLAGS_FAST += $(CPPFLAGS_FAST_EXTRA)  
9 -  
10 -CFLAGS += -Wall -Wextra -Werror  
11 -CFLAGS_DEBUG = $(CFLAGS) -O0 -g $(CFLAGS_DEBUG_EXTRA)  
12 -CFLAGS_FAST = $(CFLAGS) -O3 $(CFLAGS_FAST_EXTRA)  
13 -CFLAGS_LIB = $(CFLAGS_FAST) -fPIC  
14 -  
15 -test: test_g test_fast  
16 - ./test_g  
17 - ./test_fast  
18 -  
19 -test_g: http_parser_g.o test_g.o  
20 - $(CC) $(CFLAGS_DEBUG) $(LDFLAGS) http_parser_g.o test_g.o -o $@  
21 -  
22 -test_g.o: test.c http_parser.h Makefile  
23 - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c test.c -o $@  
24 -  
25 -http_parser_g.o: http_parser.c http_parser.h Makefile  
26 - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) -c http_parser.c -o $@  
27 -  
28 -test_fast: http_parser.o test.o http_parser.h  
29 - $(CC) $(CFLAGS_FAST) $(LDFLAGS) http_parser.o test.o -o $@  
30 -  
31 -test.o: test.c http_parser.h Makefile  
32 - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c test.c -o $@  
33 -  
34 -http_parser.o: http_parser.c http_parser.h Makefile  
35 - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) -c http_parser.c  
36 -  
37 -test-run-timed: test_fast  
38 - while(true) do time ./test_fast > /dev/null; done  
39 -  
40 -test-valgrind: test_g  
41 - valgrind ./test_g  
42 -  
43 -libhttp_parser.o: http_parser.c http_parser.h Makefile  
44 - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_LIB) -c http_parser.c -o libhttp_parser.o  
45 -  
46 -library: libhttp_parser.o  
47 - $(CC) -shared -o libhttp_parser.so libhttp_parser.o  
48 -  
49 -package: http_parser.o  
50 - $(AR) rcs libhttp_parser.a http_parser.o  
51 -  
52 -url_parser: http_parser.o contrib/url_parser.c  
53 - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o $@  
54 -  
55 -url_parser_g: http_parser_g.o contrib/url_parser.c  
56 - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o $@  
57 -  
58 -parsertrace: http_parser.o contrib/parsertrace.c  
59 - $(CC) $(CPPFLAGS_FAST) $(CFLAGS_FAST) $^ -o parsertrace  
60 -  
61 -parsertrace_g: http_parser_g.o contrib/parsertrace.c  
62 - $(CC) $(CPPFLAGS_DEBUG) $(CFLAGS_DEBUG) $^ -o parsertrace_g  
63 -  
64 -tags: http_parser.c http_parser.h test.c  
65 - ctags $^  
66 -  
67 -clean:  
68 - rm -f *.o *.a tags test test_fast test_g \  
69 - http_parser.tar libhttp_parser.so \  
70 - url_parser url_parser_g parsertrace parsertrace_g  
71 -  
72 -contrib/url_parser.c: http_parser.h  
73 -contrib/parsertrace.c: http_parser.h  
74 -  
75 -.PHONY: clean package test-run test-run-timed test-valgrind  
3rdparty/http-parser-2.1/README.md deleted
1 -HTTP Parser  
2 -===========  
3 -  
4 -[![Build Status](https://travis-ci.org/joyent/http-parser.png?branch=master)](https://travis-ci.org/joyent/http-parser)  
5 -  
6 -This is a parser for HTTP messages written in C. It parses both requests and  
7 -responses. The parser is designed to be used in performance HTTP  
8 -applications. It does not make any syscalls nor allocations, it does not  
9 -buffer data, it can be interrupted at anytime. Depending on your  
10 -architecture, it only requires about 40 bytes of data per message  
11 -stream (in a web server that is per connection).  
12 -  
13 -Features:  
14 -  
15 - * No dependencies  
16 - * Handles persistent streams (keep-alive).  
17 - * Decodes chunked encoding.  
18 - * Upgrade support  
19 - * Defends against buffer overflow attacks.  
20 -  
21 -The parser extracts the following information from HTTP messages:  
22 -  
23 - * Header fields and values  
24 - * Content-Length  
25 - * Request method  
26 - * Response status code  
27 - * Transfer-Encoding  
28 - * HTTP version  
29 - * Request URL  
30 - * Message body  
31 -  
32 -  
33 -Usage  
34 ------  
35 -  
36 -One `http_parser` object is used per TCP connection. Initialize the struct  
37 -using `http_parser_init()` and set the callbacks. That might look something  
38 -like this for a request parser:  
39 -  
40 - http_parser_settings settings;  
41 - settings.on_url = my_url_callback;  
42 - settings.on_header_field = my_header_field_callback;  
43 - /* ... */  
44 -  
45 - http_parser *parser = malloc(sizeof(http_parser));  
46 - http_parser_init(parser, HTTP_REQUEST);  
47 - parser->data = my_socket;  
48 -  
49 -When data is received on the socket execute the parser and check for errors.  
50 -  
51 - size_t len = 80*1024, nparsed;  
52 - char buf[len];  
53 - ssize_t recved;  
54 -  
55 - recved = recv(fd, buf, len, 0);  
56 -  
57 - if (recved < 0) {  
58 - /* Handle error. */  
59 - }  
60 -  
61 - /* Start up / continue the parser.  
62 - * Note we pass recved==0 to signal that EOF has been recieved.  
63 - */  
64 - nparsed = http_parser_execute(parser, &settings, buf, recved);  
65 -  
66 - if (parser->upgrade) {  
67 - /* handle new protocol */  
68 - } else if (nparsed != recved) {  
69 - /* Handle error. Usually just close the connection. */  
70 - }  
71 -  
72 -HTTP needs to know where the end of the stream is. For example, sometimes  
73 -servers send responses without Content-Length and expect the client to  
74 -consume input (for the body) until EOF. To tell http_parser about EOF, give  
75 -`0` as the forth parameter to `http_parser_execute()`. Callbacks and errors  
76 -can still be encountered during an EOF, so one must still be prepared  
77 -to receive them.  
78 -  
79 -Scalar valued message information such as `status_code`, `method`, and the  
80 -HTTP version are stored in the parser structure. This data is only  
81 -temporally stored in `http_parser` and gets reset on each new message. If  
82 -this information is needed later, copy it out of the structure during the  
83 -`headers_complete` callback.  
84 -  
85 -The parser decodes the transfer-encoding for both requests and responses  
86 -transparently. That is, a chunked encoding is decoded before being sent to  
87 -the on_body callback.  
88 -  
89 -  
90 -The Special Problem of Upgrade  
91 -------------------------------  
92 -  
93 -HTTP supports upgrading the connection to a different protocol. An  
94 -increasingly common example of this is the Web Socket protocol which sends  
95 -a request like  
96 -  
97 - GET /demo HTTP/1.1  
98 - Upgrade: WebSocket  
99 - Connection: Upgrade  
100 - Host: example.com  
101 - Origin: http://example.com  
102 - WebSocket-Protocol: sample  
103 -  
104 -followed by non-HTTP data.  
105 -  
106 -(See http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-75 for more  
107 -information the Web Socket protocol.)  
108 -  
109 -To support this, the parser will treat this as a normal HTTP message without a  
110 -body. Issuing both on_headers_complete and on_message_complete callbacks. However  
111 -http_parser_execute() will stop parsing at the end of the headers and return.  
112 -  
113 -The user is expected to check if `parser->upgrade` has been set to 1 after  
114 -`http_parser_execute()` returns. Non-HTTP data begins at the buffer supplied  
115 -offset by the return value of `http_parser_execute()`.  
116 -  
117 -  
118 -Callbacks  
119 ----------  
120 -  
121 -During the `http_parser_execute()` call, the callbacks set in  
122 -`http_parser_settings` will be executed. The parser maintains state and  
123 -never looks behind, so buffering the data is not necessary. If you need to  
124 -save certain data for later usage, you can do that from the callbacks.  
125 -  
126 -There are two types of callbacks:  
127 -  
128 -* notification `typedef int (*http_cb) (http_parser*);`  
129 - Callbacks: on_message_begin, on_headers_complete, on_message_complete.  
130 -* data `typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);`  
131 - Callbacks: (requests only) on_uri,  
132 - (common) on_header_field, on_header_value, on_body;  
133 -  
134 -Callbacks must return 0 on success. Returning a non-zero value indicates  
135 -error to the parser, making it exit immediately.  
136 -  
137 -In case you parse HTTP message in chunks (i.e. `read()` request line  
138 -from socket, parse, read half headers, parse, etc) your data callbacks  
139 -may be called more than once. Http-parser guarantees that data pointer is only  
140 -valid for the lifetime of callback. You can also `read()` into a heap allocated  
141 -buffer to avoid copying memory around if this fits your application.  
142 -  
143 -Reading headers may be a tricky task if you read/parse headers partially.  
144 -Basically, you need to remember whether last header callback was field or value  
145 -and apply following logic:  
146 -  
147 - (on_header_field and on_header_value shortened to on_h_*)  
148 - ------------------------ ------------ --------------------------------------------  
149 - | State (prev. callback) | Callback | Description/action |  
150 - ------------------------ ------------ --------------------------------------------  
151 - | nothing (first call) | on_h_field | Allocate new buffer and copy callback data |  
152 - | | | into it |  
153 - ------------------------ ------------ --------------------------------------------  
154 - | value | on_h_field | New header started. |  
155 - | | | Copy current name,value buffers to headers |  
156 - | | | list and allocate new buffer for new name |  
157 - ------------------------ ------------ --------------------------------------------  
158 - | field | on_h_field | Previous name continues. Reallocate name |  
159 - | | | buffer and append callback data to it |  
160 - ------------------------ ------------ --------------------------------------------  
161 - | field | on_h_value | Value for current header started. Allocate |  
162 - | | | new buffer and copy callback data to it |  
163 - ------------------------ ------------ --------------------------------------------  
164 - | value | on_h_value | Value continues. Reallocate value buffer |  
165 - | | | and append callback data to it |  
166 - ------------------------ ------------ --------------------------------------------  
167 -  
168 -  
169 -Parsing URLs  
170 -------------  
171 -  
172 -A simplistic zero-copy URL parser is provided as `http_parser_parse_url()`.  
173 -Users of this library may wish to use it to parse URLs constructed from  
174 -consecutive `on_url` callbacks.  
175 -  
176 -See examples of reading in headers:  
177 -  
178 -* [partial example](http://gist.github.com/155877) in C  
179 -* [from http-parser tests](http://github.com/joyent/http-parser/blob/37a0ff8/test.c#L403) in C  
180 -* [from Node library](http://github.com/joyent/node/blob/842eaf4/src/http.js#L284) in Javascript  
3rdparty/http-parser-2.1/contrib/parsertrace.c deleted
1 -/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev  
2 - *  
3 - * Additional changes are licensed under the same terms as NGINX and  
4 - * copyright Joyent, Inc. and other Node contributors. All rights reserved.  
5 - *  
6 - * Permission is hereby granted, free of charge, to any person obtaining a copy  
7 - * of this software and associated documentation files (the "Software"), to  
8 - * deal in the Software without restriction, including without limitation the  
9 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
10 - * sell copies of the Software, and to permit persons to whom the Software is  
11 - * furnished to do so, subject to the following conditions:  
12 - *  
13 - * The above copyright notice and this permission notice shall be included in  
14 - * all copies or substantial portions of the Software.  
15 - *  
16 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
18 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
19 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
20 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
21 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS  
22 - * IN THE SOFTWARE.  
23 - */  
24 -  
25 -/* Dump what the parser finds to stdout as it happen */  
26 -  
27 -#include "http_parser.h"  
28 -#include <stdio.h>  
29 -#include <stdlib.h>  
30 -#include <string.h>  
31 -  
32 -int on_message_begin(http_parser* _) {  
33 - (void)_;  
34 - printf("\n***MESSAGE BEGIN***\n\n");  
35 - return 0;  
36 -}  
37 -  
38 -int on_headers_complete(http_parser* _) {  
39 - (void)_;  
40 - printf("\n***HEADERS COMPLETE***\n\n");  
41 - return 0;  
42 -}  
43 -  
44 -int on_message_complete(http_parser* _) {  
45 - (void)_;  
46 - printf("\n***MESSAGE COMPLETE***\n\n");  
47 - return 0;  
48 -}  
49 -  
50 -int on_url(http_parser* _, const char* at, size_t length) {  
51 - (void)_;  
52 - printf("Url: %.*s\n", (int)length, at);  
53 - return 0;  
54 -}  
55 -  
56 -int on_header_field(http_parser* _, const char* at, size_t length) {  
57 - (void)_;  
58 - printf("Header field: %.*s\n", (int)length, at);  
59 - return 0;  
60 -}  
61 -  
62 -int on_header_value(http_parser* _, const char* at, size_t length) {  
63 - (void)_;  
64 - printf("Header value: %.*s\n", (int)length, at);  
65 - return 0;  
66 -}  
67 -  
68 -int on_body(http_parser* _, const char* at, size_t length) {  
69 - (void)_;  
70 - printf("Body: %.*s\n", (int)length, at);  
71 - return 0;  
72 -}  
73 -  
74 -void usage(const char* name) {  
75 - fprintf(stderr,  
76 - "Usage: %s $type $filename\n"  
77 - " type: -x, where x is one of {r,b,q}\n"  
78 - " parses file as a Response, reQuest, or Both\n",  
79 - name);  
80 - exit(EXIT_FAILURE);  
81 -}  
82 -  
83 -int main(int argc, char* argv[]) {  
84 - enum http_parser_type file_type;  
85 -  
86 - if (argc != 3) {  
87 - usage(argv[0]);  
88 - }  
89 -  
90 - char* type = argv[1];  
91 - if (type[0] != '-') {  
92 - usage(argv[0]);  
93 - }  
94 -  
95 - switch (type[1]) {  
96 - /* in the case of "-", type[1] will be NUL */  
97 - case 'r':  
98 - file_type = HTTP_RESPONSE;  
99 - break;  
100 - case 'q':  
101 - file_type = HTTP_REQUEST;  
102 - break;  
103 - case 'b':  
104 - file_type = HTTP_BOTH;  
105 - break;  
106 - default:  
107 - usage(argv[0]);  
108 - }  
109 -  
110 - char* filename = argv[2];  
111 - FILE* file = fopen(filename, "r");  
112 - if (file == NULL) {  
113 - perror("fopen");  
114 - return EXIT_FAILURE;  
115 - }  
116 -  
117 - fseek(file, 0, SEEK_END);  
118 - long file_length = ftell(file);  
119 - if (file_length == -1) {  
120 - perror("ftell");  
121 - return EXIT_FAILURE;  
122 - }  
123 - fseek(file, 0, SEEK_SET);  
124 -  
125 - char* data = malloc(file_length);  
126 - if (fread(data, 1, file_length, file) != (size_t)file_length) {  
127 - fprintf(stderr, "couldn't read entire file\n");  
128 - free(data);  
129 - return EXIT_FAILURE;  
130 - }  
131 -  
132 - http_parser_settings settings;  
133 - memset(&settings, 0, sizeof(settings));  
134 - settings.on_message_begin = on_message_begin;  
135 - settings.on_url = on_url;  
136 - settings.on_header_field = on_header_field;  
137 - settings.on_header_value = on_header_value;  
138 - settings.on_headers_complete = on_headers_complete;  
139 - settings.on_body = on_body;  
140 - settings.on_message_complete = on_message_complete;  
141 -  
142 - http_parser parser;  
143 - http_parser_init(&parser, file_type);  
144 - size_t nparsed = http_parser_execute(&parser, &settings, data, file_length);  
145 - free(data);  
146 -  
147 - if (nparsed != (size_t)file_length) {  
148 - fprintf(stderr,  
149 - "Error: %s (%s)\n",  
150 - http_errno_description(HTTP_PARSER_ERRNO(&parser)),  
151 - http_errno_name(HTTP_PARSER_ERRNO(&parser)));  
152 - return EXIT_FAILURE;  
153 - }  
154 -  
155 - return EXIT_SUCCESS;  
156 -}  
3rdparty/http-parser-2.1/contrib/url_parser.c deleted
1 -#include "http_parser.h"  
2 -#include <stdio.h>  
3 -#include <string.h>  
4 -  
5 -void  
6 -dump_url (const char *url, const struct http_parser_url *u)  
7 -{  
8 - unsigned int i;  
9 -  
10 - printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);  
11 - for (i = 0; i < UF_MAX; i++) {  
12 - if ((u->field_set & (1 << i)) == 0) {  
13 - printf("\tfield_data[%u]: unset\n", i);  
14 - continue;  
15 - }  
16 -  
17 - printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n",  
18 - i,  
19 - u->field_data[i].off,  
20 - u->field_data[i].len,  
21 - u->field_data[i].len,  
22 - url + u->field_data[i].off);  
23 - }  
24 -}  
25 -  
26 -int main(int argc, char ** argv) {  
27 - if (argc != 3) {  
28 - printf("Syntax : %s connect|get url\n", argv[0]);  
29 - return 1;  
30 - }  
31 - struct http_parser_url u;  
32 - int len = strlen(argv[2]);  
33 - int connect = strcmp("connect", argv[1]) == 0 ? 1 : 0;  
34 - printf("Parsing %s, connect %d\n", argv[2], connect);  
35 -  
36 - int result = http_parser_parse_url(argv[2], len, connect, &u);  
37 - if (result != 0) {  
38 - printf("Parse error : %d\n", result);  
39 - return result;  
40 - }  
41 - printf("Parse ok, result : \n");  
42 - dump_url(argv[2], &u);  
43 - return 0;  
44 -}  
45 \ No newline at end of file 0 \ No newline at end of file
3rdparty/http-parser-2.1/http_parser.c deleted
1 -/* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev  
2 - *  
3 - * Additional changes are licensed under the same terms as NGINX and  
4 - * copyright Joyent, Inc. and other Node contributors. All rights reserved.  
5 - *  
6 - * Permission is hereby granted, free of charge, to any person obtaining a copy  
7 - * of this software and associated documentation files (the "Software"), to  
8 - * deal in the Software without restriction, including without limitation the  
9 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
10 - * sell copies of the Software, and to permit persons to whom the Software is  
11 - * furnished to do so, subject to the following conditions:  
12 - *  
13 - * The above copyright notice and this permission notice shall be included in  
14 - * all copies or substantial portions of the Software.  
15 - *  
16 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
17 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
18 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
19 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
20 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
21 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS  
22 - * IN THE SOFTWARE.  
23 - */  
24 -#include "http_parser.h"  
25 -#include <assert.h>  
26 -#include <stddef.h>  
27 -#include <ctype.h>  
28 -#include <stdlib.h>  
29 -#include <string.h>  
30 -#include <limits.h>  
31 -  
32 -#ifndef ULLONG_MAX  
33 -# define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */  
34 -#endif  
35 -  
36 -#ifndef MIN  
37 -# define MIN(a,b) ((a) < (b) ? (a) : (b))  
38 -#endif  
39 -  
40 -#ifndef ARRAY_SIZE  
41 -# define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))  
42 -#endif  
43 -  
44 -#ifndef BIT_AT  
45 -# define BIT_AT(a, i) \  
46 - (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \  
47 - (1 << ((unsigned int) (i) & 7))))  
48 -#endif  
49 -  
50 -#ifndef ELEM_AT  
51 -# define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))  
52 -#endif  
53 -  
54 -#define SET_ERRNO(e) \  
55 -do { \  
56 - parser->http_errno = (e); \  
57 -} while(0)  
58 -  
59 -  
60 -/* Run the notify callback FOR, returning ER if it fails */  
61 -#define CALLBACK_NOTIFY_(FOR, ER) \  
62 -do { \  
63 - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \  
64 - \  
65 - if (settings->on_##FOR) { \  
66 - if (0 != settings->on_##FOR(parser)) { \  
67 - SET_ERRNO(HPE_CB_##FOR); \  
68 - } \  
69 - \  
70 - /* We either errored above or got paused; get out */ \  
71 - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \  
72 - return (ER); \  
73 - } \  
74 - } \  
75 -} while (0)  
76 -  
77 -/* Run the notify callback FOR and consume the current byte */  
78 -#define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)  
79 -  
80 -/* Run the notify callback FOR and don't consume the current byte */  
81 -#define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)  
82 -  
83 -/* Run data callback FOR with LEN bytes, returning ER if it fails */  
84 -#define CALLBACK_DATA_(FOR, LEN, ER) \  
85 -do { \  
86 - assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \  
87 - \  
88 - if (FOR##_mark) { \  
89 - if (settings->on_##FOR) { \  
90 - if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \  
91 - SET_ERRNO(HPE_CB_##FOR); \  
92 - } \  
93 - \  
94 - /* We either errored above or got paused; get out */ \  
95 - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \  
96 - return (ER); \  
97 - } \  
98 - } \  
99 - FOR##_mark = NULL; \  
100 - } \  
101 -} while (0)  
102 -  
103 -/* Run the data callback FOR and consume the current byte */  
104 -#define CALLBACK_DATA(FOR) \  
105 - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)  
106 -  
107 -/* Run the data callback FOR and don't consume the current byte */  
108 -#define CALLBACK_DATA_NOADVANCE(FOR) \  
109 - CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)  
110 -  
111 -/* Set the mark FOR; non-destructive if mark is already set */  
112 -#define MARK(FOR) \  
113 -do { \  
114 - if (!FOR##_mark) { \  
115 - FOR##_mark = p; \  
116 - } \  
117 -} while (0)  
118 -  
119 -  
120 -#define PROXY_CONNECTION "proxy-connection"  
121 -#define CONNECTION "connection"  
122 -#define CONTENT_LENGTH "content-length"  
123 -#define TRANSFER_ENCODING "transfer-encoding"  
124 -#define UPGRADE "upgrade"  
125 -#define CHUNKED "chunked"  
126 -#define KEEP_ALIVE "keep-alive"  
127 -#define CLOSE "close"  
128 -  
129 -  
130 -static const char *method_strings[] =  
131 - {  
132 -#define XX(num, name, string) #string,  
133 - HTTP_METHOD_MAP(XX)  
134 -#undef XX  
135 - };  
136 -  
137 -  
138 -/* Tokens as defined by rfc 2616. Also lowercases them.  
139 - * token = 1*<any CHAR except CTLs or separators>  
140 - * separators = "(" | ")" | "<" | ">" | "@"  
141 - * | "," | ";" | ":" | "\" | <">  
142 - * | "/" | "[" | "]" | "?" | "="  
143 - * | "{" | "}" | SP | HT  
144 - */  
145 -static const char tokens[256] = {  
146 -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */  
147 - 0, 0, 0, 0, 0, 0, 0, 0,  
148 -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */  
149 - 0, 0, 0, 0, 0, 0, 0, 0,  
150 -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */  
151 - 0, 0, 0, 0, 0, 0, 0, 0,  
152 -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */  
153 - 0, 0, 0, 0, 0, 0, 0, 0,  
154 -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */  
155 - 0, '!', 0, '#', '$', '%', '&', '\'',  
156 -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */  
157 - 0, 0, '*', '+', 0, '-', '.', 0,  
158 -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */  
159 - '0', '1', '2', '3', '4', '5', '6', '7',  
160 -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */  
161 - '8', '9', 0, 0, 0, 0, 0, 0,  
162 -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */  
163 - 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',  
164 -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */  
165 - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',  
166 -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */  
167 - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  
168 -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */  
169 - 'x', 'y', 'z', 0, 0, 0, '^', '_',  
170 -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */  
171 - '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',  
172 -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */  
173 - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',  
174 -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */  
175 - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',  
176 -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */  
177 - 'x', 'y', 'z', 0, '|', 0, '~', 0 };  
178 -  
179 -  
180 -static const int8_t unhex[256] =  
181 - {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  
182 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  
183 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  
184 - , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1  
185 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1  
186 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  
187 - ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1  
188 - ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1  
189 - };  
190 -  
191 -  
192 -#if HTTP_PARSER_STRICT  
193 -# define T(v) 0  
194 -#else  
195 -# define T(v) v  
196 -#endif  
197 -  
198 -  
199 -static const uint8_t normal_url_char[32] = {  
200 -/* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */  
201 - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,  
202 -/* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */  
203 - 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,  
204 -/* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */  
205 - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,  
206 -/* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */  
207 - 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,  
208 -/* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */  
209 - 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,  
210 -/* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */  
211 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
212 -/* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */  
213 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
214 -/* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */  
215 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,  
216 -/* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */  
217 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
218 -/* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */  
219 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
220 -/* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */  
221 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
222 -/* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */  
223 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
224 -/* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */  
225 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
226 -/* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */  
227 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
228 -/* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */  
229 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,  
230 -/* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */  
231 - 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };  
232 -  
233 -#undef T  
234 -  
235 -enum state  
236 - { s_dead = 1 /* important that this is > 0 */  
237 -  
238 - , s_start_req_or_res  
239 - , s_res_or_resp_H  
240 - , s_start_res  
241 - , s_res_H  
242 - , s_res_HT  
243 - , s_res_HTT  
244 - , s_res_HTTP  
245 - , s_res_first_http_major  
246 - , s_res_http_major  
247 - , s_res_first_http_minor  
248 - , s_res_http_minor  
249 - , s_res_first_status_code  
250 - , s_res_status_code  
251 - , s_res_status  
252 - , s_res_line_almost_done  
253 -  
254 - , s_start_req  
255 -  
256 - , s_req_method  
257 - , s_req_spaces_before_url  
258 - , s_req_schema  
259 - , s_req_schema_slash  
260 - , s_req_schema_slash_slash  
261 - , s_req_server_start  
262 - , s_req_server  
263 - , s_req_server_with_at  
264 - , s_req_path  
265 - , s_req_query_string_start  
266 - , s_req_query_string  
267 - , s_req_fragment_start  
268 - , s_req_fragment  
269 - , s_req_http_start  
270 - , s_req_http_H  
271 - , s_req_http_HT  
272 - , s_req_http_HTT  
273 - , s_req_http_HTTP  
274 - , s_req_first_http_major  
275 - , s_req_http_major  
276 - , s_req_first_http_minor  
277 - , s_req_http_minor  
278 - , s_req_line_almost_done  
279 -  
280 - , s_header_field_start  
281 - , s_header_field  
282 - , s_header_value_start  
283 - , s_header_value  
284 - , s_header_value_lws  
285 -  
286 - , s_header_almost_done  
287 -  
288 - , s_chunk_size_start  
289 - , s_chunk_size  
290 - , s_chunk_parameters  
291 - , s_chunk_size_almost_done  
292 -  
293 - , s_headers_almost_done  
294 - , s_headers_done  
295 -  
296 - /* Important: 's_headers_done' must be the last 'header' state. All  
297 - * states beyond this must be 'body' states. It is used for overflow  
298 - * checking. See the PARSING_HEADER() macro.  
299 - */  
300 -  
301 - , s_chunk_data  
302 - , s_chunk_data_almost_done  
303 - , s_chunk_data_done  
304 -  
305 - , s_body_identity  
306 - , s_body_identity_eof  
307 -  
308 - , s_message_done  
309 - };  
310 -  
311 -  
312 -#define PARSING_HEADER(state) (state <= s_headers_done)  
313 -  
314 -  
315 -enum header_states  
316 - { h_general = 0  
317 - , h_C  
318 - , h_CO  
319 - , h_CON  
320 -  
321 - , h_matching_connection  
322 - , h_matching_proxy_connection  
323 - , h_matching_content_length  
324 - , h_matching_transfer_encoding  
325 - , h_matching_upgrade  
326 -  
327 - , h_connection  
328 - , h_content_length  
329 - , h_transfer_encoding  
330 - , h_upgrade  
331 -  
332 - , h_matching_transfer_encoding_chunked  
333 - , h_matching_connection_keep_alive  
334 - , h_matching_connection_close  
335 -  
336 - , h_transfer_encoding_chunked  
337 - , h_connection_keep_alive  
338 - , h_connection_close  
339 - };  
340 -  
341 -enum http_host_state  
342 - {  
343 - s_http_host_dead = 1  
344 - , s_http_userinfo_start  
345 - , s_http_userinfo  
346 - , s_http_host_start  
347 - , s_http_host_v6_start  
348 - , s_http_host  
349 - , s_http_host_v6  
350 - , s_http_host_v6_end  
351 - , s_http_host_port_start  
352 - , s_http_host_port  
353 -};  
354 -  
355 -/* Macros for character classes; depends on strict-mode */  
356 -#define CR '\r'  
357 -#define LF '\n'  
358 -#define LOWER(c) (unsigned char)(c | 0x20)  
359 -#define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')  
360 -#define IS_NUM(c) ((c) >= '0' && (c) <= '9')  
361 -#define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))  
362 -#define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))  
363 -#define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \  
364 - (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \  
365 - (c) == ')')  
366 -#define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \  
367 - (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \  
368 - (c) == '$' || (c) == ',')  
369 -  
370 -#if HTTP_PARSER_STRICT  
371 -#define TOKEN(c) (tokens[(unsigned char)c])  
372 -#define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))  
373 -#define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')  
374 -#else  
375 -#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])  
376 -#define IS_URL_CHAR(c) \  
377 - (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))  
378 -#define IS_HOST_CHAR(c) \  
379 - (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')  
380 -#endif  
381 -  
382 -  
383 -#define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)  
384 -  
385 -  
386 -#if HTTP_PARSER_STRICT  
387 -# define STRICT_CHECK(cond) \  
388 -do { \  
389 - if (cond) { \  
390 - SET_ERRNO(HPE_STRICT); \  
391 - goto error; \  
392 - } \  
393 -} while (0)  
394 -# define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)  
395 -#else  
396 -# define STRICT_CHECK(cond)  
397 -# define NEW_MESSAGE() start_state  
398 -#endif  
399 -  
400 -  
401 -/* Map errno values to strings for human-readable output */  
402 -#define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },  
403 -static struct {  
404 - const char *name;  
405 - const char *description;  
406 -} http_strerror_tab[] = {  
407 - HTTP_ERRNO_MAP(HTTP_STRERROR_GEN)  
408 -};  
409 -#undef HTTP_STRERROR_GEN  
410 -  
411 -int http_message_needs_eof(const http_parser *parser);  
412 -  
413 -/* Our URL parser.  
414 - *  
415 - * This is designed to be shared by http_parser_execute() for URL validation,  
416 - * hence it has a state transition + byte-for-byte interface. In addition, it  
417 - * is meant to be embedded in http_parser_parse_url(), which does the dirty  
418 - * work of turning state transitions URL components for its API.  
419 - *  
420 - * This function should only be invoked with non-space characters. It is  
421 - * assumed that the caller cares about (and can detect) the transition between  
422 - * URL and non-URL states by looking for these.  
423 - */  
424 -static enum state  
425 -parse_url_char(enum state s, const char ch)  
426 -{  
427 - if (ch == ' ' || ch == '\r' || ch == '\n') {  
428 - return s_dead;  
429 - }  
430 -  
431 -#if HTTP_PARSER_STRICT  
432 - if (ch == '\t' || ch == '\f') {  
433 - return s_dead;  
434 - }  
435 -#endif  
436 -  
437 - switch (s) {  
438 - case s_req_spaces_before_url:  
439 - /* Proxied requests are followed by scheme of an absolute URI (alpha).  
440 - * All methods except CONNECT are followed by '/' or '*'.  
441 - */  
442 -  
443 - if (ch == '/' || ch == '*') {  
444 - return s_req_path;  
445 - }  
446 -  
447 - if (IS_ALPHA(ch)) {  
448 - return s_req_schema;  
449 - }  
450 -  
451 - break;  
452 -  
453 - case s_req_schema:  
454 - if (IS_ALPHA(ch)) {  
455 - return s;  
456 - }  
457 -  
458 - if (ch == ':') {  
459 - return s_req_schema_slash;  
460 - }  
461 -  
462 - break;  
463 -  
464 - case s_req_schema_slash:  
465 - if (ch == '/') {  
466 - return s_req_schema_slash_slash;  
467 - }  
468 -  
469 - break;  
470 -  
471 - case s_req_schema_slash_slash:  
472 - if (ch == '/') {  
473 - return s_req_server_start;  
474 - }  
475 -  
476 - break;  
477 -  
478 - case s_req_server_with_at:  
479 - if (ch == '@') {  
480 - return s_dead;  
481 - }  
482 -  
483 - /* FALLTHROUGH */  
484 - case s_req_server_start:  
485 - case s_req_server:  
486 - if (ch == '/') {  
487 - return s_req_path;  
488 - }  
489 -  
490 - if (ch == '?') {  
491 - return s_req_query_string_start;  
492 - }  
493 -  
494 - if (ch == '@') {  
495 - return s_req_server_with_at;  
496 - }  
497 -  
498 - if (IS_USERINFO_CHAR(ch) || ch == '[' || ch == ']') {  
499 - return s_req_server;  
500 - }  
501 -  
502 - break;  
503 -  
504 - case s_req_path:  
505 - if (IS_URL_CHAR(ch)) {  
506 - return s;  
507 - }  
508 -  
509 - switch (ch) {  
510 - case '?':  
511 - return s_req_query_string_start;  
512 -  
513 - case '#':  
514 - return s_req_fragment_start;  
515 - }  
516 -  
517 - break;  
518 -  
519 - case s_req_query_string_start:  
520 - case s_req_query_string:  
521 - if (IS_URL_CHAR(ch)) {  
522 - return s_req_query_string;  
523 - }  
524 -  
525 - switch (ch) {  
526 - case '?':  
527 - /* allow extra '?' in query string */  
528 - return s_req_query_string;  
529 -  
530 - case '#':  
531 - return s_req_fragment_start;  
532 - }  
533 -  
534 - break;  
535 -  
536 - case s_req_fragment_start:  
537 - if (IS_URL_CHAR(ch)) {  
538 - return s_req_fragment;  
539 - }  
540 -  
541 - switch (ch) {  
542 - case '?':  
543 - return s_req_fragment;  
544 -  
545 - case '#':  
546 - return s;  
547 - }  
548 -  
549 - break;  
550 -  
551 - case s_req_fragment:  
552 - if (IS_URL_CHAR(ch)) {  
553 - return s;  
554 - }  
555 -  
556 - switch (ch) {  
557 - case '?':  
558 - case '#':  
559 - return s;  
560 - }  
561 -  
562 - break;  
563 -  
564 - default:  
565 - break;  
566 - }  
567 -  
568 - /* We should never fall out of the switch above unless there's an error */  
569 - return s_dead;  
570 -}  
571 -  
572 -size_t http_parser_execute (http_parser *parser,  
573 - const http_parser_settings *settings,  
574 - const char *data,  
575 - size_t len)  
576 -{  
577 - char c, ch;  
578 - int8_t unhex_val;  
579 - const char *p = data;  
580 - const char *header_field_mark = 0;  
581 - const char *header_value_mark = 0;  
582 - const char *url_mark = 0;  
583 - const char *body_mark = 0;  
584 -  
585 - /* We're in an error state. Don't bother doing anything. */  
586 - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {  
587 - return 0;  
588 - }  
589 -  
590 - if (len == 0) {  
591 - switch (parser->state) {  
592 - case s_body_identity_eof:  
593 - /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if  
594 - * we got paused.  
595 - */  
596 - CALLBACK_NOTIFY_NOADVANCE(message_complete);  
597 - return 0;  
598 -  
599 - case s_dead:  
600 - case s_start_req_or_res:  
601 - case s_start_res:  
602 - case s_start_req:  
603 - return 0;  
604 -  
605 - default:  
606 - SET_ERRNO(HPE_INVALID_EOF_STATE);  
607 - return 1;  
608 - }  
609 - }  
610 -  
611 -  
612 - if (parser->state == s_header_field)  
613 - header_field_mark = data;  
614 - if (parser->state == s_header_value)  
615 - header_value_mark = data;  
616 - switch (parser->state) {  
617 - case s_req_path:  
618 - case s_req_schema:  
619 - case s_req_schema_slash:  
620 - case s_req_schema_slash_slash:  
621 - case s_req_server_start:  
622 - case s_req_server:  
623 - case s_req_server_with_at:  
624 - case s_req_query_string_start:  
625 - case s_req_query_string:  
626 - case s_req_fragment_start:  
627 - case s_req_fragment:  
628 - url_mark = data;  
629 - break;  
630 - }  
631 -  
632 - for (p=data; p != data + len; p++) {  
633 - ch = *p;  
634 -  
635 - if (PARSING_HEADER(parser->state)) {  
636 - ++parser->nread;  
637 - /* Buffer overflow attack */  
638 - if (parser->nread > HTTP_MAX_HEADER_SIZE) {  
639 - SET_ERRNO(HPE_HEADER_OVERFLOW);  
640 - goto error;  
641 - }  
642 - }  
643 -  
644 - reexecute_byte:  
645 - switch (parser->state) {  
646 -  
647 - case s_dead:  
648 - /* this state is used after a 'Connection: close' message  
649 - * the parser will error out if it reads another message  
650 - */  
651 - if (ch == CR || ch == LF)  
652 - break;  
653 -  
654 - SET_ERRNO(HPE_CLOSED_CONNECTION);  
655 - goto error;  
656 -  
657 - case s_start_req_or_res:  
658 - {  
659 - if (ch == CR || ch == LF)  
660 - break;  
661 - parser->flags = 0;  
662 - parser->content_length = ULLONG_MAX;  
663 -  
664 - if (ch == 'H') {  
665 - parser->state = s_res_or_resp_H;  
666 -  
667 - CALLBACK_NOTIFY(message_begin);  
668 - } else {  
669 - parser->type = HTTP_REQUEST;  
670 - parser->state = s_start_req;  
671 - goto reexecute_byte;  
672 - }  
673 -  
674 - break;  
675 - }  
676 -  
677 - case s_res_or_resp_H:  
678 - if (ch == 'T') {  
679 - parser->type = HTTP_RESPONSE;  
680 - parser->state = s_res_HT;  
681 - } else {  
682 - if (ch != 'E') {  
683 - SET_ERRNO(HPE_INVALID_CONSTANT);  
684 - goto error;  
685 - }  
686 -  
687 - parser->type = HTTP_REQUEST;  
688 - parser->method = HTTP_HEAD;  
689 - parser->index = 2;  
690 - parser->state = s_req_method;  
691 - }  
692 - break;  
693 -  
694 - case s_start_res:  
695 - {  
696 - parser->flags = 0;  
697 - parser->content_length = ULLONG_MAX;  
698 -  
699 - switch (ch) {  
700 - case 'H':  
701 - parser->state = s_res_H;  
702 - break;  
703 -  
704 - case CR:  
705 - case LF:  
706 - break;  
707 -  
708 - default:  
709 - SET_ERRNO(HPE_INVALID_CONSTANT);  
710 - goto error;  
711 - }  
712 -  
713 - CALLBACK_NOTIFY(message_begin);  
714 - break;  
715 - }  
716 -  
717 - case s_res_H:  
718 - STRICT_CHECK(ch != 'T');  
719 - parser->state = s_res_HT;  
720 - break;  
721 -  
722 - case s_res_HT:  
723 - STRICT_CHECK(ch != 'T');  
724 - parser->state = s_res_HTT;  
725 - break;  
726 -  
727 - case s_res_HTT:  
728 - STRICT_CHECK(ch != 'P');  
729 - parser->state = s_res_HTTP;  
730 - break;  
731 -  
732 - case s_res_HTTP:  
733 - STRICT_CHECK(ch != '/');  
734 - parser->state = s_res_first_http_major;  
735 - break;  
736 -  
737 - case s_res_first_http_major:  
738 - if (ch < '0' || ch > '9') {  
739 - SET_ERRNO(HPE_INVALID_VERSION);  
740 - goto error;  
741 - }  
742 -  
743 - parser->http_major = ch - '0';  
744 - parser->state = s_res_http_major;  
745 - break;  
746 -  
747 - /* major HTTP version or dot */  
748 - case s_res_http_major:  
749 - {  
750 - if (ch == '.') {  
751 - parser->state = s_res_first_http_minor;  
752 - break;  
753 - }  
754 -  
755 - if (!IS_NUM(ch)) {  
756 - SET_ERRNO(HPE_INVALID_VERSION);  
757 - goto error;  
758 - }  
759 -  
760 - parser->http_major *= 10;  
761 - parser->http_major += ch - '0';  
762 -  
763 - if (parser->http_major > 999) {  
764 - SET_ERRNO(HPE_INVALID_VERSION);  
765 - goto error;  
766 - }  
767 -  
768 - break;  
769 - }  
770 -  
771 - /* first digit of minor HTTP version */  
772 - case s_res_first_http_minor:  
773 - if (!IS_NUM(ch)) {  
774 - SET_ERRNO(HPE_INVALID_VERSION);  
775 - goto error;  
776 - }  
777 -  
778 - parser->http_minor = ch - '0';  
779 - parser->state = s_res_http_minor;  
780 - break;  
781 -  
782 - /* minor HTTP version or end of request line */  
783 - case s_res_http_minor:  
784 - {  
785 - if (ch == ' ') {  
786 - parser->state = s_res_first_status_code;  
787 - break;  
788 - }  
789 -  
790 - if (!IS_NUM(ch)) {  
791 - SET_ERRNO(HPE_INVALID_VERSION);  
792 - goto error;  
793 - }  
794 -  
795 - parser->http_minor *= 10;  
796 - parser->http_minor += ch - '0';  
797 -  
798 - if (parser->http_minor > 999) {  
799 - SET_ERRNO(HPE_INVALID_VERSION);  
800 - goto error;  
801 - }  
802 -  
803 - break;  
804 - }  
805 -  
806 - case s_res_first_status_code:  
807 - {  
808 - if (!IS_NUM(ch)) {  
809 - if (ch == ' ') {  
810 - break;  
811 - }  
812 -  
813 - SET_ERRNO(HPE_INVALID_STATUS);  
814 - goto error;  
815 - }  
816 - parser->status_code = ch - '0';  
817 - parser->state = s_res_status_code;  
818 - break;  
819 - }  
820 -  
821 - case s_res_status_code:  
822 - {  
823 - if (!IS_NUM(ch)) {  
824 - switch (ch) {  
825 - case ' ':  
826 - parser->state = s_res_status;  
827 - break;  
828 - case CR:  
829 - parser->state = s_res_line_almost_done;  
830 - break;  
831 - case LF:  
832 - parser->state = s_header_field_start;  
833 - break;  
834 - default:  
835 - SET_ERRNO(HPE_INVALID_STATUS);  
836 - goto error;  
837 - }  
838 - break;  
839 - }  
840 -  
841 - parser->status_code *= 10;  
842 - parser->status_code += ch - '0';  
843 -  
844 - if (parser->status_code > 999) {  
845 - SET_ERRNO(HPE_INVALID_STATUS);  
846 - goto error;  
847 - }  
848 -  
849 - break;  
850 - }  
851 -  
852 - case s_res_status:  
853 - /* the human readable status. e.g. "NOT FOUND"  
854 - * we are not humans so just ignore this */  
855 - if (ch == CR) {  
856 - parser->state = s_res_line_almost_done;  
857 - break;  
858 - }  
859 -  
860 - if (ch == LF) {  
861 - parser->state = s_header_field_start;  
862 - break;  
863 - }  
864 - break;  
865 -  
866 - case s_res_line_almost_done:  
867 - STRICT_CHECK(ch != LF);  
868 - parser->state = s_header_field_start;  
869 - CALLBACK_NOTIFY(status_complete);  
870 - break;  
871 -  
872 - case s_start_req:  
873 - {  
874 - if (ch == CR || ch == LF)  
875 - break;  
876 - parser->flags = 0;  
877 - parser->content_length = ULLONG_MAX;  
878 -  
879 - if (!IS_ALPHA(ch)) {  
880 - SET_ERRNO(HPE_INVALID_METHOD);  
881 - goto error;  
882 - }  
883 -  
884 - parser->method = (enum http_method) 0;  
885 - parser->index = 1;  
886 - switch (ch) {  
887 - case 'C': parser->method = HTTP_CONNECT; /* or COPY, CHECKOUT */ break;  
888 - case 'D': parser->method = HTTP_DELETE; break;  
889 - case 'G': parser->method = HTTP_GET; break;  
890 - case 'H': parser->method = HTTP_HEAD; break;  
891 - case 'L': parser->method = HTTP_LOCK; break;  
892 - case 'M': parser->method = HTTP_MKCOL; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;  
893 - case 'N': parser->method = HTTP_NOTIFY; break;  
894 - case 'O': parser->method = HTTP_OPTIONS; break;  
895 - case 'P': parser->method = HTTP_POST;  
896 - /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE */  
897 - break;  
898 - case 'R': parser->method = HTTP_REPORT; break;  
899 - case 'S': parser->method = HTTP_SUBSCRIBE; /* or SEARCH */ break;  
900 - case 'T': parser->method = HTTP_TRACE; break;  
901 - case 'U': parser->method = HTTP_UNLOCK; /* or UNSUBSCRIBE */ break;  
902 - default:  
903 - SET_ERRNO(HPE_INVALID_METHOD);  
904 - goto error;  
905 - }  
906 - parser->state = s_req_method;  
907 -  
908 - CALLBACK_NOTIFY(message_begin);  
909 -  
910 - break;  
911 - }  
912 -  
913 - case s_req_method:  
914 - {  
915 - const char *matcher;  
916 - if (ch == '\0') {  
917 - SET_ERRNO(HPE_INVALID_METHOD);  
918 - goto error;  
919 - }  
920 -  
921 - matcher = method_strings[parser->method];  
922 - if (ch == ' ' && matcher[parser->index] == '\0') {  
923 - parser->state = s_req_spaces_before_url;  
924 - } else if (ch == matcher[parser->index]) {  
925 - ; /* nada */  
926 - } else if (parser->method == HTTP_CONNECT) {  
927 - if (parser->index == 1 && ch == 'H') {  
928 - parser->method = HTTP_CHECKOUT;  
929 - } else if (parser->index == 2 && ch == 'P') {  
930 - parser->method = HTTP_COPY;  
931 - } else {  
932 - goto error;  
933 - }  
934 - } else if (parser->method == HTTP_MKCOL) {  
935 - if (parser->index == 1 && ch == 'O') {  
936 - parser->method = HTTP_MOVE;  
937 - } else if (parser->index == 1 && ch == 'E') {  
938 - parser->method = HTTP_MERGE;  
939 - } else if (parser->index == 1 && ch == '-') {  
940 - parser->method = HTTP_MSEARCH;  
941 - } else if (parser->index == 2 && ch == 'A') {  
942 - parser->method = HTTP_MKACTIVITY;  
943 - } else {  
944 - goto error;  
945 - }  
946 - } else if (parser->method == HTTP_SUBSCRIBE) {  
947 - if (parser->index == 1 && ch == 'E') {  
948 - parser->method = HTTP_SEARCH;  
949 - } else {  
950 - goto error;  
951 - }  
952 - } else if (parser->index == 1 && parser->method == HTTP_POST) {  
953 - if (ch == 'R') {  
954 - parser->method = HTTP_PROPFIND; /* or HTTP_PROPPATCH */  
955 - } else if (ch == 'U') {  
956 - parser->method = HTTP_PUT; /* or HTTP_PURGE */  
957 - } else if (ch == 'A') {  
958 - parser->method = HTTP_PATCH;  
959 - } else {  
960 - goto error;  
961 - }  
962 - } else if (parser->index == 2) {  
963 - if (parser->method == HTTP_PUT) {  
964 - if (ch == 'R') parser->method = HTTP_PURGE;  
965 - } else if (parser->method == HTTP_UNLOCK) {  
966 - if (ch == 'S') parser->method = HTTP_UNSUBSCRIBE;  
967 - }  
968 - } else if (parser->index == 4 && parser->method == HTTP_PROPFIND && ch == 'P') {  
969 - parser->method = HTTP_PROPPATCH;  
970 - } else {  
971 - SET_ERRNO(HPE_INVALID_METHOD);  
972 - goto error;  
973 - }  
974 -  
975 - ++parser->index;  
976 - break;  
977 - }  
978 -  
979 - case s_req_spaces_before_url:  
980 - {  
981 - if (ch == ' ') break;  
982 -  
983 - MARK(url);  
984 - if (parser->method == HTTP_CONNECT) {  
985 - parser->state = s_req_server_start;  
986 - }  
987 -  
988 - parser->state = parse_url_char((enum state)parser->state, ch);  
989 - if (parser->state == s_dead) {  
990 - SET_ERRNO(HPE_INVALID_URL);  
991 - goto error;  
992 - }  
993 -  
994 - break;  
995 - }  
996 -  
997 - case s_req_schema:  
998 - case s_req_schema_slash:  
999 - case s_req_schema_slash_slash:  
1000 - case s_req_server_start:  
1001 - {  
1002 - switch (ch) {  
1003 - /* No whitespace allowed here */  
1004 - case ' ':  
1005 - case CR:  
1006 - case LF:  
1007 - SET_ERRNO(HPE_INVALID_URL);  
1008 - goto error;  
1009 - default:  
1010 - parser->state = parse_url_char((enum state)parser->state, ch);  
1011 - if (parser->state == s_dead) {  
1012 - SET_ERRNO(HPE_INVALID_URL);  
1013 - goto error;  
1014 - }  
1015 - }  
1016 -  
1017 - break;  
1018 - }  
1019 -  
1020 - case s_req_server:  
1021 - case s_req_server_with_at:  
1022 - case s_req_path:  
1023 - case s_req_query_string_start:  
1024 - case s_req_query_string:  
1025 - case s_req_fragment_start:  
1026 - case s_req_fragment:  
1027 - {  
1028 - switch (ch) {  
1029 - case ' ':  
1030 - parser->state = s_req_http_start;  
1031 - CALLBACK_DATA(url);  
1032 - break;  
1033 - case CR:  
1034 - case LF:  
1035 - parser->http_major = 0;  
1036 - parser->http_minor = 9;  
1037 - parser->state = (ch == CR) ?  
1038 - s_req_line_almost_done :  
1039 - s_header_field_start;  
1040 - CALLBACK_DATA(url);  
1041 - break;  
1042 - default:  
1043 - parser->state = parse_url_char((enum state)parser->state, ch);  
1044 - if (parser->state == s_dead) {  
1045 - SET_ERRNO(HPE_INVALID_URL);  
1046 - goto error;  
1047 - }  
1048 - }  
1049 - break;  
1050 - }  
1051 -  
1052 - case s_req_http_start:  
1053 - switch (ch) {  
1054 - case 'H':  
1055 - parser->state = s_req_http_H;  
1056 - break;  
1057 - case ' ':  
1058 - break;  
1059 - default:  
1060 - SET_ERRNO(HPE_INVALID_CONSTANT);  
1061 - goto error;  
1062 - }  
1063 - break;  
1064 -  
1065 - case s_req_http_H:  
1066 - STRICT_CHECK(ch != 'T');  
1067 - parser->state = s_req_http_HT;  
1068 - break;  
1069 -  
1070 - case s_req_http_HT:  
1071 - STRICT_CHECK(ch != 'T');  
1072 - parser->state = s_req_http_HTT;  
1073 - break;  
1074 -  
1075 - case s_req_http_HTT:  
1076 - STRICT_CHECK(ch != 'P');  
1077 - parser->state = s_req_http_HTTP;  
1078 - break;  
1079 -  
1080 - case s_req_http_HTTP:  
1081 - STRICT_CHECK(ch != '/');  
1082 - parser->state = s_req_first_http_major;  
1083 - break;  
1084 -  
1085 - /* first digit of major HTTP version */  
1086 - case s_req_first_http_major:  
1087 - if (ch < '1' || ch > '9') {  
1088 - SET_ERRNO(HPE_INVALID_VERSION);  
1089 - goto error;  
1090 - }  
1091 -  
1092 - parser->http_major = ch - '0';  
1093 - parser->state = s_req_http_major;  
1094 - break;  
1095 -  
1096 - /* major HTTP version or dot */  
1097 - case s_req_http_major:  
1098 - {  
1099 - if (ch == '.') {  
1100 - parser->state = s_req_first_http_minor;  
1101 - break;  
1102 - }  
1103 -  
1104 - if (!IS_NUM(ch)) {  
1105 - SET_ERRNO(HPE_INVALID_VERSION);  
1106 - goto error;  
1107 - }  
1108 -  
1109 - parser->http_major *= 10;  
1110 - parser->http_major += ch - '0';  
1111 -  
1112 - if (parser->http_major > 999) {  
1113 - SET_ERRNO(HPE_INVALID_VERSION);  
1114 - goto error;  
1115 - }  
1116 -  
1117 - break;  
1118 - }  
1119 -  
1120 - /* first digit of minor HTTP version */  
1121 - case s_req_first_http_minor:  
1122 - if (!IS_NUM(ch)) {  
1123 - SET_ERRNO(HPE_INVALID_VERSION);  
1124 - goto error;  
1125 - }  
1126 -  
1127 - parser->http_minor = ch - '0';  
1128 - parser->state = s_req_http_minor;  
1129 - break;  
1130 -  
1131 - /* minor HTTP version or end of request line */  
1132 - case s_req_http_minor:  
1133 - {  
1134 - if (ch == CR) {  
1135 - parser->state = s_req_line_almost_done;  
1136 - break;  
1137 - }  
1138 -  
1139 - if (ch == LF) {  
1140 - parser->state = s_header_field_start;  
1141 - break;  
1142 - }  
1143 -  
1144 - /* XXX allow spaces after digit? */  
1145 -  
1146 - if (!IS_NUM(ch)) {  
1147 - SET_ERRNO(HPE_INVALID_VERSION);  
1148 - goto error;  
1149 - }  
1150 -  
1151 - parser->http_minor *= 10;  
1152 - parser->http_minor += ch - '0';  
1153 -  
1154 - if (parser->http_minor > 999) {  
1155 - SET_ERRNO(HPE_INVALID_VERSION);  
1156 - goto error;  
1157 - }  
1158 -  
1159 - break;  
1160 - }  
1161 -  
1162 - /* end of request line */  
1163 - case s_req_line_almost_done:  
1164 - {  
1165 - if (ch != LF) {  
1166 - SET_ERRNO(HPE_LF_EXPECTED);  
1167 - goto error;  
1168 - }  
1169 -  
1170 - parser->state = s_header_field_start;  
1171 - break;  
1172 - }  
1173 -  
1174 - case s_header_field_start:  
1175 - {  
1176 - if (ch == CR) {  
1177 - parser->state = s_headers_almost_done;  
1178 - break;  
1179 - }  
1180 -  
1181 - if (ch == LF) {  
1182 - /* they might be just sending \n instead of \r\n so this would be  
1183 - * the second \n to denote the end of headers*/  
1184 - parser->state = s_headers_almost_done;  
1185 - goto reexecute_byte;  
1186 - }  
1187 -  
1188 - c = TOKEN(ch);  
1189 -  
1190 - if (!c) {  
1191 - SET_ERRNO(HPE_INVALID_HEADER_TOKEN);  
1192 - goto error;  
1193 - }  
1194 -  
1195 - MARK(header_field);  
1196 -  
1197 - parser->index = 0;  
1198 - parser->state = s_header_field;  
1199 -  
1200 - switch (c) {  
1201 - case 'c':  
1202 - parser->header_state = h_C;  
1203 - break;  
1204 -  
1205 - case 'p':  
1206 - parser->header_state = h_matching_proxy_connection;  
1207 - break;  
1208 -  
1209 - case 't':  
1210 - parser->header_state = h_matching_transfer_encoding;  
1211 - break;  
1212 -  
1213 - case 'u':  
1214 - parser->header_state = h_matching_upgrade;  
1215 - break;  
1216 -  
1217 - default:  
1218 - parser->header_state = h_general;  
1219 - break;  
1220 - }  
1221 - break;  
1222 - }  
1223 -  
1224 - case s_header_field:  
1225 - {  
1226 - c = TOKEN(ch);  
1227 -  
1228 - if (c) {  
1229 - switch (parser->header_state) {  
1230 - case h_general:  
1231 - break;  
1232 -  
1233 - case h_C:  
1234 - parser->index++;  
1235 - parser->header_state = (c == 'o' ? h_CO : h_general);  
1236 - break;  
1237 -  
1238 - case h_CO:  
1239 - parser->index++;  
1240 - parser->header_state = (c == 'n' ? h_CON : h_general);  
1241 - break;  
1242 -  
1243 - case h_CON:  
1244 - parser->index++;  
1245 - switch (c) {  
1246 - case 'n':  
1247 - parser->header_state = h_matching_connection;  
1248 - break;  
1249 - case 't':  
1250 - parser->header_state = h_matching_content_length;  
1251 - break;  
1252 - default:  
1253 - parser->header_state = h_general;  
1254 - break;  
1255 - }  
1256 - break;  
1257 -  
1258 - /* connection */  
1259 -  
1260 - case h_matching_connection:  
1261 - parser->index++;  
1262 - if (parser->index > sizeof(CONNECTION)-1  
1263 - || c != CONNECTION[parser->index]) {  
1264 - parser->header_state = h_general;  
1265 - } else if (parser->index == sizeof(CONNECTION)-2) {  
1266 - parser->header_state = h_connection;  
1267 - }  
1268 - break;  
1269 -  
1270 - /* proxy-connection */  
1271 -  
1272 - case h_matching_proxy_connection:  
1273 - parser->index++;  
1274 - if (parser->index > sizeof(PROXY_CONNECTION)-1  
1275 - || c != PROXY_CONNECTION[parser->index]) {  
1276 - parser->header_state = h_general;  
1277 - } else if (parser->index == sizeof(PROXY_CONNECTION)-2) {  
1278 - parser->header_state = h_connection;  
1279 - }  
1280 - break;  
1281 -  
1282 - /* content-length */  
1283 -  
1284 - case h_matching_content_length:  
1285 - parser->index++;  
1286 - if (parser->index > sizeof(CONTENT_LENGTH)-1  
1287 - || c != CONTENT_LENGTH[parser->index]) {  
1288 - parser->header_state = h_general;  
1289 - } else if (parser->index == sizeof(CONTENT_LENGTH)-2) {  
1290 - parser->header_state = h_content_length;  
1291 - }  
1292 - break;  
1293 -  
1294 - /* transfer-encoding */  
1295 -  
1296 - case h_matching_transfer_encoding:  
1297 - parser->index++;  
1298 - if (parser->index > sizeof(TRANSFER_ENCODING)-1  
1299 - || c != TRANSFER_ENCODING[parser->index]) {  
1300 - parser->header_state = h_general;  
1301 - } else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {  
1302 - parser->header_state = h_transfer_encoding;  
1303 - }  
1304 - break;  
1305 -  
1306 - /* upgrade */  
1307 -  
1308 - case h_matching_upgrade:  
1309 - parser->index++;  
1310 - if (parser->index > sizeof(UPGRADE)-1  
1311 - || c != UPGRADE[parser->index]) {  
1312 - parser->header_state = h_general;  
1313 - } else if (parser->index == sizeof(UPGRADE)-2) {  
1314 - parser->header_state = h_upgrade;  
1315 - }  
1316 - break;  
1317 -  
1318 - case h_connection:  
1319 - case h_content_length:  
1320 - case h_transfer_encoding:  
1321 - case h_upgrade:  
1322 - if (ch != ' ') parser->header_state = h_general;  
1323 - break;  
1324 -  
1325 - default:  
1326 - assert(0 && "Unknown header_state");  
1327 - break;  
1328 - }  
1329 - break;  
1330 - }  
1331 -  
1332 - if (ch == ':') {  
1333 - parser->state = s_header_value_start;  
1334 - CALLBACK_DATA(header_field);  
1335 - break;  
1336 - }  
1337 -  
1338 - if (ch == CR) {  
1339 - parser->state = s_header_almost_done;  
1340 - CALLBACK_DATA(header_field);  
1341 - break;  
1342 - }  
1343 -  
1344 - if (ch == LF) {  
1345 - parser->state = s_header_field_start;  
1346 - CALLBACK_DATA(header_field);  
1347 - break;  
1348 - }  
1349 -  
1350 - SET_ERRNO(HPE_INVALID_HEADER_TOKEN);  
1351 - goto error;  
1352 - }  
1353 -  
1354 - case s_header_value_start:  
1355 - {  
1356 - if (ch == ' ' || ch == '\t') break;  
1357 -  
1358 - MARK(header_value);  
1359 -  
1360 - parser->state = s_header_value;  
1361 - parser->index = 0;  
1362 -  
1363 - if (ch == CR) {  
1364 - parser->header_state = h_general;  
1365 - parser->state = s_header_almost_done;  
1366 - CALLBACK_DATA(header_value);  
1367 - break;  
1368 - }  
1369 -  
1370 - if (ch == LF) {  
1371 - parser->state = s_header_field_start;  
1372 - CALLBACK_DATA(header_value);  
1373 - break;  
1374 - }  
1375 -  
1376 - c = LOWER(ch);  
1377 -  
1378 - switch (parser->header_state) {  
1379 - case h_upgrade:  
1380 - parser->flags |= F_UPGRADE;  
1381 - parser->header_state = h_general;  
1382 - break;  
1383 -  
1384 - case h_transfer_encoding:  
1385 - /* looking for 'Transfer-Encoding: chunked' */  
1386 - if ('c' == c) {  
1387 - parser->header_state = h_matching_transfer_encoding_chunked;  
1388 - } else {  
1389 - parser->header_state = h_general;  
1390 - }  
1391 - break;  
1392 -  
1393 - case h_content_length:  
1394 - if (!IS_NUM(ch)) {  
1395 - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);  
1396 - goto error;  
1397 - }  
1398 -  
1399 - parser->content_length = ch - '0';  
1400 - break;  
1401 -  
1402 - case h_connection:  
1403 - /* looking for 'Connection: keep-alive' */  
1404 - if (c == 'k') {  
1405 - parser->header_state = h_matching_connection_keep_alive;  
1406 - /* looking for 'Connection: close' */  
1407 - } else if (c == 'c') {  
1408 - parser->header_state = h_matching_connection_close;  
1409 - } else {  
1410 - parser->header_state = h_general;  
1411 - }  
1412 - break;  
1413 -  
1414 - default:  
1415 - parser->header_state = h_general;  
1416 - break;  
1417 - }  
1418 - break;  
1419 - }  
1420 -  
1421 - case s_header_value:  
1422 - {  
1423 -  
1424 - if (ch == CR) {  
1425 - parser->state = s_header_almost_done;  
1426 - CALLBACK_DATA(header_value);  
1427 - break;  
1428 - }  
1429 -  
1430 - if (ch == LF) {  
1431 - parser->state = s_header_almost_done;  
1432 - CALLBACK_DATA_NOADVANCE(header_value);  
1433 - goto reexecute_byte;  
1434 - }  
1435 -  
1436 - c = LOWER(ch);  
1437 -  
1438 - switch (parser->header_state) {  
1439 - case h_general:  
1440 - break;  
1441 -  
1442 - case h_connection:  
1443 - case h_transfer_encoding:  
1444 - assert(0 && "Shouldn't get here.");  
1445 - break;  
1446 -  
1447 - case h_content_length:  
1448 - {  
1449 - uint64_t t;  
1450 -  
1451 - if (ch == ' ') break;  
1452 -  
1453 - if (!IS_NUM(ch)) {  
1454 - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);  
1455 - goto error;  
1456 - }  
1457 -  
1458 - t = parser->content_length;  
1459 - t *= 10;  
1460 - t += ch - '0';  
1461 -  
1462 - /* Overflow? */  
1463 - if (t < parser->content_length || t == ULLONG_MAX) {  
1464 - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);  
1465 - goto error;  
1466 - }  
1467 -  
1468 - parser->content_length = t;  
1469 - break;  
1470 - }  
1471 -  
1472 - /* Transfer-Encoding: chunked */  
1473 - case h_matching_transfer_encoding_chunked:  
1474 - parser->index++;  
1475 - if (parser->index > sizeof(CHUNKED)-1  
1476 - || c != CHUNKED[parser->index]) {  
1477 - parser->header_state = h_general;  
1478 - } else if (parser->index == sizeof(CHUNKED)-2) {  
1479 - parser->header_state = h_transfer_encoding_chunked;  
1480 - }  
1481 - break;  
1482 -  
1483 - /* looking for 'Connection: keep-alive' */  
1484 - case h_matching_connection_keep_alive:  
1485 - parser->index++;  
1486 - if (parser->index > sizeof(KEEP_ALIVE)-1  
1487 - || c != KEEP_ALIVE[parser->index]) {  
1488 - parser->header_state = h_general;  
1489 - } else if (parser->index == sizeof(KEEP_ALIVE)-2) {  
1490 - parser->header_state = h_connection_keep_alive;  
1491 - }  
1492 - break;  
1493 -  
1494 - /* looking for 'Connection: close' */  
1495 - case h_matching_connection_close:  
1496 - parser->index++;  
1497 - if (parser->index > sizeof(CLOSE)-1 || c != CLOSE[parser->index]) {  
1498 - parser->header_state = h_general;  
1499 - } else if (parser->index == sizeof(CLOSE)-2) {  
1500 - parser->header_state = h_connection_close;  
1501 - }  
1502 - break;  
1503 -  
1504 - case h_transfer_encoding_chunked:  
1505 - case h_connection_keep_alive:  
1506 - case h_connection_close:  
1507 - if (ch != ' ') parser->header_state = h_general;  
1508 - break;  
1509 -  
1510 - default:  
1511 - parser->state = s_header_value;  
1512 - parser->header_state = h_general;  
1513 - break;  
1514 - }  
1515 - break;  
1516 - }  
1517 -  
1518 - case s_header_almost_done:  
1519 - {  
1520 - STRICT_CHECK(ch != LF);  
1521 -  
1522 - parser->state = s_header_value_lws;  
1523 -  
1524 - switch (parser->header_state) {  
1525 - case h_connection_keep_alive:  
1526 - parser->flags |= F_CONNECTION_KEEP_ALIVE;  
1527 - break;  
1528 - case h_connection_close:  
1529 - parser->flags |= F_CONNECTION_CLOSE;  
1530 - break;  
1531 - case h_transfer_encoding_chunked:  
1532 - parser->flags |= F_CHUNKED;  
1533 - break;  
1534 - default:  
1535 - break;  
1536 - }  
1537 -  
1538 - break;  
1539 - }  
1540 -  
1541 - case s_header_value_lws:  
1542 - {  
1543 - if (ch == ' ' || ch == '\t')  
1544 - parser->state = s_header_value_start;  
1545 - else  
1546 - {  
1547 - parser->state = s_header_field_start;  
1548 - goto reexecute_byte;  
1549 - }  
1550 - break;  
1551 - }  
1552 -  
1553 - case s_headers_almost_done:  
1554 - {  
1555 - STRICT_CHECK(ch != LF);  
1556 -  
1557 - if (parser->flags & F_TRAILING) {  
1558 - /* End of a chunked request */  
1559 - parser->state = NEW_MESSAGE();  
1560 - CALLBACK_NOTIFY(message_complete);  
1561 - break;  
1562 - }  
1563 -  
1564 - parser->state = s_headers_done;  
1565 -  
1566 - /* Set this here so that on_headers_complete() callbacks can see it */  
1567 - parser->upgrade =  
1568 - (parser->flags & F_UPGRADE || parser->method == HTTP_CONNECT);  
1569 -  
1570 - /* Here we call the headers_complete callback. This is somewhat  
1571 - * different than other callbacks because if the user returns 1, we  
1572 - * will interpret that as saying that this message has no body. This  
1573 - * is needed for the annoying case of recieving a response to a HEAD  
1574 - * request.  
1575 - *  
1576 - * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so  
1577 - * we have to simulate it by handling a change in errno below.  
1578 - */  
1579 - if (settings->on_headers_complete) {  
1580 - switch (settings->on_headers_complete(parser)) {  
1581 - case 0:  
1582 - break;  
1583 -  
1584 - case 1:  
1585 - parser->flags |= F_SKIPBODY;  
1586 - break;  
1587 -  
1588 - default:  
1589 - SET_ERRNO(HPE_CB_headers_complete);  
1590 - return p - data; /* Error */  
1591 - }  
1592 - }  
1593 -  
1594 - if (HTTP_PARSER_ERRNO(parser) != HPE_OK) {  
1595 - return p - data;  
1596 - }  
1597 -  
1598 - goto reexecute_byte;  
1599 - }  
1600 -  
1601 - case s_headers_done:  
1602 - {  
1603 - STRICT_CHECK(ch != LF);  
1604 -  
1605 - parser->nread = 0;  
1606 -  
1607 - /* Exit, the rest of the connect is in a different protocol. */  
1608 - if (parser->upgrade) {  
1609 - parser->state = NEW_MESSAGE();  
1610 - CALLBACK_NOTIFY(message_complete);  
1611 - return (p - data) + 1;  
1612 - }  
1613 -  
1614 - if (parser->flags & F_SKIPBODY) {  
1615 - parser->state = NEW_MESSAGE();  
1616 - CALLBACK_NOTIFY(message_complete);  
1617 - } else if (parser->flags & F_CHUNKED) {  
1618 - /* chunked encoding - ignore Content-Length header */  
1619 - parser->state = s_chunk_size_start;  
1620 - } else {  
1621 - if (parser->content_length == 0) {  
1622 - /* Content-Length header given but zero: Content-Length: 0\r\n */  
1623 - parser->state = NEW_MESSAGE();  
1624 - CALLBACK_NOTIFY(message_complete);  
1625 - } else if (parser->content_length != ULLONG_MAX) {  
1626 - /* Content-Length header given and non-zero */  
1627 - parser->state = s_body_identity;  
1628 - } else {  
1629 - if (parser->type == HTTP_REQUEST ||  
1630 - !http_message_needs_eof(parser)) {  
1631 - /* Assume content-length 0 - read the next */  
1632 - parser->state = NEW_MESSAGE();  
1633 - CALLBACK_NOTIFY(message_complete);  
1634 - } else {  
1635 - /* Read body until EOF */  
1636 - parser->state = s_body_identity_eof;  
1637 - }  
1638 - }  
1639 - }  
1640 -  
1641 - break;  
1642 - }  
1643 -  
1644 - case s_body_identity:  
1645 - {  
1646 - uint64_t to_read = MIN(parser->content_length,  
1647 - (uint64_t) ((data + len) - p));  
1648 -  
1649 - assert(parser->content_length != 0  
1650 - && parser->content_length != ULLONG_MAX);  
1651 -  
1652 - /* The difference between advancing content_length and p is because  
1653 - * the latter will automaticaly advance on the next loop iteration.  
1654 - * Further, if content_length ends up at 0, we want to see the last  
1655 - * byte again for our message complete callback.  
1656 - */  
1657 - MARK(body);  
1658 - parser->content_length -= to_read;  
1659 - p += to_read - 1;  
1660 -  
1661 - if (parser->content_length == 0) {  
1662 - parser->state = s_message_done;  
1663 -  
1664 - /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.  
1665 - *  
1666 - * The alternative to doing this is to wait for the next byte to  
1667 - * trigger the data callback, just as in every other case. The  
1668 - * problem with this is that this makes it difficult for the test  
1669 - * harness to distinguish between complete-on-EOF and  
1670 - * complete-on-length. It's not clear that this distinction is  
1671 - * important for applications, but let's keep it for now.  
1672 - */  
1673 - CALLBACK_DATA_(body, p - body_mark + 1, p - data);  
1674 - goto reexecute_byte;  
1675 - }  
1676 -  
1677 - break;  
1678 - }  
1679 -  
1680 - /* read until EOF */  
1681 - case s_body_identity_eof:  
1682 - MARK(body);  
1683 - p = data + len - 1;  
1684 -  
1685 - break;  
1686 -  
1687 - case s_message_done:  
1688 - parser->state = NEW_MESSAGE();  
1689 - CALLBACK_NOTIFY(message_complete);  
1690 - break;  
1691 -  
1692 - case s_chunk_size_start:  
1693 - {  
1694 - assert(parser->nread == 1);  
1695 - assert(parser->flags & F_CHUNKED);  
1696 -  
1697 - unhex_val = unhex[(unsigned char)ch];  
1698 - if (unhex_val == -1) {  
1699 - SET_ERRNO(HPE_INVALID_CHUNK_SIZE);  
1700 - goto error;  
1701 - }  
1702 -  
1703 - parser->content_length = unhex_val;  
1704 - parser->state = s_chunk_size;  
1705 - break;  
1706 - }  
1707 -  
1708 - case s_chunk_size:  
1709 - {  
1710 - uint64_t t;  
1711 -  
1712 - assert(parser->flags & F_CHUNKED);  
1713 -  
1714 - if (ch == CR) {  
1715 - parser->state = s_chunk_size_almost_done;  
1716 - break;  
1717 - }  
1718 -  
1719 - unhex_val = unhex[(unsigned char)ch];  
1720 -  
1721 - if (unhex_val == -1) {  
1722 - if (ch == ';' || ch == ' ') {  
1723 - parser->state = s_chunk_parameters;  
1724 - break;  
1725 - }  
1726 -  
1727 - SET_ERRNO(HPE_INVALID_CHUNK_SIZE);  
1728 - goto error;  
1729 - }  
1730 -  
1731 - t = parser->content_length;  
1732 - t *= 16;  
1733 - t += unhex_val;  
1734 -  
1735 - /* Overflow? */  
1736 - if (t < parser->content_length || t == ULLONG_MAX) {  
1737 - SET_ERRNO(HPE_INVALID_CONTENT_LENGTH);  
1738 - goto error;  
1739 - }  
1740 -  
1741 - parser->content_length = t;  
1742 - break;  
1743 - }  
1744 -  
1745 - case s_chunk_parameters:  
1746 - {  
1747 - assert(parser->flags & F_CHUNKED);  
1748 - /* just ignore this shit. TODO check for overflow */  
1749 - if (ch == CR) {  
1750 - parser->state = s_chunk_size_almost_done;  
1751 - break;  
1752 - }  
1753 - break;  
1754 - }  
1755 -  
1756 - case s_chunk_size_almost_done:  
1757 - {  
1758 - assert(parser->flags & F_CHUNKED);  
1759 - STRICT_CHECK(ch != LF);  
1760 -  
1761 - parser->nread = 0;  
1762 -  
1763 - if (parser->content_length == 0) {  
1764 - parser->flags |= F_TRAILING;  
1765 - parser->state = s_header_field_start;  
1766 - } else {  
1767 - parser->state = s_chunk_data;  
1768 - }  
1769 - break;  
1770 - }  
1771 -  
1772 - case s_chunk_data:  
1773 - {  
1774 - uint64_t to_read = MIN(parser->content_length,  
1775 - (uint64_t) ((data + len) - p));  
1776 -  
1777 - assert(parser->flags & F_CHUNKED);  
1778 - assert(parser->content_length != 0  
1779 - && parser->content_length != ULLONG_MAX);  
1780 -  
1781 - /* See the explanation in s_body_identity for why the content  
1782 - * length and data pointers are managed this way.  
1783 - */  
1784 - MARK(body);  
1785 - parser->content_length -= to_read;  
1786 - p += to_read - 1;  
1787 -  
1788 - if (parser->content_length == 0) {  
1789 - parser->state = s_chunk_data_almost_done;  
1790 - }  
1791 -  
1792 - break;  
1793 - }  
1794 -  
1795 - case s_chunk_data_almost_done:  
1796 - assert(parser->flags & F_CHUNKED);  
1797 - assert(parser->content_length == 0);  
1798 - STRICT_CHECK(ch != CR);  
1799 - parser->state = s_chunk_data_done;  
1800 - CALLBACK_DATA(body);  
1801 - break;  
1802 -  
1803 - case s_chunk_data_done:  
1804 - assert(parser->flags & F_CHUNKED);  
1805 - STRICT_CHECK(ch != LF);  
1806 - parser->nread = 0;  
1807 - parser->state = s_chunk_size_start;  
1808 - break;  
1809 -  
1810 - default:  
1811 - assert(0 && "unhandled state");  
1812 - SET_ERRNO(HPE_INVALID_INTERNAL_STATE);  
1813 - goto error;  
1814 - }  
1815 - }  
1816 -  
1817 - /* Run callbacks for any marks that we have leftover after we ran our of  
1818 - * bytes. There should be at most one of these set, so it's OK to invoke  
1819 - * them in series (unset marks will not result in callbacks).  
1820 - *  
1821 - * We use the NOADVANCE() variety of callbacks here because 'p' has already  
1822 - * overflowed 'data' and this allows us to correct for the off-by-one that  
1823 - * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'  
1824 - * value that's in-bounds).  
1825 - */  
1826 -  
1827 - assert(((header_field_mark ? 1 : 0) +  
1828 - (header_value_mark ? 1 : 0) +  
1829 - (url_mark ? 1 : 0) +  
1830 - (body_mark ? 1 : 0)) <= 1);  
1831 -  
1832 - CALLBACK_DATA_NOADVANCE(header_field);  
1833 - CALLBACK_DATA_NOADVANCE(header_value);  
1834 - CALLBACK_DATA_NOADVANCE(url);  
1835 - CALLBACK_DATA_NOADVANCE(body);  
1836 -  
1837 - return len;  
1838 -  
1839 -error:  
1840 - if (HTTP_PARSER_ERRNO(parser) == HPE_OK) {  
1841 - SET_ERRNO(HPE_UNKNOWN);  
1842 - }  
1843 -  
1844 - return (p - data);  
1845 -}  
1846 -  
1847 -  
1848 -/* Does the parser need to see an EOF to find the end of the message? */  
1849 -int  
1850 -http_message_needs_eof (const http_parser *parser)  
1851 -{  
1852 - if (parser->type == HTTP_REQUEST) {  
1853 - return 0;  
1854 - }  
1855 -  
1856 - /* See RFC 2616 section 4.4 */  
1857 - if (parser->status_code / 100 == 1 || /* 1xx e.g. Continue */  
1858 - parser->status_code == 204 || /* No Content */  
1859 - parser->status_code == 304 || /* Not Modified */  
1860 - parser->flags & F_SKIPBODY) { /* response to a HEAD request */  
1861 - return 0;  
1862 - }  
1863 -  
1864 - if ((parser->flags & F_CHUNKED) || parser->content_length != ULLONG_MAX) {  
1865 - return 0;  
1866 - }  
1867 -  
1868 - return 1;  
1869 -}  
1870 -  
1871 -  
1872 -int  
1873 -http_should_keep_alive (const http_parser *parser)  
1874 -{  
1875 - if (parser->http_major > 0 && parser->http_minor > 0) {  
1876 - /* HTTP/1.1 */  
1877 - if (parser->flags & F_CONNECTION_CLOSE) {  
1878 - return 0;  
1879 - }  
1880 - } else {  
1881 - /* HTTP/1.0 or earlier */  
1882 - if (!(parser->flags & F_CONNECTION_KEEP_ALIVE)) {  
1883 - return 0;  
1884 - }  
1885 - }  
1886 -  
1887 - return !http_message_needs_eof(parser);  
1888 -}  
1889 -  
1890 -  
1891 -const char *  
1892 -http_method_str (enum http_method m)  
1893 -{  
1894 - return ELEM_AT(method_strings, m, "<unknown>");  
1895 -}  
1896 -  
1897 -  
1898 -void  
1899 -http_parser_init (http_parser *parser, enum http_parser_type t)  
1900 -{  
1901 - void *data = parser->data; /* preserve application data */  
1902 - memset(parser, 0, sizeof(*parser));  
1903 - parser->data = data;  
1904 - parser->type = t;  
1905 - parser->state = (t == HTTP_REQUEST ? s_start_req : (t == HTTP_RESPONSE ? s_start_res : s_start_req_or_res));  
1906 - parser->http_errno = HPE_OK;  
1907 -}  
1908 -  
1909 -const char *  
1910 -http_errno_name(enum http_errno err) {  
1911 - assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));  
1912 - return http_strerror_tab[err].name;  
1913 -}  
1914 -  
1915 -const char *  
1916 -http_errno_description(enum http_errno err) {  
1917 - assert(err < (sizeof(http_strerror_tab)/sizeof(http_strerror_tab[0])));  
1918 - return http_strerror_tab[err].description;  
1919 -}  
1920 -  
1921 -static enum http_host_state  
1922 -http_parse_host_char(enum http_host_state s, const char ch) {  
1923 - switch(s) {  
1924 - case s_http_userinfo:  
1925 - case s_http_userinfo_start:  
1926 - if (ch == '@') {  
1927 - return s_http_host_start;  
1928 - }  
1929 -  
1930 - if (IS_USERINFO_CHAR(ch)) {  
1931 - return s_http_userinfo;  
1932 - }  
1933 - break;  
1934 -  
1935 - case s_http_host_start:  
1936 - if (ch == '[') {  
1937 - return s_http_host_v6_start;  
1938 - }  
1939 -  
1940 - if (IS_HOST_CHAR(ch)) {  
1941 - return s_http_host;  
1942 - }  
1943 -  
1944 - break;  
1945 -  
1946 - case s_http_host:  
1947 - if (IS_HOST_CHAR(ch)) {  
1948 - return s_http_host;  
1949 - }  
1950 -  
1951 - /* FALLTHROUGH */  
1952 - case s_http_host_v6_end:  
1953 - if (ch == ':') {  
1954 - return s_http_host_port_start;  
1955 - }  
1956 -  
1957 - break;  
1958 -  
1959 - case s_http_host_v6:  
1960 - if (ch == ']') {  
1961 - return s_http_host_v6_end;  
1962 - }  
1963 -  
1964 - /* FALLTHROUGH */  
1965 - case s_http_host_v6_start:  
1966 - if (IS_HEX(ch) || ch == ':' || ch == '.') {  
1967 - return s_http_host_v6;  
1968 - }  
1969 -  
1970 - break;  
1971 -  
1972 - case s_http_host_port:  
1973 - case s_http_host_port_start:  
1974 - if (IS_NUM(ch)) {  
1975 - return s_http_host_port;  
1976 - }  
1977 -  
1978 - break;  
1979 -  
1980 - default:  
1981 - break;  
1982 - }  
1983 - return s_http_host_dead;  
1984 -}  
1985 -  
1986 -static int  
1987 -http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {  
1988 - enum http_host_state s;  
1989 -  
1990 - const char *p;  
1991 - size_t buflen = u->field_data[UF_HOST].off + u->field_data[UF_HOST].len;  
1992 -  
1993 - u->field_data[UF_HOST].len = 0;  
1994 -  
1995 - s = found_at ? s_http_userinfo_start : s_http_host_start;  
1996 -  
1997 - for (p = buf + u->field_data[UF_HOST].off; p < buf + buflen; p++) {  
1998 - enum http_host_state new_s = http_parse_host_char(s, *p);  
1999 -  
2000 - if (new_s == s_http_host_dead) {  
2001 - return 1;  
2002 - }  
2003 -  
2004 - switch(new_s) {  
2005 - case s_http_host:  
2006 - if (s != s_http_host) {  
2007 - u->field_data[UF_HOST].off = (uint16_t) (p - buf);  
2008 - }  
2009 - u->field_data[UF_HOST].len++;  
2010 - break;  
2011 -  
2012 - case s_http_host_v6:  
2013 - if (s != s_http_host_v6) {  
2014 - u->field_data[UF_HOST].off = (uint16_t) (p - buf);  
2015 - }  
2016 - u->field_data[UF_HOST].len++;  
2017 - break;  
2018 -  
2019 - case s_http_host_port:  
2020 - if (s != s_http_host_port) {  
2021 - u->field_data[UF_PORT].off = (uint16_t) (p - buf);  
2022 - u->field_data[UF_PORT].len = 0;  
2023 - u->field_set |= (1 << UF_PORT);  
2024 - }  
2025 - u->field_data[UF_PORT].len++;  
2026 - break;  
2027 -  
2028 - case s_http_userinfo:  
2029 - if (s != s_http_userinfo) {  
2030 - u->field_data[UF_USERINFO].off = (uint16_t) (p - buf) ;  
2031 - u->field_data[UF_USERINFO].len = 0;  
2032 - u->field_set |= (1 << UF_USERINFO);  
2033 - }  
2034 - u->field_data[UF_USERINFO].len++;  
2035 - break;  
2036 -  
2037 - default:  
2038 - break;  
2039 - }  
2040 - s = new_s;  
2041 - }  
2042 -  
2043 - /* Make sure we don't end somewhere unexpected */  
2044 - switch (s) {  
2045 - case s_http_host_start:  
2046 - case s_http_host_v6_start:  
2047 - case s_http_host_v6:  
2048 - case s_http_host_port_start:  
2049 - case s_http_userinfo:  
2050 - case s_http_userinfo_start:  
2051 - return 1;  
2052 - default:  
2053 - break;  
2054 - }  
2055 -  
2056 - return 0;  
2057 -}  
2058 -  
2059 -int  
2060 -http_parser_parse_url(const char *buf, size_t buflen, int is_connect,  
2061 - struct http_parser_url *u)  
2062 -{  
2063 - enum state s;  
2064 - const char *p;  
2065 - enum http_parser_url_fields uf, old_uf;  
2066 - int found_at = 0;  
2067 -  
2068 - u->port = u->field_set = 0;  
2069 - s = is_connect ? s_req_server_start : s_req_spaces_before_url;  
2070 - uf = old_uf = UF_MAX;  
2071 -  
2072 - for (p = buf; p < buf + buflen; p++) {  
2073 - s = parse_url_char(s, *p);  
2074 -  
2075 - /* Figure out the next field that we're operating on */  
2076 - switch (s) {  
2077 - case s_dead:  
2078 - return 1;  
2079 -  
2080 - /* Skip delimeters */  
2081 - case s_req_schema_slash:  
2082 - case s_req_schema_slash_slash:  
2083 - case s_req_server_start:  
2084 - case s_req_query_string_start:  
2085 - case s_req_fragment_start:  
2086 - continue;  
2087 -  
2088 - case s_req_schema:  
2089 - uf = UF_SCHEMA;  
2090 - break;  
2091 -  
2092 - case s_req_server_with_at:  
2093 - found_at = 1;  
2094 -  
2095 - /* FALLTROUGH */  
2096 - case s_req_server:  
2097 - uf = UF_HOST;  
2098 - break;  
2099 -  
2100 - case s_req_path:  
2101 - uf = UF_PATH;  
2102 - break;  
2103 -  
2104 - case s_req_query_string:  
2105 - uf = UF_QUERY;  
2106 - break;  
2107 -  
2108 - case s_req_fragment:  
2109 - uf = UF_FRAGMENT;  
2110 - break;  
2111 -  
2112 - default:  
2113 - assert(!"Unexpected state");  
2114 - return 1;  
2115 - }  
2116 -  
2117 - /* Nothing's changed; soldier on */  
2118 - if (uf == old_uf) {  
2119 - u->field_data[uf].len++;  
2120 - continue;  
2121 - }  
2122 -  
2123 - u->field_data[uf].off = (uint16_t) (p - buf);  
2124 - u->field_data[uf].len = 1;  
2125 -  
2126 - u->field_set |= (1 << uf);  
2127 - old_uf = uf;  
2128 - }  
2129 -  
2130 - /* host must be present if there is a schema */  
2131 - /* parsing http:///toto will fail */  
2132 - if ((u->field_set & ((1 << UF_SCHEMA) | (1 << UF_HOST))) != 0) {  
2133 - if (http_parse_host(buf, u, found_at) != 0) {  
2134 - return 1;  
2135 - }  
2136 - }  
2137 -  
2138 - /* CONNECT requests can only contain "hostname:port" */  
2139 - if (is_connect && u->field_set != ((1 << UF_HOST)|(1 << UF_PORT))) {  
2140 - return 1;  
2141 - }  
2142 -  
2143 - if (u->field_set & (1 << UF_PORT)) {  
2144 - /* Don't bother with endp; we've already validated the string */  
2145 - unsigned long v = strtoul(buf + u->field_data[UF_PORT].off, NULL, 10);  
2146 -  
2147 - /* Ports have a max value of 2^16 */  
2148 - if (v > 0xffff) {  
2149 - return 1;  
2150 - }  
2151 -  
2152 - u->port = (uint16_t) v;  
2153 - }  
2154 -  
2155 - return 0;  
2156 -}  
2157 -  
2158 -void  
2159 -http_parser_pause(http_parser *parser, int paused) {  
2160 - /* Users should only be pausing/unpausing a parser that is not in an error  
2161 - * state. In non-debug builds, there's not much that we can do about this  
2162 - * other than ignore it.  
2163 - */  
2164 - if (HTTP_PARSER_ERRNO(parser) == HPE_OK ||  
2165 - HTTP_PARSER_ERRNO(parser) == HPE_PAUSED) {  
2166 - SET_ERRNO((paused) ? HPE_PAUSED : HPE_OK);  
2167 - } else {  
2168 - assert(0 && "Attempting to pause parser in error state");  
2169 - }  
2170 -}  
2171 -  
2172 -int  
2173 -http_body_is_final(const struct http_parser *parser) {  
2174 - return parser->state == s_message_done;  
2175 -}  
3rdparty/http-parser-2.1/http_parser.gyp deleted
1 -# This file is used with the GYP meta build system.  
2 -# http://code.google.com/p/gyp/  
3 -# To build try this:  
4 -# svn co http://gyp.googlecode.com/svn/trunk gyp  
5 -# ./gyp/gyp -f make --depth=`pwd` http_parser.gyp  
6 -# ./out/Debug/test  
7 -{  
8 - 'target_defaults': {  
9 - 'default_configuration': 'Debug',  
10 - 'configurations': {  
11 - # TODO: hoist these out and put them somewhere common, because  
12 - # RuntimeLibrary MUST MATCH across the entire project  
13 - 'Debug': {  
14 - 'defines': [ 'DEBUG', '_DEBUG' ],  
15 - 'cflags': [ '-Wall', '-Wextra', '-O0', '-g', '-ftrapv' ],  
16 - 'msvs_settings': {  
17 - 'VCCLCompilerTool': {  
18 - 'RuntimeLibrary': 1, # static debug  
19 - },  
20 - },  
21 - },  
22 - 'Release': {  
23 - 'defines': [ 'NDEBUG' ],  
24 - 'cflags': [ '-Wall', '-Wextra', '-O3' ],  
25 - 'msvs_settings': {  
26 - 'VCCLCompilerTool': {  
27 - 'RuntimeLibrary': 0, # static release  
28 - },  
29 - },  
30 - }  
31 - },  
32 - 'msvs_settings': {  
33 - 'VCCLCompilerTool': {  
34 - },  
35 - 'VCLibrarianTool': {  
36 - },  
37 - 'VCLinkerTool': {  
38 - 'GenerateDebugInformation': 'true',  
39 - },  
40 - },  
41 - 'conditions': [  
42 - ['OS == "win"', {  
43 - 'defines': [  
44 - 'WIN32'  
45 - ],  
46 - }]  
47 - ],  
48 - },  
49 -  
50 - 'targets': [  
51 - {  
52 - 'target_name': 'http_parser',  
53 - 'type': 'static_library',  
54 - 'include_dirs': [ '.' ],  
55 - 'direct_dependent_settings': {  
56 - 'defines': [ 'HTTP_PARSER_STRICT=0' ],  
57 - 'include_dirs': [ '.' ],  
58 - },  
59 - 'defines': [ 'HTTP_PARSER_STRICT=0' ],  
60 - 'sources': [ './http_parser.c', ],  
61 - 'conditions': [  
62 - ['OS=="win"', {  
63 - 'msvs_settings': {  
64 - 'VCCLCompilerTool': {  
65 - # Compile as C++. http_parser.c is actually C99, but C++ is  
66 - # close enough in this case.  
67 - 'CompileAs': 2,  
68 - },  
69 - },  
70 - }]  
71 - ],  
72 - },  
73 -  
74 - {  
75 - 'target_name': 'http_parser_strict',  
76 - 'type': 'static_library',  
77 - 'include_dirs': [ '.' ],  
78 - 'direct_dependent_settings': {  
79 - 'defines': [ 'HTTP_PARSER_STRICT=1' ],  
80 - 'include_dirs': [ '.' ],  
81 - },  
82 - 'defines': [ 'HTTP_PARSER_STRICT=1' ],  
83 - 'sources': [ './http_parser.c', ],  
84 - 'conditions': [  
85 - ['OS=="win"', {  
86 - 'msvs_settings': {  
87 - 'VCCLCompilerTool': {  
88 - # Compile as C++. http_parser.c is actually C99, but C++ is  
89 - # close enough in this case.  
90 - 'CompileAs': 2,  
91 - },  
92 - },  
93 - }]  
94 - ],  
95 - },  
96 -  
97 - {  
98 - 'target_name': 'test-nonstrict',  
99 - 'type': 'executable',  
100 - 'dependencies': [ 'http_parser' ],  
101 - 'sources': [ 'test.c' ]  
102 - },  
103 -  
104 - {  
105 - 'target_name': 'test-strict',  
106 - 'type': 'executable',  
107 - 'dependencies': [ 'http_parser_strict' ],  
108 - 'sources': [ 'test.c' ]  
109 - }  
110 - ]  
111 -}  
3rdparty/http-parser-2.1/http_parser.h deleted
1 -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.  
2 - *  
3 - * Permission is hereby granted, free of charge, to any person obtaining a copy  
4 - * of this software and associated documentation files (the "Software"), to  
5 - * deal in the Software without restriction, including without limitation the  
6 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
7 - * sell copies of the Software, and to permit persons to whom the Software is  
8 - * furnished to do so, subject to the following conditions:  
9 - *  
10 - * The above copyright notice and this permission notice shall be included in  
11 - * all copies or substantial portions of the Software.  
12 - *  
13 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
14 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
15 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
16 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
17 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
18 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS  
19 - * IN THE SOFTWARE.  
20 - */  
21 -#ifndef http_parser_h  
22 -#define http_parser_h  
23 -#ifdef __cplusplus  
24 -extern "C" {  
25 -#endif  
26 -  
27 -#define HTTP_PARSER_VERSION_MAJOR 2  
28 -#define HTTP_PARSER_VERSION_MINOR 1  
29 -  
30 -#include <sys/types.h>  
31 -#if defined(_WIN32) && !defined(__MINGW32__) && (!defined(_MSC_VER) || _MSC_VER<1600)  
32 -#include <BaseTsd.h>  
33 -#include <stddef.h>  
34 -typedef __int8 int8_t;  
35 -typedef unsigned __int8 uint8_t;  
36 -typedef __int16 int16_t;  
37 -typedef unsigned __int16 uint16_t;  
38 -typedef __int32 int32_t;  
39 -typedef unsigned __int32 uint32_t;  
40 -typedef __int64 int64_t;  
41 -typedef unsigned __int64 uint64_t;  
42 -#else  
43 -#include <stdint.h>  
44 -#endif  
45 -  
46 -/* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run  
47 - * faster  
48 - */  
49 -#ifndef HTTP_PARSER_STRICT  
50 -# define HTTP_PARSER_STRICT 1  
51 -#endif  
52 -  
53 -/* Maximium header size allowed */  
54 -#define HTTP_MAX_HEADER_SIZE (80*1024)  
55 -  
56 -  
57 -typedef struct http_parser http_parser;  
58 -typedef struct http_parser_settings http_parser_settings;  
59 -  
60 -  
61 -/* Callbacks should return non-zero to indicate an error. The parser will  
62 - * then halt execution.  
63 - *  
64 - * The one exception is on_headers_complete. In a HTTP_RESPONSE parser  
65 - * returning '1' from on_headers_complete will tell the parser that it  
66 - * should not expect a body. This is used when receiving a response to a  
67 - * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:  
68 - * chunked' headers that indicate the presence of a body.  
69 - *  
70 - * http_data_cb does not return data chunks. It will be call arbitrarally  
71 - * many times for each string. E.G. you might get 10 callbacks for "on_url"  
72 - * each providing just a few characters more data.  
73 - */  
74 -typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);  
75 -typedef int (*http_cb) (http_parser*);  
76 -  
77 -  
78 -/* Request Methods */  
79 -#define HTTP_METHOD_MAP(XX) \  
80 - XX(0, DELETE, DELETE) \  
81 - XX(1, GET, GET) \  
82 - XX(2, HEAD, HEAD) \  
83 - XX(3, POST, POST) \  
84 - XX(4, PUT, PUT) \  
85 - /* pathological */ \  
86 - XX(5, CONNECT, CONNECT) \  
87 - XX(6, OPTIONS, OPTIONS) \  
88 - XX(7, TRACE, TRACE) \  
89 - /* webdav */ \  
90 - XX(8, COPY, COPY) \  
91 - XX(9, LOCK, LOCK) \  
92 - XX(10, MKCOL, MKCOL) \  
93 - XX(11, MOVE, MOVE) \  
94 - XX(12, PROPFIND, PROPFIND) \  
95 - XX(13, PROPPATCH, PROPPATCH) \  
96 - XX(14, SEARCH, SEARCH) \  
97 - XX(15, UNLOCK, UNLOCK) \  
98 - /* subversion */ \  
99 - XX(16, REPORT, REPORT) \  
100 - XX(17, MKACTIVITY, MKACTIVITY) \  
101 - XX(18, CHECKOUT, CHECKOUT) \  
102 - XX(19, MERGE, MERGE) \  
103 - /* upnp */ \  
104 - XX(20, MSEARCH, M-SEARCH) \  
105 - XX(21, NOTIFY, NOTIFY) \  
106 - XX(22, SUBSCRIBE, SUBSCRIBE) \  
107 - XX(23, UNSUBSCRIBE, UNSUBSCRIBE) \  
108 - /* RFC-5789 */ \  
109 - XX(24, PATCH, PATCH) \  
110 - XX(25, PURGE, PURGE) \  
111 -  
112 -enum http_method  
113 - {  
114 -#define XX(num, name, string) HTTP_##name = num,  
115 - HTTP_METHOD_MAP(XX)  
116 -#undef XX  
117 - };  
118 -  
119 -  
120 -enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };  
121 -  
122 -  
123 -/* Flag values for http_parser.flags field */  
124 -enum flags  
125 - { F_CHUNKED = 1 << 0  
126 - , F_CONNECTION_KEEP_ALIVE = 1 << 1  
127 - , F_CONNECTION_CLOSE = 1 << 2  
128 - , F_TRAILING = 1 << 3  
129 - , F_UPGRADE = 1 << 4  
130 - , F_SKIPBODY = 1 << 5  
131 - };  
132 -  
133 -  
134 -/* Map for errno-related constants  
135 - *  
136 - * The provided argument should be a macro that takes 2 arguments.  
137 - */  
138 -#define HTTP_ERRNO_MAP(XX) \  
139 - /* No error */ \  
140 - XX(OK, "success") \  
141 - \  
142 - /* Callback-related errors */ \  
143 - XX(CB_message_begin, "the on_message_begin callback failed") \  
144 - XX(CB_status_complete, "the on_status_complete callback failed") \  
145 - XX(CB_url, "the on_url callback failed") \  
146 - XX(CB_header_field, "the on_header_field callback failed") \  
147 - XX(CB_header_value, "the on_header_value callback failed") \  
148 - XX(CB_headers_complete, "the on_headers_complete callback failed") \  
149 - XX(CB_body, "the on_body callback failed") \  
150 - XX(CB_message_complete, "the on_message_complete callback failed") \  
151 - \  
152 - /* Parsing-related errors */ \  
153 - XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \  
154 - XX(HEADER_OVERFLOW, \  
155 - "too many header bytes seen; overflow detected") \  
156 - XX(CLOSED_CONNECTION, \  
157 - "data received after completed connection: close message") \  
158 - XX(INVALID_VERSION, "invalid HTTP version") \  
159 - XX(INVALID_STATUS, "invalid HTTP status code") \  
160 - XX(INVALID_METHOD, "invalid HTTP method") \  
161 - XX(INVALID_URL, "invalid URL") \  
162 - XX(INVALID_HOST, "invalid host") \  
163 - XX(INVALID_PORT, "invalid port") \  
164 - XX(INVALID_PATH, "invalid path") \  
165 - XX(INVALID_QUERY_STRING, "invalid query string") \  
166 - XX(INVALID_FRAGMENT, "invalid fragment") \  
167 - XX(LF_EXPECTED, "LF character expected") \  
168 - XX(INVALID_HEADER_TOKEN, "invalid character in header") \  
169 - XX(INVALID_CONTENT_LENGTH, \  
170 - "invalid character in content-length header") \  
171 - XX(INVALID_CHUNK_SIZE, \  
172 - "invalid character in chunk size header") \  
173 - XX(INVALID_CONSTANT, "invalid constant string") \  
174 - XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\  
175 - XX(STRICT, "strict mode assertion failed") \  
176 - XX(PAUSED, "parser is paused") \  
177 - XX(UNKNOWN, "an unknown error occurred")  
178 -  
179 -  
180 -/* Define HPE_* values for each errno value above */  
181 -#define HTTP_ERRNO_GEN(n, s) HPE_##n,  
182 -enum http_errno {  
183 - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)  
184 -};  
185 -#undef HTTP_ERRNO_GEN  
186 -  
187 -  
188 -/* Get an http_errno value from an http_parser */  
189 -#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)  
190 -  
191 -  
192 -struct http_parser {  
193 - /** PRIVATE **/  
194 - unsigned char type : 2; /* enum http_parser_type */  
195 - unsigned char flags : 6; /* F_* values from 'flags' enum; semi-public */  
196 - unsigned char state; /* enum state from http_parser.c */  
197 - unsigned char header_state; /* enum header_state from http_parser.c */  
198 - unsigned char index; /* index into current matcher */  
199 -  
200 - uint32_t nread; /* # bytes read in various scenarios */  
201 - uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */  
202 -  
203 - /** READ-ONLY **/  
204 - unsigned short http_major;  
205 - unsigned short http_minor;  
206 - unsigned short status_code; /* responses only */  
207 - unsigned char method; /* requests only */  
208 - unsigned char http_errno : 7;  
209 -  
210 - /* 1 = Upgrade header was present and the parser has exited because of that.  
211 - * 0 = No upgrade header present.  
212 - * Should be checked when http_parser_execute() returns in addition to  
213 - * error checking.  
214 - */  
215 - unsigned char upgrade : 1;  
216 -  
217 - /** PUBLIC **/  
218 - void *data; /* A pointer to get hook to the "connection" or "socket" object */  
219 -};  
220 -  
221 -  
222 -struct http_parser_settings {  
223 - http_cb on_message_begin;  
224 - http_data_cb on_url;  
225 - http_cb on_status_complete;  
226 - http_data_cb on_header_field;  
227 - http_data_cb on_header_value;  
228 - http_cb on_headers_complete;  
229 - http_data_cb on_body;  
230 - http_cb on_message_complete;  
231 -};  
232 -  
233 -  
234 -enum http_parser_url_fields  
235 - { UF_SCHEMA = 0  
236 - , UF_HOST = 1  
237 - , UF_PORT = 2  
238 - , UF_PATH = 3  
239 - , UF_QUERY = 4  
240 - , UF_FRAGMENT = 5  
241 - , UF_USERINFO = 6  
242 - , UF_MAX = 7  
243 - };  
244 -  
245 -  
246 -/* Result structure for http_parser_parse_url().  
247 - *  
248 - * Callers should index into field_data[] with UF_* values iff field_set  
249 - * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and  
250 - * because we probably have padding left over), we convert any port to  
251 - * a uint16_t.  
252 - */  
253 -struct http_parser_url {  
254 - uint16_t field_set; /* Bitmask of (1 << UF_*) values */  
255 - uint16_t port; /* Converted UF_PORT string */  
256 -  
257 - struct {  
258 - uint16_t off; /* Offset into buffer in which field starts */  
259 - uint16_t len; /* Length of run in buffer */  
260 - } field_data[UF_MAX];  
261 -};  
262 -  
263 -  
264 -void http_parser_init(http_parser *parser, enum http_parser_type type);  
265 -  
266 -  
267 -size_t http_parser_execute(http_parser *parser,  
268 - const http_parser_settings *settings,  
269 - const char *data,  
270 - size_t len);  
271 -  
272 -  
273 -/* If http_should_keep_alive() in the on_headers_complete or  
274 - * on_message_complete callback returns 0, then this should be  
275 - * the last message on the connection.  
276 - * If you are the server, respond with the "Connection: close" header.  
277 - * If you are the client, close the connection.  
278 - */  
279 -int http_should_keep_alive(const http_parser *parser);  
280 -  
281 -/* Returns a string version of the HTTP method. */  
282 -const char *http_method_str(enum http_method m);  
283 -  
284 -/* Return a string name of the given error */  
285 -const char *http_errno_name(enum http_errno err);  
286 -  
287 -/* Return a string description of the given error */  
288 -const char *http_errno_description(enum http_errno err);  
289 -  
290 -/* Parse a URL; return nonzero on failure */  
291 -int http_parser_parse_url(const char *buf, size_t buflen,  
292 - int is_connect,  
293 - struct http_parser_url *u);  
294 -  
295 -/* Pause or un-pause the parser; a nonzero value pauses */  
296 -void http_parser_pause(http_parser *parser, int paused);  
297 -  
298 -/* Checks if this is the final chunk of the body. */  
299 -int http_body_is_final(const http_parser *parser);  
300 -  
301 -#ifdef __cplusplus  
302 -}  
303 -#endif  
304 -#endif  
3rdparty/http-parser-2.1/test.c deleted
1 -/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.  
2 - *  
3 - * Permission is hereby granted, free of charge, to any person obtaining a copy  
4 - * of this software and associated documentation files (the "Software"), to  
5 - * deal in the Software without restriction, including without limitation the  
6 - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  
7 - * sell copies of the Software, and to permit persons to whom the Software is  
8 - * furnished to do so, subject to the following conditions:  
9 - *  
10 - * The above copyright notice and this permission notice shall be included in  
11 - * all copies or substantial portions of the Software.  
12 - *  
13 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
14 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
15 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
16 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
17 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING  
18 - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS  
19 - * IN THE SOFTWARE.  
20 - */  
21 -#include "http_parser.h"  
22 -#include <stdlib.h>  
23 -#include <assert.h>  
24 -#include <stdio.h>  
25 -#include <stdlib.h> /* rand */  
26 -#include <string.h>  
27 -#include <stdarg.h>  
28 -  
29 -#undef TRUE  
30 -#define TRUE 1  
31 -#undef FALSE  
32 -#define FALSE 0  
33 -  
34 -#define MAX_HEADERS 13  
35 -#define MAX_ELEMENT_SIZE 2048  
36 -  
37 -#define MIN(a,b) ((a) < (b) ? (a) : (b))  
38 -  
39 -static http_parser *parser;  
40 -  
41 -struct message {  
42 - const char *name; // for debugging purposes  
43 - const char *raw;  
44 - enum http_parser_type type;  
45 - enum http_method method;  
46 - int status_code;  
47 - char request_path[MAX_ELEMENT_SIZE];  
48 - char request_url[MAX_ELEMENT_SIZE];  
49 - char fragment[MAX_ELEMENT_SIZE];  
50 - char query_string[MAX_ELEMENT_SIZE];  
51 - char body[MAX_ELEMENT_SIZE];  
52 - size_t body_size;  
53 - const char *host;  
54 - const char *userinfo;  
55 - uint16_t port;  
56 - int num_headers;  
57 - enum { NONE=0, FIELD, VALUE } last_header_element;  
58 - char headers [MAX_HEADERS][2][MAX_ELEMENT_SIZE];  
59 - int should_keep_alive;  
60 -  
61 - const char *upgrade; // upgraded body  
62 -  
63 - unsigned short http_major;  
64 - unsigned short http_minor;  
65 -  
66 - int message_begin_cb_called;  
67 - int headers_complete_cb_called;  
68 - int message_complete_cb_called;  
69 - int message_complete_on_eof;  
70 - int body_is_final;  
71 -};  
72 -  
73 -static int currently_parsing_eof;  
74 -  
75 -static struct message messages[5];  
76 -static int num_messages;  
77 -static http_parser_settings *current_pause_parser;  
78 -  
79 -/* * R E Q U E S T S * */  
80 -const struct message requests[] =  
81 -#define CURL_GET 0  
82 -{ {.name= "curl get"  
83 - ,.type= HTTP_REQUEST  
84 - ,.raw= "GET /test HTTP/1.1\r\n"  
85 - "User-Agent: curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1\r\n"  
86 - "Host: 0.0.0.0=5000\r\n"  
87 - "Accept: */*\r\n"  
88 - "\r\n"  
89 - ,.should_keep_alive= TRUE  
90 - ,.message_complete_on_eof= FALSE  
91 - ,.http_major= 1  
92 - ,.http_minor= 1  
93 - ,.method= HTTP_GET  
94 - ,.query_string= ""  
95 - ,.fragment= ""  
96 - ,.request_path= "/test"  
97 - ,.request_url= "/test"  
98 - ,.num_headers= 3  
99 - ,.headers=  
100 - { { "User-Agent", "curl/7.18.0 (i486-pc-linux-gnu) libcurl/7.18.0 OpenSSL/0.9.8g zlib/1.2.3.3 libidn/1.1" }  
101 - , { "Host", "0.0.0.0=5000" }  
102 - , { "Accept", "*/*" }  
103 - }  
104 - ,.body= ""  
105 - }  
106 -  
107 -#define FIREFOX_GET 1  
108 -, {.name= "firefox get"  
109 - ,.type= HTTP_REQUEST  
110 - ,.raw= "GET /favicon.ico HTTP/1.1\r\n"  
111 - "Host: 0.0.0.0=5000\r\n"  
112 - "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0\r\n"  
113 - "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n"  
114 - "Accept-Language: en-us,en;q=0.5\r\n"  
115 - "Accept-Encoding: gzip,deflate\r\n"  
116 - "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n"  
117 - "Keep-Alive: 300\r\n"  
118 - "Connection: keep-alive\r\n"  
119 - "\r\n"  
120 - ,.should_keep_alive= TRUE  
121 - ,.message_complete_on_eof= FALSE  
122 - ,.http_major= 1  
123 - ,.http_minor= 1  
124 - ,.method= HTTP_GET  
125 - ,.query_string= ""  
126 - ,.fragment= ""  
127 - ,.request_path= "/favicon.ico"  
128 - ,.request_url= "/favicon.ico"  
129 - ,.num_headers= 8  
130 - ,.headers=  
131 - { { "Host", "0.0.0.0=5000" }  
132 - , { "User-Agent", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9) Gecko/2008061015 Firefox/3.0" }  
133 - , { "Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" }  
134 - , { "Accept-Language", "en-us,en;q=0.5" }  
135 - , { "Accept-Encoding", "gzip,deflate" }  
136 - , { "Accept-Charset", "ISO-8859-1,utf-8;q=0.7,*;q=0.7" }  
137 - , { "Keep-Alive", "300" }  
138 - , { "Connection", "keep-alive" }  
139 - }  
140 - ,.body= ""  
141 - }  
142 -  
143 -#define DUMBFUCK 2  
144 -, {.name= "dumbfuck"  
145 - ,.type= HTTP_REQUEST  
146 - ,.raw= "GET /dumbfuck HTTP/1.1\r\n"  
147 - "aaaaaaaaaaaaa:++++++++++\r\n"  
148 - "\r\n"  
149 - ,.should_keep_alive= TRUE  
150 - ,.message_complete_on_eof= FALSE  
151 - ,.http_major= 1  
152 - ,.http_minor= 1  
153 - ,.method= HTTP_GET  
154 - ,.query_string= ""  
155 - ,.fragment= ""  
156 - ,.request_path= "/dumbfuck"  
157 - ,.request_url= "/dumbfuck"  
158 - ,.num_headers= 1  
159 - ,.headers=  
160 - { { "aaaaaaaaaaaaa", "++++++++++" }  
161 - }  
162 - ,.body= ""  
163 - }  
164 -  
165 -#define FRAGMENT_IN_URI 3  
166 -, {.name= "fragment in url"  
167 - ,.type= HTTP_REQUEST  
168 - ,.raw= "GET /forums/1/topics/2375?page=1#posts-17408 HTTP/1.1\r\n"  
169 - "\r\n"  
170 - ,.should_keep_alive= TRUE  
171 - ,.message_complete_on_eof= FALSE  
172 - ,.http_major= 1  
173 - ,.http_minor= 1  
174 - ,.method= HTTP_GET  
175 - ,.query_string= "page=1"  
176 - ,.fragment= "posts-17408"  
177 - ,.request_path= "/forums/1/topics/2375"  
178 - /* XXX request url does include fragment? */  
179 - ,.request_url= "/forums/1/topics/2375?page=1#posts-17408"  
180 - ,.num_headers= 0  
181 - ,.body= ""  
182 - }  
183 -  
184 -#define GET_NO_HEADERS_NO_BODY 4  
185 -, {.name= "get no headers no body"  
186 - ,.type= HTTP_REQUEST  
187 - ,.raw= "GET /get_no_headers_no_body/world HTTP/1.1\r\n"  
188 - "\r\n"  
189 - ,.should_keep_alive= TRUE  
190 - ,.message_complete_on_eof= FALSE /* would need Connection: close */  
191 - ,.http_major= 1  
192 - ,.http_minor= 1  
193 - ,.method= HTTP_GET  
194 - ,.query_string= ""  
195 - ,.fragment= ""  
196 - ,.request_path= "/get_no_headers_no_body/world"  
197 - ,.request_url= "/get_no_headers_no_body/world"  
198 - ,.num_headers= 0  
199 - ,.body= ""  
200 - }  
201 -  
202 -#define GET_ONE_HEADER_NO_BODY 5  
203 -, {.name= "get one header no body"  
204 - ,.type= HTTP_REQUEST  
205 - ,.raw= "GET /get_one_header_no_body HTTP/1.1\r\n"  
206 - "Accept: */*\r\n"  
207 - "\r\n"  
208 - ,.should_keep_alive= TRUE  
209 - ,.message_complete_on_eof= FALSE /* would need Connection: close */  
210 - ,.http_major= 1  
211 - ,.http_minor= 1  
212 - ,.method= HTTP_GET  
213 - ,.query_string= ""  
214 - ,.fragment= ""  
215 - ,.request_path= "/get_one_header_no_body"  
216 - ,.request_url= "/get_one_header_no_body"  
217 - ,.num_headers= 1  
218 - ,.headers=  
219 - { { "Accept" , "*/*" }  
220 - }  
221 - ,.body= ""  
222 - }  
223 -  
224 -#define GET_FUNKY_CONTENT_LENGTH 6  
225 -, {.name= "get funky content length body hello"  
226 - ,.type= HTTP_REQUEST  
227 - ,.raw= "GET /get_funky_content_length_body_hello HTTP/1.0\r\n"  
228 - "conTENT-Length: 5\r\n"  
229 - "\r\n"  
230 - "HELLO"  
231 - ,.should_keep_alive= FALSE  
232 - ,.message_complete_on_eof= FALSE  
233 - ,.http_major= 1  
234 - ,.http_minor= 0  
235 - ,.method= HTTP_GET  
236 - ,.query_string= ""  
237 - ,.fragment= ""  
238 - ,.request_path= "/get_funky_content_length_body_hello"  
239 - ,.request_url= "/get_funky_content_length_body_hello"  
240 - ,.num_headers= 1  
241 - ,.headers=  
242 - { { "conTENT-Length" , "5" }  
243 - }  
244 - ,.body= "HELLO"  
245 - }  
246 -  
247 -#define POST_IDENTITY_BODY_WORLD 7  
248 -, {.name= "post identity body world"  
249 - ,.type= HTTP_REQUEST  
250 - ,.raw= "POST /post_identity_body_world?q=search#hey HTTP/1.1\r\n"  
251 - "Accept: */*\r\n"  
252 - "Transfer-Encoding: identity\r\n"  
253 - "Content-Length: 5\r\n"  
254 - "\r\n"  
255 - "World"  
256 - ,.should_keep_alive= TRUE  
257 - ,.message_complete_on_eof= FALSE  
258 - ,.http_major= 1  
259 - ,.http_minor= 1  
260 - ,.method= HTTP_POST  
261 - ,.query_string= "q=search"  
262 - ,.fragment= "hey"  
263 - ,.request_path= "/post_identity_body_world"  
264 - ,.request_url= "/post_identity_body_world?q=search#hey"  
265 - ,.num_headers= 3  
266 - ,.headers=  
267 - { { "Accept", "*/*" }  
268 - , { "Transfer-Encoding", "identity" }  
269 - , { "Content-Length", "5" }  
270 - }  
271 - ,.body= "World"  
272 - }  
273 -  
274 -#define POST_CHUNKED_ALL_YOUR_BASE 8  
275 -, {.name= "post - chunked body: all your base are belong to us"  
276 - ,.type= HTTP_REQUEST  
277 - ,.raw= "POST /post_chunked_all_your_base HTTP/1.1\r\n"  
278 - "Transfer-Encoding: chunked\r\n"  
279 - "\r\n"  
280 - "1e\r\nall your base are belong to us\r\n"  
281 - "0\r\n"  
282 - "\r\n"  
283 - ,.should_keep_alive= TRUE  
284 - ,.message_complete_on_eof= FALSE  
285 - ,.http_major= 1  
286 - ,.http_minor= 1  
287 - ,.method= HTTP_POST  
288 - ,.query_string= ""  
289 - ,.fragment= ""  
290 - ,.request_path= "/post_chunked_all_your_base"  
291 - ,.request_url= "/post_chunked_all_your_base"  
292 - ,.num_headers= 1  
293 - ,.headers=  
294 - { { "Transfer-Encoding" , "chunked" }  
295 - }  
296 - ,.body= "all your base are belong to us"  
297 - }  
298 -  
299 -#define TWO_CHUNKS_MULT_ZERO_END 9  
300 -, {.name= "two chunks ; triple zero ending"  
301 - ,.type= HTTP_REQUEST  
302 - ,.raw= "POST /two_chunks_mult_zero_end HTTP/1.1\r\n"  
303 - "Transfer-Encoding: chunked\r\n"  
304 - "\r\n"  
305 - "5\r\nhello\r\n"  
306 - "6\r\n world\r\n"  
307 - "000\r\n"  
308 - "\r\n"  
309 - ,.should_keep_alive= TRUE  
310 - ,.message_complete_on_eof= FALSE  
311 - ,.http_major= 1  
312 - ,.http_minor= 1  
313 - ,.method= HTTP_POST  
314 - ,.query_string= ""  
315 - ,.fragment= ""  
316 - ,.request_path= "/two_chunks_mult_zero_end"  
317 - ,.request_url= "/two_chunks_mult_zero_end"  
318 - ,.num_headers= 1  
319 - ,.headers=  
320 - { { "Transfer-Encoding", "chunked" }  
321 - }  
322 - ,.body= "hello world"  
323 - }  
324 -  
325 -#define CHUNKED_W_TRAILING_HEADERS 10  
326 -, {.name= "chunked with trailing headers. blech."  
327 - ,.type= HTTP_REQUEST  
328 - ,.raw= "POST /chunked_w_trailing_headers HTTP/1.1\r\n"  
329 - "Transfer-Encoding: chunked\r\n"  
330 - "\r\n"  
331 - "5\r\nhello\r\n"  
332 - "6\r\n world\r\n"  
333 - "0\r\n"  
334 - "Vary: *\r\n"  
335 - "Content-Type: text/plain\r\n"  
336 - "\r\n"  
337 - ,.should_keep_alive= TRUE  
338 - ,.message_complete_on_eof= FALSE  
339 - ,.http_major= 1  
340 - ,.http_minor= 1  
341 - ,.method= HTTP_POST  
342 - ,.query_string= ""  
343 - ,.fragment= ""  
344 - ,.request_path= "/chunked_w_trailing_headers"  
345 - ,.request_url= "/chunked_w_trailing_headers"  
346 - ,.num_headers= 3  
347 - ,.headers=  
348 - { { "Transfer-Encoding", "chunked" }  
349 - , { "Vary", "*" }  
350 - , { "Content-Type", "text/plain" }  
351 - }  
352 - ,.body= "hello world"  
353 - }  
354 -  
355 -#define CHUNKED_W_BULLSHIT_AFTER_LENGTH 11  
356 -, {.name= "with bullshit after the length"  
357 - ,.type= HTTP_REQUEST  
358 - ,.raw= "POST /chunked_w_bullshit_after_length HTTP/1.1\r\n"  
359 - "Transfer-Encoding: chunked\r\n"  
360 - "\r\n"  
361 - "5; ihatew3;whatthefuck=aretheseparametersfor\r\nhello\r\n"  
362 - "6; blahblah; blah\r\n world\r\n"  
363 - "0\r\n"  
364 - "\r\n"  
365 - ,.should_keep_alive= TRUE  
366 - ,.message_complete_on_eof= FALSE  
367 - ,.http_major= 1  
368 - ,.http_minor= 1  
369 - ,.method= HTTP_POST  
370 - ,.query_string= ""  
371 - ,.fragment= ""  
372 - ,.request_path= "/chunked_w_bullshit_after_length"  
373 - ,.request_url= "/chunked_w_bullshit_after_length"  
374 - ,.num_headers= 1  
375 - ,.headers=  
376 - { { "Transfer-Encoding", "chunked" }  
377 - }  
378 - ,.body= "hello world"  
379 - }  
380 -  
381 -#define WITH_QUOTES 12  
382 -, {.name= "with quotes"  
383 - ,.type= HTTP_REQUEST  
384 - ,.raw= "GET /with_\"stupid\"_quotes?foo=\"bar\" HTTP/1.1\r\n\r\n"  
385 - ,.should_keep_alive= TRUE  
386 - ,.message_complete_on_eof= FALSE  
387 - ,.http_major= 1  
388 - ,.http_minor= 1  
389 - ,.method= HTTP_GET  
390 - ,.query_string= "foo=\"bar\""  
391 - ,.fragment= ""  
392 - ,.request_path= "/with_\"stupid\"_quotes"  
393 - ,.request_url= "/with_\"stupid\"_quotes?foo=\"bar\""  
394 - ,.num_headers= 0  
395 - ,.headers= { }  
396 - ,.body= ""  
397 - }  
398 -  
399 -#define APACHEBENCH_GET 13  
400 -/* The server receiving this request SHOULD NOT wait for EOF  
401 - * to know that content-length == 0.  
402 - * How to represent this in a unit test? message_complete_on_eof  
403 - * Compare with NO_CONTENT_LENGTH_RESPONSE.  
404 - */  
405 -, {.name = "apachebench get"  
406 - ,.type= HTTP_REQUEST  
407 - ,.raw= "GET /test HTTP/1.0\r\n"  
408 - "Host: 0.0.0.0:5000\r\n"  
409 - "User-Agent: ApacheBench/2.3\r\n"  
410 - "Accept: */*\r\n\r\n"  
411 - ,.should_keep_alive= FALSE  
412 - ,.message_complete_on_eof= FALSE  
413 - ,.http_major= 1  
414 - ,.http_minor= 0  
415 - ,.method= HTTP_GET  
416 - ,.query_string= ""  
417 - ,.fragment= ""  
418 - ,.request_path= "/test"  
419 - ,.request_url= "/test"  
420 - ,.num_headers= 3  
421 - ,.headers= { { "Host", "0.0.0.0:5000" }  
422 - , { "User-Agent", "ApacheBench/2.3" }  
423 - , { "Accept", "*/*" }  
424 - }  
425 - ,.body= ""  
426 - }  
427 -  
428 -#define QUERY_URL_WITH_QUESTION_MARK_GET 14  
429 -/* Some clients include '?' characters in query strings.  
430 - */  
431 -, {.name = "query url with question mark"  
432 - ,.type= HTTP_REQUEST  
433 - ,.raw= "GET /test.cgi?foo=bar?baz HTTP/1.1\r\n\r\n"  
434 - ,.should_keep_alive= TRUE  
435 - ,.message_complete_on_eof= FALSE  
436 - ,.http_major= 1  
437 - ,.http_minor= 1  
438 - ,.method= HTTP_GET  
439 - ,.query_string= "foo=bar?baz"  
440 - ,.fragment= ""  
441 - ,.request_path= "/test.cgi"  
442 - ,.request_url= "/test.cgi?foo=bar?baz"  
443 - ,.num_headers= 0  
444 - ,.headers= {}  
445 - ,.body= ""  
446 - }  
447 -  
448 -#define PREFIX_NEWLINE_GET 15  
449 -/* Some clients, especially after a POST in a keep-alive connection,  
450 - * will send an extra CRLF before the next request  
451 - */  
452 -, {.name = "newline prefix get"  
453 - ,.type= HTTP_REQUEST  
454 - ,.raw= "\r\nGET /test HTTP/1.1\r\n\r\n"  
455 - ,.should_keep_alive= TRUE  
456 - ,.message_complete_on_eof= FALSE  
457 - ,.http_major= 1  
458 - ,.http_minor= 1  
459 - ,.method= HTTP_GET  
460 - ,.query_string= ""  
461 - ,.fragment= ""  
462 - ,.request_path= "/test"  
463 - ,.request_url= "/test"  
464 - ,.num_headers= 0  
465 - ,.headers= { }  
466 - ,.body= ""  
467 - }  
468 -  
469 -#define UPGRADE_REQUEST 16  
470 -, {.name = "upgrade request"  
471 - ,.type= HTTP_REQUEST  
472 - ,.raw= "GET /demo HTTP/1.1\r\n"  
473 - "Host: example.com\r\n"  
474 - "Connection: Upgrade\r\n"  
475 - "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n"  
476 - "Sec-WebSocket-Protocol: sample\r\n"  
477 - "Upgrade: WebSocket\r\n"  
478 - "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n"  
479 - "Origin: http://example.com\r\n"  
480 - "\r\n"  
481 - "Hot diggity dogg"  
482 - ,.should_keep_alive= TRUE  
483 - ,.message_complete_on_eof= FALSE  
484 - ,.http_major= 1  
485 - ,.http_minor= 1  
486 - ,.method= HTTP_GET  
487 - ,.query_string= ""  
488 - ,.fragment= ""  
489 - ,.request_path= "/demo"  
490 - ,.request_url= "/demo"  
491 - ,.num_headers= 7  
492 - ,.upgrade="Hot diggity dogg"  
493 - ,.headers= { { "Host", "example.com" }  
494 - , { "Connection", "Upgrade" }  
495 - , { "Sec-WebSocket-Key2", "12998 5 Y3 1 .P00" }  
496 - , { "Sec-WebSocket-Protocol", "sample" }  
497 - , { "Upgrade", "WebSocket" }  
498 - , { "Sec-WebSocket-Key1", "4 @1 46546xW%0l 1 5" }  
499 - , { "Origin", "http://example.com" }  
500 - }  
501 - ,.body= ""  
502 - }  
503 -  
504 -#define CONNECT_REQUEST 17  
505 -, {.name = "connect request"  
506 - ,.type= HTTP_REQUEST  
507 - ,.raw= "CONNECT 0-home0.netscape.com:443 HTTP/1.0\r\n"  
508 - "User-agent: Mozilla/1.1N\r\n"  
509 - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"  
510 - "\r\n"  
511 - "some data\r\n"  
512 - "and yet even more data"  
513 - ,.should_keep_alive= FALSE  
514 - ,.message_complete_on_eof= FALSE  
515 - ,.http_major= 1  
516 - ,.http_minor= 0  
517 - ,.method= HTTP_CONNECT  
518 - ,.query_string= ""  
519 - ,.fragment= ""  
520 - ,.request_path= ""  
521 - ,.request_url= "0-home0.netscape.com:443"  
522 - ,.num_headers= 2  
523 - ,.upgrade="some data\r\nand yet even more data"  
524 - ,.headers= { { "User-agent", "Mozilla/1.1N" }  
525 - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }  
526 - }  
527 - ,.body= ""  
528 - }  
529 -  
530 -#define REPORT_REQ 18  
531 -, {.name= "report request"  
532 - ,.type= HTTP_REQUEST  
533 - ,.raw= "REPORT /test HTTP/1.1\r\n"  
534 - "\r\n"  
535 - ,.should_keep_alive= TRUE  
536 - ,.message_complete_on_eof= FALSE  
537 - ,.http_major= 1  
538 - ,.http_minor= 1  
539 - ,.method= HTTP_REPORT  
540 - ,.query_string= ""  
541 - ,.fragment= ""  
542 - ,.request_path= "/test"  
543 - ,.request_url= "/test"  
544 - ,.num_headers= 0  
545 - ,.headers= {}  
546 - ,.body= ""  
547 - }  
548 -  
549 -#define NO_HTTP_VERSION 19  
550 -, {.name= "request with no http version"  
551 - ,.type= HTTP_REQUEST  
552 - ,.raw= "GET /\r\n"  
553 - "\r\n"  
554 - ,.should_keep_alive= FALSE  
555 - ,.message_complete_on_eof= FALSE  
556 - ,.http_major= 0  
557 - ,.http_minor= 9  
558 - ,.method= HTTP_GET  
559 - ,.query_string= ""  
560 - ,.fragment= ""  
561 - ,.request_path= "/"  
562 - ,.request_url= "/"  
563 - ,.num_headers= 0  
564 - ,.headers= {}  
565 - ,.body= ""  
566 - }  
567 -  
568 -#define MSEARCH_REQ 20  
569 -, {.name= "m-search request"  
570 - ,.type= HTTP_REQUEST  
571 - ,.raw= "M-SEARCH * HTTP/1.1\r\n"  
572 - "HOST: 239.255.255.250:1900\r\n"  
573 - "MAN: \"ssdp:discover\"\r\n"  
574 - "ST: \"ssdp:all\"\r\n"  
575 - "\r\n"  
576 - ,.should_keep_alive= TRUE  
577 - ,.message_complete_on_eof= FALSE  
578 - ,.http_major= 1  
579 - ,.http_minor= 1  
580 - ,.method= HTTP_MSEARCH  
581 - ,.query_string= ""  
582 - ,.fragment= ""  
583 - ,.request_path= "*"  
584 - ,.request_url= "*"  
585 - ,.num_headers= 3  
586 - ,.headers= { { "HOST", "239.255.255.250:1900" }  
587 - , { "MAN", "\"ssdp:discover\"" }  
588 - , { "ST", "\"ssdp:all\"" }  
589 - }  
590 - ,.body= ""  
591 - }  
592 -  
593 -#define LINE_FOLDING_IN_HEADER 21  
594 -, {.name= "line folding in header value"  
595 - ,.type= HTTP_REQUEST  
596 - ,.raw= "GET / HTTP/1.1\r\n"  
597 - "Line1: abc\r\n"  
598 - "\tdef\r\n"  
599 - " ghi\r\n"  
600 - "\t\tjkl\r\n"  
601 - " mno \r\n"  
602 - "\t \tqrs\r\n"  
603 - "Line2: \t line2\t\r\n"  
604 - "\r\n"  
605 - ,.should_keep_alive= TRUE  
606 - ,.message_complete_on_eof= FALSE  
607 - ,.http_major= 1  
608 - ,.http_minor= 1  
609 - ,.method= HTTP_GET  
610 - ,.query_string= ""  
611 - ,.fragment= ""  
612 - ,.request_path= "/"  
613 - ,.request_url= "/"  
614 - ,.num_headers= 2  
615 - ,.headers= { { "Line1", "abcdefghijklmno qrs" }  
616 - , { "Line2", "line2\t" }  
617 - }  
618 - ,.body= ""  
619 - }  
620 -  
621 -  
622 -#define QUERY_TERMINATED_HOST 22  
623 -, {.name= "host terminated by a query string"  
624 - ,.type= HTTP_REQUEST  
625 - ,.raw= "GET http://hypnotoad.org?hail=all HTTP/1.1\r\n"  
626 - "\r\n"  
627 - ,.should_keep_alive= TRUE  
628 - ,.message_complete_on_eof= FALSE  
629 - ,.http_major= 1  
630 - ,.http_minor= 1  
631 - ,.method= HTTP_GET  
632 - ,.query_string= "hail=all"  
633 - ,.fragment= ""  
634 - ,.request_path= ""  
635 - ,.request_url= "http://hypnotoad.org?hail=all"  
636 - ,.host= "hypnotoad.org"  
637 - ,.num_headers= 0  
638 - ,.headers= { }  
639 - ,.body= ""  
640 - }  
641 -  
642 -#define QUERY_TERMINATED_HOSTPORT 23  
643 -, {.name= "host:port terminated by a query string"  
644 - ,.type= HTTP_REQUEST  
645 - ,.raw= "GET http://hypnotoad.org:1234?hail=all HTTP/1.1\r\n"  
646 - "\r\n"  
647 - ,.should_keep_alive= TRUE  
648 - ,.message_complete_on_eof= FALSE  
649 - ,.http_major= 1  
650 - ,.http_minor= 1  
651 - ,.method= HTTP_GET  
652 - ,.query_string= "hail=all"  
653 - ,.fragment= ""  
654 - ,.request_path= ""  
655 - ,.request_url= "http://hypnotoad.org:1234?hail=all"  
656 - ,.host= "hypnotoad.org"  
657 - ,.port= 1234  
658 - ,.num_headers= 0  
659 - ,.headers= { }  
660 - ,.body= ""  
661 - }  
662 -  
663 -#define SPACE_TERMINATED_HOSTPORT 24  
664 -, {.name= "host:port terminated by a space"  
665 - ,.type= HTTP_REQUEST  
666 - ,.raw= "GET http://hypnotoad.org:1234 HTTP/1.1\r\n"  
667 - "\r\n"  
668 - ,.should_keep_alive= TRUE  
669 - ,.message_complete_on_eof= FALSE  
670 - ,.http_major= 1  
671 - ,.http_minor= 1  
672 - ,.method= HTTP_GET  
673 - ,.query_string= ""  
674 - ,.fragment= ""  
675 - ,.request_path= ""  
676 - ,.request_url= "http://hypnotoad.org:1234"  
677 - ,.host= "hypnotoad.org"  
678 - ,.port= 1234  
679 - ,.num_headers= 0  
680 - ,.headers= { }  
681 - ,.body= ""  
682 - }  
683 -  
684 -#define PATCH_REQ 25  
685 -, {.name = "PATCH request"  
686 - ,.type= HTTP_REQUEST  
687 - ,.raw= "PATCH /file.txt HTTP/1.1\r\n"  
688 - "Host: www.example.com\r\n"  
689 - "Content-Type: application/example\r\n"  
690 - "If-Match: \"e0023aa4e\"\r\n"  
691 - "Content-Length: 10\r\n"  
692 - "\r\n"  
693 - "cccccccccc"  
694 - ,.should_keep_alive= TRUE  
695 - ,.message_complete_on_eof= FALSE  
696 - ,.http_major= 1  
697 - ,.http_minor= 1  
698 - ,.method= HTTP_PATCH  
699 - ,.query_string= ""  
700 - ,.fragment= ""  
701 - ,.request_path= "/file.txt"  
702 - ,.request_url= "/file.txt"  
703 - ,.num_headers= 4  
704 - ,.headers= { { "Host", "www.example.com" }  
705 - , { "Content-Type", "application/example" }  
706 - , { "If-Match", "\"e0023aa4e\"" }  
707 - , { "Content-Length", "10" }  
708 - }  
709 - ,.body= "cccccccccc"  
710 - }  
711 -  
712 -#define CONNECT_CAPS_REQUEST 26  
713 -, {.name = "connect caps request"  
714 - ,.type= HTTP_REQUEST  
715 - ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n"  
716 - "User-agent: Mozilla/1.1N\r\n"  
717 - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"  
718 - "\r\n"  
719 - ,.should_keep_alive= FALSE  
720 - ,.message_complete_on_eof= FALSE  
721 - ,.http_major= 1  
722 - ,.http_minor= 0  
723 - ,.method= HTTP_CONNECT  
724 - ,.query_string= ""  
725 - ,.fragment= ""  
726 - ,.request_path= ""  
727 - ,.request_url= "HOME0.NETSCAPE.COM:443"  
728 - ,.num_headers= 2  
729 - ,.upgrade=""  
730 - ,.headers= { { "User-agent", "Mozilla/1.1N" }  
731 - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }  
732 - }  
733 - ,.body= ""  
734 - }  
735 -  
736 -#if !HTTP_PARSER_STRICT  
737 -#define UTF8_PATH_REQ 27  
738 -, {.name= "utf-8 path request"  
739 - ,.type= HTTP_REQUEST  
740 - ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n"  
741 - "Host: github.com\r\n"  
742 - "\r\n"  
743 - ,.should_keep_alive= TRUE  
744 - ,.message_complete_on_eof= FALSE  
745 - ,.http_major= 1  
746 - ,.http_minor= 1  
747 - ,.method= HTTP_GET  
748 - ,.query_string= "q=1"  
749 - ,.fragment= "narf"  
750 - ,.request_path= "/δ¶/δt/pope"  
751 - ,.request_url= "/δ¶/δt/pope?q=1#narf"  
752 - ,.num_headers= 1  
753 - ,.headers= { {"Host", "github.com" }  
754 - }  
755 - ,.body= ""  
756 - }  
757 -  
758 -#define HOSTNAME_UNDERSCORE 28  
759 -, {.name = "hostname underscore"  
760 - ,.type= HTTP_REQUEST  
761 - ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n"  
762 - "User-agent: Mozilla/1.1N\r\n"  
763 - "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n"  
764 - "\r\n"  
765 - ,.should_keep_alive= FALSE  
766 - ,.message_complete_on_eof= FALSE  
767 - ,.http_major= 1  
768 - ,.http_minor= 0  
769 - ,.method= HTTP_CONNECT  
770 - ,.query_string= ""  
771 - ,.fragment= ""  
772 - ,.request_path= ""  
773 - ,.request_url= "home_0.netscape.com:443"  
774 - ,.num_headers= 2  
775 - ,.upgrade=""  
776 - ,.headers= { { "User-agent", "Mozilla/1.1N" }  
777 - , { "Proxy-authorization", "basic aGVsbG86d29ybGQ=" }  
778 - }  
779 - ,.body= ""  
780 - }  
781 -#endif /* !HTTP_PARSER_STRICT */  
782 -  
783 -/* see https://github.com/ry/http-parser/issues/47 */  
784 -#define EAT_TRAILING_CRLF_NO_CONNECTION_CLOSE 29  
785 -, {.name = "eat CRLF between requests, no \"Connection: close\" header"  
786 - ,.raw= "POST / HTTP/1.1\r\n"  
787 - "Host: www.example.com\r\n"  
788 - "Content-Type: application/x-www-form-urlencoded\r\n"  
789 - "Content-Length: 4\r\n"  
790 - "\r\n"  
791 - "q=42\r\n" /* note the trailing CRLF */  
792 - ,.should_keep_alive= TRUE  
793 - ,.message_complete_on_eof= FALSE  
794 - ,.http_major= 1  
795 - ,.http_minor= 1  
796 - ,.method= HTTP_POST  
797 - ,.query_string= ""  
798 - ,.fragment= ""  
799 - ,.request_path= "/"  
800 - ,.request_url= "/"  
801 - ,.num_headers= 3  
802 - ,.upgrade= 0  
803 - ,.headers= { { "Host", "www.example.com" }  
804 - , { "Content-Type", "application/x-www-form-urlencoded" }  
805 - , { "Content-Length", "4" }  
806 - }  
807 - ,.body= "q=42"  
808 - }  
809 -  
810 -/* see https://github.com/ry/http-parser/issues/47 */  
811 -#define EAT_TRAILING_CRLF_WITH_CONNECTION_CLOSE 30  
812 -, {.name = "eat CRLF between requests even if \"Connection: close\" is set"  
813 - ,.raw= "POST / HTTP/1.1\r\n"  
814 - "Host: www.example.com\r\n"  
815 - "Content-Type: application/x-www-form-urlencoded\r\n"  
816 - "Content-Length: 4\r\n"  
817 - "Connection: close\r\n"  
818 - "\r\n"  
819 - "q=42\r\n" /* note the trailing CRLF */  
820 - ,.should_keep_alive= FALSE  
821 - ,.message_complete_on_eof= FALSE /* input buffer isn't empty when on_message_complete is called */  
822 - ,.http_major= 1  
823 - ,.http_minor= 1  
824 - ,.method= HTTP_POST  
825 - ,.query_string= ""  
826 - ,.fragment= ""  
827 - ,.request_path= "/"  
828 - ,.request_url= "/"  
829 - ,.num_headers= 4  
830 - ,.upgrade= 0  
831 - ,.headers= { { "Host", "www.example.com" }  
832 - , { "Content-Type", "application/x-www-form-urlencoded" }  
833 - , { "Content-Length", "4" }  
834 - , { "Connection", "close" }  
835 - }  
836 - ,.body= "q=42"  
837 - }  
838 -  
839 -#define PURGE_REQ 31  
840 -, {.name = "PURGE request"  
841 - ,.type= HTTP_REQUEST  
842 - ,.raw= "PURGE /file.txt HTTP/1.1\r\n"  
843 - "Host: www.example.com\r\n"  
844 - "\r\n"  
845 - ,.should_keep_alive= TRUE  
846 - ,.message_complete_on_eof= FALSE  
847 - ,.http_major= 1  
848 - ,.http_minor= 1  
849 - ,.method= HTTP_PURGE  
850 - ,.query_string= ""  
851 - ,.fragment= ""  
852 - ,.request_path= "/file.txt"  
853 - ,.request_url= "/file.txt"  
854 - ,.num_headers= 1  
855 - ,.headers= { { "Host", "www.example.com" } }  
856 - ,.body= ""  
857 - }  
858 -  
859 -#define SEARCH_REQ 32  
860 -, {.name = "SEARCH request"  
861 - ,.type= HTTP_REQUEST  
862 - ,.raw= "SEARCH / HTTP/1.1\r\n"  
863 - "Host: www.example.com\r\n"  
864 - "\r\n"  
865 - ,.should_keep_alive= TRUE  
866 - ,.message_complete_on_eof= FALSE  
867 - ,.http_major= 1  
868 - ,.http_minor= 1  
869 - ,.method= HTTP_SEARCH  
870 - ,.query_string= ""  
871 - ,.fragment= ""  
872 - ,.request_path= "/"  
873 - ,.request_url= "/"  
874 - ,.num_headers= 1  
875 - ,.headers= { { "Host", "www.example.com" } }  
876 - ,.body= ""  
877 - }  
878 -  
879 -#define PROXY_WITH_BASIC_AUTH 33  
880 -, {.name= "host:port and basic_auth"  
881 - ,.type= HTTP_REQUEST  
882 - ,.raw= "GET http://a%12:b!&*$@hypnotoad.org:1234/toto HTTP/1.1\r\n"  
883 - "\r\n"  
884 - ,.should_keep_alive= TRUE  
885 - ,.message_complete_on_eof= FALSE  
886 - ,.http_major= 1  
887 - ,.http_minor= 1  
888 - ,.method= HTTP_GET  
889 - ,.fragment= ""  
890 - ,.request_path= "/toto"  
891 - ,.request_url= "http://a%12:b!&*$@hypnotoad.org:1234/toto"  
892 - ,.host= "hypnotoad.org"  
893 - ,.userinfo= "a%12:b!&*$"  
894 - ,.port= 1234  
895 - ,.num_headers= 0  
896 - ,.headers= { }  
897 - ,.body= ""  
898 - }  
899 -  
900 -  
901 -, {.name= NULL } /* sentinel */  
902 -};  
903 -  
904 -/* * R E S P O N S E S * */  
905 -const struct message responses[] =  
906 -#define GOOGLE_301 0  
907 -{ {.name= "google 301"  
908 - ,.type= HTTP_RESPONSE  
909 - ,.raw= "HTTP/1.1 301 Moved Permanently\r\n"  
910 - "Location: http://www.google.com/\r\n"  
911 - "Content-Type: text/html; charset=UTF-8\r\n"  
912 - "Date: Sun, 26 Apr 2009 11:11:49 GMT\r\n"  
913 - "Expires: Tue, 26 May 2009 11:11:49 GMT\r\n"  
914 - "X-$PrototypeBI-Version: 1.6.0.3\r\n" /* $ char in header field */  
915 - "Cache-Control: public, max-age=2592000\r\n"  
916 - "Server: gws\r\n"  
917 - "Content-Length: 219 \r\n"  
918 - "\r\n"  
919 - "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"  
920 - "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"  
921 - "<H1>301 Moved</H1>\n"  
922 - "The document has moved\n"  
923 - "<A HREF=\"http://www.google.com/\">here</A>.\r\n"  
924 - "</BODY></HTML>\r\n"  
925 - ,.should_keep_alive= TRUE  
926 - ,.message_complete_on_eof= FALSE  
927 - ,.http_major= 1  
928 - ,.http_minor= 1  
929 - ,.status_code= 301  
930 - ,.num_headers= 8  
931 - ,.headers=  
932 - { { "Location", "http://www.google.com/" }  
933 - , { "Content-Type", "text/html; charset=UTF-8" }  
934 - , { "Date", "Sun, 26 Apr 2009 11:11:49 GMT" }  
935 - , { "Expires", "Tue, 26 May 2009 11:11:49 GMT" }  
936 - , { "X-$PrototypeBI-Version", "1.6.0.3" }  
937 - , { "Cache-Control", "public, max-age=2592000" }  
938 - , { "Server", "gws" }  
939 - , { "Content-Length", "219 " }  
940 - }  
941 - ,.body= "<HTML><HEAD><meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\">\n"  
942 - "<TITLE>301 Moved</TITLE></HEAD><BODY>\n"  
943 - "<H1>301 Moved</H1>\n"  
944 - "The document has moved\n"  
945 - "<A HREF=\"http://www.google.com/\">here</A>.\r\n"  
946 - "</BODY></HTML>\r\n"  
947 - }  
948 -  
949 -#define NO_CONTENT_LENGTH_RESPONSE 1  
950 -/* The client should wait for the server's EOF. That is, when content-length  
951 - * is not specified, and "Connection: close", the end of body is specified  
952 - * by the EOF.  
953 - * Compare with APACHEBENCH_GET  
954 - */  
955 -, {.name= "no content-length response"  
956 - ,.type= HTTP_RESPONSE  
957 - ,.raw= "HTTP/1.1 200 OK\r\n"  
958 - "Date: Tue, 04 Aug 2009 07:59:32 GMT\r\n"  
959 - "Server: Apache\r\n"  
960 - "X-Powered-By: Servlet/2.5 JSP/2.1\r\n"  
961 - "Content-Type: text/xml; charset=utf-8\r\n"  
962 - "Connection: close\r\n"  
963 - "\r\n"  
964 - "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"  
965 - "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"  
966 - " <SOAP-ENV:Body>\n"  
967 - " <SOAP-ENV:Fault>\n"  
968 - " <faultcode>SOAP-ENV:Client</faultcode>\n"  
969 - " <faultstring>Client Error</faultstring>\n"  
970 - " </SOAP-ENV:Fault>\n"  
971 - " </SOAP-ENV:Body>\n"  
972 - "</SOAP-ENV:Envelope>"  
973 - ,.should_keep_alive= FALSE  
974 - ,.message_complete_on_eof= TRUE  
975 - ,.http_major= 1  
976 - ,.http_minor= 1  
977 - ,.status_code= 200  
978 - ,.num_headers= 5  
979 - ,.headers=  
980 - { { "Date", "Tue, 04 Aug 2009 07:59:32 GMT" }  
981 - , { "Server", "Apache" }  
982 - , { "X-Powered-By", "Servlet/2.5 JSP/2.1" }  
983 - , { "Content-Type", "text/xml; charset=utf-8" }  
984 - , { "Connection", "close" }  
985 - }  
986 - ,.body= "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"  
987 - "<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\n"  
988 - " <SOAP-ENV:Body>\n"  
989 - " <SOAP-ENV:Fault>\n"  
990 - " <faultcode>SOAP-ENV:Client</faultcode>\n"  
991 - " <faultstring>Client Error</faultstring>\n"  
992 - " </SOAP-ENV:Fault>\n"  
993 - " </SOAP-ENV:Body>\n"  
994 - "</SOAP-ENV:Envelope>"  
995 - }  
996 -  
997 -#define NO_HEADERS_NO_BODY_404 2  
998 -, {.name= "404 no headers no body"  
999 - ,.type= HTTP_RESPONSE  
1000 - ,.raw= "HTTP/1.1 404 Not Found\r\n\r\n"  
1001 - ,.should_keep_alive= FALSE  
1002 - ,.message_complete_on_eof= TRUE  
1003 - ,.http_major= 1  
1004 - ,.http_minor= 1  
1005 - ,.status_code= 404  
1006 - ,.num_headers= 0  
1007 - ,.headers= {}  
1008 - ,.body_size= 0  
1009 - ,.body= ""  
1010 - }  
1011 -  
1012 -#define NO_REASON_PHRASE 3  
1013 -, {.name= "301 no response phrase"  
1014 - ,.type= HTTP_RESPONSE  
1015 - ,.raw= "HTTP/1.1 301\r\n\r\n"  
1016 - ,.should_keep_alive = FALSE  
1017 - ,.message_complete_on_eof= TRUE  
1018 - ,.http_major= 1  
1019 - ,.http_minor= 1  
1020 - ,.status_code= 301  
1021 - ,.num_headers= 0  
1022 - ,.headers= {}  
1023 - ,.body= ""  
1024 - }  
1025 -  
1026 -#define TRAILING_SPACE_ON_CHUNKED_BODY 4  
1027 -, {.name="200 trailing space on chunked body"  
1028 - ,.type= HTTP_RESPONSE  
1029 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1030 - "Content-Type: text/plain\r\n"  
1031 - "Transfer-Encoding: chunked\r\n"  
1032 - "\r\n"  
1033 - "25 \r\n"  
1034 - "This is the data in the first chunk\r\n"  
1035 - "\r\n"  
1036 - "1C\r\n"  
1037 - "and this is the second one\r\n"  
1038 - "\r\n"  
1039 - "0 \r\n"  
1040 - "\r\n"  
1041 - ,.should_keep_alive= TRUE  
1042 - ,.message_complete_on_eof= FALSE  
1043 - ,.http_major= 1  
1044 - ,.http_minor= 1  
1045 - ,.status_code= 200  
1046 - ,.num_headers= 2  
1047 - ,.headers=  
1048 - { {"Content-Type", "text/plain" }  
1049 - , {"Transfer-Encoding", "chunked" }  
1050 - }  
1051 - ,.body_size = 37+28  
1052 - ,.body =  
1053 - "This is the data in the first chunk\r\n"  
1054 - "and this is the second one\r\n"  
1055 -  
1056 - }  
1057 -  
1058 -#define NO_CARRIAGE_RET 5  
1059 -, {.name="no carriage ret"  
1060 - ,.type= HTTP_RESPONSE  
1061 - ,.raw= "HTTP/1.1 200 OK\n"  
1062 - "Content-Type: text/html; charset=utf-8\n"  
1063 - "Connection: close\n"  
1064 - "\n"  
1065 - "these headers are from http://news.ycombinator.com/"  
1066 - ,.should_keep_alive= FALSE  
1067 - ,.message_complete_on_eof= TRUE  
1068 - ,.http_major= 1  
1069 - ,.http_minor= 1  
1070 - ,.status_code= 200  
1071 - ,.num_headers= 2  
1072 - ,.headers=  
1073 - { {"Content-Type", "text/html; charset=utf-8" }  
1074 - , {"Connection", "close" }  
1075 - }  
1076 - ,.body= "these headers are from http://news.ycombinator.com/"  
1077 - }  
1078 -  
1079 -#define PROXY_CONNECTION 6  
1080 -, {.name="proxy connection"  
1081 - ,.type= HTTP_RESPONSE  
1082 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1083 - "Content-Type: text/html; charset=UTF-8\r\n"  
1084 - "Content-Length: 11\r\n"  
1085 - "Proxy-Connection: close\r\n"  
1086 - "Date: Thu, 31 Dec 2009 20:55:48 +0000\r\n"  
1087 - "\r\n"  
1088 - "hello world"  
1089 - ,.should_keep_alive= FALSE  
1090 - ,.message_complete_on_eof= FALSE  
1091 - ,.http_major= 1  
1092 - ,.http_minor= 1  
1093 - ,.status_code= 200  
1094 - ,.num_headers= 4  
1095 - ,.headers=  
1096 - { {"Content-Type", "text/html; charset=UTF-8" }  
1097 - , {"Content-Length", "11" }  
1098 - , {"Proxy-Connection", "close" }  
1099 - , {"Date", "Thu, 31 Dec 2009 20:55:48 +0000"}  
1100 - }  
1101 - ,.body= "hello world"  
1102 - }  
1103 -  
1104 -#define UNDERSTORE_HEADER_KEY 7  
1105 - // shown by  
1106 - // curl -o /dev/null -v "http://ad.doubleclick.net/pfadx/DARTSHELLCONFIGXML;dcmt=text/xml;"  
1107 -, {.name="underscore header key"  
1108 - ,.type= HTTP_RESPONSE  
1109 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1110 - "Server: DCLK-AdSvr\r\n"  
1111 - "Content-Type: text/xml\r\n"  
1112 - "Content-Length: 0\r\n"  
1113 - "DCLK_imp: v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o\r\n\r\n"  
1114 - ,.should_keep_alive= TRUE  
1115 - ,.message_complete_on_eof= FALSE  
1116 - ,.http_major= 1  
1117 - ,.http_minor= 1  
1118 - ,.status_code= 200  
1119 - ,.num_headers= 4  
1120 - ,.headers=  
1121 - { {"Server", "DCLK-AdSvr" }  
1122 - , {"Content-Type", "text/xml" }  
1123 - , {"Content-Length", "0" }  
1124 - , {"DCLK_imp", "v7;x;114750856;0-0;0;17820020;0/0;21603567/21621457/1;;~okv=;dcmt=text/xml;;~cs=o" }  
1125 - }  
1126 - ,.body= ""  
1127 - }  
1128 -  
1129 -#define BONJOUR_MADAME_FR 8  
1130 -/* The client should not merge two headers fields when the first one doesn't  
1131 - * have a value.  
1132 - */  
1133 -, {.name= "bonjourmadame.fr"  
1134 - ,.type= HTTP_RESPONSE  
1135 - ,.raw= "HTTP/1.0 301 Moved Permanently\r\n"  
1136 - "Date: Thu, 03 Jun 2010 09:56:32 GMT\r\n"  
1137 - "Server: Apache/2.2.3 (Red Hat)\r\n"  
1138 - "Cache-Control: public\r\n"  
1139 - "Pragma: \r\n"  
1140 - "Location: http://www.bonjourmadame.fr/\r\n"  
1141 - "Vary: Accept-Encoding\r\n"  
1142 - "Content-Length: 0\r\n"  
1143 - "Content-Type: text/html; charset=UTF-8\r\n"  
1144 - "Connection: keep-alive\r\n"  
1145 - "\r\n"  
1146 - ,.should_keep_alive= TRUE  
1147 - ,.message_complete_on_eof= FALSE  
1148 - ,.http_major= 1  
1149 - ,.http_minor= 0  
1150 - ,.status_code= 301  
1151 - ,.num_headers= 9  
1152 - ,.headers=  
1153 - { { "Date", "Thu, 03 Jun 2010 09:56:32 GMT" }  
1154 - , { "Server", "Apache/2.2.3 (Red Hat)" }  
1155 - , { "Cache-Control", "public" }  
1156 - , { "Pragma", "" }  
1157 - , { "Location", "http://www.bonjourmadame.fr/" }  
1158 - , { "Vary", "Accept-Encoding" }  
1159 - , { "Content-Length", "0" }  
1160 - , { "Content-Type", "text/html; charset=UTF-8" }  
1161 - , { "Connection", "keep-alive" }  
1162 - }  
1163 - ,.body= ""  
1164 - }  
1165 -  
1166 -#define RES_FIELD_UNDERSCORE 9  
1167 -/* Should handle spaces in header fields */  
1168 -, {.name= "field underscore"  
1169 - ,.type= HTTP_RESPONSE  
1170 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1171 - "Date: Tue, 28 Sep 2010 01:14:13 GMT\r\n"  
1172 - "Server: Apache\r\n"  
1173 - "Cache-Control: no-cache, must-revalidate\r\n"  
1174 - "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"  
1175 - ".et-Cookie: PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com\r\n"  
1176 - "Vary: Accept-Encoding\r\n"  
1177 - "_eep-Alive: timeout=45\r\n" /* semantic value ignored */  
1178 - "_onnection: Keep-Alive\r\n" /* semantic value ignored */  
1179 - "Transfer-Encoding: chunked\r\n"  
1180 - "Content-Type: text/html\r\n"  
1181 - "Connection: close\r\n"  
1182 - "\r\n"  
1183 - "0\r\n\r\n"  
1184 - ,.should_keep_alive= FALSE  
1185 - ,.message_complete_on_eof= FALSE  
1186 - ,.http_major= 1  
1187 - ,.http_minor= 1  
1188 - ,.status_code= 200  
1189 - ,.num_headers= 11  
1190 - ,.headers=  
1191 - { { "Date", "Tue, 28 Sep 2010 01:14:13 GMT" }  
1192 - , { "Server", "Apache" }  
1193 - , { "Cache-Control", "no-cache, must-revalidate" }  
1194 - , { "Expires", "Mon, 26 Jul 1997 05:00:00 GMT" }  
1195 - , { ".et-Cookie", "PlaxoCS=1274804622353690521; path=/; domain=.plaxo.com" }  
1196 - , { "Vary", "Accept-Encoding" }  
1197 - , { "_eep-Alive", "timeout=45" }  
1198 - , { "_onnection", "Keep-Alive" }  
1199 - , { "Transfer-Encoding", "chunked" }  
1200 - , { "Content-Type", "text/html" }  
1201 - , { "Connection", "close" }  
1202 - }  
1203 - ,.body= ""  
1204 - }  
1205 -  
1206 -#define NON_ASCII_IN_STATUS_LINE 10  
1207 -/* Should handle non-ASCII in status line */  
1208 -, {.name= "non-ASCII in status line"  
1209 - ,.type= HTTP_RESPONSE  
1210 - ,.raw= "HTTP/1.1 500 Oriëntatieprobleem\r\n"  
1211 - "Date: Fri, 5 Nov 2010 23:07:12 GMT+2\r\n"  
1212 - "Content-Length: 0\r\n"  
1213 - "Connection: close\r\n"  
1214 - "\r\n"  
1215 - ,.should_keep_alive= FALSE  
1216 - ,.message_complete_on_eof= FALSE  
1217 - ,.http_major= 1  
1218 - ,.http_minor= 1  
1219 - ,.status_code= 500  
1220 - ,.num_headers= 3  
1221 - ,.headers=  
1222 - { { "Date", "Fri, 5 Nov 2010 23:07:12 GMT+2" }  
1223 - , { "Content-Length", "0" }  
1224 - , { "Connection", "close" }  
1225 - }  
1226 - ,.body= ""  
1227 - }  
1228 -  
1229 -#define HTTP_VERSION_0_9 11  
1230 -/* Should handle HTTP/0.9 */  
1231 -, {.name= "http version 0.9"  
1232 - ,.type= HTTP_RESPONSE  
1233 - ,.raw= "HTTP/0.9 200 OK\r\n"  
1234 - "\r\n"  
1235 - ,.should_keep_alive= FALSE  
1236 - ,.message_complete_on_eof= TRUE  
1237 - ,.http_major= 0  
1238 - ,.http_minor= 9  
1239 - ,.status_code= 200  
1240 - ,.num_headers= 0  
1241 - ,.headers=  
1242 - {}  
1243 - ,.body= ""  
1244 - }  
1245 -  
1246 -#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12  
1247 -/* The client should wait for the server's EOF. That is, when neither  
1248 - * content-length nor transfer-encoding is specified, the end of body  
1249 - * is specified by the EOF.  
1250 - */  
1251 -, {.name= "neither content-length nor transfer-encoding response"  
1252 - ,.type= HTTP_RESPONSE  
1253 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1254 - "Content-Type: text/plain\r\n"  
1255 - "\r\n"  
1256 - "hello world"  
1257 - ,.should_keep_alive= FALSE  
1258 - ,.message_complete_on_eof= TRUE  
1259 - ,.http_major= 1  
1260 - ,.http_minor= 1  
1261 - ,.status_code= 200  
1262 - ,.num_headers= 1  
1263 - ,.headers=  
1264 - { { "Content-Type", "text/plain" }  
1265 - }  
1266 - ,.body= "hello world"  
1267 - }  
1268 -  
1269 -#define NO_BODY_HTTP10_KA_200 13  
1270 -, {.name= "HTTP/1.0 with keep-alive and EOF-terminated 200 status"  
1271 - ,.type= HTTP_RESPONSE  
1272 - ,.raw= "HTTP/1.0 200 OK\r\n"  
1273 - "Connection: keep-alive\r\n"  
1274 - "\r\n"  
1275 - ,.should_keep_alive= FALSE  
1276 - ,.message_complete_on_eof= TRUE  
1277 - ,.http_major= 1  
1278 - ,.http_minor= 0  
1279 - ,.status_code= 200  
1280 - ,.num_headers= 1  
1281 - ,.headers=  
1282 - { { "Connection", "keep-alive" }  
1283 - }  
1284 - ,.body_size= 0  
1285 - ,.body= ""  
1286 - }  
1287 -  
1288 -#define NO_BODY_HTTP10_KA_204 14  
1289 -, {.name= "HTTP/1.0 with keep-alive and a 204 status"  
1290 - ,.type= HTTP_RESPONSE  
1291 - ,.raw= "HTTP/1.0 204 No content\r\n"  
1292 - "Connection: keep-alive\r\n"  
1293 - "\r\n"  
1294 - ,.should_keep_alive= TRUE  
1295 - ,.message_complete_on_eof= FALSE  
1296 - ,.http_major= 1  
1297 - ,.http_minor= 0  
1298 - ,.status_code= 204  
1299 - ,.num_headers= 1  
1300 - ,.headers=  
1301 - { { "Connection", "keep-alive" }  
1302 - }  
1303 - ,.body_size= 0  
1304 - ,.body= ""  
1305 - }  
1306 -  
1307 -#define NO_BODY_HTTP11_KA_200 15  
1308 -, {.name= "HTTP/1.1 with an EOF-terminated 200 status"  
1309 - ,.type= HTTP_RESPONSE  
1310 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1311 - "\r\n"  
1312 - ,.should_keep_alive= FALSE  
1313 - ,.message_complete_on_eof= TRUE  
1314 - ,.http_major= 1  
1315 - ,.http_minor= 1  
1316 - ,.status_code= 200  
1317 - ,.num_headers= 0  
1318 - ,.headers={}  
1319 - ,.body_size= 0  
1320 - ,.body= ""  
1321 - }  
1322 -  
1323 -#define NO_BODY_HTTP11_KA_204 16  
1324 -, {.name= "HTTP/1.1 with a 204 status"  
1325 - ,.type= HTTP_RESPONSE  
1326 - ,.raw= "HTTP/1.1 204 No content\r\n"  
1327 - "\r\n"  
1328 - ,.should_keep_alive= TRUE  
1329 - ,.message_complete_on_eof= FALSE  
1330 - ,.http_major= 1  
1331 - ,.http_minor= 1  
1332 - ,.status_code= 204  
1333 - ,.num_headers= 0  
1334 - ,.headers={}  
1335 - ,.body_size= 0  
1336 - ,.body= ""  
1337 - }  
1338 -  
1339 -#define NO_BODY_HTTP11_NOKA_204 17  
1340 -, {.name= "HTTP/1.1 with a 204 status and keep-alive disabled"  
1341 - ,.type= HTTP_RESPONSE  
1342 - ,.raw= "HTTP/1.1 204 No content\r\n"  
1343 - "Connection: close\r\n"  
1344 - "\r\n"  
1345 - ,.should_keep_alive= FALSE  
1346 - ,.message_complete_on_eof= FALSE  
1347 - ,.http_major= 1  
1348 - ,.http_minor= 1  
1349 - ,.status_code= 204  
1350 - ,.num_headers= 1  
1351 - ,.headers=  
1352 - { { "Connection", "close" }  
1353 - }  
1354 - ,.body_size= 0  
1355 - ,.body= ""  
1356 - }  
1357 -  
1358 -#define NO_BODY_HTTP11_KA_CHUNKED_200 18  
1359 -, {.name= "HTTP/1.1 with chunked endocing and a 200 response"  
1360 - ,.type= HTTP_RESPONSE  
1361 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1362 - "Transfer-Encoding: chunked\r\n"  
1363 - "\r\n"  
1364 - "0\r\n"  
1365 - "\r\n"  
1366 - ,.should_keep_alive= TRUE  
1367 - ,.message_complete_on_eof= FALSE  
1368 - ,.http_major= 1  
1369 - ,.http_minor= 1  
1370 - ,.status_code= 200  
1371 - ,.num_headers= 1  
1372 - ,.headers=  
1373 - { { "Transfer-Encoding", "chunked" }  
1374 - }  
1375 - ,.body_size= 0  
1376 - ,.body= ""  
1377 - }  
1378 -  
1379 -#if !HTTP_PARSER_STRICT  
1380 -#define SPACE_IN_FIELD_RES 19  
1381 -/* Should handle spaces in header fields */  
1382 -, {.name= "field space"  
1383 - ,.type= HTTP_RESPONSE  
1384 - ,.raw= "HTTP/1.1 200 OK\r\n"  
1385 - "Server: Microsoft-IIS/6.0\r\n"  
1386 - "X-Powered-By: ASP.NET\r\n"  
1387 - "en-US Content-Type: text/xml\r\n" /* this is the problem */  
1388 - "Content-Type: text/xml\r\n"  
1389 - "Content-Length: 16\r\n"  
1390 - "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n"  
1391 - "Connection: keep-alive\r\n"  
1392 - "\r\n"  
1393 - "<xml>hello</xml>" /* fake body */  
1394 - ,.should_keep_alive= TRUE  
1395 - ,.message_complete_on_eof= FALSE  
1396 - ,.http_major= 1  
1397 - ,.http_minor= 1  
1398 - ,.status_code= 200  
1399 - ,.num_headers= 7  
1400 - ,.headers=  
1401 - { { "Server", "Microsoft-IIS/6.0" }  
1402 - , { "X-Powered-By", "ASP.NET" }  
1403 - , { "en-US Content-Type", "text/xml" }  
1404 - , { "Content-Type", "text/xml" }  
1405 - , { "Content-Length", "16" }  
1406 - , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" }  
1407 - , { "Connection", "keep-alive" }  
1408 - }  
1409 - ,.body= "<xml>hello</xml>"  
1410 - }  
1411 -#endif /* !HTTP_PARSER_STRICT */  
1412 -  
1413 -, {.name= NULL } /* sentinel */  
1414 -};  
1415 -  
1416 -/* strnlen() is a POSIX.2008 addition. Can't rely on it being available so  
1417 - * define it ourselves.  
1418 - */  
1419 -size_t  
1420 -strnlen(const char *s, size_t maxlen)  
1421 -{  
1422 - const char *p;  
1423 -  
1424 - p = memchr(s, '\0', maxlen);  
1425 - if (p == NULL)  
1426 - return maxlen;  
1427 -  
1428 - return p - s;  
1429 -}  
1430 -  
1431 -size_t  
1432 -strlncat(char *dst, size_t len, const char *src, size_t n)  
1433 -{  
1434 - size_t slen;  
1435 - size_t dlen;  
1436 - size_t rlen;  
1437 - size_t ncpy;  
1438 -  
1439 - slen = strnlen(src, n);  
1440 - dlen = strnlen(dst, len);  
1441 -  
1442 - if (dlen < len) {  
1443 - rlen = len - dlen;  
1444 - ncpy = slen < rlen ? slen : (rlen - 1);  
1445 - memcpy(dst + dlen, src, ncpy);  
1446 - dst[dlen + ncpy] = '\0';  
1447 - }  
1448 -  
1449 - assert(len > slen + dlen);  
1450 - return slen + dlen;  
1451 -}  
1452 -  
1453 -size_t  
1454 -strlcat(char *dst, const char *src, size_t len)  
1455 -{  
1456 - return strlncat(dst, len, src, (size_t) -1);  
1457 -}  
1458 -  
1459 -size_t  
1460 -strlncpy(char *dst, size_t len, const char *src, size_t n)  
1461 -{  
1462 - size_t slen;  
1463 - size_t ncpy;  
1464 -  
1465 - slen = strnlen(src, n);  
1466 -  
1467 - if (len > 0) {  
1468 - ncpy = slen < len ? slen : (len - 1);  
1469 - memcpy(dst, src, ncpy);  
1470 - dst[ncpy] = '\0';  
1471 - }  
1472 -  
1473 - assert(len > slen);  
1474 - return slen;  
1475 -}  
1476 -  
1477 -size_t  
1478 -strlcpy(char *dst, const char *src, size_t len)  
1479 -{  
1480 - return strlncpy(dst, len, src, (size_t) -1);  
1481 -}  
1482 -  
1483 -int  
1484 -request_url_cb (http_parser *p, const char *buf, size_t len)  
1485 -{  
1486 - assert(p == parser);  
1487 - strlncat(messages[num_messages].request_url,  
1488 - sizeof(messages[num_messages].request_url),  
1489 - buf,  
1490 - len);  
1491 - return 0;  
1492 -}  
1493 -  
1494 -int  
1495 -status_complete_cb (http_parser *p) {  
1496 - assert(p == parser);  
1497 - p->data++;  
1498 - return 0;  
1499 -}  
1500 -  
1501 -int  
1502 -header_field_cb (http_parser *p, const char *buf, size_t len)  
1503 -{  
1504 - assert(p == parser);  
1505 - struct message *m = &messages[num_messages];  
1506 -  
1507 - if (m->last_header_element != FIELD)  
1508 - m->num_headers++;  
1509 -  
1510 - strlncat(m->headers[m->num_headers-1][0],  
1511 - sizeof(m->headers[m->num_headers-1][0]),  
1512 - buf,  
1513 - len);  
1514 -  
1515 - m->last_header_element = FIELD;  
1516 -  
1517 - return 0;  
1518 -}  
1519 -  
1520 -int  
1521 -header_value_cb (http_parser *p, const char *buf, size_t len)  
1522 -{  
1523 - assert(p == parser);  
1524 - struct message *m = &messages[num_messages];  
1525 -  
1526 - strlncat(m->headers[m->num_headers-1][1],  
1527 - sizeof(m->headers[m->num_headers-1][1]),  
1528 - buf,  
1529 - len);  
1530 -  
1531 - m->last_header_element = VALUE;  
1532 -  
1533 - return 0;  
1534 -}  
1535 -  
1536 -void  
1537 -check_body_is_final (const http_parser *p)  
1538 -{  
1539 - if (messages[num_messages].body_is_final) {  
1540 - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "  
1541 - "on last on_body callback call "  
1542 - "but it doesn't! ***\n\n");  
1543 - assert(0);  
1544 - abort();  
1545 - }  
1546 - messages[num_messages].body_is_final = http_body_is_final(p);  
1547 -}  
1548 -  
1549 -int  
1550 -body_cb (http_parser *p, const char *buf, size_t len)  
1551 -{  
1552 - assert(p == parser);  
1553 - strlncat(messages[num_messages].body,  
1554 - sizeof(messages[num_messages].body),  
1555 - buf,  
1556 - len);  
1557 - messages[num_messages].body_size += len;  
1558 - check_body_is_final(p);  
1559 - // printf("body_cb: '%s'\n", requests[num_messages].body);  
1560 - return 0;  
1561 -}  
1562 -  
1563 -int  
1564 -count_body_cb (http_parser *p, const char *buf, size_t len)  
1565 -{  
1566 - assert(p == parser);  
1567 - assert(buf);  
1568 - messages[num_messages].body_size += len;  
1569 - check_body_is_final(p);  
1570 - return 0;  
1571 -}  
1572 -  
1573 -int  
1574 -message_begin_cb (http_parser *p)  
1575 -{  
1576 - assert(p == parser);  
1577 - messages[num_messages].message_begin_cb_called = TRUE;  
1578 - return 0;  
1579 -}  
1580 -  
1581 -int  
1582 -headers_complete_cb (http_parser *p)  
1583 -{  
1584 - assert(p == parser);  
1585 - messages[num_messages].method = parser->method;  
1586 - messages[num_messages].status_code = parser->status_code;  
1587 - messages[num_messages].http_major = parser->http_major;  
1588 - messages[num_messages].http_minor = parser->http_minor;  
1589 - messages[num_messages].headers_complete_cb_called = TRUE;  
1590 - messages[num_messages].should_keep_alive = http_should_keep_alive(parser);  
1591 - return 0;  
1592 -}  
1593 -  
1594 -int  
1595 -message_complete_cb (http_parser *p)  
1596 -{  
1597 - assert(p == parser);  
1598 - if (messages[num_messages].should_keep_alive != http_should_keep_alive(parser))  
1599 - {  
1600 - fprintf(stderr, "\n\n *** Error http_should_keep_alive() should have same "  
1601 - "value in both on_message_complete and on_headers_complete "  
1602 - "but it doesn't! ***\n\n");  
1603 - assert(0);  
1604 - abort();  
1605 - }  
1606 -  
1607 - if (messages[num_messages].body_size &&  
1608 - http_body_is_final(p) &&  
1609 - !messages[num_messages].body_is_final)  
1610 - {  
1611 - fprintf(stderr, "\n\n *** Error http_body_is_final() should return 1 "  
1612 - "on last on_body callback call "  
1613 - "but it doesn't! ***\n\n");  
1614 - assert(0);  
1615 - abort();  
1616 - }  
1617 -  
1618 - messages[num_messages].message_complete_cb_called = TRUE;  
1619 -  
1620 - messages[num_messages].message_complete_on_eof = currently_parsing_eof;  
1621 -  
1622 - num_messages++;  
1623 - return 0;  
1624 -}  
1625 -  
1626 -/* These dontcall_* callbacks exist so that we can verify that when we're  
1627 - * paused, no additional callbacks are invoked */  
1628 -int  
1629 -dontcall_message_begin_cb (http_parser *p)  
1630 -{  
1631 - if (p) { } // gcc  
1632 - fprintf(stderr, "\n\n*** on_message_begin() called on paused parser ***\n\n");  
1633 - abort();  
1634 -}  
1635 -  
1636 -int  
1637 -dontcall_header_field_cb (http_parser *p, const char *buf, size_t len)  
1638 -{  
1639 - if (p || buf || len) { } // gcc  
1640 - fprintf(stderr, "\n\n*** on_header_field() called on paused parser ***\n\n");  
1641 - abort();  
1642 -}  
1643 -  
1644 -int  
1645 -dontcall_header_value_cb (http_parser *p, const char *buf, size_t len)  
1646 -{  
1647 - if (p || buf || len) { } // gcc  
1648 - fprintf(stderr, "\n\n*** on_header_value() called on paused parser ***\n\n");  
1649 - abort();  
1650 -}  
1651 -  
1652 -int  
1653 -dontcall_request_url_cb (http_parser *p, const char *buf, size_t len)  
1654 -{  
1655 - if (p || buf || len) { } // gcc  
1656 - fprintf(stderr, "\n\n*** on_request_url() called on paused parser ***\n\n");  
1657 - abort();  
1658 -}  
1659 -  
1660 -int  
1661 -dontcall_body_cb (http_parser *p, const char *buf, size_t len)  
1662 -{  
1663 - if (p || buf || len) { } // gcc  
1664 - fprintf(stderr, "\n\n*** on_body_cb() called on paused parser ***\n\n");  
1665 - abort();  
1666 -}  
1667 -  
1668 -int  
1669 -dontcall_headers_complete_cb (http_parser *p)  
1670 -{  
1671 - if (p) { } // gcc  
1672 - fprintf(stderr, "\n\n*** on_headers_complete() called on paused "  
1673 - "parser ***\n\n");  
1674 - abort();  
1675 -}  
1676 -  
1677 -int  
1678 -dontcall_message_complete_cb (http_parser *p)  
1679 -{  
1680 - if (p) { } // gcc  
1681 - fprintf(stderr, "\n\n*** on_message_complete() called on paused "  
1682 - "parser ***\n\n");  
1683 - abort();  
1684 -}  
1685 -  
1686 -static http_parser_settings settings_dontcall =  
1687 - {.on_message_begin = dontcall_message_begin_cb  
1688 - ,.on_header_field = dontcall_header_field_cb  
1689 - ,.on_header_value = dontcall_header_value_cb  
1690 - ,.on_url = dontcall_request_url_cb  
1691 - ,.on_body = dontcall_body_cb  
1692 - ,.on_headers_complete = dontcall_headers_complete_cb  
1693 - ,.on_message_complete = dontcall_message_complete_cb  
1694 - };  
1695 -  
1696 -/* These pause_* callbacks always pause the parser and just invoke the regular  
1697 - * callback that tracks content. Before returning, we overwrite the parser  
1698 - * settings to point to the _dontcall variety so that we can verify that  
1699 - * the pause actually did, you know, pause. */  
1700 -int  
1701 -pause_message_begin_cb (http_parser *p)  
1702 -{  
1703 - http_parser_pause(p, 1);  
1704 - *current_pause_parser = settings_dontcall;  
1705 - return message_begin_cb(p);  
1706 -}  
1707 -  
1708 -int  
1709 -pause_header_field_cb (http_parser *p, const char *buf, size_t len)  
1710 -{  
1711 - http_parser_pause(p, 1);  
1712 - *current_pause_parser = settings_dontcall;  
1713 - return header_field_cb(p, buf, len);  
1714 -}  
1715 -  
1716 -int  
1717 -pause_header_value_cb (http_parser *p, const char *buf, size_t len)  
1718 -{  
1719 - http_parser_pause(p, 1);  
1720 - *current_pause_parser = settings_dontcall;  
1721 - return header_value_cb(p, buf, len);  
1722 -}  
1723 -  
1724 -int  
1725 -pause_request_url_cb (http_parser *p, const char *buf, size_t len)  
1726 -{  
1727 - http_parser_pause(p, 1);  
1728 - *current_pause_parser = settings_dontcall;  
1729 - return request_url_cb(p, buf, len);  
1730 -}  
1731 -  
1732 -int  
1733 -pause_body_cb (http_parser *p, const char *buf, size_t len)  
1734 -{  
1735 - http_parser_pause(p, 1);  
1736 - *current_pause_parser = settings_dontcall;  
1737 - return body_cb(p, buf, len);  
1738 -}  
1739 -  
1740 -int  
1741 -pause_headers_complete_cb (http_parser *p)  
1742 -{  
1743 - http_parser_pause(p, 1);  
1744 - *current_pause_parser = settings_dontcall;  
1745 - return headers_complete_cb(p);  
1746 -}  
1747 -  
1748 -int  
1749 -pause_message_complete_cb (http_parser *p)  
1750 -{  
1751 - http_parser_pause(p, 1);  
1752 - *current_pause_parser = settings_dontcall;  
1753 - return message_complete_cb(p);  
1754 -}  
1755 -  
1756 -static http_parser_settings settings_pause =  
1757 - {.on_message_begin = pause_message_begin_cb  
1758 - ,.on_header_field = pause_header_field_cb  
1759 - ,.on_header_value = pause_header_value_cb  
1760 - ,.on_url = pause_request_url_cb  
1761 - ,.on_body = pause_body_cb  
1762 - ,.on_headers_complete = pause_headers_complete_cb  
1763 - ,.on_message_complete = pause_message_complete_cb  
1764 - };  
1765 -  
1766 -static http_parser_settings settings =  
1767 - {.on_message_begin = message_begin_cb  
1768 - ,.on_header_field = header_field_cb  
1769 - ,.on_header_value = header_value_cb  
1770 - ,.on_url = request_url_cb  
1771 - ,.on_body = body_cb  
1772 - ,.on_headers_complete = headers_complete_cb  
1773 - ,.on_message_complete = message_complete_cb  
1774 - };  
1775 -  
1776 -static http_parser_settings settings_count_body =  
1777 - {.on_message_begin = message_begin_cb  
1778 - ,.on_header_field = header_field_cb  
1779 - ,.on_header_value = header_value_cb  
1780 - ,.on_url = request_url_cb  
1781 - ,.on_body = count_body_cb  
1782 - ,.on_headers_complete = headers_complete_cb  
1783 - ,.on_message_complete = message_complete_cb  
1784 - };  
1785 -  
1786 -static http_parser_settings settings_null =  
1787 - {.on_message_begin = 0  
1788 - ,.on_header_field = 0  
1789 - ,.on_header_value = 0  
1790 - ,.on_url = 0  
1791 - ,.on_body = 0  
1792 - ,.on_headers_complete = 0  
1793 - ,.on_message_complete = 0  
1794 - };  
1795 -  
1796 -void  
1797 -parser_init (enum http_parser_type type)  
1798 -{  
1799 - num_messages = 0;  
1800 -  
1801 - assert(parser == NULL);  
1802 -  
1803 - parser = malloc(sizeof(http_parser));  
1804 -  
1805 - http_parser_init(parser, type);  
1806 -  
1807 - memset(&messages, 0, sizeof messages);  
1808 -  
1809 -}  
1810 -  
1811 -void  
1812 -parser_free ()  
1813 -{  
1814 - assert(parser);  
1815 - free(parser);  
1816 - parser = NULL;  
1817 -}  
1818 -  
1819 -size_t parse (const char *buf, size_t len)  
1820 -{  
1821 - size_t nparsed;  
1822 - currently_parsing_eof = (len == 0);  
1823 - nparsed = http_parser_execute(parser, &settings, buf, len);  
1824 - return nparsed;  
1825 -}  
1826 -  
1827 -size_t parse_count_body (const char *buf, size_t len)  
1828 -{  
1829 - size_t nparsed;  
1830 - currently_parsing_eof = (len == 0);  
1831 - nparsed = http_parser_execute(parser, &settings_count_body, buf, len);  
1832 - return nparsed;  
1833 -}  
1834 -  
1835 -size_t parse_pause (const char *buf, size_t len)  
1836 -{  
1837 - size_t nparsed;  
1838 - http_parser_settings s = settings_pause;  
1839 -  
1840 - currently_parsing_eof = (len == 0);  
1841 - current_pause_parser = &s;  
1842 - nparsed = http_parser_execute(parser, current_pause_parser, buf, len);  
1843 - return nparsed;  
1844 -}  
1845 -  
1846 -static inline int  
1847 -check_str_eq (const struct message *m,  
1848 - const char *prop,  
1849 - const char *expected,  
1850 - const char *found) {  
1851 - if ((expected == NULL) != (found == NULL)) {  
1852 - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);  
1853 - printf("expected %s\n", (expected == NULL) ? "NULL" : expected);  
1854 - printf(" found %s\n", (found == NULL) ? "NULL" : found);  
1855 - return 0;  
1856 - }  
1857 - if (expected != NULL && 0 != strcmp(expected, found)) {  
1858 - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);  
1859 - printf("expected '%s'\n", expected);  
1860 - printf(" found '%s'\n", found);  
1861 - return 0;  
1862 - }  
1863 - return 1;  
1864 -}  
1865 -  
1866 -static inline int  
1867 -check_num_eq (const struct message *m,  
1868 - const char *prop,  
1869 - int expected,  
1870 - int found) {  
1871 - if (expected != found) {  
1872 - printf("\n*** Error: %s in '%s' ***\n\n", prop, m->name);  
1873 - printf("expected %d\n", expected);  
1874 - printf(" found %d\n", found);  
1875 - return 0;  
1876 - }  
1877 - return 1;  
1878 -}  
1879 -  
1880 -#define MESSAGE_CHECK_STR_EQ(expected, found, prop) \  
1881 - if (!check_str_eq(expected, #prop, expected->prop, found->prop)) return 0  
1882 -  
1883 -#define MESSAGE_CHECK_NUM_EQ(expected, found, prop) \  
1884 - if (!check_num_eq(expected, #prop, expected->prop, found->prop)) return 0  
1885 -  
1886 -#define MESSAGE_CHECK_URL_EQ(u, expected, found, prop, fn) \  
1887 -do { \  
1888 - char ubuf[256]; \  
1889 - \  
1890 - if ((u)->field_set & (1 << (fn))) { \  
1891 - memcpy(ubuf, (found)->request_url + (u)->field_data[(fn)].off, \  
1892 - (u)->field_data[(fn)].len); \  
1893 - ubuf[(u)->field_data[(fn)].len] = '\0'; \  
1894 - } else { \  
1895 - ubuf[0] = '\0'; \  
1896 - } \  
1897 - \  
1898 - check_str_eq(expected, #prop, expected->prop, ubuf); \  
1899 -} while(0)  
1900 -  
1901 -int  
1902 -message_eq (int index, const struct message *expected)  
1903 -{  
1904 - int i;  
1905 - struct message *m = &messages[index];  
1906 -  
1907 - MESSAGE_CHECK_NUM_EQ(expected, m, http_major);  
1908 - MESSAGE_CHECK_NUM_EQ(expected, m, http_minor);  
1909 -  
1910 - if (expected->type == HTTP_REQUEST) {  
1911 - MESSAGE_CHECK_NUM_EQ(expected, m, method);  
1912 - } else {  
1913 - MESSAGE_CHECK_NUM_EQ(expected, m, status_code);  
1914 - }  
1915 -  
1916 - MESSAGE_CHECK_NUM_EQ(expected, m, should_keep_alive);  
1917 - MESSAGE_CHECK_NUM_EQ(expected, m, message_complete_on_eof);  
1918 -  
1919 - assert(m->message_begin_cb_called);  
1920 - assert(m->headers_complete_cb_called);  
1921 - assert(m->message_complete_cb_called);  
1922 -  
1923 -  
1924 - MESSAGE_CHECK_STR_EQ(expected, m, request_url);  
1925 -  
1926 - /* Check URL components; we can't do this w/ CONNECT since it doesn't  
1927 - * send us a well-formed URL.  
1928 - */  
1929 - if (*m->request_url && m->method != HTTP_CONNECT) {  
1930 - struct http_parser_url u;  
1931 -  
1932 - if (http_parser_parse_url(m->request_url, strlen(m->request_url), 0, &u)) {  
1933 - fprintf(stderr, "\n\n*** failed to parse URL %s ***\n\n",  
1934 - m->request_url);  
1935 - abort();  
1936 - }  
1937 -  
1938 - if (expected->host) {  
1939 - MESSAGE_CHECK_URL_EQ(&u, expected, m, host, UF_HOST);  
1940 - }  
1941 -  
1942 - if (expected->userinfo) {  
1943 - MESSAGE_CHECK_URL_EQ(&u, expected, m, userinfo, UF_USERINFO);  
1944 - }  
1945 -  
1946 - m->port = (u.field_set & (1 << UF_PORT)) ?  
1947 - u.port : 0;  
1948 -  
1949 - MESSAGE_CHECK_URL_EQ(&u, expected, m, query_string, UF_QUERY);  
1950 - MESSAGE_CHECK_URL_EQ(&u, expected, m, fragment, UF_FRAGMENT);  
1951 - MESSAGE_CHECK_URL_EQ(&u, expected, m, request_path, UF_PATH);  
1952 - MESSAGE_CHECK_NUM_EQ(expected, m, port);  
1953 - }  
1954 -  
1955 - if (expected->body_size) {  
1956 - MESSAGE_CHECK_NUM_EQ(expected, m, body_size);  
1957 - } else {  
1958 - MESSAGE_CHECK_STR_EQ(expected, m, body);  
1959 - }  
1960 -  
1961 - MESSAGE_CHECK_NUM_EQ(expected, m, num_headers);  
1962 -  
1963 - int r;  
1964 - for (i = 0; i < m->num_headers; i++) {  
1965 - r = check_str_eq(expected, "header field", expected->headers[i][0], m->headers[i][0]);  
1966 - if (!r) return 0;  
1967 - r = check_str_eq(expected, "header value", expected->headers[i][1], m->headers[i][1]);  
1968 - if (!r) return 0;  
1969 - }  
1970 -  
1971 - MESSAGE_CHECK_STR_EQ(expected, m, upgrade);  
1972 -  
1973 - return 1;  
1974 -}  
1975 -  
1976 -/* Given a sequence of varargs messages, return the number of them that the  
1977 - * parser should successfully parse, taking into account that upgraded  
1978 - * messages prevent all subsequent messages from being parsed.  
1979 - */  
1980 -size_t  
1981 -count_parsed_messages(const size_t nmsgs, ...) {  
1982 - size_t i;  
1983 - va_list ap;  
1984 -  
1985 - va_start(ap, nmsgs);  
1986 -  
1987 - for (i = 0; i < nmsgs; i++) {  
1988 - struct message *m = va_arg(ap, struct message *);  
1989 -  
1990 - if (m->upgrade) {  
1991 - va_end(ap);  
1992 - return i + 1;  
1993 - }  
1994 - }  
1995 -  
1996 - va_end(ap);  
1997 - return nmsgs;  
1998 -}  
1999 -  
2000 -/* Given a sequence of bytes and the number of these that we were able to  
2001 - * parse, verify that upgrade bodies are correct.  
2002 - */  
2003 -void  
2004 -upgrade_message_fix(char *body, const size_t nread, const size_t nmsgs, ...) {  
2005 - va_list ap;  
2006 - size_t i;  
2007 - size_t off = 0;  
2008 -  
2009 - va_start(ap, nmsgs);  
2010 -  
2011 - for (i = 0; i < nmsgs; i++) {  
2012 - struct message *m = va_arg(ap, struct message *);  
2013 -  
2014 - off += strlen(m->raw);  
2015 -  
2016 - if (m->upgrade) {  
2017 - off -= strlen(m->upgrade);  
2018 -  
2019 - /* Check the portion of the response after its specified upgrade */  
2020 - if (!check_str_eq(m, "upgrade", body + off, body + nread)) {  
2021 - abort();  
2022 - }  
2023 -  
2024 - /* Fix up the response so that message_eq() will verify the beginning  
2025 - * of the upgrade */  
2026 - *(body + nread + strlen(m->upgrade)) = '\0';  
2027 - messages[num_messages -1 ].upgrade = body + nread;  
2028 -  
2029 - va_end(ap);  
2030 - return;  
2031 - }  
2032 - }  
2033 -  
2034 - va_end(ap);  
2035 - printf("\n\n*** Error: expected a message with upgrade ***\n");  
2036 -  
2037 - abort();  
2038 -}  
2039 -  
2040 -static void  
2041 -print_error (const char *raw, size_t error_location)  
2042 -{  
2043 - fprintf(stderr, "\n*** %s ***\n\n",  
2044 - http_errno_description(HTTP_PARSER_ERRNO(parser)));  
2045 -  
2046 - int this_line = 0, char_len = 0;  
2047 - size_t i, j, len = strlen(raw), error_location_line = 0;  
2048 - for (i = 0; i < len; i++) {  
2049 - if (i == error_location) this_line = 1;  
2050 - switch (raw[i]) {  
2051 - case '\r':  
2052 - char_len = 2;  
2053 - fprintf(stderr, "\\r");  
2054 - break;  
2055 -  
2056 - case '\n':  
2057 - char_len = 2;  
2058 - fprintf(stderr, "\\n\n");  
2059 -  
2060 - if (this_line) goto print;  
2061 -  
2062 - error_location_line = 0;  
2063 - continue;  
2064 -  
2065 - default:  
2066 - char_len = 1;  
2067 - fputc(raw[i], stderr);  
2068 - break;  
2069 - }  
2070 - if (!this_line) error_location_line += char_len;  
2071 - }  
2072 -  
2073 - fprintf(stderr, "[eof]\n");  
2074 -  
2075 - print:  
2076 - for (j = 0; j < error_location_line; j++) {  
2077 - fputc(' ', stderr);  
2078 - }  
2079 - fprintf(stderr, "^\n\nerror location: %u\n", (unsigned int)error_location);  
2080 -}  
2081 -  
2082 -void  
2083 -test_preserve_data (void)  
2084 -{  
2085 - char my_data[] = "application-specific data";  
2086 - http_parser parser;  
2087 - parser.data = my_data;  
2088 - http_parser_init(&parser, HTTP_REQUEST);  
2089 - if (parser.data != my_data) {  
2090 - printf("\n*** parser.data not preserved accross http_parser_init ***\n\n");  
2091 - abort();  
2092 - }  
2093 -}  
2094 -  
2095 -struct url_test {  
2096 - const char *name;  
2097 - const char *url;  
2098 - int is_connect;  
2099 - struct http_parser_url u;  
2100 - int rv;  
2101 -};  
2102 -  
2103 -const struct url_test url_tests[] =  
2104 -{ {.name="proxy request"  
2105 - ,.url="http://hostname/"  
2106 - ,.is_connect=0  
2107 - ,.u=  
2108 - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)  
2109 - ,.port=0  
2110 - ,.field_data=  
2111 - {{ 0, 4 } /* UF_SCHEMA */  
2112 - ,{ 7, 8 } /* UF_HOST */  
2113 - ,{ 0, 0 } /* UF_PORT */  
2114 - ,{ 15, 1 } /* UF_PATH */  
2115 - ,{ 0, 0 } /* UF_QUERY */  
2116 - ,{ 0, 0 } /* UF_FRAGMENT */  
2117 - ,{ 0, 0 } /* UF_USERINFO */  
2118 - }  
2119 - }  
2120 - ,.rv=0  
2121 - }  
2122 -  
2123 -, {.name="proxy request with port"  
2124 - ,.url="http://hostname:444/"  
2125 - ,.is_connect=0  
2126 - ,.u=  
2127 - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)  
2128 - ,.port=444  
2129 - ,.field_data=  
2130 - {{ 0, 4 } /* UF_SCHEMA */  
2131 - ,{ 7, 8 } /* UF_HOST */  
2132 - ,{ 16, 3 } /* UF_PORT */  
2133 - ,{ 19, 1 } /* UF_PATH */  
2134 - ,{ 0, 0 } /* UF_QUERY */  
2135 - ,{ 0, 0 } /* UF_FRAGMENT */  
2136 - ,{ 0, 0 } /* UF_USERINFO */  
2137 - }  
2138 - }  
2139 - ,.rv=0  
2140 - }  
2141 -  
2142 -, {.name="CONNECT request"  
2143 - ,.url="hostname:443"  
2144 - ,.is_connect=1  
2145 - ,.u=  
2146 - {.field_set=(1 << UF_HOST) | (1 << UF_PORT)  
2147 - ,.port=443  
2148 - ,.field_data=  
2149 - {{ 0, 0 } /* UF_SCHEMA */  
2150 - ,{ 0, 8 } /* UF_HOST */  
2151 - ,{ 9, 3 } /* UF_PORT */  
2152 - ,{ 0, 0 } /* UF_PATH */  
2153 - ,{ 0, 0 } /* UF_QUERY */  
2154 - ,{ 0, 0 } /* UF_FRAGMENT */  
2155 - ,{ 0, 0 } /* UF_USERINFO */  
2156 - }  
2157 - }  
2158 - ,.rv=0  
2159 - }  
2160 -  
2161 -, {.name="CONNECT request but not connect"  
2162 - ,.url="hostname:443"  
2163 - ,.is_connect=0  
2164 - ,.rv=1  
2165 - }  
2166 -  
2167 -, {.name="proxy ipv6 request"  
2168 - ,.url="http://[1:2::3:4]/"  
2169 - ,.is_connect=0  
2170 - ,.u=  
2171 - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)  
2172 - ,.port=0  
2173 - ,.field_data=  
2174 - {{ 0, 4 } /* UF_SCHEMA */  
2175 - ,{ 8, 8 } /* UF_HOST */  
2176 - ,{ 0, 0 } /* UF_PORT */  
2177 - ,{ 17, 1 } /* UF_PATH */  
2178 - ,{ 0, 0 } /* UF_QUERY */  
2179 - ,{ 0, 0 } /* UF_FRAGMENT */  
2180 - ,{ 0, 0 } /* UF_USERINFO */  
2181 - }  
2182 - }  
2183 - ,.rv=0  
2184 - }  
2185 -  
2186 -, {.name="proxy ipv6 request with port"  
2187 - ,.url="http://[1:2::3:4]:67/"  
2188 - ,.is_connect=0  
2189 - ,.u=  
2190 - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PORT) | (1 << UF_PATH)  
2191 - ,.port=67  
2192 - ,.field_data=  
2193 - {{ 0, 4 } /* UF_SCHEMA */  
2194 - ,{ 8, 8 } /* UF_HOST */  
2195 - ,{ 18, 2 } /* UF_PORT */  
2196 - ,{ 20, 1 } /* UF_PATH */  
2197 - ,{ 0, 0 } /* UF_QUERY */  
2198 - ,{ 0, 0 } /* UF_FRAGMENT */  
2199 - ,{ 0, 0 } /* UF_USERINFO */  
2200 - }  
2201 - }  
2202 - ,.rv=0  
2203 - }  
2204 -  
2205 -, {.name="CONNECT ipv6 address"  
2206 - ,.url="[1:2::3:4]:443"  
2207 - ,.is_connect=1  
2208 - ,.u=  
2209 - {.field_set=(1 << UF_HOST) | (1 << UF_PORT)  
2210 - ,.port=443  
2211 - ,.field_data=  
2212 - {{ 0, 0 } /* UF_SCHEMA */  
2213 - ,{ 1, 8 } /* UF_HOST */  
2214 - ,{ 11, 3 } /* UF_PORT */  
2215 - ,{ 0, 0 } /* UF_PATH */  
2216 - ,{ 0, 0 } /* UF_QUERY */  
2217 - ,{ 0, 0 } /* UF_FRAGMENT */  
2218 - ,{ 0, 0 } /* UF_USERINFO */  
2219 - }  
2220 - }  
2221 - ,.rv=0  
2222 - }  
2223 -  
2224 -, {.name="ipv4 in ipv6 address"  
2225 - ,.url="http://[2001:0000:0000:0000:0000:0000:1.9.1.1]/"  
2226 - ,.is_connect=0  
2227 - ,.u=  
2228 - {.field_set=(1 << UF_SCHEMA) | (1 << UF_HOST) | (1 << UF_PATH)  
2229 - ,.port=0  
2230 - ,.field_data=  
2231 - {{ 0, 4 } /* UF_SCHEMA */  
2232 - ,{ 8, 37 } /* UF_HOST */  
2233 - ,{ 0, 0 } /* UF_PORT */  
2234 - ,{ 46, 1 } /* UF_PATH */  
2235 - ,{ 0, 0 } /* UF_QUERY */  
2236 - ,{ 0, 0 } /* UF_FRAGMENT */  
2237 - ,{ 0, 0 } /* UF_USERINFO */  
2238 - }  
2239 - }  
2240 - ,.rv=0  
2241 - }  
2242 -  
2243 -, {.name="extra ? in query string"  
2244 - ,.url="http://a.tbcdn.cn/p/fp/2010c/??fp-header-min.css,fp-base-min.css,"  
2245 - "fp-channel-min.css,fp-product-min.css,fp-mall-min.css,fp-category-min.css,"  
2246 - "fp-sub-min.css,fp-gdp4p-min.css,fp-css3-min.css,fp-misc-min.css?t=20101022.css"  
2247 - ,.is_connect=0  
2248 - ,.u=  
2249 - {.field_set=(1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY)  
2250 - ,.port=0  
2251 - ,.field_data=  
2252 - {{ 0, 4 } /* UF_SCHEMA */  
2253 - ,{ 7, 10 } /* UF_HOST */  
2254 - ,{ 0, 0 } /* UF_PORT */  
2255 - ,{ 17, 12 } /* UF_PATH */  
2256 - ,{ 30,187 } /* UF_QUERY */  
2257 - ,{ 0, 0 } /* UF_FRAGMENT */  
2258 - ,{ 0, 0 } /* UF_USERINFO */  
2259 - }  
2260 - }  
2261 - ,.rv=0  
2262 - }  
2263 -  
2264 -, {.name="space URL encoded"  
2265 - ,.url="/toto.html?toto=a%20b"  
2266 - ,.is_connect=0  
2267 - ,.u=  
2268 - {.field_set= (1<<UF_PATH) | (1<<UF_QUERY)  
2269 - ,.port=0  
2270 - ,.field_data=  
2271 - {{ 0, 0 } /* UF_SCHEMA */  
2272 - ,{ 0, 0 } /* UF_HOST */  
2273 - ,{ 0, 0 } /* UF_PORT */  
2274 - ,{ 0, 10 } /* UF_PATH */  
2275 - ,{ 11, 10 } /* UF_QUERY */  
2276 - ,{ 0, 0 } /* UF_FRAGMENT */  
2277 - ,{ 0, 0 } /* UF_USERINFO */  
2278 - }  
2279 - }  
2280 - ,.rv=0  
2281 - }  
2282 -  
2283 -  
2284 -, {.name="URL fragment"  
2285 - ,.url="/toto.html#titi"  
2286 - ,.is_connect=0  
2287 - ,.u=  
2288 - {.field_set= (1<<UF_PATH) | (1<<UF_FRAGMENT)  
2289 - ,.port=0  
2290 - ,.field_data=  
2291 - {{ 0, 0 } /* UF_SCHEMA */  
2292 - ,{ 0, 0 } /* UF_HOST */  
2293 - ,{ 0, 0 } /* UF_PORT */  
2294 - ,{ 0, 10 } /* UF_PATH */  
2295 - ,{ 0, 0 } /* UF_QUERY */  
2296 - ,{ 11, 4 } /* UF_FRAGMENT */  
2297 - ,{ 0, 0 } /* UF_USERINFO */  
2298 - }  
2299 - }  
2300 - ,.rv=0  
2301 - }  
2302 -  
2303 -, {.name="complex URL fragment"  
2304 - ,.url="http://www.webmasterworld.com/r.cgi?f=21&d=8405&url="  
2305 - "http://www.example.com/index.html?foo=bar&hello=world#midpage"  
2306 - ,.is_connect=0  
2307 - ,.u=  
2308 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_QUERY) |\  
2309 - (1<<UF_FRAGMENT)  
2310 - ,.port=0  
2311 - ,.field_data=  
2312 - {{ 0, 4 } /* UF_SCHEMA */  
2313 - ,{ 7, 22 } /* UF_HOST */  
2314 - ,{ 0, 0 } /* UF_PORT */  
2315 - ,{ 29, 6 } /* UF_PATH */  
2316 - ,{ 36, 69 } /* UF_QUERY */  
2317 - ,{106, 7 } /* UF_FRAGMENT */  
2318 - ,{ 0, 0 } /* UF_USERINFO */  
2319 - }  
2320 - }  
2321 - ,.rv=0  
2322 - }  
2323 -  
2324 -, {.name="complex URL from node js url parser doc"  
2325 - ,.url="http://host.com:8080/p/a/t/h?query=string#hash"  
2326 - ,.is_connect=0  
2327 - ,.u=  
2328 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\  
2329 - (1<<UF_QUERY) | (1<<UF_FRAGMENT)  
2330 - ,.port=8080  
2331 - ,.field_data=  
2332 - {{ 0, 4 } /* UF_SCHEMA */  
2333 - ,{ 7, 8 } /* UF_HOST */  
2334 - ,{ 16, 4 } /* UF_PORT */  
2335 - ,{ 20, 8 } /* UF_PATH */  
2336 - ,{ 29, 12 } /* UF_QUERY */  
2337 - ,{ 42, 4 } /* UF_FRAGMENT */  
2338 - ,{ 0, 0 } /* UF_USERINFO */  
2339 - }  
2340 - }  
2341 - ,.rv=0  
2342 - }  
2343 -  
2344 -, {.name="complex URL with basic auth from node js url parser doc"  
2345 - ,.url="http://a:b@host.com:8080/p/a/t/h?query=string#hash"  
2346 - ,.is_connect=0  
2347 - ,.u=  
2348 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PORT) | (1<<UF_PATH) |\  
2349 - (1<<UF_QUERY) | (1<<UF_FRAGMENT) | (1<<UF_USERINFO)  
2350 - ,.port=8080  
2351 - ,.field_data=  
2352 - {{ 0, 4 } /* UF_SCHEMA */  
2353 - ,{ 11, 8 } /* UF_HOST */  
2354 - ,{ 20, 4 } /* UF_PORT */  
2355 - ,{ 24, 8 } /* UF_PATH */  
2356 - ,{ 33, 12 } /* UF_QUERY */  
2357 - ,{ 46, 4 } /* UF_FRAGMENT */  
2358 - ,{ 7, 3 } /* UF_USERINFO */  
2359 - }  
2360 - }  
2361 - ,.rv=0  
2362 - }  
2363 -  
2364 -, {.name="double @"  
2365 - ,.url="http://a:b@@hostname:443/"  
2366 - ,.is_connect=0  
2367 - ,.rv=1  
2368 - }  
2369 -  
2370 -, {.name="proxy empty host"  
2371 - ,.url="http://:443/"  
2372 - ,.is_connect=0  
2373 - ,.rv=1  
2374 - }  
2375 -  
2376 -, {.name="proxy empty port"  
2377 - ,.url="http://hostname:/"  
2378 - ,.is_connect=0  
2379 - ,.rv=1  
2380 - }  
2381 -  
2382 -, {.name="CONNECT with basic auth"  
2383 - ,.url="a:b@hostname:443"  
2384 - ,.is_connect=1  
2385 - ,.rv=1  
2386 - }  
2387 -  
2388 -, {.name="CONNECT empty host"  
2389 - ,.url=":443"  
2390 - ,.is_connect=1  
2391 - ,.rv=1  
2392 - }  
2393 -  
2394 -, {.name="CONNECT empty port"  
2395 - ,.url="hostname:"  
2396 - ,.is_connect=1  
2397 - ,.rv=1  
2398 - }  
2399 -  
2400 -, {.name="CONNECT with extra bits"  
2401 - ,.url="hostname:443/"  
2402 - ,.is_connect=1  
2403 - ,.rv=1  
2404 - }  
2405 -  
2406 -, {.name="space in URL"  
2407 - ,.url="/foo bar/"  
2408 - ,.rv=1 /* s_dead */  
2409 - }  
2410 -  
2411 -, {.name="proxy basic auth with space url encoded"  
2412 - ,.url="http://a%20:b@host.com/"  
2413 - ,.is_connect=0  
2414 - ,.u=  
2415 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)  
2416 - ,.port=0  
2417 - ,.field_data=  
2418 - {{ 0, 4 } /* UF_SCHEMA */  
2419 - ,{ 14, 8 } /* UF_HOST */  
2420 - ,{ 0, 0 } /* UF_PORT */  
2421 - ,{ 22, 1 } /* UF_PATH */  
2422 - ,{ 0, 0 } /* UF_QUERY */  
2423 - ,{ 0, 0 } /* UF_FRAGMENT */  
2424 - ,{ 7, 6 } /* UF_USERINFO */  
2425 - }  
2426 - }  
2427 - ,.rv=0  
2428 - }  
2429 -  
2430 -, {.name="carriage return in URL"  
2431 - ,.url="/foo\rbar/"  
2432 - ,.rv=1 /* s_dead */  
2433 - }  
2434 -  
2435 -, {.name="proxy double : in URL"  
2436 - ,.url="http://hostname::443/"  
2437 - ,.rv=1 /* s_dead */  
2438 - }  
2439 -  
2440 -, {.name="proxy basic auth with double :"  
2441 - ,.url="http://a::b@host.com/"  
2442 - ,.is_connect=0  
2443 - ,.u=  
2444 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)  
2445 - ,.port=0  
2446 - ,.field_data=  
2447 - {{ 0, 4 } /* UF_SCHEMA */  
2448 - ,{ 12, 8 } /* UF_HOST */  
2449 - ,{ 0, 0 } /* UF_PORT */  
2450 - ,{ 20, 1 } /* UF_PATH */  
2451 - ,{ 0, 0 } /* UF_QUERY */  
2452 - ,{ 0, 0 } /* UF_FRAGMENT */  
2453 - ,{ 7, 4 } /* UF_USERINFO */  
2454 - }  
2455 - }  
2456 - ,.rv=0  
2457 - }  
2458 -  
2459 -, {.name="line feed in URL"  
2460 - ,.url="/foo\nbar/"  
2461 - ,.rv=1 /* s_dead */  
2462 - }  
2463 -  
2464 -, {.name="proxy empty basic auth"  
2465 - ,.url="http://@hostname/fo"  
2466 - ,.u=  
2467 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)  
2468 - ,.port=0  
2469 - ,.field_data=  
2470 - {{ 0, 4 } /* UF_SCHEMA */  
2471 - ,{ 8, 8 } /* UF_HOST */  
2472 - ,{ 0, 0 } /* UF_PORT */  
2473 - ,{ 16, 3 } /* UF_PATH */  
2474 - ,{ 0, 0 } /* UF_QUERY */  
2475 - ,{ 0, 0 } /* UF_FRAGMENT */  
2476 - ,{ 0, 0 } /* UF_USERINFO */  
2477 - }  
2478 - }  
2479 - ,.rv=0  
2480 - }  
2481 -, {.name="proxy line feed in hostname"  
2482 - ,.url="http://host\name/fo"  
2483 - ,.rv=1 /* s_dead */  
2484 - }  
2485 -  
2486 -, {.name="proxy % in hostname"  
2487 - ,.url="http://host%name/fo"  
2488 - ,.rv=1 /* s_dead */  
2489 - }  
2490 -  
2491 -, {.name="proxy ; in hostname"  
2492 - ,.url="http://host;ame/fo"  
2493 - ,.rv=1 /* s_dead */  
2494 - }  
2495 -  
2496 -, {.name="proxy basic auth with unreservedchars"  
2497 - ,.url="http://a!;-_!=+$@host.com/"  
2498 - ,.is_connect=0  
2499 - ,.u=  
2500 - {.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH) | (1<<UF_USERINFO)  
2501 - ,.port=0  
2502 - ,.field_data=  
2503 - {{ 0, 4 } /* UF_SCHEMA */  
2504 - ,{ 17, 8 } /* UF_HOST */  
2505 - ,{ 0, 0 } /* UF_PORT */  
2506 - ,{ 25, 1 } /* UF_PATH */  
2507 - ,{ 0, 0 } /* UF_QUERY */  
2508 - ,{ 0, 0 } /* UF_FRAGMENT */  
2509 - ,{ 7, 9 } /* UF_USERINFO */  
2510 - }  
2511 - }  
2512 - ,.rv=0  
2513 - }  
2514 -  
2515 -, {.name="proxy only empty basic auth"  
2516 - ,.url="http://@/fo"  
2517 - ,.rv=1 /* s_dead */  
2518 - }  
2519 -  
2520 -, {.name="proxy only basic auth"  
2521 - ,.url="http://toto@/fo"  
2522 - ,.rv=1 /* s_dead */  
2523 - }  
2524 -  
2525 -, {.name="proxy emtpy hostname"  
2526 - ,.url="http:///fo"  
2527 - ,.rv=1 /* s_dead */  
2528 - }  
2529 -  
2530 -, {.name="proxy = in URL"  
2531 - ,.url="http://host=ame/fo"  
2532 - ,.rv=1 /* s_dead */  
2533 - }  
2534 -  
2535 -#if HTTP_PARSER_STRICT  
2536 -  
2537 -, {.name="tab in URL"  
2538 - ,.url="/foo\tbar/"  
2539 - ,.rv=1 /* s_dead */  
2540 - }  
2541 -  
2542 -, {.name="form feed in URL"  
2543 - ,.url="/foo\fbar/"  
2544 - ,.rv=1 /* s_dead */  
2545 - }  
2546 -  
2547 -#else /* !HTTP_PARSER_STRICT */  
2548 -  
2549 -, {.name="tab in URL"  
2550 - ,.url="/foo\tbar/"  
2551 - ,.u=  
2552 - {.field_set=(1 << UF_PATH)  
2553 - ,.field_data=  
2554 - {{ 0, 0 } /* UF_SCHEMA */  
2555 - ,{ 0, 0 } /* UF_HOST */  
2556 - ,{ 0, 0 } /* UF_PORT */  
2557 - ,{ 0, 9 } /* UF_PATH */  
2558 - ,{ 0, 0 } /* UF_QUERY */  
2559 - ,{ 0, 0 } /* UF_FRAGMENT */  
2560 - ,{ 0, 0 } /* UF_USERINFO */  
2561 - }  
2562 - }  
2563 - ,.rv=0  
2564 - }  
2565 -  
2566 -, {.name="form feed in URL"  
2567 - ,.url="/foo\fbar/"  
2568 - ,.u=  
2569 - {.field_set=(1 << UF_PATH)  
2570 - ,.field_data=  
2571 - {{ 0, 0 } /* UF_SCHEMA */  
2572 - ,{ 0, 0 } /* UF_HOST */  
2573 - ,{ 0, 0 } /* UF_PORT */  
2574 - ,{ 0, 9 } /* UF_PATH */  
2575 - ,{ 0, 0 } /* UF_QUERY */  
2576 - ,{ 0, 0 } /* UF_FRAGMENT */  
2577 - ,{ 0, 0 } /* UF_USERINFO */  
2578 - }  
2579 - }  
2580 - ,.rv=0  
2581 - }  
2582 -#endif  
2583 -};  
2584 -  
2585 -void  
2586 -dump_url (const char *url, const struct http_parser_url *u)  
2587 -{  
2588 - unsigned int i;  
2589 -  
2590 - printf("\tfield_set: 0x%x, port: %u\n", u->field_set, u->port);  
2591 - for (i = 0; i < UF_MAX; i++) {  
2592 - if ((u->field_set & (1 << i)) == 0) {  
2593 - printf("\tfield_data[%u]: unset\n", i);  
2594 - continue;  
2595 - }  
2596 -  
2597 - printf("\tfield_data[%u]: off: %u len: %u part: \"%.*s\n\"",  
2598 - i,  
2599 - u->field_data[i].off,  
2600 - u->field_data[i].len,  
2601 - u->field_data[i].len,  
2602 - url + u->field_data[i].off);  
2603 - }  
2604 -}  
2605 -  
2606 -void  
2607 -test_parse_url (void)  
2608 -{  
2609 - struct http_parser_url u;  
2610 - const struct url_test *test;  
2611 - unsigned int i;  
2612 - int rv;  
2613 -  
2614 - for (i = 0; i < (sizeof(url_tests) / sizeof(url_tests[0])); i++) {  
2615 - test = &url_tests[i];  
2616 - memset(&u, 0, sizeof(u));  
2617 -  
2618 - rv = http_parser_parse_url(test->url,  
2619 - strlen(test->url),  
2620 - test->is_connect,  
2621 - &u);  
2622 -  
2623 - if (test->rv == 0) {  
2624 - if (rv != 0) {  
2625 - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "  
2626 - "unexpected rv %d ***\n\n", test->url, test->name, rv);  
2627 - abort();  
2628 - }  
2629 -  
2630 - if (memcmp(&u, &test->u, sizeof(u)) != 0) {  
2631 - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" failed ***\n",  
2632 - test->url, test->name);  
2633 -  
2634 - printf("target http_parser_url:\n");  
2635 - dump_url(test->url, &test->u);  
2636 - printf("result http_parser_url:\n");  
2637 - dump_url(test->url, &u);  
2638 -  
2639 - abort();  
2640 - }  
2641 - } else {  
2642 - /* test->rv != 0 */  
2643 - if (rv == 0) {  
2644 - printf("\n*** http_parser_parse_url(\"%s\") \"%s\" test failed, "  
2645 - "unexpected rv %d ***\n\n", test->url, test->name, rv);  
2646 - abort();  
2647 - }  
2648 - }  
2649 - }  
2650 -}  
2651 -  
2652 -void  
2653 -test_method_str (void)  
2654 -{  
2655 - assert(0 == strcmp("GET", http_method_str(HTTP_GET)));  
2656 - assert(0 == strcmp("<unknown>", http_method_str(1337)));  
2657 -}  
2658 -  
2659 -void  
2660 -test_message (const struct message *message)  
2661 -{  
2662 - size_t raw_len = strlen(message->raw);  
2663 - size_t msg1len;  
2664 - for (msg1len = 0; msg1len < raw_len; msg1len++) {  
2665 - parser_init(message->type);  
2666 -  
2667 - size_t read;  
2668 - const char *msg1 = message->raw;  
2669 - const char *msg2 = msg1 + msg1len;  
2670 - size_t msg2len = raw_len - msg1len;  
2671 -  
2672 - if (msg1len) {  
2673 - read = parse(msg1, msg1len);  
2674 -  
2675 - if (message->upgrade && parser->upgrade) {  
2676 - messages[num_messages - 1].upgrade = msg1 + read;  
2677 - goto test;  
2678 - }  
2679 -  
2680 - if (read != msg1len) {  
2681 - print_error(msg1, read);  
2682 - abort();  
2683 - }  
2684 - }  
2685 -  
2686 -  
2687 - read = parse(msg2, msg2len);  
2688 -  
2689 - if (message->upgrade && parser->upgrade) {  
2690 - messages[num_messages - 1].upgrade = msg2 + read;  
2691 - goto test;  
2692 - }  
2693 -  
2694 - if (read != msg2len) {  
2695 - print_error(msg2, read);  
2696 - abort();  
2697 - }  
2698 -  
2699 - read = parse(NULL, 0);  
2700 -  
2701 - if (read != 0) {  
2702 - print_error(message->raw, read);  
2703 - abort();  
2704 - }  
2705 -  
2706 - test:  
2707 -  
2708 - if (num_messages != 1) {  
2709 - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);  
2710 - abort();  
2711 - }  
2712 -  
2713 - if(!message_eq(0, message)) abort();  
2714 -  
2715 - parser_free();  
2716 - }  
2717 -}  
2718 -  
2719 -void  
2720 -test_message_count_body (const struct message *message)  
2721 -{  
2722 - parser_init(message->type);  
2723 -  
2724 - size_t read;  
2725 - size_t l = strlen(message->raw);  
2726 - size_t i, toread;  
2727 - size_t chunk = 4024;  
2728 -  
2729 - for (i = 0; i < l; i+= chunk) {  
2730 - toread = MIN(l-i, chunk);  
2731 - read = parse_count_body(message->raw + i, toread);  
2732 - if (read != toread) {  
2733 - print_error(message->raw, read);  
2734 - abort();  
2735 - }  
2736 - }  
2737 -  
2738 -  
2739 - read = parse_count_body(NULL, 0);  
2740 - if (read != 0) {  
2741 - print_error(message->raw, read);  
2742 - abort();  
2743 - }  
2744 -  
2745 - if (num_messages != 1) {  
2746 - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", message->name);  
2747 - abort();  
2748 - }  
2749 -  
2750 - if(!message_eq(0, message)) abort();  
2751 -  
2752 - parser_free();  
2753 -}  
2754 -  
2755 -void  
2756 -test_simple (const char *buf, enum http_errno err_expected)  
2757 -{  
2758 - parser_init(HTTP_REQUEST);  
2759 -  
2760 - size_t parsed;  
2761 - int pass;  
2762 - enum http_errno err;  
2763 -  
2764 - parsed = parse(buf, strlen(buf));  
2765 - pass = (parsed == strlen(buf));  
2766 - err = HTTP_PARSER_ERRNO(parser);  
2767 - parsed = parse(NULL, 0);  
2768 - pass &= (parsed == 0);  
2769 -  
2770 - parser_free();  
2771 -  
2772 - /* In strict mode, allow us to pass with an unexpected HPE_STRICT as  
2773 - * long as the caller isn't expecting success.  
2774 - */  
2775 -#if HTTP_PARSER_STRICT  
2776 - if (err_expected != err && err_expected != HPE_OK && err != HPE_STRICT) {  
2777 -#else  
2778 - if (err_expected != err) {  
2779 -#endif  
2780 - fprintf(stderr, "\n*** test_simple expected %s, but saw %s ***\n\n%s\n",  
2781 - http_errno_name(err_expected), http_errno_name(err), buf);  
2782 - abort();  
2783 - }  
2784 -}  
2785 -  
2786 -void  
2787 -test_header_overflow_error (int req)  
2788 -{  
2789 - http_parser parser;  
2790 - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);  
2791 - size_t parsed;  
2792 - const char *buf;  
2793 - buf = req ? "GET / HTTP/1.1\r\n" : "HTTP/1.0 200 OK\r\n";  
2794 - parsed = http_parser_execute(&parser, &settings_null, buf, strlen(buf));  
2795 - assert(parsed == strlen(buf));  
2796 -  
2797 - buf = "header-key: header-value\r\n";  
2798 - size_t buflen = strlen(buf);  
2799 -  
2800 - int i;  
2801 - for (i = 0; i < 10000; i++) {  
2802 - parsed = http_parser_execute(&parser, &settings_null, buf, buflen);  
2803 - if (parsed != buflen) {  
2804 - //fprintf(stderr, "error found on iter %d\n", i);  
2805 - assert(HTTP_PARSER_ERRNO(&parser) == HPE_HEADER_OVERFLOW);  
2806 - return;  
2807 - }  
2808 - }  
2809 -  
2810 - fprintf(stderr, "\n*** Error expected but none in header overflow test ***\n");  
2811 - abort();  
2812 -}  
2813 -  
2814 -static void  
2815 -test_content_length_overflow (const char *buf, size_t buflen, int expect_ok)  
2816 -{  
2817 - http_parser parser;  
2818 - http_parser_init(&parser, HTTP_RESPONSE);  
2819 - http_parser_execute(&parser, &settings_null, buf, buflen);  
2820 -  
2821 - if (expect_ok)  
2822 - assert(HTTP_PARSER_ERRNO(&parser) == HPE_OK);  
2823 - else  
2824 - assert(HTTP_PARSER_ERRNO(&parser) == HPE_INVALID_CONTENT_LENGTH);  
2825 -}  
2826 -  
2827 -void  
2828 -test_header_content_length_overflow_error (void)  
2829 -{  
2830 -#define X(size) \  
2831 - "HTTP/1.1 200 OK\r\n" \  
2832 - "Content-Length: " #size "\r\n" \  
2833 - "\r\n"  
2834 - const char a[] = X(18446744073709551614); /* 2^64-2 */  
2835 - const char b[] = X(18446744073709551615); /* 2^64-1 */  
2836 - const char c[] = X(18446744073709551616); /* 2^64 */  
2837 -#undef X  
2838 - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */  
2839 - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */  
2840 - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */  
2841 -}  
2842 -  
2843 -void  
2844 -test_chunk_content_length_overflow_error (void)  
2845 -{  
2846 -#define X(size) \  
2847 - "HTTP/1.1 200 OK\r\n" \  
2848 - "Transfer-Encoding: chunked\r\n" \  
2849 - "\r\n" \  
2850 - #size "\r\n" \  
2851 - "..."  
2852 - const char a[] = X(FFFFFFFFFFFFFFFE); /* 2^64-2 */  
2853 - const char b[] = X(FFFFFFFFFFFFFFFF); /* 2^64-1 */  
2854 - const char c[] = X(10000000000000000); /* 2^64 */  
2855 -#undef X  
2856 - test_content_length_overflow(a, sizeof(a) - 1, 1); /* expect ok */  
2857 - test_content_length_overflow(b, sizeof(b) - 1, 0); /* expect failure */  
2858 - test_content_length_overflow(c, sizeof(c) - 1, 0); /* expect failure */  
2859 -}  
2860 -  
2861 -void  
2862 -test_no_overflow_long_body (int req, size_t length)  
2863 -{  
2864 - http_parser parser;  
2865 - http_parser_init(&parser, req ? HTTP_REQUEST : HTTP_RESPONSE);  
2866 - size_t parsed;  
2867 - size_t i;  
2868 - char buf1[3000];  
2869 - size_t buf1len = sprintf(buf1, "%s\r\nConnection: Keep-Alive\r\nContent-Length: %lu\r\n\r\n",  
2870 - req ? "POST / HTTP/1.0" : "HTTP/1.0 200 OK", (unsigned long)length);  
2871 - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);  
2872 - if (parsed != buf1len)  
2873 - goto err;  
2874 -  
2875 - for (i = 0; i < length; i++) {  
2876 - char foo = 'a';  
2877 - parsed = http_parser_execute(&parser, &settings_null, &foo, 1);  
2878 - if (parsed != 1)  
2879 - goto err;  
2880 - }  
2881 -  
2882 - parsed = http_parser_execute(&parser, &settings_null, buf1, buf1len);  
2883 - if (parsed != buf1len) goto err;  
2884 - return;  
2885 -  
2886 - err:  
2887 - fprintf(stderr,  
2888 - "\n*** error in test_no_overflow_long_body %s of length %lu ***\n",  
2889 - req ? "REQUEST" : "RESPONSE",  
2890 - (unsigned long)length);  
2891 - abort();  
2892 -}  
2893 -  
2894 -void  
2895 -test_multiple3 (const struct message *r1, const struct message *r2, const struct message *r3)  
2896 -{  
2897 - int message_count = count_parsed_messages(3, r1, r2, r3);  
2898 -  
2899 - char total[ strlen(r1->raw)  
2900 - + strlen(r2->raw)  
2901 - + strlen(r3->raw)  
2902 - + 1  
2903 - ];  
2904 - total[0] = '\0';  
2905 -  
2906 - strcat(total, r1->raw);  
2907 - strcat(total, r2->raw);  
2908 - strcat(total, r3->raw);  
2909 -  
2910 - parser_init(r1->type);  
2911 -  
2912 - size_t read;  
2913 -  
2914 - read = parse(total, strlen(total));  
2915 -  
2916 - if (parser->upgrade) {  
2917 - upgrade_message_fix(total, read, 3, r1, r2, r3);  
2918 - goto test;  
2919 - }  
2920 -  
2921 - if (read != strlen(total)) {  
2922 - print_error(total, read);  
2923 - abort();  
2924 - }  
2925 -  
2926 - read = parse(NULL, 0);  
2927 -  
2928 - if (read != 0) {  
2929 - print_error(total, read);  
2930 - abort();  
2931 - }  
2932 -  
2933 -test:  
2934 -  
2935 - if (message_count != num_messages) {  
2936 - fprintf(stderr, "\n\n*** Parser didn't see 3 messages only %d *** \n", num_messages);  
2937 - abort();  
2938 - }  
2939 -  
2940 - if (!message_eq(0, r1)) abort();  
2941 - if (message_count > 1 && !message_eq(1, r2)) abort();  
2942 - if (message_count > 2 && !message_eq(2, r3)) abort();  
2943 -  
2944 - parser_free();  
2945 -}  
2946 -  
2947 -/* SCAN through every possible breaking to make sure the  
2948 - * parser can handle getting the content in any chunks that  
2949 - * might come from the socket  
2950 - */  
2951 -void  
2952 -test_scan (const struct message *r1, const struct message *r2, const struct message *r3)  
2953 -{  
2954 - char total[80*1024] = "\0";  
2955 - char buf1[80*1024] = "\0";  
2956 - char buf2[80*1024] = "\0";  
2957 - char buf3[80*1024] = "\0";  
2958 -  
2959 - strcat(total, r1->raw);  
2960 - strcat(total, r2->raw);  
2961 - strcat(total, r3->raw);  
2962 -  
2963 - size_t read;  
2964 -  
2965 - int total_len = strlen(total);  
2966 -  
2967 - int total_ops = 2 * (total_len - 1) * (total_len - 2) / 2;  
2968 - int ops = 0 ;  
2969 -  
2970 - size_t buf1_len, buf2_len, buf3_len;  
2971 - int message_count = count_parsed_messages(3, r1, r2, r3);  
2972 -  
2973 - int i,j,type_both;  
2974 - for (type_both = 0; type_both < 2; type_both ++ ) {  
2975 - for (j = 2; j < total_len; j ++ ) {  
2976 - for (i = 1; i < j; i ++ ) {  
2977 -  
2978 - if (ops % 1000 == 0) {  
2979 - printf("\b\b\b\b%3.0f%%", 100 * (float)ops /(float)total_ops);  
2980 - fflush(stdout);  
2981 - }  
2982 - ops += 1;  
2983 -  
2984 - parser_init(type_both ? HTTP_BOTH : r1->type);  
2985 -  
2986 - buf1_len = i;  
2987 - strlncpy(buf1, sizeof(buf1), total, buf1_len);  
2988 - buf1[buf1_len] = 0;  
2989 -  
2990 - buf2_len = j - i;  
2991 - strlncpy(buf2, sizeof(buf1), total+i, buf2_len);  
2992 - buf2[buf2_len] = 0;  
2993 -  
2994 - buf3_len = total_len - j;  
2995 - strlncpy(buf3, sizeof(buf1), total+j, buf3_len);  
2996 - buf3[buf3_len] = 0;  
2997 -  
2998 - read = parse(buf1, buf1_len);  
2999 -  
3000 - if (parser->upgrade) goto test;  
3001 -  
3002 - if (read != buf1_len) {  
3003 - print_error(buf1, read);  
3004 - goto error;  
3005 - }  
3006 -  
3007 - read += parse(buf2, buf2_len);  
3008 -  
3009 - if (parser->upgrade) goto test;  
3010 -  
3011 - if (read != buf1_len + buf2_len) {  
3012 - print_error(buf2, read);  
3013 - goto error;  
3014 - }  
3015 -  
3016 - read += parse(buf3, buf3_len);  
3017 -  
3018 - if (parser->upgrade) goto test;  
3019 -  
3020 - if (read != buf1_len + buf2_len + buf3_len) {  
3021 - print_error(buf3, read);  
3022 - goto error;  
3023 - }  
3024 -  
3025 - parse(NULL, 0);  
3026 -  
3027 -test:  
3028 - if (parser->upgrade) {  
3029 - upgrade_message_fix(total, read, 3, r1, r2, r3);  
3030 - }  
3031 -  
3032 - if (message_count != num_messages) {  
3033 - fprintf(stderr, "\n\nParser didn't see %d messages only %d\n",  
3034 - message_count, num_messages);  
3035 - goto error;  
3036 - }  
3037 -  
3038 - if (!message_eq(0, r1)) {  
3039 - fprintf(stderr, "\n\nError matching messages[0] in test_scan.\n");  
3040 - goto error;  
3041 - }  
3042 -  
3043 - if (message_count > 1 && !message_eq(1, r2)) {  
3044 - fprintf(stderr, "\n\nError matching messages[1] in test_scan.\n");  
3045 - goto error;  
3046 - }  
3047 -  
3048 - if (message_count > 2 && !message_eq(2, r3)) {  
3049 - fprintf(stderr, "\n\nError matching messages[2] in test_scan.\n");  
3050 - goto error;  
3051 - }  
3052 -  
3053 - parser_free();  
3054 - }  
3055 - }  
3056 - }  
3057 - puts("\b\b\b\b100%");  
3058 - return;  
3059 -  
3060 - error:  
3061 - fprintf(stderr, "i=%d j=%d\n", i, j);  
3062 - fprintf(stderr, "buf1 (%u) %s\n\n", (unsigned int)buf1_len, buf1);  
3063 - fprintf(stderr, "buf2 (%u) %s\n\n", (unsigned int)buf2_len , buf2);  
3064 - fprintf(stderr, "buf3 (%u) %s\n", (unsigned int)buf3_len, buf3);  
3065 - abort();  
3066 -}  
3067 -  
3068 -// user required to free the result  
3069 -// string terminated by \0  
3070 -char *  
3071 -create_large_chunked_message (int body_size_in_kb, const char* headers)  
3072 -{  
3073 - int i;  
3074 - size_t wrote = 0;  
3075 - size_t headers_len = strlen(headers);  
3076 - size_t bufsize = headers_len + (5+1024+2)*body_size_in_kb + 6;  
3077 - char * buf = malloc(bufsize);  
3078 -  
3079 - memcpy(buf, headers, headers_len);  
3080 - wrote += headers_len;  
3081 -  
3082 - for (i = 0; i < body_size_in_kb; i++) {  
3083 - // write 1kb chunk into the body.  
3084 - memcpy(buf + wrote, "400\r\n", 5);  
3085 - wrote += 5;  
3086 - memset(buf + wrote, 'C', 1024);  
3087 - wrote += 1024;  
3088 - strcpy(buf + wrote, "\r\n");  
3089 - wrote += 2;  
3090 - }  
3091 -  
3092 - memcpy(buf + wrote, "0\r\n\r\n", 6);  
3093 - wrote += 6;  
3094 - assert(wrote == bufsize);  
3095 -  
3096 - return buf;  
3097 -}  
3098 -  
3099 -void  
3100 -test_status_complete (void)  
3101 -{  
3102 - parser_init(HTTP_RESPONSE);  
3103 - parser->data = 0;  
3104 - http_parser_settings settings = settings_null;  
3105 - settings.on_status_complete = status_complete_cb;  
3106 -  
3107 - char *response = "don't mind me, just a simple response";  
3108 - http_parser_execute(parser, &settings, response, strlen(response));  
3109 - assert(parser->data == (void*)0); // the status_complete callback was never called  
3110 - assert(parser->http_errno == HPE_INVALID_CONSTANT); // the errno for an invalid status line  
3111 -}  
3112 -  
3113 -/* Verify that we can pause parsing at any of the bytes in the  
3114 - * message and still get the result that we're expecting. */  
3115 -void  
3116 -test_message_pause (const struct message *msg)  
3117 -{  
3118 - char *buf = (char*) msg->raw;  
3119 - size_t buflen = strlen(msg->raw);  
3120 - size_t nread;  
3121 -  
3122 - parser_init(msg->type);  
3123 -  
3124 - do {  
3125 - nread = parse_pause(buf, buflen);  
3126 -  
3127 - // We can only set the upgrade buffer once we've gotten our message  
3128 - // completion callback.  
3129 - if (messages[0].message_complete_cb_called &&  
3130 - msg->upgrade &&  
3131 - parser->upgrade) {  
3132 - messages[0].upgrade = buf + nread;  
3133 - goto test;  
3134 - }  
3135 -  
3136 - if (nread < buflen) {  
3137 -  
3138 - // Not much do to if we failed a strict-mode check  
3139 - if (HTTP_PARSER_ERRNO(parser) == HPE_STRICT) {  
3140 - parser_free();  
3141 - return;  
3142 - }  
3143 -  
3144 - assert (HTTP_PARSER_ERRNO(parser) == HPE_PAUSED);  
3145 - }  
3146 -  
3147 - buf += nread;  
3148 - buflen -= nread;  
3149 - http_parser_pause(parser, 0);  
3150 - } while (buflen > 0);  
3151 -  
3152 - nread = parse_pause(NULL, 0);  
3153 - assert (nread == 0);  
3154 -  
3155 -test:  
3156 - if (num_messages != 1) {  
3157 - printf("\n*** num_messages != 1 after testing '%s' ***\n\n", msg->name);  
3158 - abort();  
3159 - }  
3160 -  
3161 - if(!message_eq(0, msg)) abort();  
3162 -  
3163 - parser_free();  
3164 -}  
3165 -  
3166 -int  
3167 -main (void)  
3168 -{  
3169 - parser = NULL;  
3170 - int i, j, k;  
3171 - int request_count;  
3172 - int response_count;  
3173 -  
3174 - printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));  
3175 -  
3176 - for (request_count = 0; requests[request_count].name; request_count++);  
3177 - for (response_count = 0; responses[response_count].name; response_count++);  
3178 -  
3179 - //// API  
3180 - test_preserve_data();  
3181 - test_parse_url();  
3182 - test_method_str();  
3183 -  
3184 - //// OVERFLOW CONDITIONS  
3185 -  
3186 - test_header_overflow_error(HTTP_REQUEST);  
3187 - test_no_overflow_long_body(HTTP_REQUEST, 1000);  
3188 - test_no_overflow_long_body(HTTP_REQUEST, 100000);  
3189 -  
3190 - test_header_overflow_error(HTTP_RESPONSE);  
3191 - test_no_overflow_long_body(HTTP_RESPONSE, 1000);  
3192 - test_no_overflow_long_body(HTTP_RESPONSE, 100000);  
3193 -  
3194 - test_header_content_length_overflow_error();  
3195 - test_chunk_content_length_overflow_error();  
3196 -  
3197 - //// RESPONSES  
3198 -  
3199 - for (i = 0; i < response_count; i++) {  
3200 - test_message(&responses[i]);  
3201 - }  
3202 -  
3203 - for (i = 0; i < response_count; i++) {  
3204 - test_message_pause(&responses[i]);  
3205 - }  
3206 -  
3207 - for (i = 0; i < response_count; i++) {  
3208 - if (!responses[i].should_keep_alive) continue;  
3209 - for (j = 0; j < response_count; j++) {  
3210 - if (!responses[j].should_keep_alive) continue;  
3211 - for (k = 0; k < response_count; k++) {  
3212 - test_multiple3(&responses[i], &responses[j], &responses[k]);  
3213 - }  
3214 - }  
3215 - }  
3216 -  
3217 - test_message_count_body(&responses[NO_HEADERS_NO_BODY_404]);  
3218 - test_message_count_body(&responses[TRAILING_SPACE_ON_CHUNKED_BODY]);  
3219 -  
3220 - // test very large chunked response  
3221 - {  
3222 - char * msg = create_large_chunked_message(31337,  
3223 - "HTTP/1.0 200 OK\r\n"  
3224 - "Transfer-Encoding: chunked\r\n"  
3225 - "Content-Type: text/plain\r\n"  
3226 - "\r\n");  
3227 - struct message large_chunked =  
3228 - {.name= "large chunked"  
3229 - ,.type= HTTP_RESPONSE  
3230 - ,.raw= msg  
3231 - ,.should_keep_alive= FALSE  
3232 - ,.message_complete_on_eof= FALSE  
3233 - ,.http_major= 1  
3234 - ,.http_minor= 0  
3235 - ,.status_code= 200  
3236 - ,.num_headers= 2  
3237 - ,.headers=  
3238 - { { "Transfer-Encoding", "chunked" }  
3239 - , { "Content-Type", "text/plain" }  
3240 - }  
3241 - ,.body_size= 31337*1024  
3242 - };  
3243 - test_message_count_body(&large_chunked);  
3244 - free(msg);  
3245 - }  
3246 -  
3247 -  
3248 -  
3249 - printf("response scan 1/2 ");  
3250 - test_scan( &responses[TRAILING_SPACE_ON_CHUNKED_BODY]  
3251 - , &responses[NO_BODY_HTTP10_KA_204]  
3252 - , &responses[NO_REASON_PHRASE]  
3253 - );  
3254 -  
3255 - printf("response scan 2/2 ");  
3256 - test_scan( &responses[BONJOUR_MADAME_FR]  
3257 - , &responses[UNDERSTORE_HEADER_KEY]  
3258 - , &responses[NO_CARRIAGE_RET]  
3259 - );  
3260 -  
3261 - puts("responses okay");  
3262 -  
3263 -  
3264 - /// REQUESTS  
3265 -  
3266 - test_simple("hello world", HPE_INVALID_METHOD);  
3267 - test_simple("GET / HTP/1.1\r\n\r\n", HPE_INVALID_VERSION);  
3268 -  
3269 -  
3270 - test_simple("ASDF / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);  
3271 - test_simple("PROPPATCHA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);  
3272 - test_simple("GETA / HTTP/1.1\r\n\r\n", HPE_INVALID_METHOD);  
3273 -  
3274 - // Well-formed but incomplete  
3275 - test_simple("GET / HTTP/1.1\r\n"  
3276 - "Content-Type: text/plain\r\n"  
3277 - "Content-Length: 6\r\n"  
3278 - "\r\n"  
3279 - "fooba",  
3280 - HPE_OK);  
3281 -  
3282 - static const char *all_methods[] = {  
3283 - "DELETE",  
3284 - "GET",  
3285 - "HEAD",  
3286 - "POST",  
3287 - "PUT",  
3288 - //"CONNECT", //CONNECT can't be tested like other methods, it's a tunnel  
3289 - "OPTIONS",  
3290 - "TRACE",  
3291 - "COPY",  
3292 - "LOCK",  
3293 - "MKCOL",  
3294 - "MOVE",  
3295 - "PROPFIND",  
3296 - "PROPPATCH",  
3297 - "UNLOCK",  
3298 - "REPORT",  
3299 - "MKACTIVITY",  
3300 - "CHECKOUT",  
3301 - "MERGE",  
3302 - "M-SEARCH",  
3303 - "NOTIFY",  
3304 - "SUBSCRIBE",  
3305 - "UNSUBSCRIBE",  
3306 - "PATCH",  
3307 - 0 };  
3308 - const char **this_method;  
3309 - for (this_method = all_methods; *this_method; this_method++) {  
3310 - char buf[200];  
3311 - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);  
3312 - test_simple(buf, HPE_OK);  
3313 - }  
3314 -  
3315 - static const char *bad_methods[] = {  
3316 - "C******",  
3317 - "M****",  
3318 - 0 };  
3319 - for (this_method = bad_methods; *this_method; this_method++) {  
3320 - char buf[200];  
3321 - sprintf(buf, "%s / HTTP/1.1\r\n\r\n", *this_method);  
3322 - test_simple(buf, HPE_UNKNOWN);  
3323 - }  
3324 -  
3325 - const char *dumbfuck2 =  
3326 - "GET / HTTP/1.1\r\n"  
3327 - "X-SSL-Bullshit: -----BEGIN CERTIFICATE-----\r\n"  
3328 - "\tMIIFbTCCBFWgAwIBAgICH4cwDQYJKoZIhvcNAQEFBQAwcDELMAkGA1UEBhMCVUsx\r\n"  
3329 - "\tETAPBgNVBAoTCGVTY2llbmNlMRIwEAYDVQQLEwlBdXRob3JpdHkxCzAJBgNVBAMT\r\n"  
3330 - "\tAkNBMS0wKwYJKoZIhvcNAQkBFh5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMu\r\n"  
3331 - "\tdWswHhcNMDYwNzI3MTQxMzI4WhcNMDcwNzI3MTQxMzI4WjBbMQswCQYDVQQGEwJV\r\n"  
3332 - "\tSzERMA8GA1UEChMIZVNjaWVuY2UxEzARBgNVBAsTCk1hbmNoZXN0ZXIxCzAJBgNV\r\n"  
3333 - "\tBAcTmrsogriqMWLAk1DMRcwFQYDVQQDEw5taWNoYWVsIHBhcmQYJKoZIhvcNAQEB\r\n"  
3334 - "\tBQADggEPADCCAQoCggEBANPEQBgl1IaKdSS1TbhF3hEXSl72G9J+WC/1R64fAcEF\r\n"  
3335 - "\tW51rEyFYiIeZGx/BVzwXbeBoNUK41OK65sxGuflMo5gLflbwJtHBRIEKAfVVp3YR\r\n"  
3336 - "\tgW7cMA/s/XKgL1GEC7rQw8lIZT8RApukCGqOVHSi/F1SiFlPDxuDfmdiNzL31+sL\r\n"  
3337 - "\t0iwHDdNkGjy5pyBSB8Y79dsSJtCW/iaLB0/n8Sj7HgvvZJ7x0fr+RQjYOUUfrePP\r\n"  
3338 - "\tu2MSpFyf+9BbC/aXgaZuiCvSR+8Snv3xApQY+fULK/xY8h8Ua51iXoQ5jrgu2SqR\r\n"  
3339 - "\twgA7BUi3G8LFzMBl8FRCDYGUDy7M6QaHXx1ZWIPWNKsCAwEAAaOCAiQwggIgMAwG\r\n"  
3340 - "\tA1UdEwEB/wQCMAAwEQYJYIZIAYb4QgHTTPAQDAgWgMA4GA1UdDwEB/wQEAwID6DAs\r\n"  
3341 - "\tBglghkgBhvhCAQ0EHxYdVUsgZS1TY2llbmNlIFVzZXIgQ2VydGlmaWNhdGUwHQYD\r\n"  
3342 - "\tVR0OBBYEFDTt/sf9PeMaZDHkUIldrDYMNTBZMIGaBgNVHSMEgZIwgY+AFAI4qxGj\r\n"  
3343 - "\tloCLDdMVKwiljjDastqooXSkcjBwMQswCQYDVQQGEwJVSzERMA8GA1UEChMIZVNj\r\n"  
3344 - "\taWVuY2UxEjAQBgNVBAsTCUF1dGhvcml0eTELMAkGA1UEAxMCQ0ExLTArBgkqhkiG\r\n"  
3345 - "\t9w0BCQEWHmNhLW9wZXJhdG9yQGdyaWQtc3VwcG9ydC5hYy51a4IBADApBgNVHRIE\r\n"  
3346 - "\tIjAggR5jYS1vcGVyYXRvckBncmlkLXN1cHBvcnQuYWMudWswGQYDVR0gBBIwEDAO\r\n"  
3347 - "\tBgwrBgEEAdkvAQEBAQYwPQYJYIZIAYb4QgEEBDAWLmh0dHA6Ly9jYS5ncmlkLXN1\r\n"  
3348 - "\tcHBvcnQuYWMudmT4sopwqlBWsvcHViL2NybC9jYWNybC5jcmwwPQYJYIZIAYb4QgEDBDAWLmh0\r\n"  
3349 - "\tdHA6Ly9jYS5ncmlkLXN1cHBvcnQuYWMudWsvcHViL2NybC9jYWNybC5jcmwwPwYD\r\n"  
3350 - "\tVR0fBDgwNjA0oDKgMIYuaHR0cDovL2NhLmdyaWQt5hYy51ay9wdWIv\r\n"  
3351 - "\tY3JsL2NhY3JsLmNybDANBgkqhkiG9w0BAQUFAAOCAQEAS/U4iiooBENGW/Hwmmd3\r\n"  
3352 - "\tXCy6Zrt08YjKCzGNjorT98g8uGsqYjSxv/hmi0qlnlHs+k/3Iobc3LjS5AMYr5L8\r\n"  
3353 - "\tUO7OSkgFFlLHQyC9JzPfmLCAugvzEbyv4Olnsr8hbxF1MbKZoQxUZtMVu29wjfXk\r\n"  
3354 - "\thTeApBv7eaKCWpSp7MCbvgzm74izKhu3vlDk9w6qVrxePfGgpKPqfHiOoGhFnbTK\r\n"  
3355 - "\twTC6o2xq5y0qZ03JonF7OJspEd3I5zKY3E+ov7/ZhW6DqT8UFvsAdjvQbXyhV8Eu\r\n"  
3356 - "\tYhixw1aKEPzNjNowuIseVogKOLXxWI5vAi5HgXdS0/ES5gDGsABo4fqovUKlgop3\r\n"  
3357 - "\tRA==\r\n"  
3358 - "\t-----END CERTIFICATE-----\r\n"  
3359 - "\r\n";  
3360 - test_simple(dumbfuck2, HPE_OK);  
3361 -  
3362 -#if 0  
3363 - // NOTE(Wed Nov 18 11:57:27 CET 2009) this seems okay. we just read body  
3364 - // until EOF.  
3365 - //  
3366 - // no content-length  
3367 - // error if there is a body without content length  
3368 - const char *bad_get_no_headers_no_body = "GET /bad_get_no_headers_no_body/world HTTP/1.1\r\n"  
3369 - "Accept: */*\r\n"  
3370 - "\r\n"  
3371 - "HELLO";  
3372 - test_simple(bad_get_no_headers_no_body, 0);  
3373 -#endif  
3374 - /* TODO sending junk and large headers gets rejected */  
3375 -  
3376 -  
3377 - /* check to make sure our predefined requests are okay */  
3378 - for (i = 0; requests[i].name; i++) {  
3379 - test_message(&requests[i]);  
3380 - }  
3381 -  
3382 - for (i = 0; i < request_count; i++) {  
3383 - test_message_pause(&requests[i]);  
3384 - }  
3385 -  
3386 - for (i = 0; i < request_count; i++) {  
3387 - if (!requests[i].should_keep_alive) continue;  
3388 - for (j = 0; j < request_count; j++) {  
3389 - if (!requests[j].should_keep_alive) continue;  
3390 - for (k = 0; k < request_count; k++) {  
3391 - test_multiple3(&requests[i], &requests[j], &requests[k]);  
3392 - }  
3393 - }  
3394 - }  
3395 -  
3396 - printf("request scan 1/4 ");  
3397 - test_scan( &requests[GET_NO_HEADERS_NO_BODY]  
3398 - , &requests[GET_ONE_HEADER_NO_BODY]  
3399 - , &requests[GET_NO_HEADERS_NO_BODY]  
3400 - );  
3401 -  
3402 - printf("request scan 2/4 ");  
3403 - test_scan( &requests[POST_CHUNKED_ALL_YOUR_BASE]  
3404 - , &requests[POST_IDENTITY_BODY_WORLD]  
3405 - , &requests[GET_FUNKY_CONTENT_LENGTH]  
3406 - );  
3407 -  
3408 - printf("request scan 3/4 ");  
3409 - test_scan( &requests[TWO_CHUNKS_MULT_ZERO_END]  
3410 - , &requests[CHUNKED_W_TRAILING_HEADERS]  
3411 - , &requests[CHUNKED_W_BULLSHIT_AFTER_LENGTH]  
3412 - );  
3413 -  
3414 - printf("request scan 4/4 ");  
3415 - test_scan( &requests[QUERY_URL_WITH_QUESTION_MARK_GET]  
3416 - , &requests[PREFIX_NEWLINE_GET ]  
3417 - , &requests[CONNECT_REQUEST]  
3418 - );  
3419 -  
3420 - test_status_complete();  
3421 -  
3422 - puts("requests okay");  
3423 -  
3424 - return 0;  
3425 -}