1#include <stdlib.h> 2#include <stdio.h> 3#include <string.h> 4 5#include "llhttp.h" 6 7#define CALLBACK_MAYBE(PARSER, NAME) \ 8 do { \ 9 const llhttp_settings_t* settings; \ 10 settings = (const llhttp_settings_t*) (PARSER)->settings; \ 11 if (settings == NULL || settings->NAME == NULL) { \ 12 err = 0; \ 13 break; \ 14 } \ 15 err = settings->NAME((PARSER)); \ 16 } while (0) 17 18#define SPAN_CALLBACK_MAYBE(PARSER, NAME, START, LEN) \ 19 do { \ 20 const llhttp_settings_t* settings; \ 21 settings = (const llhttp_settings_t*) (PARSER)->settings; \ 22 if (settings == NULL || settings->NAME == NULL) { \ 23 err = 0; \ 24 break; \ 25 } \ 26 err = settings->NAME((PARSER), (START), (LEN)); \ 27 if (err == -1) { \ 28 err = HPE_USER; \ 29 llhttp_set_error_reason((PARSER), "Span callback error in " #NAME); \ 30 } \ 31 } while (0) 32 33void llhttp_init(llhttp_t* parser, llhttp_type_t type, 34 const llhttp_settings_t* settings) { 35 llhttp__internal_init(parser); 36 37 parser->type = type; 38 parser->settings = (void*) settings; 39} 40 41 42#if defined(__wasm__) 43 44extern int wasm_on_message_begin(llhttp_t * p); 45extern int wasm_on_url(llhttp_t* p, const char* at, size_t length); 46extern int wasm_on_status(llhttp_t* p, const char* at, size_t length); 47extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length); 48extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length); 49extern int wasm_on_headers_complete(llhttp_t * p, int status_code, 50 uint8_t upgrade, int should_keep_alive); 51extern int wasm_on_body(llhttp_t* p, const char* at, size_t length); 52extern int wasm_on_message_complete(llhttp_t * p); 53 54static int wasm_on_headers_complete_wrap(llhttp_t* p) { 55 return wasm_on_headers_complete(p, p->status_code, p->upgrade, 56 llhttp_should_keep_alive(p)); 57} 58 59const llhttp_settings_t wasm_settings = { 60 wasm_on_message_begin, 61 wasm_on_url, 62 wasm_on_status, 63 wasm_on_header_field, 64 wasm_on_header_value, 65 wasm_on_headers_complete_wrap, 66 wasm_on_body, 67 wasm_on_message_complete, 68 NULL, 69 NULL, 70}; 71 72 73llhttp_t* llhttp_alloc(llhttp_type_t type) { 74 llhttp_t* parser = malloc(sizeof(llhttp_t)); 75 llhttp_init(parser, type, &wasm_settings); 76 return parser; 77} 78 79void llhttp_free(llhttp_t* parser) { 80 free(parser); 81} 82 83/* Some getters required to get stuff from the parser */ 84 85uint8_t llhttp_get_type(llhttp_t* parser) { 86 return parser->type; 87} 88 89uint8_t llhttp_get_http_major(llhttp_t* parser) { 90 return parser->http_major; 91} 92 93uint8_t llhttp_get_http_minor(llhttp_t* parser) { 94 return parser->http_minor; 95} 96 97uint8_t llhttp_get_method(llhttp_t* parser) { 98 return parser->method; 99} 100 101int llhttp_get_status_code(llhttp_t* parser) { 102 return parser->status_code; 103} 104 105uint8_t llhttp_get_upgrade(llhttp_t* parser) { 106 return parser->upgrade; 107} 108 109#endif // defined(__wasm__) 110 111 112void llhttp_reset(llhttp_t* parser) { 113 llhttp_type_t type = parser->type; 114 const llhttp_settings_t* settings = parser->settings; 115 void* data = parser->data; 116 uint8_t lenient_flags = parser->lenient_flags; 117 118 llhttp__internal_init(parser); 119 120 parser->type = type; 121 parser->settings = (void*) settings; 122 parser->data = data; 123 parser->lenient_flags = lenient_flags; 124} 125 126 127llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) { 128 return llhttp__internal_execute(parser, data, data + len); 129} 130 131 132void llhttp_settings_init(llhttp_settings_t* settings) { 133 memset(settings, 0, sizeof(*settings)); 134} 135 136 137llhttp_errno_t llhttp_finish(llhttp_t* parser) { 138 int err; 139 140 /* We're in an error state. Don't bother doing anything. */ 141 if (parser->error != 0) { 142 return 0; 143 } 144 145 switch (parser->finish) { 146 case HTTP_FINISH_SAFE_WITH_CB: 147 CALLBACK_MAYBE(parser, on_message_complete); 148 if (err != HPE_OK) return err; 149 150 /* FALLTHROUGH */ 151 case HTTP_FINISH_SAFE: 152 return HPE_OK; 153 case HTTP_FINISH_UNSAFE: 154 parser->reason = "Invalid EOF state"; 155 return HPE_INVALID_EOF_STATE; 156 default: 157 abort(); 158 } 159} 160 161 162void llhttp_pause(llhttp_t* parser) { 163 if (parser->error != HPE_OK) { 164 return; 165 } 166 167 parser->error = HPE_PAUSED; 168 parser->reason = "Paused"; 169} 170 171 172void llhttp_resume(llhttp_t* parser) { 173 if (parser->error != HPE_PAUSED) { 174 return; 175 } 176 177 parser->error = 0; 178} 179 180 181void llhttp_resume_after_upgrade(llhttp_t* parser) { 182 if (parser->error != HPE_PAUSED_UPGRADE) { 183 return; 184 } 185 186 parser->error = 0; 187} 188 189 190llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) { 191 return parser->error; 192} 193 194 195const char* llhttp_get_error_reason(const llhttp_t* parser) { 196 return parser->reason; 197} 198 199 200void llhttp_set_error_reason(llhttp_t* parser, const char* reason) { 201 parser->reason = reason; 202} 203 204 205const char* llhttp_get_error_pos(const llhttp_t* parser) { 206 return parser->error_pos; 207} 208 209 210const char* llhttp_errno_name(llhttp_errno_t err) { 211#define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME; 212 switch (err) { 213 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) 214 default: abort(); 215 } 216#undef HTTP_ERRNO_GEN 217} 218 219 220const char* llhttp_method_name(llhttp_method_t method) { 221#define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING; 222 switch (method) { 223 HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN) 224 default: abort(); 225 } 226#undef HTTP_METHOD_GEN 227} 228 229 230void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) { 231 if (enabled) { 232 parser->lenient_flags |= LENIENT_HEADERS; 233 } else { 234 parser->lenient_flags &= ~LENIENT_HEADERS; 235 } 236} 237 238 239void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) { 240 if (enabled) { 241 parser->lenient_flags |= LENIENT_CHUNKED_LENGTH; 242 } else { 243 parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH; 244 } 245} 246 247 248void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) { 249 if (enabled) { 250 parser->lenient_flags |= LENIENT_KEEP_ALIVE; 251 } else { 252 parser->lenient_flags &= ~LENIENT_KEEP_ALIVE; 253 } 254} 255 256void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) { 257 if (enabled) { 258 parser->lenient_flags |= LENIENT_TRANSFER_ENCODING; 259 } else { 260 parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING; 261 } 262} 263 264/* Callbacks */ 265 266 267int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) { 268 int err; 269 CALLBACK_MAYBE(s, on_message_begin); 270 return err; 271} 272 273 274int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) { 275 int err; 276 SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p); 277 return err; 278} 279 280 281int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) { 282 int err; 283 CALLBACK_MAYBE(s, on_url_complete); 284 return err; 285} 286 287 288int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) { 289 int err; 290 SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p); 291 return err; 292} 293 294 295int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) { 296 int err; 297 CALLBACK_MAYBE(s, on_status_complete); 298 return err; 299} 300 301 302int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) { 303 int err; 304 SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p); 305 return err; 306} 307 308 309int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) { 310 int err; 311 CALLBACK_MAYBE(s, on_header_field_complete); 312 return err; 313} 314 315 316int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) { 317 int err; 318 SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p); 319 return err; 320} 321 322 323int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) { 324 int err; 325 CALLBACK_MAYBE(s, on_header_value_complete); 326 return err; 327} 328 329 330int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) { 331 int err; 332 CALLBACK_MAYBE(s, on_headers_complete); 333 return err; 334} 335 336 337int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) { 338 int err; 339 CALLBACK_MAYBE(s, on_message_complete); 340 return err; 341} 342 343 344int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) { 345 int err; 346 SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p); 347 return err; 348} 349 350 351int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) { 352 int err; 353 CALLBACK_MAYBE(s, on_chunk_header); 354 return err; 355} 356 357 358int llhttp__on_chunk_parameters(llhttp_t* s, const char* p, const char* endp) { 359 int err; 360 SPAN_CALLBACK_MAYBE(s, on_chunk_parameters, p, endp - p); 361 return err; 362} 363 364 365int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) { 366 int err; 367 CALLBACK_MAYBE(s, on_chunk_complete); 368 return err; 369} 370 371 372/* Private */ 373 374 375void llhttp__debug(llhttp_t* s, const char* p, const char* endp, 376 const char* msg) { 377 if (p == endp) { 378 fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type, 379 s->flags, msg); 380 } else { 381 fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s, 382 s->type, s->flags, *p, msg); 383 } 384} 385