Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-http by
http_parser.h
00001 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy 00004 * of this software and associated documentation files (the "Software"), to 00005 * deal in the Software without restriction, including without limitation the 00006 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 00007 * sell copies of the Software, and to permit persons to whom the Software is 00008 * furnished to do so, subject to the following conditions: 00009 * 00010 * The above copyright notice and this permission notice shall be included in 00011 * all copies or substantial portions of the Software. 00012 * 00013 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00014 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00015 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00016 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00017 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 00018 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 00019 * IN THE SOFTWARE. 00020 */ 00021 #ifndef http_parser_h 00022 #define http_parser_h 00023 #ifdef __cplusplus 00024 extern "C" { 00025 #endif 00026 00027 /* Also update SONAME in the Makefile whenever you change these. */ 00028 #define HTTP_PARSER_VERSION_MAJOR 2 00029 #define HTTP_PARSER_VERSION_MINOR 7 00030 #define HTTP_PARSER_VERSION_PATCH 1 00031 00032 typedef unsigned int size_t; 00033 00034 #if defined(_WIN32) && !defined(__MINGW32__) && \ 00035 (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) 00036 #include <BaseTsd.h> 00037 #include <stddef.h> 00038 typedef __int8 int8_t; 00039 typedef unsigned __int8 uint8_t; 00040 typedef __int16 int16_t; 00041 typedef unsigned __int16 uint16_t; 00042 typedef __int32 int32_t; 00043 typedef unsigned __int32 uint32_t; 00044 typedef __int64 int64_t; 00045 typedef unsigned __int64 uint64_t; 00046 #else 00047 #include <stdint.h> 00048 #endif 00049 00050 /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run 00051 * faster 00052 */ 00053 #ifndef HTTP_PARSER_STRICT 00054 # define HTTP_PARSER_STRICT 1 00055 #endif 00056 00057 /* Maximium header size allowed. If the macro is not defined 00058 * before including this header then the default is used. To 00059 * change the maximum header size, define the macro in the build 00060 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove 00061 * the effective limit on the size of the header, define the macro 00062 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) 00063 */ 00064 #ifndef HTTP_MAX_HEADER_SIZE 00065 # define HTTP_MAX_HEADER_SIZE (80*1024) 00066 #endif 00067 00068 typedef struct http_parser http_parser; 00069 typedef struct http_parser_settings http_parser_settings; 00070 00071 00072 /* Callbacks should return non-zero to indicate an error. The parser will 00073 * then halt execution. 00074 * 00075 * The one exception is on_headers_complete. In a HTTP_RESPONSE parser 00076 * returning '1' from on_headers_complete will tell the parser that it 00077 * should not expect a body. This is used when receiving a response to a 00078 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: 00079 * chunked' headers that indicate the presence of a body. 00080 * 00081 * Returning `2` from on_headers_complete will tell parser that it should not 00082 * expect neither a body nor any futher responses on this connection. This is 00083 * useful for handling responses to a CONNECT request which may not contain 00084 * `Upgrade` or `Connection: upgrade` headers. 00085 * 00086 * http_data_cb does not return data chunks. It will be called arbitrarily 00087 * many times for each string. E.G. you might get 10 callbacks for "on_url" 00088 * each providing just a few characters more data. 00089 */ 00090 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length); 00091 typedef int (*http_cb) (http_parser*); 00092 00093 00094 /* Status Codes */ 00095 #define HTTP_STATUS_MAP(XX) \ 00096 XX(100, CONTINUE, Continue) \ 00097 XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \ 00098 XX(102, PROCESSING, Processing) \ 00099 XX(200, OK, OK) \ 00100 XX(201, CREATED, Created) \ 00101 XX(202, ACCEPTED, Accepted) \ 00102 XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \ 00103 XX(204, NO_CONTENT, No Content) \ 00104 XX(205, RESET_CONTENT, Reset Content) \ 00105 XX(206, PARTIAL_CONTENT, Partial Content) \ 00106 XX(207, MULTI_STATUS, Multi-Status) \ 00107 XX(208, ALREADY_REPORTED, Already Reported) \ 00108 XX(226, IM_USED, IM Used) \ 00109 XX(300, MULTIPLE_CHOICES, Multiple Choices) \ 00110 XX(301, MOVED_PERMANENTLY, Moved Permanently) \ 00111 XX(302, FOUND, Found) \ 00112 XX(303, SEE_OTHER, See Other) \ 00113 XX(304, NOT_MODIFIED, Not Modified) \ 00114 XX(305, USE_PROXY, Use Proxy) \ 00115 XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \ 00116 XX(308, PERMANENT_REDIRECT, Permanent Redirect) \ 00117 XX(400, BAD_REQUEST, Bad Request) \ 00118 XX(401, UNAUTHORIZED, Unauthorized) \ 00119 XX(402, PAYMENT_REQUIRED, Payment Required) \ 00120 XX(403, FORBIDDEN, Forbidden) \ 00121 XX(404, NOT_FOUND, Not Found) \ 00122 XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \ 00123 XX(406, NOT_ACCEPTABLE, Not Acceptable) \ 00124 XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \ 00125 XX(408, REQUEST_TIMEOUT, Request Timeout) \ 00126 XX(409, CONFLICT, Conflict) \ 00127 XX(410, GONE, Gone) \ 00128 XX(411, LENGTH_REQUIRED, Length Required) \ 00129 XX(412, PRECONDITION_FAILED, Precondition Failed) \ 00130 XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \ 00131 XX(414, URI_TOO_LONG, URI Too Long) \ 00132 XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \ 00133 XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \ 00134 XX(417, EXPECTATION_FAILED, Expectation Failed) \ 00135 XX(421, MISDIRECTED_REQUEST, Misdirected Request) \ 00136 XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \ 00137 XX(423, LOCKED, Locked) \ 00138 XX(424, FAILED_DEPENDENCY, Failed Dependency) \ 00139 XX(426, UPGRADE_REQUIRED, Upgrade Required) \ 00140 XX(428, PRECONDITION_REQUIRED, Precondition Required) \ 00141 XX(429, TOO_MANY_REQUESTS, Too Many Requests) \ 00142 XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \ 00143 XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \ 00144 XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \ 00145 XX(501, NOT_IMPLEMENTED, Not Implemented) \ 00146 XX(502, BAD_GATEWAY, Bad Gateway) \ 00147 XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \ 00148 XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \ 00149 XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \ 00150 XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \ 00151 XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \ 00152 XX(508, LOOP_DETECTED, Loop Detected) \ 00153 XX(510, NOT_EXTENDED, Not Extended) \ 00154 XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \ 00155 00156 enum http_status 00157 { 00158 #define XX(num, name, string) HTTP_STATUS_##name = num, 00159 HTTP_STATUS_MAP(XX) 00160 #undef XX 00161 }; 00162 00163 00164 /* Request Methods */ 00165 #define HTTP_METHOD_MAP(XX) \ 00166 XX(0, DELETE, DELETE) \ 00167 XX(1, GET, GET) \ 00168 XX(2, HEAD, HEAD) \ 00169 XX(3, POST, POST) \ 00170 XX(4, PUT, PUT) \ 00171 /* pathological */ \ 00172 XX(5, CONNECT, CONNECT) \ 00173 XX(6, OPTIONS, OPTIONS) \ 00174 XX(7, TRACE, TRACE) \ 00175 /* WebDAV */ \ 00176 XX(8, COPY, COPY) \ 00177 XX(9, LOCK, LOCK) \ 00178 XX(10, MKCOL, MKCOL) \ 00179 XX(11, MOVE, MOVE) \ 00180 XX(12, PROPFIND, PROPFIND) \ 00181 XX(13, PROPPATCH, PROPPATCH) \ 00182 XX(14, SEARCH, SEARCH) \ 00183 XX(15, UNLOCK, UNLOCK) \ 00184 XX(16, BIND, BIND) \ 00185 XX(17, REBIND, REBIND) \ 00186 XX(18, UNBIND, UNBIND) \ 00187 XX(19, ACL, ACL) \ 00188 /* subversion */ \ 00189 XX(20, REPORT, REPORT) \ 00190 XX(21, MKACTIVITY, MKACTIVITY) \ 00191 XX(22, CHECKOUT, CHECKOUT) \ 00192 XX(23, MERGE, MERGE) \ 00193 /* upnp */ \ 00194 XX(24, MSEARCH, M-SEARCH) \ 00195 XX(25, NOTIFY, NOTIFY) \ 00196 XX(26, SUBSCRIBE, SUBSCRIBE) \ 00197 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 00198 /* RFC-5789 */ \ 00199 XX(28, PATCH, PATCH) \ 00200 XX(29, PURGE, PURGE) \ 00201 /* CalDAV */ \ 00202 XX(30, MKCALENDAR, MKCALENDAR) \ 00203 /* RFC-2068, section 19.6.1.2 */ \ 00204 XX(31, LINK, LINK) \ 00205 XX(32, UNLINK, UNLINK) \ 00206 00207 enum http_method 00208 { 00209 #define XX(num, name, string) HTTP_##name = num, 00210 HTTP_METHOD_MAP(XX) 00211 #undef XX 00212 }; 00213 00214 00215 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; 00216 00217 00218 /* Flag values for http_parser.flags field */ 00219 enum flags 00220 { F_CHUNKED = 1 << 0 00221 , F_CONNECTION_KEEP_ALIVE = 1 << 1 00222 , F_CONNECTION_CLOSE = 1 << 2 00223 , F_CONNECTION_UPGRADE = 1 << 3 00224 , F_TRAILING = 1 << 4 00225 , F_UPGRADE = 1 << 5 00226 , F_SKIPBODY = 1 << 6 00227 , F_CONTENTLENGTH = 1 << 7 00228 }; 00229 00230 00231 /* Map for errno-related constants 00232 * 00233 * The provided argument should be a macro that takes 2 arguments. 00234 */ 00235 #define HTTP_ERRNO_MAP(XX) \ 00236 /* No error */ \ 00237 XX(OK, "success") \ 00238 \ 00239 /* Callback-related errors */ \ 00240 XX(CB_message_begin, "the on_message_begin callback failed") \ 00241 XX(CB_url, "the on_url callback failed") \ 00242 XX(CB_header_field, "the on_header_field callback failed") \ 00243 XX(CB_header_value, "the on_header_value callback failed") \ 00244 XX(CB_headers_complete, "the on_headers_complete callback failed") \ 00245 XX(CB_body, "the on_body callback failed") \ 00246 XX(CB_message_complete, "the on_message_complete callback failed") \ 00247 XX(CB_status, "the on_status callback failed") \ 00248 XX(CB_chunk_header, "the on_chunk_header callback failed") \ 00249 XX(CB_chunk_complete, "the on_chunk_complete callback failed") \ 00250 \ 00251 /* Parsing-related errors */ \ 00252 XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \ 00253 XX(HEADER_OVERFLOW, \ 00254 "too many header bytes seen; overflow detected") \ 00255 XX(CLOSED_CONNECTION, \ 00256 "data received after completed connection: close message") \ 00257 XX(INVALID_VERSION, "invalid HTTP version") \ 00258 XX(INVALID_STATUS, "invalid HTTP status code") \ 00259 XX(INVALID_METHOD, "invalid HTTP method") \ 00260 XX(INVALID_URL, "invalid URL") \ 00261 XX(INVALID_HOST, "invalid host") \ 00262 XX(INVALID_PORT, "invalid port") \ 00263 XX(INVALID_PATH, "invalid path") \ 00264 XX(INVALID_QUERY_STRING, "invalid query string") \ 00265 XX(INVALID_FRAGMENT, "invalid fragment") \ 00266 XX(LF_EXPECTED, "LF character expected") \ 00267 XX(INVALID_HEADER_TOKEN, "invalid character in header") \ 00268 XX(INVALID_CONTENT_LENGTH, \ 00269 "invalid character in content-length header") \ 00270 XX(UNEXPECTED_CONTENT_LENGTH, \ 00271 "unexpected content-length header") \ 00272 XX(INVALID_CHUNK_SIZE, \ 00273 "invalid character in chunk size header") \ 00274 XX(INVALID_CONSTANT, "invalid constant string") \ 00275 XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\ 00276 XX(STRICT, "strict mode assertion failed") \ 00277 XX(PAUSED, "parser is paused") \ 00278 XX(UNKNOWN, "an unknown error occurred") 00279 00280 00281 /* Define HPE_* values for each errno value above */ 00282 #define HTTP_ERRNO_GEN(n, s) HPE_##n, 00283 enum http_errno { 00284 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) 00285 }; 00286 #undef HTTP_ERRNO_GEN 00287 00288 00289 /* Get an http_errno value from an http_parser */ 00290 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) 00291 00292 00293 struct http_parser { 00294 /** PRIVATE **/ 00295 unsigned int type : 2; /* enum http_parser_type */ 00296 unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */ 00297 unsigned int state : 7; /* enum state from http_parser.c */ 00298 unsigned int header_state : 7; /* enum header_state from http_parser.c */ 00299 unsigned int index : 7; /* index into current matcher */ 00300 unsigned int lenient_http_headers : 1; 00301 00302 uint32_t nread; /* # bytes read in various scenarios */ 00303 uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ 00304 00305 /** READ-ONLY **/ 00306 unsigned short http_major; 00307 unsigned short http_minor; 00308 unsigned int status_code : 16; /* responses only */ 00309 unsigned int method : 8; /* requests only */ 00310 unsigned int http_errno : 7; 00311 00312 /* 1 = Upgrade header was present and the parser has exited because of that. 00313 * 0 = No upgrade header present. 00314 * Should be checked when http_parser_execute() returns in addition to 00315 * error checking. 00316 */ 00317 unsigned int upgrade : 1; 00318 00319 /** PUBLIC **/ 00320 void *data; /* A pointer to get hook to the "connection" or "socket" object */ 00321 }; 00322 00323 00324 struct http_parser_settings { 00325 http_cb on_message_begin; 00326 http_data_cb on_url; 00327 http_data_cb on_status; 00328 http_data_cb on_header_field; 00329 http_data_cb on_header_value; 00330 http_cb on_headers_complete; 00331 http_data_cb on_body; 00332 http_cb on_message_complete; 00333 /* When on_chunk_header is called, the current chunk length is stored 00334 * in parser->content_length. 00335 */ 00336 http_cb on_chunk_header; 00337 http_cb on_chunk_complete; 00338 }; 00339 00340 00341 enum http_parser_url_fields 00342 { UF_SCHEMA = 0 00343 , UF_HOST = 1 00344 , UF_PORT = 2 00345 , UF_PATH = 3 00346 , UF_QUERY = 4 00347 , UF_FRAGMENT = 5 00348 , UF_USERINFO = 6 00349 , UF_MAX = 7 00350 }; 00351 00352 00353 /* Result structure for http_parser_parse_url(). 00354 * 00355 * Callers should index into field_data[] with UF_* values iff field_set 00356 * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and 00357 * because we probably have padding left over), we convert any port to 00358 * a uint16_t. 00359 */ 00360 struct http_parser_url { 00361 uint16_t field_set; /* Bitmask of (1 << UF_*) values */ 00362 uint16_t port; /* Converted UF_PORT string */ 00363 00364 struct { 00365 uint16_t off; /* Offset into buffer in which field starts */ 00366 uint16_t len; /* Length of run in buffer */ 00367 } field_data[UF_MAX]; 00368 }; 00369 00370 00371 /* Returns the library version. Bits 16-23 contain the major version number, 00372 * bits 8-15 the minor version number and bits 0-7 the patch level. 00373 * Usage example: 00374 * 00375 * unsigned long version = http_parser_version(); 00376 * unsigned major = (version >> 16) & 255; 00377 * unsigned minor = (version >> 8) & 255; 00378 * unsigned patch = version & 255; 00379 * printf("http_parser v%u.%u.%u\n", major, minor, patch); 00380 */ 00381 unsigned long http_parser_version(void); 00382 00383 void http_parser_init(http_parser *parser, enum http_parser_type type); 00384 00385 00386 /* Initialize http_parser_settings members to 0 00387 */ 00388 void http_parser_settings_init(http_parser_settings *settings); 00389 00390 00391 /* Executes the parser. Returns number of parsed bytes. Sets 00392 * `parser->http_errno` on error. */ 00393 size_t http_parser_execute(http_parser *parser, 00394 const http_parser_settings *settings, 00395 const char *data, 00396 size_t len); 00397 00398 00399 /* If http_should_keep_alive() in the on_headers_complete or 00400 * on_message_complete callback returns 0, then this should be 00401 * the last message on the connection. 00402 * If you are the server, respond with the "Connection: close" header. 00403 * If you are the client, close the connection. 00404 */ 00405 int http_should_keep_alive(const http_parser *parser); 00406 00407 /* Returns a string version of the HTTP method. */ 00408 const char *http_method_str(enum http_method m); 00409 00410 /* Return a string name of the given error */ 00411 const char *http_errno_name(enum http_errno err); 00412 00413 /* Return a string description of the given error */ 00414 const char *http_errno_description(enum http_errno err); 00415 00416 /* Initialize all http_parser_url members to 0 */ 00417 void http_parser_url_init(struct http_parser_url *u); 00418 00419 /* Parse a URL; return nonzero on failure */ 00420 int http_parser_parse_url(const char *buf, size_t buflen, 00421 int is_connect, 00422 struct http_parser_url *u); 00423 00424 /* Pause or un-pause the parser; a nonzero value pauses */ 00425 void http_parser_pause(http_parser *parser, int paused); 00426 00427 /* Checks if this is the final chunk of the body. */ 00428 int http_body_is_final(const http_parser *parser); 00429 00430 #ifdef __cplusplus 00431 } 00432 #endif 00433 #endif
Generated on Fri Jul 22 2022 08:07:18 by
1.7.2
