1 #ifndef INCLUDE_LLHTTP_H_ 2 #define INCLUDE_LLHTTP_H_ 3 4 #define LLHTTP_VERSION_MAJOR 2 5 #define LLHTTP_VERSION_MINOR 1 6 #define LLHTTP_VERSION_PATCH 3 7 8 #ifndef LLHTTP_STRICT_MODE 9 # define LLHTTP_STRICT_MODE 0 10 #endif 11 12 #ifndef INCLUDE_LLHTTP_ITSELF_H_ 13 #define INCLUDE_LLHTTP_ITSELF_H_ 14 #ifdef __cplusplus 15 extern "C" { 16 #endif 17 18 #include <stdint.h> 19 20 typedef struct llhttp__internal_s llhttp__internal_t; 21 struct llhttp__internal_s { 22 int32_t _index; 23 void* _span_pos0; 24 void* _span_cb0; 25 int32_t error; 26 const char* reason; 27 const char* error_pos; 28 void* data; 29 void* _current; 30 uint64_t content_length; 31 uint8_t type; 32 uint8_t method; 33 uint8_t http_major; 34 uint8_t http_minor; 35 uint8_t header_state; 36 uint16_t flags; 37 uint8_t upgrade; 38 uint16_t status_code; 39 uint8_t finish; 40 void* settings; 41 }; 42 43 int llhttp__internal_init(llhttp__internal_t* s); 44 int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp); 45 46 #ifdef __cplusplus 47 } /* extern "C" */ 48 #endif 49 #endif /* INCLUDE_LLHTTP_ITSELF_H_ */ 50 51 #ifndef LLLLHTTP_C_HEADERS_ 52 #define LLLLHTTP_C_HEADERS_ 53 #ifdef __cplusplus 54 extern "C" { 55 #endif 56 57 enum llhttp_errno { 58 HPE_OK = 0, 59 HPE_INTERNAL = 1, 60 HPE_STRICT = 2, 61 HPE_LF_EXPECTED = 3, 62 HPE_UNEXPECTED_CONTENT_LENGTH = 4, 63 HPE_CLOSED_CONNECTION = 5, 64 HPE_INVALID_METHOD = 6, 65 HPE_INVALID_URL = 7, 66 HPE_INVALID_CONSTANT = 8, 67 HPE_INVALID_VERSION = 9, 68 HPE_INVALID_HEADER_TOKEN = 10, 69 HPE_INVALID_CONTENT_LENGTH = 11, 70 HPE_INVALID_CHUNK_SIZE = 12, 71 HPE_INVALID_STATUS = 13, 72 HPE_INVALID_EOF_STATE = 14, 73 HPE_INVALID_TRANSFER_ENCODING = 15, 74 HPE_CB_MESSAGE_BEGIN = 16, 75 HPE_CB_HEADERS_COMPLETE = 17, 76 HPE_CB_MESSAGE_COMPLETE = 18, 77 HPE_CB_CHUNK_HEADER = 19, 78 HPE_CB_CHUNK_COMPLETE = 20, 79 HPE_PAUSED = 21, 80 HPE_PAUSED_UPGRADE = 22, 81 HPE_USER = 23 82 }; 83 typedef enum llhttp_errno llhttp_errno_t; 84 85 enum llhttp_flags { 86 F_CONNECTION_KEEP_ALIVE = 0x1, 87 F_CONNECTION_CLOSE = 0x2, 88 F_CONNECTION_UPGRADE = 0x4, 89 F_CHUNKED = 0x8, 90 F_UPGRADE = 0x10, 91 F_CONTENT_LENGTH = 0x20, 92 F_SKIPBODY = 0x40, 93 F_TRAILING = 0x80, 94 F_LENIENT = 0x100, 95 F_TRANSFER_ENCODING = 0x200 96 }; 97 typedef enum llhttp_flags llhttp_flags_t; 98 99 enum llhttp_type { 100 HTTP_BOTH = 0, 101 HTTP_REQUEST = 1, 102 HTTP_RESPONSE = 2 103 }; 104 typedef enum llhttp_type llhttp_type_t; 105 106 enum llhttp_finish { 107 HTTP_FINISH_SAFE = 0, 108 HTTP_FINISH_SAFE_WITH_CB = 1, 109 HTTP_FINISH_UNSAFE = 2 110 }; 111 typedef enum llhttp_finish llhttp_finish_t; 112 113 enum llhttp_method { 114 HTTP_DELETE = 0, 115 HTTP_GET = 1, 116 HTTP_HEAD = 2, 117 HTTP_POST = 3, 118 HTTP_PUT = 4, 119 HTTP_CONNECT = 5, 120 HTTP_OPTIONS = 6, 121 HTTP_TRACE = 7, 122 HTTP_COPY = 8, 123 HTTP_LOCK = 9, 124 HTTP_MKCOL = 10, 125 HTTP_MOVE = 11, 126 HTTP_PROPFIND = 12, 127 HTTP_PROPPATCH = 13, 128 HTTP_SEARCH = 14, 129 HTTP_UNLOCK = 15, 130 HTTP_BIND = 16, 131 HTTP_REBIND = 17, 132 HTTP_UNBIND = 18, 133 HTTP_ACL = 19, 134 HTTP_REPORT = 20, 135 HTTP_MKACTIVITY = 21, 136 HTTP_CHECKOUT = 22, 137 HTTP_MERGE = 23, 138 HTTP_MSEARCH = 24, 139 HTTP_NOTIFY = 25, 140 HTTP_SUBSCRIBE = 26, 141 HTTP_UNSUBSCRIBE = 27, 142 HTTP_PATCH = 28, 143 HTTP_PURGE = 29, 144 HTTP_MKCALENDAR = 30, 145 HTTP_LINK = 31, 146 HTTP_UNLINK = 32, 147 HTTP_SOURCE = 33, 148 HTTP_PRI = 34 149 }; 150 typedef enum llhttp_method llhttp_method_t; 151 152 #define HTTP_ERRNO_MAP(XX) \ 153 XX(0, OK, OK) \ 154 XX(1, INTERNAL, INTERNAL) \ 155 XX(2, STRICT, STRICT) \ 156 XX(3, LF_EXPECTED, LF_EXPECTED) \ 157 XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \ 158 XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \ 159 XX(6, INVALID_METHOD, INVALID_METHOD) \ 160 XX(7, INVALID_URL, INVALID_URL) \ 161 XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \ 162 XX(9, INVALID_VERSION, INVALID_VERSION) \ 163 XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \ 164 XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \ 165 XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \ 166 XX(13, INVALID_STATUS, INVALID_STATUS) \ 167 XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \ 168 XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \ 169 XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \ 170 XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \ 171 XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \ 172 XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \ 173 XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ 174 XX(21, PAUSED, PAUSED) \ 175 XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ 176 XX(23, USER, USER) \ 177 178 179 #define HTTP_METHOD_MAP(XX) \ 180 XX(0, DELETE, DELETE) \ 181 XX(1, GET, GET) \ 182 XX(2, HEAD, HEAD) \ 183 XX(3, POST, POST) \ 184 XX(4, PUT, PUT) \ 185 XX(5, CONNECT, CONNECT) \ 186 XX(6, OPTIONS, OPTIONS) \ 187 XX(7, TRACE, TRACE) \ 188 XX(8, COPY, COPY) \ 189 XX(9, LOCK, LOCK) \ 190 XX(10, MKCOL, MKCOL) \ 191 XX(11, MOVE, MOVE) \ 192 XX(12, PROPFIND, PROPFIND) \ 193 XX(13, PROPPATCH, PROPPATCH) \ 194 XX(14, SEARCH, SEARCH) \ 195 XX(15, UNLOCK, UNLOCK) \ 196 XX(16, BIND, BIND) \ 197 XX(17, REBIND, REBIND) \ 198 XX(18, UNBIND, UNBIND) \ 199 XX(19, ACL, ACL) \ 200 XX(20, REPORT, REPORT) \ 201 XX(21, MKACTIVITY, MKACTIVITY) \ 202 XX(22, CHECKOUT, CHECKOUT) \ 203 XX(23, MERGE, MERGE) \ 204 XX(24, MSEARCH, M-SEARCH) \ 205 XX(25, NOTIFY, NOTIFY) \ 206 XX(26, SUBSCRIBE, SUBSCRIBE) \ 207 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 208 XX(28, PATCH, PATCH) \ 209 XX(29, PURGE, PURGE) \ 210 XX(30, MKCALENDAR, MKCALENDAR) \ 211 XX(31, LINK, LINK) \ 212 XX(32, UNLINK, UNLINK) \ 213 XX(33, SOURCE, SOURCE) \ 214 XX(34, PRI, PRI) \ 215 216 217 218 #ifdef __cplusplus 219 } /* extern "C" */ 220 #endif 221 #endif /* LLLLHTTP_C_HEADERS_ */ 222 223 #ifndef INCLUDE_LLHTTP_API_H_ 224 #define INCLUDE_LLHTTP_API_H_ 225 #ifdef __cplusplus 226 extern "C" { 227 #endif 228 #include <stddef.h> 229 230 typedef llhttp__internal_t llhttp_t; 231 typedef struct llhttp_settings_s llhttp_settings_t; 232 233 typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length); 234 typedef int (*llhttp_cb)(llhttp_t*); 235 236 struct llhttp_settings_s { 237 /* Possible return values 0, -1, `HPE_PAUSED` */ 238 llhttp_cb on_message_begin; 239 240 llhttp_data_cb on_url; 241 llhttp_data_cb on_status; 242 llhttp_data_cb on_header_field; 243 llhttp_data_cb on_header_value; 244 245 /* Possible return values: 246 * 0 - Proceed normally 247 * 1 - Assume that request/response has no body, and proceed to parsing the 248 * next message 249 * 2 - Assume absence of body (as above) and make `llhttp_execute()` return 250 * `HPE_PAUSED_UPGRADE` 251 * -1 - Error 252 * `HPE_PAUSED` 253 */ 254 llhttp_cb on_headers_complete; 255 256 llhttp_data_cb on_body; 257 258 /* Possible return values 0, -1, `HPE_PAUSED` */ 259 llhttp_cb on_message_complete; 260 261 /* When on_chunk_header is called, the current chunk length is stored 262 * in parser->content_length. 263 * Possible return values 0, -1, `HPE_PAUSED` 264 */ 265 llhttp_cb on_chunk_header; 266 llhttp_cb on_chunk_complete; 267 }; 268 269 /* Initialize the parser with specific type and user settings */ 270 void llhttp_init(llhttp_t* parser, llhttp_type_t type, 271 const llhttp_settings_t* settings); 272 273 /* Initialize the settings object */ 274 void llhttp_settings_init(llhttp_settings_t* settings); 275 276 /* Parse full or partial request/response, invoking user callbacks along the 277 * way. 278 * 279 * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing 280 * interrupts, and such errno is returned from `llhttp_execute()`. If 281 * `HPE_PAUSED` was used as a errno, the execution can be resumed with 282 * `llhttp_resume()` call. 283 * 284 * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` 285 * is returned after fully parsing the request/response. If the user wishes to 286 * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`. 287 * 288 * NOTE: if this function ever returns a non-pause type error, it will continue 289 * to return the same error upon each successive call up until `llhttp_init()` 290 * is called. 291 */ 292 llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); 293 294 /* This method should be called when the other side has no further bytes to 295 * send (e.g. shutdown of readable side of the TCP connection.) 296 * 297 * Requests without `Content-Length` and other messages might require treating 298 * all incoming bytes as the part of the body, up to the last byte of the 299 * connection. This method will invoke `on_message_complete()` callback if the 300 * request was terminated safely. Otherwise a error code would be returned. 301 */ 302 llhttp_errno_t llhttp_finish(llhttp_t* parser); 303 304 /* Returns `1` if the incoming message is parsed until the last byte, and has 305 * to be completed by calling `llhttp_finish()` on EOF 306 */ 307 int llhttp_message_needs_eof(const llhttp_t* parser); 308 309 /* Returns `1` if there might be any other messages following the last that was 310 * successfully parsed. 311 */ 312 int llhttp_should_keep_alive(const llhttp_t* parser); 313 314 /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set 315 * appropriate error reason. 316 * 317 * Important: do not call this from user callbacks! User callbacks must return 318 * `HPE_PAUSED` if pausing is required. 319 */ 320 void llhttp_pause(llhttp_t* parser); 321 322 /* Might be called to resume the execution after the pause in user's callback. 323 * See `llhttp_execute()` above for details. 324 * 325 * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. 326 */ 327 void llhttp_resume(llhttp_t* parser); 328 329 /* Might be called to resume the execution after the pause in user's callback. 330 * See `llhttp_execute()` above for details. 331 * 332 * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` 333 */ 334 void llhttp_resume_after_upgrade(llhttp_t* parser); 335 336 /* Returns the latest return error */ 337 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); 338 339 /* Returns the verbal explanation of the latest returned error. 340 * 341 * Note: User callback should set error reason when returning the error. See 342 * `llhttp_set_error_reason()` for details. 343 */ 344 const char* llhttp_get_error_reason(const llhttp_t* parser); 345 346 /* Assign verbal description to the returned error. Must be called in user 347 * callbacks right before returning the errno. 348 * 349 * Note: `HPE_USER` error code might be useful in user callbacks. 350 */ 351 void llhttp_set_error_reason(llhttp_t* parser, const char* reason); 352 353 /* Returns the pointer to the last parsed byte before the returned error. The 354 * pointer is relative to the `data` argument of `llhttp_execute()`. 355 * 356 * Note: this method might be useful for counting the number of parsed bytes. 357 */ 358 const char* llhttp_get_error_pos(const llhttp_t* parser); 359 360 /* Returns textual name of error code */ 361 const char* llhttp_errno_name(llhttp_errno_t err); 362 363 /* Returns textual name of HTTP method */ 364 const char* llhttp_method_name(llhttp_method_t method); 365 366 367 /* Enables/disables lenient header value parsing (disabled by default). 368 * 369 * Lenient parsing disables header value token checks, extending llhttp's 370 * protocol support to highly non-compliant clients/server. No 371 * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when 372 * lenient parsing is "on". 373 * 374 * **(USE AT YOUR OWN RISK)** 375 */ 376 void llhttp_set_lenient(llhttp_t* parser, int enabled); 377 378 #ifdef __cplusplus 379 } /* extern "C" */ 380 #endif 381 #endif /* INCLUDE_LLHTTP_API_H_ */ 382 383 #endif /* INCLUDE_LLHTTP_H_ */ 384