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 <zephyr/net/http/method.h> 49 #include <zephyr/net/http/parser_state.h> 50 #include <zephyr/net/http/parser_url.h> 51 52 #ifdef __cplusplus 53 extern "C" { 54 #endif 55 56 /* Maximum header size allowed. If the macro is not defined 57 * before including this header then the default is used. To 58 * change the maximum header size, define the macro in the build 59 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove 60 * the effective limit on the size of the header, define the macro 61 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff) 62 */ 63 #ifndef HTTP_MAX_HEADER_SIZE 64 # define HTTP_MAX_HEADER_SIZE (80 * 1024) 65 #endif 66 67 struct http_parser; 68 struct http_parser_settings; 69 70 71 /* Callbacks should return non-zero to indicate an error. The parser will 72 * then halt execution. 73 * 74 * The one exception is on_headers_complete. In a HTTP_RESPONSE parser 75 * returning '1' from on_headers_complete will tell the parser that it 76 * should not expect a body. This is used when receiving a response to a 77 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding: 78 * chunked' headers that indicate the presence of a body. 79 * 80 * Returning `2` from on_headers_complete will tell parser that it should not 81 * expect neither a body nor any further responses on this connection. This is 82 * useful for handling responses to a CONNECT request which may not contain 83 * `Upgrade` or `Connection: upgrade` headers. 84 * 85 * http_data_cb does not return data chunks. It will be called arbitrarily 86 * many times for each string. E.G. you might get 10 callbacks for "on_url" 87 * each providing just a few characters more data. 88 */ 89 typedef int (*http_data_cb)(struct http_parser *, const char *at, 90 size_t length); 91 typedef int (*http_cb)(struct http_parser *); 92 93 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH }; 94 95 /* Flag values for http_parser.flags field */ 96 enum flags { 97 F_CHUNKED = 1 << 0, 98 F_CONNECTION_KEEP_ALIVE = 1 << 1, 99 F_CONNECTION_CLOSE = 1 << 2, 100 F_CONNECTION_UPGRADE = 1 << 3, 101 F_TRAILING = 1 << 4, 102 F_UPGRADE = 1 << 5, 103 F_SKIPBODY = 1 << 6, 104 F_CONTENTLENGTH = 1 << 7 105 }; 106 107 enum http_errno { 108 HPE_OK, 109 HPE_CB_message_begin, 110 HPE_CB_url, 111 HPE_CB_header_field, 112 HPE_CB_header_value, 113 HPE_CB_headers_complete, 114 HPE_CB_body, 115 HPE_CB_message_complete, 116 HPE_CB_status, 117 HPE_CB_chunk_header, 118 HPE_CB_chunk_complete, 119 HPE_INVALID_EOF_STATE, 120 HPE_HEADER_OVERFLOW, 121 HPE_CLOSED_CONNECTION, 122 HPE_INVALID_VERSION, 123 HPE_INVALID_STATUS, 124 HPE_INVALID_METHOD, 125 HPE_INVALID_URL, 126 HPE_INVALID_HOST, 127 HPE_INVALID_PORT, 128 HPE_INVALID_PATH, 129 HPE_INVALID_QUERY_STRING, 130 HPE_INVALID_FRAGMENT, 131 HPE_LF_EXPECTED, 132 HPE_INVALID_HEADER_TOKEN, 133 HPE_INVALID_CONTENT_LENGTH, 134 HPE_UNEXPECTED_CONTENT_LENGTH, 135 HPE_INVALID_CHUNK_SIZE, 136 HPE_INVALID_CONSTANT, 137 HPE_INVALID_INTERNAL_STATE, 138 HPE_STRICT, 139 HPE_PAUSED, 140 HPE_UNKNOWN 141 }; 142 143 /* Get an http_errno value from an http_parser */ 144 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno) 145 146 147 struct http_parser { 148 /** PRIVATE **/ 149 unsigned int type : 2; /* enum http_parser_type */ 150 unsigned int flags : 8; /* F_xxx values from 'flags' enum; 151 * semi-public 152 */ 153 unsigned int state : 7; /* enum state from http_parser.c */ 154 unsigned int header_state : 7; /* enum header_state from http_parser.c 155 */ 156 unsigned int index : 7; /* index into current matcher */ 157 unsigned int lenient_http_headers : 1; 158 159 uint32_t nread; /* # bytes read in various scenarios */ 160 uint64_t content_length; /* # bytes in body (0 if no Content-Length 161 * header) 162 */ 163 /** READ-ONLY **/ 164 unsigned short http_major; 165 unsigned short http_minor; 166 unsigned int status_code : 16; /* responses only */ 167 unsigned int method : 8; /* requests only */ 168 unsigned int http_errno : 7; 169 170 /* 1 = Upgrade header was present and the parser has exited because of 171 * that. 172 * 0 = No upgrade header present. 173 * Should be checked when http_parser_execute() returns in addition to 174 * error checking. 175 */ 176 unsigned int upgrade : 1; 177 178 /** PUBLIC **/ 179 void *data; /* A pointer to get hook to the "connection" or "socket" 180 * object 181 */ 182 183 /* Remote socket address of http connection, where parser can initiate 184 * replies if necessary. 185 */ 186 const struct sockaddr *addr; 187 }; 188 189 190 struct http_parser_settings { 191 http_cb on_message_begin; 192 http_data_cb on_url; 193 http_data_cb on_status; 194 http_data_cb on_header_field; 195 http_data_cb on_header_value; 196 http_cb on_headers_complete; 197 http_data_cb on_body; 198 http_cb on_message_complete; 199 /* When on_chunk_header is called, the current chunk length is stored 200 * in parser->content_length. 201 */ 202 http_cb on_chunk_header; 203 http_cb on_chunk_complete; 204 }; 205 206 207 /* Returns the library version. Bits 16-23 contain the major version number, 208 * bits 8-15 the minor version number and bits 0-7 the patch level. 209 * Usage example: 210 * 211 * unsigned long version = http_parser_version(); 212 * unsigned major = (version >> 16) & 255; 213 * unsigned minor = (version >> 8) & 255; 214 * unsigned patch = version & 255; 215 * printf("http_parser v%u.%u.%u\n", major, minor, patch); 216 */ 217 unsigned long http_parser_version(void); 218 219 void http_parser_init(struct http_parser *parser, enum http_parser_type type); 220 221 222 /* Initialize http_parser_settings members to 0 223 */ 224 void http_parser_settings_init(struct http_parser_settings *settings); 225 226 227 /* Executes the parser. Returns number of parsed bytes. Sets 228 * `parser->http_errno` on error. 229 */ 230 231 size_t http_parser_execute(struct http_parser *parser, 232 const struct http_parser_settings *settings, 233 const char *data, size_t len); 234 235 /* If http_should_keep_alive() in the on_headers_complete or 236 * on_message_complete callback returns 0, then this should be 237 * the last message on the connection. 238 * If you are the server, respond with the "Connection: close" header. 239 * If you are the client, close the connection. 240 */ 241 int http_should_keep_alive(const struct http_parser *parser); 242 243 /* Returns a string version of the HTTP method. */ 244 const char *http_method_str(enum http_method m); 245 246 /* Return a string name of the given error */ 247 const char *http_errno_name(enum http_errno err); 248 249 /* Return a string description of the given error */ 250 const char *http_errno_description(enum http_errno err); 251 252 /* Pause or un-pause the parser; a nonzero value pauses */ 253 void http_parser_pause(struct http_parser *parser, int paused); 254 255 /* Checks if this is the final chunk of the body. */ 256 int http_body_is_final(const struct http_parser *parser); 257 258 #ifdef __cplusplus 259 } 260 #endif 261 #endif 262