1 /* SPDX-License-Identifier: MIT */ 2 3 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a copy 6 * of this software and associated documentation files (the "Software"), to 7 * deal in the Software without restriction, including without limitation the 8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9 * sell copies of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 #ifndef ZEPHYR_INCLUDE_NET_HTTP_PARSER_H_ 24 #define ZEPHYR_INCLUDE_NET_HTTP_PARSER_H_ 25 26 /* Also update SONAME in the Makefile whenever you change these. */ 27 #define HTTP_PARSER_VERSION_MAJOR 2 28 #define HTTP_PARSER_VERSION_MINOR 7 29 #define HTTP_PARSER_VERSION_PATCH 1 30 31 #include <sys/types.h> 32 #if defined(_WIN32) && !defined(__MINGW32__) && \ 33 (!defined(_MSC_VER) || _MSC_VER < 1600) && !defined(__WINE__) 34 #include <BaseTsd.h> 35 #include <stddef.h> 36 typedef __int8 int8_t; 37 typedef unsigned __int8 uint8_t; 38 typedef __int16 int16_t; 39 typedef unsigned __int16 uint16_t; 40 typedef __int32 int32_t; 41 typedef unsigned __int32 uint32_t; 42 typedef __int64 int64_t; 43 typedef unsigned __int64 uint64_t; 44 #else 45 #include <zephyr/types.h> 46 #include <stddef.h> 47 #endif 48 #include <net/http_parser_state.h> 49 #include <net/http_parser_url.h> 50 51 #ifdef __cplusplus 52 extern "C" { 53 #endif 54 55 /* Maximium header size allowed. If the macro is not defined 56 * before including this header then the default is used. To 57 * change the maximum header size, define the macro in the build 58 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove 59 * the effective limit on the size of the header, define the macro 60 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) 61 */ 62 #ifndef HTTP_MAX_HEADER_SIZE 63 # define HTTP_MAX_HEADER_SIZE (80 * 1024) 64 #endif 65 66 struct http_parser; 67 struct http_parser_settings; 68 69 70 /* Callbacks should return non-zero to indicate an error. The parser will 71 * then halt execution. 72 * 73 * The one exception is on_headers_complete. In a HTTP_RESPONSE parser 74 * returning '1' from on_headers_complete will tell the parser that it 75 * should not expect a body. This is used when receiving a response to a 76 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: 77 * chunked' headers that indicate the presence of a body. 78 * 79 * Returning `2` from on_headers_complete will tell parser that it should not 80 * expect neither a body nor any further responses on this connection. This is 81 * useful for handling responses to a CONNECT request which may not contain 82 * `Upgrade` or `Connection: upgrade` headers. 83 * 84 * http_data_cb does not return data chunks. It will be called arbitrarily 85 * many times for each string. E.G. you might get 10 callbacks for "on_url" 86 * each providing just a few characters more data. 87 */ 88 typedef int (*http_data_cb)(struct http_parser *, const char *at, 89 size_t length); 90 typedef int (*http_cb)(struct http_parser *); 91 92 enum http_method { 93 HTTP_DELETE = 0, 94 HTTP_GET = 1, 95 HTTP_HEAD = 2, 96 HTTP_POST = 3, 97 HTTP_PUT = 4, 98 HTTP_CONNECT = 5, 99 HTTP_OPTIONS = 6, 100 HTTP_TRACE = 7, 101 HTTP_COPY = 8, 102 HTTP_LOCK = 9, 103 HTTP_MKCOL = 10, 104 HTTP_MOVE = 11, 105 HTTP_PROPFIND = 12, 106 HTTP_PROPPATCH = 13, 107 HTTP_SEARCH = 14, 108 HTTP_UNLOCK = 15, 109 HTTP_BIND = 16, 110 HTTP_REBIND = 17, 111 HTTP_UNBIND = 18, 112 HTTP_ACL = 19, 113 HTTP_REPORT = 20, 114 HTTP_MKACTIVITY = 21, 115 HTTP_CHECKOUT = 22, 116 HTTP_MERGE = 23, 117 HTTP_MSEARCH = 24, 118 HTTP_NOTIFY = 25, 119 HTTP_SUBSCRIBE = 26, 120 HTTP_UNSUBSCRIBE = 27, 121 HTTP_PATCH = 28, 122 HTTP_PURGE = 29, 123 HTTP_MKCALENDAR = 30, 124 HTTP_LINK = 31, 125 HTTP_UNLINK = 32 126 }; 127 128 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; 129 130 /* Flag values for http_parser.flags field */ 131 enum flags { 132 F_CHUNKED = 1 << 0, 133 F_CONNECTION_KEEP_ALIVE = 1 << 1, 134 F_CONNECTION_CLOSE = 1 << 2, 135 F_CONNECTION_UPGRADE = 1 << 3, 136 F_TRAILING = 1 << 4, 137 F_UPGRADE = 1 << 5, 138 F_SKIPBODY = 1 << 6, 139 F_CONTENTLENGTH = 1 << 7 140 }; 141 142 enum http_errno { 143 HPE_OK, 144 HPE_CB_message_begin, 145 HPE_CB_url, 146 HPE_CB_header_field, 147 HPE_CB_header_value, 148 HPE_CB_headers_complete, 149 HPE_CB_body, 150 HPE_CB_message_complete, 151 HPE_CB_status, 152 HPE_CB_chunk_header, 153 HPE_CB_chunk_complete, 154 HPE_INVALID_EOF_STATE, 155 HPE_HEADER_OVERFLOW, 156 HPE_CLOSED_CONNECTION, 157 HPE_INVALID_VERSION, 158 HPE_INVALID_STATUS, 159 HPE_INVALID_METHOD, 160 HPE_INVALID_URL, 161 HPE_INVALID_HOST, 162 HPE_INVALID_PORT, 163 HPE_INVALID_PATH, 164 HPE_INVALID_QUERY_STRING, 165 HPE_INVALID_FRAGMENT, 166 HPE_LF_EXPECTED, 167 HPE_INVALID_HEADER_TOKEN, 168 HPE_INVALID_CONTENT_LENGTH, 169 HPE_UNEXPECTED_CONTENT_LENGTH, 170 HPE_INVALID_CHUNK_SIZE, 171 HPE_INVALID_CONSTANT, 172 HPE_INVALID_INTERNAL_STATE, 173 HPE_STRICT, 174 HPE_PAUSED, 175 HPE_UNKNOWN 176 }; 177 178 /* Get an http_errno value from an http_parser */ 179 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) 180 181 182 struct http_parser { 183 /** PRIVATE **/ 184 unsigned int type : 2; /* enum http_parser_type */ 185 unsigned int flags : 8; /* F_xxx values from 'flags' enum; 186 * semi-public 187 */ 188 unsigned int state : 7; /* enum state from http_parser.c */ 189 unsigned int header_state : 7; /* enum header_state from http_parser.c 190 */ 191 unsigned int index : 7; /* index into current matcher */ 192 unsigned int lenient_http_headers : 1; 193 194 uint32_t nread; /* # bytes read in various scenarios */ 195 uint64_t content_length; /* # bytes in body (0 if no Content-Length 196 * header) 197 */ 198 /** READ-ONLY **/ 199 unsigned short http_major; 200 unsigned short http_minor; 201 unsigned int status_code : 16; /* responses only */ 202 unsigned int method : 8; /* requests only */ 203 unsigned int http_errno : 7; 204 205 /* 1 = Upgrade header was present and the parser has exited because of 206 * that. 207 * 0 = No upgrade header present. 208 * Should be checked when http_parser_execute() returns in addition to 209 * error checking. 210 */ 211 unsigned int upgrade : 1; 212 213 /** PUBLIC **/ 214 void *data; /* A pointer to get hook to the "connection" or "socket" 215 * object 216 */ 217 218 /* Remote socket address of http connection, where parser can initiate 219 * replies if necessary. 220 */ 221 const struct sockaddr *addr; 222 }; 223 224 225 struct http_parser_settings { 226 http_cb on_message_begin; 227 http_data_cb on_url; 228 http_data_cb on_status; 229 http_data_cb on_header_field; 230 http_data_cb on_header_value; 231 http_cb on_headers_complete; 232 http_data_cb on_body; 233 http_cb on_message_complete; 234 /* When on_chunk_header is called, the current chunk length is stored 235 * in parser->content_length. 236 */ 237 http_cb on_chunk_header; 238 http_cb on_chunk_complete; 239 }; 240 241 242 /* Returns the library version. Bits 16-23 contain the major version number, 243 * bits 8-15 the minor version number and bits 0-7 the patch level. 244 * Usage example: 245 * 246 * unsigned long version = http_parser_version(); 247 * unsigned major = (version >> 16) & 255; 248 * unsigned minor = (version >> 8) & 255; 249 * unsigned patch = version & 255; 250 * printf("http_parser v%u.%u.%u\n", major, minor, patch); 251 */ 252 unsigned long http_parser_version(void); 253 254 void http_parser_init(struct http_parser *parser, enum http_parser_type type); 255 256 257 /* Initialize http_parser_settings members to 0 258 */ 259 void http_parser_settings_init(struct http_parser_settings *settings); 260 261 262 /* Executes the parser. Returns number of parsed bytes. Sets 263 * `parser->http_errno` on error. 264 */ 265 266 size_t http_parser_execute(struct http_parser *parser, 267 const struct http_parser_settings *settings, 268 const char *data, size_t len); 269 270 /* If http_should_keep_alive() in the on_headers_complete or 271 * on_message_complete callback returns 0, then this should be 272 * the last message on the connection. 273 * If you are the server, respond with the "Connection: close" header. 274 * If you are the client, close the connection. 275 */ 276 int http_should_keep_alive(const struct http_parser *parser); 277 278 /* Returns a string version of the HTTP method. */ 279 const char *http_method_str(enum http_method m); 280 281 /* Return a string name of the given error */ 282 const char *http_errno_name(enum http_errno err); 283 284 /* Return a string description of the given error */ 285 const char *http_errno_description(enum http_errno err); 286 287 /* Pause or un-pause the parser; a nonzero value pauses */ 288 void http_parser_pause(struct http_parser *parser, int paused); 289 290 /* Checks if this is the final chunk of the body. */ 291 int http_body_is_final(const struct http_parser *parser); 292 293 #ifdef __cplusplus 294 } 295 #endif 296 #endif 297