1 /* Based on src/http/ngx_http_parse.c from NGINX copyright Igor Sysoev
3 * Additional changes are licensed under the same terms as NGINX and
4 * copyright Joyent, Inc. and other Node contributors. All rights reserved.
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:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
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
24 #include "http_parser.h"
33 # define ULLONG_MAX ((uint64_t) -1) /* 2^64-1 */
37 # define MIN(a,b) ((a) < (b) ? (a) : (b))
41 # define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
45 # define BIT_AT(a, i) \
46 (!!((unsigned int) (a)[(unsigned int) (i) >> 3] & \
47 (1 << ((unsigned int) (i) & 7))))
51 # define ELEM_AT(a, i, v) ((unsigned int) (i) < ARRAY_SIZE(a) ? (a)[(i)] : (v))
55 #define SET_ERRNO(e) \
57 parser->http_errno = (e); \
58 parser->error_lineno = __LINE__; \
61 #define SET_ERRNO(e) \
63 parser->http_errno = (e); \
68 /* Run the notify callback FOR, returning ER if it fails */
69 #define CALLBACK_NOTIFY_(FOR, ER) \
71 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
73 if (settings->on_##FOR) { \
74 if (0 != settings->on_##FOR(parser)) { \
75 SET_ERRNO(HPE_CB_##FOR); \
78 /* We either errored above or got paused; get out */ \
79 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \
85 /* Run the notify callback FOR and consume the current byte */
86 #define CALLBACK_NOTIFY(FOR) CALLBACK_NOTIFY_(FOR, p - data + 1)
88 /* Run the notify callback FOR and don't consume the current byte */
89 #define CALLBACK_NOTIFY_NOADVANCE(FOR) CALLBACK_NOTIFY_(FOR, p - data)
91 /* Run data callback FOR with LEN bytes, returning ER if it fails */
92 #define CALLBACK_DATA_(FOR, LEN, ER) \
94 assert(HTTP_PARSER_ERRNO(parser) == HPE_OK); \
97 if (settings->on_##FOR) { \
98 if (0 != settings->on_##FOR(parser, FOR##_mark, (LEN))) { \
99 SET_ERRNO(HPE_CB_##FOR); \
102 /* We either errored above or got paused; get out */ \
103 if (HTTP_PARSER_ERRNO(parser) != HPE_OK) { \
111 /* Run the data callback FOR and consume the current byte */
112 #define CALLBACK_DATA(FOR) \
113 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data + 1)
115 /* Run the data callback FOR and don't consume the current byte */
116 #define CALLBACK_DATA_NOADVANCE(FOR) \
117 CALLBACK_DATA_(FOR, p - FOR##_mark, p - data)
119 /* Set the mark FOR; non-destructive if mark is already set */
128 #define PROXY_CONNECTION "proxy-connection"
129 #define CONNECTION "connection"
130 #define CONTENT_LENGTH "content-length"
131 #define TRANSFER_ENCODING "transfer-encoding"
132 #define UPGRADE "upgrade"
133 #define CHUNKED "chunked"
134 #define KEEP_ALIVE "keep-alive"
135 #define CLOSE "close"
138 static const char *method_strings
[] =
140 #define XX(num, name, string) #string,
146 /* Tokens as defined by rfc 2616. Also lowercases them.
147 * token = 1*<any CHAR except CTLs or separators>
148 * separators = "(" | ")" | "<" | ">" | "@"
149 * | "," | ";" | ":" | "\" | <">
150 * | "/" | "[" | "]" | "?" | "="
151 * | "{" | "}" | SP | HT
153 static const char tokens
[256] = {
154 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
155 0, 0, 0, 0, 0, 0, 0, 0,
156 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
157 0, 0, 0, 0, 0, 0, 0, 0,
158 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
159 0, 0, 0, 0, 0, 0, 0, 0,
160 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
161 0, 0, 0, 0, 0, 0, 0, 0,
162 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
163 0, '!', 0, '#', '$', '%', '&', '\'',
164 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
165 0, 0, '*', '+', 0, '-', '.', 0,
166 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
167 '0', '1', '2', '3', '4', '5', '6', '7',
168 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
169 '8', '9', 0, 0, 0, 0, 0, 0,
170 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
171 0, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
172 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
173 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
174 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
175 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
176 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
177 'x', 'y', 'z', 0, 0, 0, '^', '_',
178 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
179 '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g',
180 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
181 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
182 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
183 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
184 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
185 'x', 'y', 'z', 0, '|', 0, '~', 0 };
188 static const int8_t unhex
[256] =
189 {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
190 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
191 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
192 , 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,-1,-1,-1,-1,-1,-1
193 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
194 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
195 ,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1
196 ,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
200 #if HTTP_PARSER_STRICT
207 static const uint8_t normal_url_char
[32] = {
208 /* 0 nul 1 soh 2 stx 3 etx 4 eot 5 enq 6 ack 7 bel */
209 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
210 /* 8 bs 9 ht 10 nl 11 vt 12 np 13 cr 14 so 15 si */
211 0 | T(2) | 0 | 0 | T(16) | 0 | 0 | 0,
212 /* 16 dle 17 dc1 18 dc2 19 dc3 20 dc4 21 nak 22 syn 23 etb */
213 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
214 /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */
215 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0,
216 /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */
217 0 | 2 | 4 | 0 | 16 | 32 | 64 | 128,
218 /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */
219 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
220 /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */
221 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
222 /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */
223 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0,
224 /* 64 @ 65 A 66 B 67 C 68 D 69 E 70 F 71 G */
225 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
226 /* 72 H 73 I 74 J 75 K 76 L 77 M 78 N 79 O */
227 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
228 /* 80 P 81 Q 82 R 83 S 84 T 85 U 86 V 87 W */
229 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
230 /* 88 X 89 Y 90 Z 91 [ 92 \ 93 ] 94 ^ 95 _ */
231 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
232 /* 96 ` 97 a 98 b 99 c 100 d 101 e 102 f 103 g */
233 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
234 /* 104 h 105 i 106 j 107 k 108 l 109 m 110 n 111 o */
235 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
236 /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */
237 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128,
238 /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */
239 1 | 2 | 4 | 8 | 16 | 32 | 64 | 0, };
244 { s_dead
= 1 /* important that this is > 0 */
253 , s_res_first_http_major
255 , s_res_first_http_minor
257 , s_res_first_status_code
260 , s_res_line_almost_done
265 , s_req_spaces_before_url
268 , s_req_schema_slash_slash
271 , s_req_server_with_at
273 , s_req_query_string_start
275 , s_req_fragment_start
282 , s_req_first_http_major
284 , s_req_first_http_minor
286 , s_req_line_almost_done
288 , s_header_field_start
290 , s_header_value_start
294 , s_header_almost_done
299 , s_chunk_size_almost_done
301 , s_headers_almost_done
304 /* Important: 's_headers_done' must be the last 'header' state. All
305 * states beyond this must be 'body' states. It is used for overflow
306 * checking. See the PARSING_HEADER() macro.
310 , s_chunk_data_almost_done
314 , s_body_identity_eof
320 #define PARSING_HEADER(state) (state <= s_headers_done)
329 , h_matching_connection
330 , h_matching_proxy_connection
331 , h_matching_content_length
332 , h_matching_transfer_encoding
337 , h_transfer_encoding
340 , h_matching_transfer_encoding_chunked
341 , h_matching_connection_keep_alive
342 , h_matching_connection_close
344 , h_transfer_encoding_chunked
345 , h_connection_keep_alive
352 , s_http_userinfo_start
355 , s_http_host_v6_start
359 , s_http_host_port_start
363 /* Macros for character classes; depends on strict-mode */
366 #define LOWER(c) (unsigned char)(c | 0x20)
367 #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z')
368 #define IS_NUM(c) ((c) >= '0' && (c) <= '9')
369 #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c))
370 #define IS_HEX(c) (IS_NUM(c) || (LOWER(c) >= 'a' && LOWER(c) <= 'f'))
371 #define IS_MARK(c) ((c) == '-' || (c) == '_' || (c) == '.' || \
372 (c) == '!' || (c) == '~' || (c) == '*' || (c) == '\'' || (c) == '(' || \
374 #define IS_USERINFO_CHAR(c) (IS_ALPHANUM(c) || IS_MARK(c) || (c) == '%' || \
375 (c) == ';' || (c) == ':' || (c) == '&' || (c) == '=' || (c) == '+' || \
376 (c) == '$' || (c) == ',')
378 #if HTTP_PARSER_STRICT
379 #define TOKEN(c) (tokens[(unsigned char)c])
380 #define IS_URL_CHAR(c) (BIT_AT(normal_url_char, (unsigned char)c))
381 #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-')
383 #define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c])
384 #define IS_URL_CHAR(c) \
385 (BIT_AT(normal_url_char, (unsigned char)c) || ((c) & 0x80))
386 #define IS_HOST_CHAR(c) \
387 (IS_ALPHANUM(c) || (c) == '.' || (c) == '-' || (c) == '_')
391 #define start_state (parser->type == HTTP_REQUEST ? s_start_req : s_start_res)
394 #if HTTP_PARSER_STRICT
395 # define STRICT_CHECK(cond) \
398 SET_ERRNO(HPE_STRICT); \
402 # define NEW_MESSAGE() (http_should_keep_alive(parser) ? start_state : s_dead)
404 # define STRICT_CHECK(cond)
405 # define NEW_MESSAGE() start_state
409 /* Map errno values to strings for human-readable output */
410 #define HTTP_STRERROR_GEN(n, s) { "HPE_" #n, s },
413 const char *description
;
414 } http_strerror_tab
[] = {
415 HTTP_ERRNO_MAP(HTTP_STRERROR_GEN
)
417 #undef HTTP_STRERROR_GEN
419 int http_message_needs_eof(const http_parser
*parser
);
423 * This is designed to be shared by http_parser_execute() for URL validation,
424 * hence it has a state transition + byte-for-byte interface. In addition, it
425 * is meant to be embedded in http_parser_parse_url(), which does the dirty
426 * work of turning state transitions URL components for its API.
428 * This function should only be invoked with non-space characters. It is
429 * assumed that the caller cares about (and can detect) the transition between
430 * URL and non-URL states by looking for these.
433 parse_url_char(enum state s
, const char ch
)
435 if (ch
== ' ' || ch
== '\r' || ch
== '\n') {
439 #if HTTP_PARSER_STRICT
440 if (ch
== '\t' || ch
== '\f') {
446 case s_req_spaces_before_url
:
447 /* Proxied requests are followed by scheme of an absolute URI (alpha).
448 * All methods except CONNECT are followed by '/' or '*'.
451 if (ch
== '/' || ch
== '*') {
467 return s_req_schema_slash
;
472 case s_req_schema_slash
:
474 return s_req_schema_slash_slash
;
479 case s_req_schema_slash_slash
:
481 return s_req_server_start
;
486 case s_req_server_with_at
:
492 case s_req_server_start
:
499 return s_req_query_string_start
;
503 return s_req_server_with_at
;
506 if (IS_USERINFO_CHAR(ch
) || ch
== '[' || ch
== ']') {
513 if (IS_URL_CHAR(ch
)) {
519 return s_req_query_string_start
;
522 return s_req_fragment_start
;
527 case s_req_query_string_start
:
528 case s_req_query_string
:
529 if (IS_URL_CHAR(ch
)) {
530 return s_req_query_string
;
535 /* allow extra '?' in query string */
536 return s_req_query_string
;
539 return s_req_fragment_start
;
544 case s_req_fragment_start
:
545 if (IS_URL_CHAR(ch
)) {
546 return s_req_fragment
;
551 return s_req_fragment
;
560 if (IS_URL_CHAR(ch
)) {
576 /* We should never fall out of the switch above unless there's an error */
580 size_t http_parser_execute (http_parser
*parser
,
581 const http_parser_settings
*settings
,
587 const char *p
= data
;
588 const char *header_field_mark
= 0;
589 const char *header_value_mark
= 0;
590 const char *url_mark
= 0;
591 const char *body_mark
= 0;
593 /* We're in an error state. Don't bother doing anything. */
594 if (HTTP_PARSER_ERRNO(parser
) != HPE_OK
) {
599 switch (parser
->state
) {
600 case s_body_identity_eof
:
601 /* Use of CALLBACK_NOTIFY() here would erroneously return 1 byte read if
604 CALLBACK_NOTIFY_NOADVANCE(message_complete
);
608 case s_start_req_or_res
:
614 SET_ERRNO(HPE_INVALID_EOF_STATE
);
620 if (parser
->state
== s_header_field
)
621 header_field_mark
= data
;
622 if (parser
->state
== s_header_value
)
623 header_value_mark
= data
;
624 switch (parser
->state
) {
627 case s_req_schema_slash
:
628 case s_req_schema_slash_slash
:
629 case s_req_server_start
:
631 case s_req_server_with_at
:
632 case s_req_query_string_start
:
633 case s_req_query_string
:
634 case s_req_fragment_start
:
640 for (p
=data
; p
!= data
+ len
; p
++) {
643 if (PARSING_HEADER(parser
->state
)) {
645 /* Buffer overflow attack */
646 if (parser
->nread
> HTTP_MAX_HEADER_SIZE
) {
647 SET_ERRNO(HPE_HEADER_OVERFLOW
);
653 switch (parser
->state
) {
656 /* this state is used after a 'Connection: close' message
657 * the parser will error out if it reads another message
659 if (ch
== CR
|| ch
== LF
)
662 SET_ERRNO(HPE_CLOSED_CONNECTION
);
665 case s_start_req_or_res
:
667 if (ch
== CR
|| ch
== LF
)
670 parser
->content_length
= ULLONG_MAX
;
673 parser
->state
= s_res_or_resp_H
;
675 CALLBACK_NOTIFY(message_begin
);
677 parser
->type
= HTTP_REQUEST
;
678 parser
->state
= s_start_req
;
685 case s_res_or_resp_H
:
687 parser
->type
= HTTP_RESPONSE
;
688 parser
->state
= s_res_HT
;
691 SET_ERRNO(HPE_INVALID_CONSTANT
);
695 parser
->type
= HTTP_REQUEST
;
696 parser
->method
= HTTP_HEAD
;
698 parser
->state
= s_req_method
;
705 parser
->content_length
= ULLONG_MAX
;
709 parser
->state
= s_res_H
;
717 SET_ERRNO(HPE_INVALID_CONSTANT
);
721 CALLBACK_NOTIFY(message_begin
);
726 STRICT_CHECK(ch
!= 'T');
727 parser
->state
= s_res_HT
;
731 STRICT_CHECK(ch
!= 'T');
732 parser
->state
= s_res_HTT
;
736 STRICT_CHECK(ch
!= 'P');
737 parser
->state
= s_res_HTTP
;
741 STRICT_CHECK(ch
!= '/');
742 parser
->state
= s_res_first_http_major
;
745 case s_res_first_http_major
:
746 if (ch
< '0' || ch
> '9') {
747 SET_ERRNO(HPE_INVALID_VERSION
);
751 parser
->http_major
= ch
- '0';
752 parser
->state
= s_res_http_major
;
755 /* major HTTP version or dot */
756 case s_res_http_major
:
759 parser
->state
= s_res_first_http_minor
;
764 SET_ERRNO(HPE_INVALID_VERSION
);
768 parser
->http_major
*= 10;
769 parser
->http_major
+= ch
- '0';
771 if (parser
->http_major
> 999) {
772 SET_ERRNO(HPE_INVALID_VERSION
);
779 /* first digit of minor HTTP version */
780 case s_res_first_http_minor
:
782 SET_ERRNO(HPE_INVALID_VERSION
);
786 parser
->http_minor
= ch
- '0';
787 parser
->state
= s_res_http_minor
;
790 /* minor HTTP version or end of request line */
791 case s_res_http_minor
:
794 parser
->state
= s_res_first_status_code
;
799 SET_ERRNO(HPE_INVALID_VERSION
);
803 parser
->http_minor
*= 10;
804 parser
->http_minor
+= ch
- '0';
806 if (parser
->http_minor
> 999) {
807 SET_ERRNO(HPE_INVALID_VERSION
);
814 case s_res_first_status_code
:
821 SET_ERRNO(HPE_INVALID_STATUS
);
824 parser
->status_code
= ch
- '0';
825 parser
->state
= s_res_status_code
;
829 case s_res_status_code
:
834 parser
->state
= s_res_status
;
837 parser
->state
= s_res_line_almost_done
;
840 parser
->state
= s_header_field_start
;
843 SET_ERRNO(HPE_INVALID_STATUS
);
849 parser
->status_code
*= 10;
850 parser
->status_code
+= ch
- '0';
852 if (parser
->status_code
> 999) {
853 SET_ERRNO(HPE_INVALID_STATUS
);
861 /* the human readable status. e.g. "NOT FOUND"
862 * we are not humans so just ignore this */
864 parser
->state
= s_res_line_almost_done
;
869 parser
->state
= s_header_field_start
;
874 case s_res_line_almost_done
:
875 STRICT_CHECK(ch
!= LF
);
876 parser
->state
= s_header_field_start
;
881 if (ch
== CR
|| ch
== LF
)
884 parser
->content_length
= ULLONG_MAX
;
887 SET_ERRNO(HPE_INVALID_METHOD
);
891 parser
->method
= (enum http_method
) 0;
894 case 'A': parser
->method
= HTTP_ANNOUNCE
; break;
895 case 'C': parser
->method
= HTTP_CONNECT
; /* or COPY, CHECKOUT */ break;
896 case 'D': parser
->method
= HTTP_DELETE
; /* or DESCRIBE */ break;
897 case 'F': parser
->method
= HTTP_FLUSH
; break;
898 case 'G': parser
->method
= HTTP_GET
; /* or GET_PARAMETER */ break;
899 case 'H': parser
->method
= HTTP_HEAD
; break;
900 case 'L': parser
->method
= HTTP_LOCK
; break;
901 case 'M': parser
->method
= HTTP_MKCOL
; /* or MOVE, MKACTIVITY, MERGE, M-SEARCH */ break;
902 case 'N': parser
->method
= HTTP_NOTIFY
; break;
903 case 'O': parser
->method
= HTTP_OPTIONS
; break;
904 case 'P': parser
->method
= HTTP_POST
;
905 /* or PROPFIND|PROPPATCH|PUT|PATCH|PURGE|PLAY|PAUSE */
907 case 'R': parser
->method
= HTTP_REPORT
; /* or REDIRECT, RECORD */ break;
908 case 'S': parser
->method
= HTTP_SUBSCRIBE
; /* or SEARCH, SETUP, SET_PARAMETER */ break;
909 case 'T': parser
->method
= HTTP_TRACE
; /* or TEARDOWN */ break;
910 case 'U': parser
->method
= HTTP_UNLOCK
; /* or UNSUBSCRIBE */ break;
912 SET_ERRNO(HPE_INVALID_METHOD
);
915 parser
->state
= s_req_method
;
917 CALLBACK_NOTIFY(message_begin
);
926 SET_ERRNO(HPE_INVALID_METHOD
);
930 matcher
= method_strings
[parser
->method
];
931 if (ch
== ' ' && matcher
[parser
->index
] == '\0') {
932 parser
->state
= s_req_spaces_before_url
;
933 } else if (ch
== matcher
[parser
->index
]) {
935 } else if (parser
->method
== HTTP_CONNECT
) {
936 if (parser
->index
== 1 && ch
== 'H') {
937 parser
->method
= HTTP_CHECKOUT
;
938 } else if (parser
->index
== 2 && ch
== 'P') {
939 parser
->method
= HTTP_COPY
;
943 } else if (parser
->index
== 2 && parser
->method
== HTTP_DELETE
&& ch
== 'S') {
944 parser
->method
= HTTP_DESCRIBE
;
945 } else if (parser
->index
== 3 && parser
->method
== HTTP_GET
&& ch
== '_') {
946 parser
->method
= HTTP_GET_PARAMETER
;
947 } else if (parser
->method
== HTTP_MKCOL
) {
948 if (parser
->index
== 1 && ch
== 'O') {
949 parser
->method
= HTTP_MOVE
;
950 } else if (parser
->index
== 1 && ch
== 'E') {
951 parser
->method
= HTTP_MERGE
;
952 } else if (parser
->index
== 1 && ch
== '-') {
953 parser
->method
= HTTP_MSEARCH
;
954 } else if (parser
->index
== 2 && ch
== 'A') {
955 parser
->method
= HTTP_MKACTIVITY
;
959 } else if (parser
->method
== HTTP_SUBSCRIBE
) {
960 if (parser
->index
== 1 && ch
== 'E') {
961 parser
->method
= HTTP_SEARCH
; /* or HTTP_SETUP or HTTP_SET_PARAMETER */
965 } else if (parser
->method
== HTTP_TRACE
) {
966 if (parser
->index
== 1 && ch
== 'E') {
967 parser
->method
= HTTP_TEARDOWN
;
971 } else if (parser
->index
== 1 && parser
->method
== HTTP_POST
) {
973 parser
->method
= HTTP_PROPFIND
; /* or HTTP_PROPPATCH */
974 } else if (ch
== 'U') {
975 parser
->method
= HTTP_PUT
; /* or HTTP_PURGE */
976 } else if (ch
== 'A') {
977 parser
->method
= HTTP_PATCH
; /* or HTTP_PAUSE */
978 } else if (ch
== 'L') {
979 parser
->method
= HTTP_PLAY
;
983 } else if (parser
->index
== 2) {
984 if (parser
->method
== HTTP_PUT
) {
985 if (ch
== 'R') parser
->method
= HTTP_PURGE
;
986 } else if (parser
->method
== HTTP_PATCH
) {
987 if (ch
== 'U') parser
->method
= HTTP_PAUSE
;
988 } else if (parser
->method
== HTTP_REPORT
&& ch
== 'D') {
989 parser
->method
= HTTP_REDIRECT
;
990 } else if (parser
->method
== HTTP_REPORT
&& ch
== 'C') {
991 parser
->method
= HTTP_RECORD
;
992 } else if (parser
->method
== HTTP_SEARCH
) {
993 if (ch
== 'T') parser
->method
= HTTP_SETUP
; /* or HTTP_SET_PARAMETER */
994 } else if (parser
->method
== HTTP_UNLOCK
) {
995 if (ch
== 'S') parser
->method
= HTTP_UNSUBSCRIBE
;
999 } else if (parser
->index
== 3 && parser
->method
== HTTP_SETUP
&& ch
== '_') {
1000 parser
->method
= HTTP_SET_PARAMETER
;
1001 } else if (parser
->index
== 4 && parser
->method
== HTTP_PROPFIND
&& ch
== 'P') {
1002 parser
->method
= HTTP_PROPPATCH
;
1004 SET_ERRNO(HPE_INVALID_METHOD
);
1012 case s_req_spaces_before_url
:
1014 if (ch
== ' ') break;
1017 if (parser
->method
== HTTP_CONNECT
) {
1018 parser
->state
= s_req_server_start
;
1021 parser
->state
= parse_url_char((enum state
)parser
->state
, ch
);
1022 if (parser
->state
== s_dead
) {
1023 SET_ERRNO(HPE_INVALID_URL
);
1031 case s_req_schema_slash
:
1032 case s_req_schema_slash_slash
:
1033 case s_req_server_start
:
1036 /* No whitespace allowed here */
1040 SET_ERRNO(HPE_INVALID_URL
);
1043 parser
->state
= parse_url_char((enum state
)parser
->state
, ch
);
1044 if (parser
->state
== s_dead
) {
1045 SET_ERRNO(HPE_INVALID_URL
);
1054 case s_req_server_with_at
:
1056 case s_req_query_string_start
:
1057 case s_req_query_string
:
1058 case s_req_fragment_start
:
1059 case s_req_fragment
:
1063 parser
->state
= s_req_http_start
;
1068 parser
->http_major
= 0;
1069 parser
->http_minor
= 9;
1070 parser
->state
= (ch
== CR
) ?
1071 s_req_line_almost_done
:
1072 s_header_field_start
;
1076 parser
->state
= parse_url_char((enum state
)parser
->state
, ch
);
1077 if (parser
->state
== s_dead
) {
1078 SET_ERRNO(HPE_INVALID_URL
);
1085 case s_req_http_start
:
1089 parser
->state
= s_req_http_H
;
1094 SET_ERRNO(HPE_INVALID_CONSTANT
);
1100 STRICT_CHECK(ch
!= 'T');
1101 parser
->state
= s_req_http_HT
;
1105 STRICT_CHECK(ch
!= 'T');
1106 parser
->state
= s_req_http_HTT
;
1109 case s_req_http_HTT
:
1110 STRICT_CHECK(ch
!= 'P');
1111 parser
->state
= s_req_http_HTTP
;
1114 case s_req_http_HTTP
:
1115 STRICT_CHECK(ch
!= '/');
1116 parser
->state
= s_req_first_http_major
;
1119 /* first digit of major HTTP version */
1120 case s_req_first_http_major
:
1121 if (ch
< '1' || ch
> '9') {
1122 SET_ERRNO(HPE_INVALID_VERSION
);
1126 parser
->http_major
= ch
- '0';
1127 parser
->state
= s_req_http_major
;
1130 /* major HTTP version or dot */
1131 case s_req_http_major
:
1134 parser
->state
= s_req_first_http_minor
;
1139 SET_ERRNO(HPE_INVALID_VERSION
);
1143 parser
->http_major
*= 10;
1144 parser
->http_major
+= ch
- '0';
1146 if (parser
->http_major
> 999) {
1147 SET_ERRNO(HPE_INVALID_VERSION
);
1154 /* first digit of minor HTTP version */
1155 case s_req_first_http_minor
:
1157 SET_ERRNO(HPE_INVALID_VERSION
);
1161 parser
->http_minor
= ch
- '0';
1162 parser
->state
= s_req_http_minor
;
1165 /* minor HTTP version or end of request line */
1166 case s_req_http_minor
:
1169 parser
->state
= s_req_line_almost_done
;
1174 parser
->state
= s_header_field_start
;
1178 /* XXX allow spaces after digit? */
1181 SET_ERRNO(HPE_INVALID_VERSION
);
1185 parser
->http_minor
*= 10;
1186 parser
->http_minor
+= ch
- '0';
1188 if (parser
->http_minor
> 999) {
1189 SET_ERRNO(HPE_INVALID_VERSION
);
1196 /* end of request line */
1197 case s_req_line_almost_done
:
1200 SET_ERRNO(HPE_LF_EXPECTED
);
1204 parser
->state
= s_header_field_start
;
1208 case s_header_field_start
:
1211 parser
->state
= s_headers_almost_done
;
1216 /* they might be just sending \n instead of \r\n so this would be
1217 * the second \n to denote the end of headers*/
1218 parser
->state
= s_headers_almost_done
;
1219 goto reexecute_byte
;
1225 SET_ERRNO(HPE_INVALID_HEADER_TOKEN
);
1232 parser
->state
= s_header_field
;
1236 parser
->header_state
= h_C
;
1240 parser
->header_state
= h_matching_proxy_connection
;
1244 parser
->header_state
= h_matching_transfer_encoding
;
1248 parser
->header_state
= h_matching_upgrade
;
1252 parser
->header_state
= h_general
;
1258 case s_header_field
:
1263 switch (parser
->header_state
) {
1269 parser
->header_state
= (c
== 'o' ? h_CO
: h_general
);
1274 parser
->header_state
= (c
== 'n' ? h_CON
: h_general
);
1281 parser
->header_state
= h_matching_connection
;
1284 parser
->header_state
= h_matching_content_length
;
1287 parser
->header_state
= h_general
;
1294 case h_matching_connection
:
1296 if (parser
->index
> sizeof(CONNECTION
)-1
1297 || c
!= CONNECTION
[parser
->index
]) {
1298 parser
->header_state
= h_general
;
1299 } else if (parser
->index
== sizeof(CONNECTION
)-2) {
1300 parser
->header_state
= h_connection
;
1304 /* proxy-connection */
1306 case h_matching_proxy_connection
:
1308 if (parser
->index
> sizeof(PROXY_CONNECTION
)-1
1309 || c
!= PROXY_CONNECTION
[parser
->index
]) {
1310 parser
->header_state
= h_general
;
1311 } else if (parser
->index
== sizeof(PROXY_CONNECTION
)-2) {
1312 parser
->header_state
= h_connection
;
1316 /* content-length */
1318 case h_matching_content_length
:
1320 if (parser
->index
> sizeof(CONTENT_LENGTH
)-1
1321 || c
!= CONTENT_LENGTH
[parser
->index
]) {
1322 parser
->header_state
= h_general
;
1323 } else if (parser
->index
== sizeof(CONTENT_LENGTH
)-2) {
1324 parser
->header_state
= h_content_length
;
1328 /* transfer-encoding */
1330 case h_matching_transfer_encoding
:
1332 if (parser
->index
> sizeof(TRANSFER_ENCODING
)-1
1333 || c
!= TRANSFER_ENCODING
[parser
->index
]) {
1334 parser
->header_state
= h_general
;
1335 } else if (parser
->index
== sizeof(TRANSFER_ENCODING
)-2) {
1336 parser
->header_state
= h_transfer_encoding
;
1342 case h_matching_upgrade
:
1344 if (parser
->index
> sizeof(UPGRADE
)-1
1345 || c
!= UPGRADE
[parser
->index
]) {
1346 parser
->header_state
= h_general
;
1347 } else if (parser
->index
== sizeof(UPGRADE
)-2) {
1348 parser
->header_state
= h_upgrade
;
1353 case h_content_length
:
1354 case h_transfer_encoding
:
1356 if (ch
!= ' ') parser
->header_state
= h_general
;
1360 assert(0 && "Unknown header_state");
1367 parser
->state
= s_header_value_start
;
1368 CALLBACK_DATA(header_field
);
1373 parser
->state
= s_header_almost_done
;
1374 CALLBACK_DATA(header_field
);
1379 parser
->state
= s_header_field_start
;
1380 CALLBACK_DATA(header_field
);
1384 SET_ERRNO(HPE_INVALID_HEADER_TOKEN
);
1388 case s_header_value_start
:
1390 if (ch
== ' ' || ch
== '\t') break;
1394 parser
->state
= s_header_value
;
1398 parser
->header_state
= h_general
;
1399 parser
->state
= s_header_almost_done
;
1400 CALLBACK_DATA(header_value
);
1405 parser
->state
= s_header_field_start
;
1406 CALLBACK_DATA(header_value
);
1412 switch (parser
->header_state
) {
1414 parser
->flags
|= F_UPGRADE
;
1415 parser
->header_state
= h_general
;
1418 case h_transfer_encoding
:
1419 /* looking for 'Transfer-Encoding: chunked' */
1421 parser
->header_state
= h_matching_transfer_encoding_chunked
;
1423 parser
->header_state
= h_general
;
1427 case h_content_length
:
1429 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH
);
1433 parser
->content_length
= ch
- '0';
1437 /* looking for 'Connection: keep-alive' */
1439 parser
->header_state
= h_matching_connection_keep_alive
;
1440 /* looking for 'Connection: close' */
1441 } else if (c
== 'c') {
1442 parser
->header_state
= h_matching_connection_close
;
1444 parser
->header_state
= h_general
;
1449 parser
->header_state
= h_general
;
1455 case s_header_value
:
1459 parser
->state
= s_header_almost_done
;
1460 CALLBACK_DATA(header_value
);
1465 parser
->state
= s_header_almost_done
;
1466 CALLBACK_DATA_NOADVANCE(header_value
);
1467 goto reexecute_byte
;
1472 switch (parser
->header_state
) {
1477 case h_transfer_encoding
:
1478 assert(0 && "Shouldn't get here.");
1481 case h_content_length
:
1485 if (ch
== ' ') break;
1488 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH
);
1492 t
= parser
->content_length
;
1497 if (t
< parser
->content_length
|| t
== ULLONG_MAX
) {
1498 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH
);
1502 parser
->content_length
= t
;
1506 /* Transfer-Encoding: chunked */
1507 case h_matching_transfer_encoding_chunked
:
1509 if (parser
->index
> sizeof(CHUNKED
)-1
1510 || c
!= CHUNKED
[parser
->index
]) {
1511 parser
->header_state
= h_general
;
1512 } else if (parser
->index
== sizeof(CHUNKED
)-2) {
1513 parser
->header_state
= h_transfer_encoding_chunked
;
1517 /* looking for 'Connection: keep-alive' */
1518 case h_matching_connection_keep_alive
:
1520 if (parser
->index
> sizeof(KEEP_ALIVE
)-1
1521 || c
!= KEEP_ALIVE
[parser
->index
]) {
1522 parser
->header_state
= h_general
;
1523 } else if (parser
->index
== sizeof(KEEP_ALIVE
)-2) {
1524 parser
->header_state
= h_connection_keep_alive
;
1528 /* looking for 'Connection: close' */
1529 case h_matching_connection_close
:
1531 if (parser
->index
> sizeof(CLOSE
)-1 || c
!= CLOSE
[parser
->index
]) {
1532 parser
->header_state
= h_general
;
1533 } else if (parser
->index
== sizeof(CLOSE
)-2) {
1534 parser
->header_state
= h_connection_close
;
1538 case h_transfer_encoding_chunked
:
1539 case h_connection_keep_alive
:
1540 case h_connection_close
:
1541 if (ch
!= ' ') parser
->header_state
= h_general
;
1545 parser
->state
= s_header_value
;
1546 parser
->header_state
= h_general
;
1552 case s_header_almost_done
:
1554 STRICT_CHECK(ch
!= LF
);
1556 parser
->state
= s_header_value_lws
;
1558 switch (parser
->header_state
) {
1559 case h_connection_keep_alive
:
1560 parser
->flags
|= F_CONNECTION_KEEP_ALIVE
;
1562 case h_connection_close
:
1563 parser
->flags
|= F_CONNECTION_CLOSE
;
1565 case h_transfer_encoding_chunked
:
1566 parser
->flags
|= F_CHUNKED
;
1575 case s_header_value_lws
:
1577 if (ch
== ' ' || ch
== '\t')
1578 parser
->state
= s_header_value_start
;
1581 parser
->state
= s_header_field_start
;
1582 goto reexecute_byte
;
1587 case s_headers_almost_done
:
1589 STRICT_CHECK(ch
!= LF
);
1591 if (parser
->flags
& F_TRAILING
) {
1592 /* End of a chunked request */
1593 parser
->state
= NEW_MESSAGE();
1594 CALLBACK_NOTIFY(message_complete
);
1598 parser
->state
= s_headers_done
;
1600 /* Set this here so that on_headers_complete() callbacks can see it */
1602 (parser
->flags
& F_UPGRADE
|| parser
->method
== HTTP_CONNECT
);
1604 /* Here we call the headers_complete callback. This is somewhat
1605 * different than other callbacks because if the user returns 1, we
1606 * will interpret that as saying that this message has no body. This
1607 * is needed for the annoying case of recieving a response to a HEAD
1610 * We'd like to use CALLBACK_NOTIFY_NOADVANCE() here but we cannot, so
1611 * we have to simulate it by handling a change in errno below.
1613 if (settings
->on_headers_complete
) {
1614 switch (settings
->on_headers_complete(parser
)) {
1619 parser
->flags
|= F_SKIPBODY
;
1623 SET_ERRNO(HPE_CB_headers_complete
);
1624 return p
- data
; /* Error */
1628 if (HTTP_PARSER_ERRNO(parser
) != HPE_OK
) {
1632 goto reexecute_byte
;
1635 case s_headers_done
:
1637 STRICT_CHECK(ch
!= LF
);
1641 /* Exit, the rest of the connect is in a different protocol. */
1642 if (parser
->upgrade
) {
1643 parser
->state
= NEW_MESSAGE();
1644 CALLBACK_NOTIFY(message_complete
);
1645 return (p
- data
) + 1;
1648 if (parser
->flags
& F_SKIPBODY
) {
1649 parser
->state
= NEW_MESSAGE();
1650 CALLBACK_NOTIFY(message_complete
);
1651 } else if (parser
->flags
& F_CHUNKED
) {
1652 /* chunked encoding - ignore Content-Length header */
1653 parser
->state
= s_chunk_size_start
;
1655 if (parser
->content_length
== 0) {
1656 /* Content-Length header given but zero: Content-Length: 0\r\n */
1657 parser
->state
= NEW_MESSAGE();
1658 CALLBACK_NOTIFY(message_complete
);
1659 } else if (parser
->content_length
!= ULLONG_MAX
) {
1660 /* Content-Length header given and non-zero */
1661 parser
->state
= s_body_identity
;
1663 if (parser
->type
== HTTP_REQUEST
||
1664 !http_message_needs_eof(parser
)) {
1665 /* Assume content-length 0 - read the next */
1666 parser
->state
= NEW_MESSAGE();
1667 CALLBACK_NOTIFY(message_complete
);
1669 /* Read body until EOF */
1670 parser
->state
= s_body_identity_eof
;
1678 case s_body_identity
:
1680 uint64_t to_read
= MIN(parser
->content_length
,
1681 (uint64_t) ((data
+ len
) - p
));
1683 assert(parser
->content_length
!= 0
1684 && parser
->content_length
!= ULLONG_MAX
);
1686 /* The difference between advancing content_length and p is because
1687 * the latter will automaticaly advance on the next loop iteration.
1688 * Further, if content_length ends up at 0, we want to see the last
1689 * byte again for our message complete callback.
1692 parser
->content_length
-= to_read
;
1695 if (parser
->content_length
== 0) {
1696 parser
->state
= s_message_done
;
1698 /* Mimic CALLBACK_DATA_NOADVANCE() but with one extra byte.
1700 * The alternative to doing this is to wait for the next byte to
1701 * trigger the data callback, just as in every other case. The
1702 * problem with this is that this makes it difficult for the test
1703 * harness to distinguish between complete-on-EOF and
1704 * complete-on-length. It's not clear that this distinction is
1705 * important for applications, but let's keep it for now.
1707 CALLBACK_DATA_(body
, p
- body_mark
+ 1, p
- data
);
1708 goto reexecute_byte
;
1714 /* read until EOF */
1715 case s_body_identity_eof
:
1721 case s_message_done
:
1722 parser
->state
= NEW_MESSAGE();
1723 CALLBACK_NOTIFY(message_complete
);
1726 case s_chunk_size_start
:
1728 assert(parser
->nread
== 1);
1729 assert(parser
->flags
& F_CHUNKED
);
1731 unhex_val
= unhex
[(unsigned char)ch
];
1732 if (unhex_val
== -1) {
1733 SET_ERRNO(HPE_INVALID_CHUNK_SIZE
);
1737 parser
->content_length
= unhex_val
;
1738 parser
->state
= s_chunk_size
;
1746 assert(parser
->flags
& F_CHUNKED
);
1749 parser
->state
= s_chunk_size_almost_done
;
1753 unhex_val
= unhex
[(unsigned char)ch
];
1755 if (unhex_val
== -1) {
1756 if (ch
== ';' || ch
== ' ') {
1757 parser
->state
= s_chunk_parameters
;
1761 SET_ERRNO(HPE_INVALID_CHUNK_SIZE
);
1765 t
= parser
->content_length
;
1770 if (t
< parser
->content_length
|| t
== ULLONG_MAX
) {
1771 SET_ERRNO(HPE_INVALID_CONTENT_LENGTH
);
1775 parser
->content_length
= t
;
1779 case s_chunk_parameters
:
1781 assert(parser
->flags
& F_CHUNKED
);
1782 /* just ignore this shit. TODO check for overflow */
1784 parser
->state
= s_chunk_size_almost_done
;
1790 case s_chunk_size_almost_done
:
1792 assert(parser
->flags
& F_CHUNKED
);
1793 STRICT_CHECK(ch
!= LF
);
1797 if (parser
->content_length
== 0) {
1798 parser
->flags
|= F_TRAILING
;
1799 parser
->state
= s_header_field_start
;
1801 parser
->state
= s_chunk_data
;
1808 uint64_t to_read
= MIN(parser
->content_length
,
1809 (uint64_t) ((data
+ len
) - p
));
1811 assert(parser
->flags
& F_CHUNKED
);
1812 assert(parser
->content_length
!= 0
1813 && parser
->content_length
!= ULLONG_MAX
);
1815 /* See the explanation in s_body_identity for why the content
1816 * length and data pointers are managed this way.
1819 parser
->content_length
-= to_read
;
1822 if (parser
->content_length
== 0) {
1823 parser
->state
= s_chunk_data_almost_done
;
1829 case s_chunk_data_almost_done
:
1830 assert(parser
->flags
& F_CHUNKED
);
1831 assert(parser
->content_length
== 0);
1832 STRICT_CHECK(ch
!= CR
);
1833 parser
->state
= s_chunk_data_done
;
1834 CALLBACK_DATA(body
);
1837 case s_chunk_data_done
:
1838 assert(parser
->flags
& F_CHUNKED
);
1839 STRICT_CHECK(ch
!= LF
);
1841 parser
->state
= s_chunk_size_start
;
1845 assert(0 && "unhandled state");
1846 SET_ERRNO(HPE_INVALID_INTERNAL_STATE
);
1851 /* Run callbacks for any marks that we have leftover after we ran our of
1852 * bytes. There should be at most one of these set, so it's OK to invoke
1853 * them in series (unset marks will not result in callbacks).
1855 * We use the NOADVANCE() variety of callbacks here because 'p' has already
1856 * overflowed 'data' and this allows us to correct for the off-by-one that
1857 * we'd otherwise have (since CALLBACK_DATA() is meant to be run with a 'p'
1858 * value that's in-bounds).
1861 assert(((header_field_mark
? 1 : 0) +
1862 (header_value_mark
? 1 : 0) +
1863 (url_mark
? 1 : 0) +
1864 (body_mark
? 1 : 0)) <= 1);
1866 CALLBACK_DATA_NOADVANCE(header_field
);
1867 CALLBACK_DATA_NOADVANCE(header_value
);
1868 CALLBACK_DATA_NOADVANCE(url
);
1869 CALLBACK_DATA_NOADVANCE(body
);
1874 if (HTTP_PARSER_ERRNO(parser
) == HPE_OK
) {
1875 SET_ERRNO(HPE_UNKNOWN
);
1882 /* Does the parser need to see an EOF to find the end of the message? */
1884 http_message_needs_eof (const http_parser
*parser
)
1886 if (parser
->type
== HTTP_REQUEST
) {
1890 /* See RFC 2616 section 4.4 */
1891 if (parser
->status_code
/ 100 == 1 || /* 1xx e.g. Continue */
1892 parser
->status_code
== 204 || /* No Content */
1893 parser
->status_code
== 304 || /* Not Modified */
1894 parser
->flags
& F_SKIPBODY
) { /* response to a HEAD request */
1898 if ((parser
->flags
& F_CHUNKED
) || parser
->content_length
!= ULLONG_MAX
) {
1907 http_should_keep_alive (const http_parser
*parser
)
1909 if (parser
->http_major
> 0 && parser
->http_minor
> 0) {
1911 if (parser
->flags
& F_CONNECTION_CLOSE
) {
1915 /* HTTP/1.0 or earlier */
1916 if (!(parser
->flags
& F_CONNECTION_KEEP_ALIVE
)) {
1921 return !http_message_needs_eof(parser
);
1926 http_method_str (enum http_method m
)
1928 return ELEM_AT(method_strings
, m
, "<unknown>");
1933 http_parser_init (http_parser
*parser
, enum http_parser_type t
)
1935 void *data
= parser
->data
; /* preserve application data */
1936 memset(parser
, 0, sizeof(*parser
));
1937 parser
->data
= data
;
1939 parser
->state
= (t
== HTTP_REQUEST
? s_start_req
: (t
== HTTP_RESPONSE
? s_start_res
: s_start_req_or_res
));
1940 parser
->http_errno
= HPE_OK
;
1944 http_errno_name(enum http_errno err
) {
1945 assert(err
< (sizeof(http_strerror_tab
)/sizeof(http_strerror_tab
[0])));
1946 return http_strerror_tab
[err
].name
;
1950 http_errno_description(enum http_errno err
) {
1951 assert(err
< (sizeof(http_strerror_tab
)/sizeof(http_strerror_tab
[0])));
1952 return http_strerror_tab
[err
].description
;
1955 static enum http_host_state
1956 http_parse_host_char(enum http_host_state s
, const char ch
) {
1958 case s_http_userinfo
:
1959 case s_http_userinfo_start
:
1961 return s_http_host_start
;
1964 if (IS_USERINFO_CHAR(ch
)) {
1965 return s_http_userinfo
;
1969 case s_http_host_start
:
1971 return s_http_host_v6_start
;
1974 if (IS_HOST_CHAR(ch
)) {
1981 if (IS_HOST_CHAR(ch
)) {
1986 case s_http_host_v6_end
:
1988 return s_http_host_port_start
;
1993 case s_http_host_v6
:
1995 return s_http_host_v6_end
;
1999 case s_http_host_v6_start
:
2000 if (IS_HEX(ch
) || ch
== ':') {
2001 return s_http_host_v6
;
2006 case s_http_host_port
:
2007 case s_http_host_port_start
:
2009 return s_http_host_port
;
2017 return s_http_host_dead
;
2021 http_parse_host(const char * buf
, struct http_parser_url
*u
, int found_at
) {
2022 enum http_host_state s
;
2025 size_t buflen
= u
->field_data
[UF_HOST
].off
+ u
->field_data
[UF_HOST
].len
;
2027 u
->field_data
[UF_HOST
].len
= 0;
2029 s
= found_at
? s_http_userinfo_start
: s_http_host_start
;
2031 for (p
= buf
+ u
->field_data
[UF_HOST
].off
; p
< buf
+ buflen
; p
++) {
2032 enum http_host_state new_s
= http_parse_host_char(s
, *p
);
2034 if (new_s
== s_http_host_dead
) {
2040 if (s
!= s_http_host
) {
2041 u
->field_data
[UF_HOST
].off
= p
- buf
;
2043 u
->field_data
[UF_HOST
].len
++;
2046 case s_http_host_v6
:
2047 if (s
!= s_http_host_v6
) {
2048 u
->field_data
[UF_HOST
].off
= p
- buf
;
2050 u
->field_data
[UF_HOST
].len
++;
2053 case s_http_host_port
:
2054 if (s
!= s_http_host_port
) {
2055 u
->field_data
[UF_PORT
].off
= p
- buf
;
2056 u
->field_data
[UF_PORT
].len
= 0;
2057 u
->field_set
|= (1 << UF_PORT
);
2059 u
->field_data
[UF_PORT
].len
++;
2062 case s_http_userinfo
:
2063 if (s
!= s_http_userinfo
) {
2064 u
->field_data
[UF_USERINFO
].off
= p
- buf
;
2065 u
->field_data
[UF_USERINFO
].len
= 0;
2066 u
->field_set
|= (1 << UF_USERINFO
);
2068 u
->field_data
[UF_USERINFO
].len
++;
2077 /* Make sure we don't end somewhere unexpected */
2079 case s_http_host_start
:
2080 case s_http_host_v6_start
:
2081 case s_http_host_v6
:
2082 case s_http_host_port_start
:
2083 case s_http_userinfo
:
2084 case s_http_userinfo_start
:
2094 http_parser_parse_url(const char *buf
, size_t buflen
, int is_connect
,
2095 struct http_parser_url
*u
)
2099 enum http_parser_url_fields uf
, old_uf
;
2102 u
->port
= u
->field_set
= 0;
2103 s
= is_connect
? s_req_server_start
: s_req_spaces_before_url
;
2104 uf
= old_uf
= UF_MAX
;
2106 for (p
= buf
; p
< buf
+ buflen
; p
++) {
2107 s
= parse_url_char(s
, *p
);
2109 /* Figure out the next field that we're operating on */
2114 /* Skip delimeters */
2115 case s_req_schema_slash
:
2116 case s_req_schema_slash_slash
:
2117 case s_req_server_start
:
2118 case s_req_query_string_start
:
2119 case s_req_fragment_start
:
2126 case s_req_server_with_at
:
2138 case s_req_query_string
:
2142 case s_req_fragment
:
2147 assert(!"Unexpected state");
2151 /* Nothing's changed; soldier on */
2153 u
->field_data
[uf
].len
++;
2157 u
->field_data
[uf
].off
= p
- buf
;
2158 u
->field_data
[uf
].len
= 1;
2160 u
->field_set
|= (1 << uf
);
2164 /* host must be present if there is a schema */
2165 /* parsing http:///toto will fail */
2166 if ((u
->field_set
& ((1 << UF_SCHEMA
) | (1 << UF_HOST
))) != 0) {
2167 if (http_parse_host(buf
, u
, found_at
) != 0) {
2172 /* CONNECT requests can only contain "hostname:port" */
2173 if (is_connect
&& u
->field_set
!= ((1 << UF_HOST
)|(1 << UF_PORT
))) {
2177 if (u
->field_set
& (1 << UF_PORT
)) {
2178 /* Don't bother with endp; we've already validated the string */
2179 unsigned long v
= strtoul(buf
+ u
->field_data
[UF_PORT
].off
, NULL
, 10);
2181 /* Ports have a max value of 2^16 */
2186 u
->port
= (uint16_t) v
;
2193 http_parser_pause(http_parser
*parser
, int paused
) {
2194 /* Users should only be pausing/unpausing a parser that is not in an error
2195 * state. In non-debug builds, there's not much that we can do about this
2196 * other than ignore it.
2198 if (HTTP_PARSER_ERRNO(parser
) == HPE_OK
||
2199 HTTP_PARSER_ERRNO(parser
) == HPE_PAUSED
) {
2200 SET_ERRNO((paused
) ? HPE_PAUSED
: HPE_OK
);
2202 assert(0 && "Attempting to pause parser in error state");
2207 http_body_is_final(const struct http_parser
*parser
) {
2208 return parser
->state
== s_message_done
;