1 #ifndef INCLUDE_LLHTTP_H_ 2 #define INCLUDE_LLHTTP_H_ 3 4 #define LLHTTP_VERSION_MAJOR 2 5 #define LLHTTP_VERSION_MINOR 2 6 #define LLHTTP_VERSION_PATCH 0 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 HTTP_DESCRIBE = 35, 150 HTTP_ANNOUNCE = 36, 151 HTTP_SETUP = 37, 152 HTTP_PLAY = 38, 153 HTTP_PAUSE = 39, 154 HTTP_TEARDOWN = 40, 155 HTTP_GET_PARAMETER = 41, 156 HTTP_SET_PARAMETER = 42, 157 HTTP_REDIRECT = 43, 158 HTTP_RECORD = 44, 159 HTTP_FLUSH = 45 160 }; 161 typedef enum llhttp_method llhttp_method_t; 162 163 #define HTTP_ERRNO_MAP(XX) \ 164 XX(0, OK, OK) \ 165 XX(1, INTERNAL, INTERNAL) \ 166 XX(2, STRICT, STRICT) \ 167 XX(3, LF_EXPECTED, LF_EXPECTED) \ 168 XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \ 169 XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \ 170 XX(6, INVALID_METHOD, INVALID_METHOD) \ 171 XX(7, INVALID_URL, INVALID_URL) \ 172 XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \ 173 XX(9, INVALID_VERSION, INVALID_VERSION) \ 174 XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \ 175 XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \ 176 XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \ 177 XX(13, INVALID_STATUS, INVALID_STATUS) \ 178 XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \ 179 XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \ 180 XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \ 181 XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \ 182 XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \ 183 XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \ 184 XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \ 185 XX(21, PAUSED, PAUSED) \ 186 XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \ 187 XX(23, USER, USER) \ 188 189 190 #define HTTP_METHOD_MAP(XX) \ 191 XX(0, DELETE, DELETE) \ 192 XX(1, GET, GET) \ 193 XX(2, HEAD, HEAD) \ 194 XX(3, POST, POST) \ 195 XX(4, PUT, PUT) \ 196 XX(5, CONNECT, CONNECT) \ 197 XX(6, OPTIONS, OPTIONS) \ 198 XX(7, TRACE, TRACE) \ 199 XX(8, COPY, COPY) \ 200 XX(9, LOCK, LOCK) \ 201 XX(10, MKCOL, MKCOL) \ 202 XX(11, MOVE, MOVE) \ 203 XX(12, PROPFIND, PROPFIND) \ 204 XX(13, PROPPATCH, PROPPATCH) \ 205 XX(14, SEARCH, SEARCH) \ 206 XX(15, UNLOCK, UNLOCK) \ 207 XX(16, BIND, BIND) \ 208 XX(17, REBIND, REBIND) \ 209 XX(18, UNBIND, UNBIND) \ 210 XX(19, ACL, ACL) \ 211 XX(20, REPORT, REPORT) \ 212 XX(21, MKACTIVITY, MKACTIVITY) \ 213 XX(22, CHECKOUT, CHECKOUT) \ 214 XX(23, MERGE, MERGE) \ 215 XX(24, MSEARCH, M-SEARCH) \ 216 XX(25, NOTIFY, NOTIFY) \ 217 XX(26, SUBSCRIBE, SUBSCRIBE) \ 218 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \ 219 XX(28, PATCH, PATCH) \ 220 XX(29, PURGE, PURGE) \ 221 XX(30, MKCALENDAR, MKCALENDAR) \ 222 XX(31, LINK, LINK) \ 223 XX(32, UNLINK, UNLINK) \ 224 XX(33, SOURCE, SOURCE) \ 225 XX(34, PRI, PRI) \ 226 XX(35, DESCRIBE, DESCRIBE) \ 227 XX(36, ANNOUNCE, ANNOUNCE) \ 228 XX(37, SETUP, SETUP) \ 229 XX(38, PLAY, PLAY) \ 230 XX(39, PAUSE, PAUSE) \ 231 XX(40, TEARDOWN, TEARDOWN) \ 232 XX(41, GET_PARAMETER, GET_PARAMETER) \ 233 XX(42, SET_PARAMETER, SET_PARAMETER) \ 234 XX(43, REDIRECT, REDIRECT) \ 235 XX(44, RECORD, RECORD) \ 236 XX(45, FLUSH, FLUSH) \ 237 238 239 240 #ifdef __cplusplus 241 } /* extern "C" */ 242 #endif 243 #endif /* LLLLHTTP_C_HEADERS_ */ 244 245 #ifndef INCLUDE_LLHTTP_API_H_ 246 #define INCLUDE_LLHTTP_API_H_ 247 #ifdef __cplusplus 248 extern "C" { 249 #endif 250 #include <stddef.h> 251 252 typedef llhttp__internal_t llhttp_t; 253 typedef struct llhttp_settings_s llhttp_settings_t; 254 255 typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length); 256 typedef int (*llhttp_cb)(llhttp_t*); 257 258 struct llhttp_settings_s { 259 /* Possible return values 0, -1, `HPE_PAUSED` */ 260 llhttp_cb on_message_begin; 261 262 llhttp_data_cb on_url; 263 llhttp_data_cb on_status; 264 llhttp_data_cb on_header_field; 265 llhttp_data_cb on_header_value; 266 267 /* Possible return values: 268 * 0 - Proceed normally 269 * 1 - Assume that request/response has no body, and proceed to parsing the 270 * next message 271 * 2 - Assume absence of body (as above) and make `llhttp_execute()` return 272 * `HPE_PAUSED_UPGRADE` 273 * -1 - Error 274 * `HPE_PAUSED` 275 */ 276 llhttp_cb on_headers_complete; 277 278 llhttp_data_cb on_body; 279 280 /* Possible return values 0, -1, `HPE_PAUSED` */ 281 llhttp_cb on_message_complete; 282 283 /* When on_chunk_header is called, the current chunk length is stored 284 * in parser->content_length. 285 * Possible return values 0, -1, `HPE_PAUSED` 286 */ 287 llhttp_cb on_chunk_header; 288 llhttp_cb on_chunk_complete; 289 }; 290 291 /* Initialize the parser with specific type and user settings. 292 * 293 * NOTE: lifetime of `settings` has to be at least the same as the lifetime of 294 * the `parser` here. In practice, `settings` has to be either a static 295 * variable or be allocated with `malloc`, `new`, etc. 296 */ 297 void llhttp_init(llhttp_t* parser, llhttp_type_t type, 298 const llhttp_settings_t* settings); 299 300 /* Initialize the settings object */ 301 void llhttp_settings_init(llhttp_settings_t* settings); 302 303 /* Parse full or partial request/response, invoking user callbacks along the 304 * way. 305 * 306 * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing 307 * interrupts, and such errno is returned from `llhttp_execute()`. If 308 * `HPE_PAUSED` was used as a errno, the execution can be resumed with 309 * `llhttp_resume()` call. 310 * 311 * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE` 312 * is returned after fully parsing the request/response. If the user wishes to 313 * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`. 314 * 315 * NOTE: if this function ever returns a non-pause type error, it will continue 316 * to return the same error upon each successive call up until `llhttp_init()` 317 * is called. 318 */ 319 llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len); 320 321 /* This method should be called when the other side has no further bytes to 322 * send (e.g. shutdown of readable side of the TCP connection.) 323 * 324 * Requests without `Content-Length` and other messages might require treating 325 * all incoming bytes as the part of the body, up to the last byte of the 326 * connection. This method will invoke `on_message_complete()` callback if the 327 * request was terminated safely. Otherwise a error code would be returned. 328 */ 329 llhttp_errno_t llhttp_finish(llhttp_t* parser); 330 331 /* Returns `1` if the incoming message is parsed until the last byte, and has 332 * to be completed by calling `llhttp_finish()` on EOF 333 */ 334 int llhttp_message_needs_eof(const llhttp_t* parser); 335 336 /* Returns `1` if there might be any other messages following the last that was 337 * successfully parsed. 338 */ 339 int llhttp_should_keep_alive(const llhttp_t* parser); 340 341 /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set 342 * appropriate error reason. 343 * 344 * Important: do not call this from user callbacks! User callbacks must return 345 * `HPE_PAUSED` if pausing is required. 346 */ 347 void llhttp_pause(llhttp_t* parser); 348 349 /* Might be called to resume the execution after the pause in user's callback. 350 * See `llhttp_execute()` above for details. 351 * 352 * Call this only if `llhttp_execute()` returns `HPE_PAUSED`. 353 */ 354 void llhttp_resume(llhttp_t* parser); 355 356 /* Might be called to resume the execution after the pause in user's callback. 357 * See `llhttp_execute()` above for details. 358 * 359 * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE` 360 */ 361 void llhttp_resume_after_upgrade(llhttp_t* parser); 362 363 /* Returns the latest return error */ 364 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser); 365 366 /* Returns the verbal explanation of the latest returned error. 367 * 368 * Note: User callback should set error reason when returning the error. See 369 * `llhttp_set_error_reason()` for details. 370 */ 371 const char* llhttp_get_error_reason(const llhttp_t* parser); 372 373 /* Assign verbal description to the returned error. Must be called in user 374 * callbacks right before returning the errno. 375 * 376 * Note: `HPE_USER` error code might be useful in user callbacks. 377 */ 378 void llhttp_set_error_reason(llhttp_t* parser, const char* reason); 379 380 /* Returns the pointer to the last parsed byte before the returned error. The 381 * pointer is relative to the `data` argument of `llhttp_execute()`. 382 * 383 * Note: this method might be useful for counting the number of parsed bytes. 384 */ 385 const char* llhttp_get_error_pos(const llhttp_t* parser); 386 387 /* Returns textual name of error code */ 388 const char* llhttp_errno_name(llhttp_errno_t err); 389 390 /* Returns textual name of HTTP method */ 391 const char* llhttp_method_name(llhttp_method_t method); 392 393 394 /* Enables/disables lenient header value parsing (disabled by default). 395 * 396 * Lenient parsing disables header value token checks, extending llhttp's 397 * protocol support to highly non-compliant clients/server. No 398 * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when 399 * lenient parsing is "on". 400 * 401 * **(USE AT YOUR OWN RISK)** 402 */ 403 void llhttp_set_lenient(llhttp_t* parser, int enabled); 404 405 #ifdef __cplusplus 406 } /* extern "C" */ 407 #endif 408 #endif /* INCLUDE_LLHTTP_API_H_ */ 409 410 #endif /* INCLUDE_LLHTTP_H_ */ 411