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