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
llhttp_init(llhttp_t * parser,llhttp_type_t type,const llhttp_settings_t * settings)33 void 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
44 extern int wasm_on_message_begin(llhttp_t * p);
45 extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
46 extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
47 extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
48 extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
49 extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
50 uint8_t upgrade, int should_keep_alive);
51 extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
52 extern int wasm_on_message_complete(llhttp_t * p);
53
wasm_on_headers_complete_wrap(llhttp_t * p)54 static 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
59 const llhttp_settings_t wasm_settings = {
60 wasm_on_message_begin,
61 wasm_on_url,
62 wasm_on_status,
63 NULL,
64 NULL,
65 wasm_on_header_field,
66 wasm_on_header_value,
67 NULL,
68 NULL,
69 wasm_on_headers_complete_wrap,
70 wasm_on_body,
71 wasm_on_message_complete,
72 NULL,
73 NULL,
74 NULL,
75 NULL,
76 NULL,
77 NULL,
78 NULL,
79 NULL,
80 NULL,
81 NULL,
82 NULL,
83 };
84
85
llhttp_alloc(llhttp_type_t type)86 llhttp_t* llhttp_alloc(llhttp_type_t type) {
87 llhttp_t* parser = malloc(sizeof(llhttp_t));
88 llhttp_init(parser, type, &wasm_settings);
89 return parser;
90 }
91
llhttp_free(llhttp_t * parser)92 void llhttp_free(llhttp_t* parser) {
93 free(parser);
94 }
95
96 #endif // defined(__wasm__)
97
98 /* Some getters required to get stuff from the parser */
99
llhttp_get_type(llhttp_t * parser)100 uint8_t llhttp_get_type(llhttp_t* parser) {
101 return parser->type;
102 }
103
llhttp_get_http_major(llhttp_t * parser)104 uint8_t llhttp_get_http_major(llhttp_t* parser) {
105 return parser->http_major;
106 }
107
llhttp_get_http_minor(llhttp_t * parser)108 uint8_t llhttp_get_http_minor(llhttp_t* parser) {
109 return parser->http_minor;
110 }
111
llhttp_get_method(llhttp_t * parser)112 uint8_t llhttp_get_method(llhttp_t* parser) {
113 return parser->method;
114 }
115
llhttp_get_status_code(llhttp_t * parser)116 int llhttp_get_status_code(llhttp_t* parser) {
117 return parser->status_code;
118 }
119
llhttp_get_upgrade(llhttp_t * parser)120 uint8_t llhttp_get_upgrade(llhttp_t* parser) {
121 return parser->upgrade;
122 }
123
124
llhttp_reset(llhttp_t * parser)125 void llhttp_reset(llhttp_t* parser) {
126 llhttp_type_t type = parser->type;
127 const llhttp_settings_t* settings = parser->settings;
128 void* data = parser->data;
129 uint16_t lenient_flags = parser->lenient_flags;
130
131 llhttp__internal_init(parser);
132
133 parser->type = type;
134 parser->settings = (void*) settings;
135 parser->data = data;
136 parser->lenient_flags = lenient_flags;
137 }
138
139
llhttp_execute(llhttp_t * parser,const char * data,size_t len)140 llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len) {
141 return llhttp__internal_execute(parser, data, data + len);
142 }
143
144
llhttp_settings_init(llhttp_settings_t * settings)145 void llhttp_settings_init(llhttp_settings_t* settings) {
146 memset(settings, 0, sizeof(*settings));
147 }
148
149
llhttp_finish(llhttp_t * parser)150 llhttp_errno_t llhttp_finish(llhttp_t* parser) {
151 int err;
152
153 /* We're in an error state. Don't bother doing anything. */
154 if (parser->error != 0) {
155 return 0;
156 }
157
158 switch (parser->finish) {
159 case HTTP_FINISH_SAFE_WITH_CB:
160 CALLBACK_MAYBE(parser, on_message_complete);
161 if (err != HPE_OK) return err;
162
163 /* FALLTHROUGH */
164 case HTTP_FINISH_SAFE:
165 return HPE_OK;
166 case HTTP_FINISH_UNSAFE:
167 parser->reason = "Invalid EOF state";
168 return HPE_INVALID_EOF_STATE;
169 default:
170 abort();
171 }
172 }
173
174
llhttp_pause(llhttp_t * parser)175 void llhttp_pause(llhttp_t* parser) {
176 if (parser->error != HPE_OK) {
177 return;
178 }
179
180 parser->error = HPE_PAUSED;
181 parser->reason = "Paused";
182 }
183
184
llhttp_resume(llhttp_t * parser)185 void llhttp_resume(llhttp_t* parser) {
186 if (parser->error != HPE_PAUSED) {
187 return;
188 }
189
190 parser->error = 0;
191 }
192
193
llhttp_resume_after_upgrade(llhttp_t * parser)194 void llhttp_resume_after_upgrade(llhttp_t* parser) {
195 if (parser->error != HPE_PAUSED_UPGRADE) {
196 return;
197 }
198
199 parser->error = 0;
200 }
201
202
llhttp_get_errno(const llhttp_t * parser)203 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
204 return parser->error;
205 }
206
207
llhttp_get_error_reason(const llhttp_t * parser)208 const char* llhttp_get_error_reason(const llhttp_t* parser) {
209 return parser->reason;
210 }
211
212
llhttp_set_error_reason(llhttp_t * parser,const char * reason)213 void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
214 parser->reason = reason;
215 }
216
217
llhttp_get_error_pos(const llhttp_t * parser)218 const char* llhttp_get_error_pos(const llhttp_t* parser) {
219 return parser->error_pos;
220 }
221
222
llhttp_errno_name(llhttp_errno_t err)223 const char* llhttp_errno_name(llhttp_errno_t err) {
224 #define HTTP_ERRNO_GEN(CODE, NAME, _) case HPE_##NAME: return "HPE_" #NAME;
225 switch (err) {
226 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
227 default: abort();
228 }
229 #undef HTTP_ERRNO_GEN
230 }
231
232
llhttp_method_name(llhttp_method_t method)233 const char* llhttp_method_name(llhttp_method_t method) {
234 #define HTTP_METHOD_GEN(NUM, NAME, STRING) case HTTP_##NAME: return #STRING;
235 switch (method) {
236 HTTP_ALL_METHOD_MAP(HTTP_METHOD_GEN)
237 default: abort();
238 }
239 #undef HTTP_METHOD_GEN
240 }
241
llhttp_status_name(llhttp_status_t status)242 const char* llhttp_status_name(llhttp_status_t status) {
243 #define HTTP_STATUS_GEN(NUM, NAME, STRING) case HTTP_STATUS_##NAME: return #STRING;
244 switch (status) {
245 HTTP_STATUS_MAP(HTTP_STATUS_GEN)
246 default: abort();
247 }
248 #undef HTTP_STATUS_GEN
249 }
250
251
llhttp_set_lenient_headers(llhttp_t * parser,int enabled)252 void llhttp_set_lenient_headers(llhttp_t* parser, int enabled) {
253 if (enabled) {
254 parser->lenient_flags |= LENIENT_HEADERS;
255 } else {
256 parser->lenient_flags &= ~LENIENT_HEADERS;
257 }
258 }
259
260
llhttp_set_lenient_chunked_length(llhttp_t * parser,int enabled)261 void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled) {
262 if (enabled) {
263 parser->lenient_flags |= LENIENT_CHUNKED_LENGTH;
264 } else {
265 parser->lenient_flags &= ~LENIENT_CHUNKED_LENGTH;
266 }
267 }
268
269
llhttp_set_lenient_keep_alive(llhttp_t * parser,int enabled)270 void llhttp_set_lenient_keep_alive(llhttp_t* parser, int enabled) {
271 if (enabled) {
272 parser->lenient_flags |= LENIENT_KEEP_ALIVE;
273 } else {
274 parser->lenient_flags &= ~LENIENT_KEEP_ALIVE;
275 }
276 }
277
llhttp_set_lenient_transfer_encoding(llhttp_t * parser,int enabled)278 void llhttp_set_lenient_transfer_encoding(llhttp_t* parser, int enabled) {
279 if (enabled) {
280 parser->lenient_flags |= LENIENT_TRANSFER_ENCODING;
281 } else {
282 parser->lenient_flags &= ~LENIENT_TRANSFER_ENCODING;
283 }
284 }
285
llhttp_set_lenient_version(llhttp_t * parser,int enabled)286 void llhttp_set_lenient_version(llhttp_t* parser, int enabled) {
287 if (enabled) {
288 parser->lenient_flags |= LENIENT_VERSION;
289 } else {
290 parser->lenient_flags &= ~LENIENT_VERSION;
291 }
292 }
293
llhttp_set_lenient_data_after_close(llhttp_t * parser,int enabled)294 void llhttp_set_lenient_data_after_close(llhttp_t* parser, int enabled) {
295 if (enabled) {
296 parser->lenient_flags |= LENIENT_DATA_AFTER_CLOSE;
297 } else {
298 parser->lenient_flags &= ~LENIENT_DATA_AFTER_CLOSE;
299 }
300 }
301
llhttp_set_lenient_optional_lf_after_cr(llhttp_t * parser,int enabled)302 void llhttp_set_lenient_optional_lf_after_cr(llhttp_t* parser, int enabled) {
303 if (enabled) {
304 parser->lenient_flags |= LENIENT_OPTIONAL_LF_AFTER_CR;
305 } else {
306 parser->lenient_flags &= ~LENIENT_OPTIONAL_LF_AFTER_CR;
307 }
308 }
309
llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t * parser,int enabled)310 void llhttp_set_lenient_optional_crlf_after_chunk(llhttp_t* parser, int enabled) {
311 if (enabled) {
312 parser->lenient_flags |= LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
313 } else {
314 parser->lenient_flags &= ~LENIENT_OPTIONAL_CRLF_AFTER_CHUNK;
315 }
316 }
317
llhttp_set_lenient_optional_cr_before_lf(llhttp_t * parser,int enabled)318 void llhttp_set_lenient_optional_cr_before_lf(llhttp_t* parser, int enabled) {
319 if (enabled) {
320 parser->lenient_flags |= LENIENT_OPTIONAL_CR_BEFORE_LF;
321 } else {
322 parser->lenient_flags &= ~LENIENT_OPTIONAL_CR_BEFORE_LF;
323 }
324 }
325
llhttp_set_lenient_spaces_after_chunk_size(llhttp_t * parser,int enabled)326 void llhttp_set_lenient_spaces_after_chunk_size(llhttp_t* parser, int enabled) {
327 if (enabled) {
328 parser->lenient_flags |= LENIENT_SPACES_AFTER_CHUNK_SIZE;
329 } else {
330 parser->lenient_flags &= ~LENIENT_SPACES_AFTER_CHUNK_SIZE;
331 }
332 }
333
334 /* Callbacks */
335
336
llhttp__on_message_begin(llhttp_t * s,const char * p,const char * endp)337 int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
338 int err;
339 CALLBACK_MAYBE(s, on_message_begin);
340 return err;
341 }
342
343
llhttp__on_url(llhttp_t * s,const char * p,const char * endp)344 int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
345 int err;
346 SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
347 return err;
348 }
349
350
llhttp__on_url_complete(llhttp_t * s,const char * p,const char * endp)351 int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
352 int err;
353 CALLBACK_MAYBE(s, on_url_complete);
354 return err;
355 }
356
357
llhttp__on_status(llhttp_t * s,const char * p,const char * endp)358 int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
359 int err;
360 SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
361 return err;
362 }
363
364
llhttp__on_status_complete(llhttp_t * s,const char * p,const char * endp)365 int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
366 int err;
367 CALLBACK_MAYBE(s, on_status_complete);
368 return err;
369 }
370
371
llhttp__on_method(llhttp_t * s,const char * p,const char * endp)372 int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) {
373 int err;
374 SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p);
375 return err;
376 }
377
378
llhttp__on_method_complete(llhttp_t * s,const char * p,const char * endp)379 int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) {
380 int err;
381 CALLBACK_MAYBE(s, on_method_complete);
382 return err;
383 }
384
385
llhttp__on_version(llhttp_t * s,const char * p,const char * endp)386 int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) {
387 int err;
388 SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p);
389 return err;
390 }
391
392
llhttp__on_version_complete(llhttp_t * s,const char * p,const char * endp)393 int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) {
394 int err;
395 CALLBACK_MAYBE(s, on_version_complete);
396 return err;
397 }
398
399
llhttp__on_header_field(llhttp_t * s,const char * p,const char * endp)400 int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
401 int err;
402 SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
403 return err;
404 }
405
406
llhttp__on_header_field_complete(llhttp_t * s,const char * p,const char * endp)407 int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
408 int err;
409 CALLBACK_MAYBE(s, on_header_field_complete);
410 return err;
411 }
412
413
llhttp__on_header_value(llhttp_t * s,const char * p,const char * endp)414 int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
415 int err;
416 SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
417 return err;
418 }
419
420
llhttp__on_header_value_complete(llhttp_t * s,const char * p,const char * endp)421 int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
422 int err;
423 CALLBACK_MAYBE(s, on_header_value_complete);
424 return err;
425 }
426
427
llhttp__on_headers_complete(llhttp_t * s,const char * p,const char * endp)428 int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
429 int err;
430 CALLBACK_MAYBE(s, on_headers_complete);
431 return err;
432 }
433
434
llhttp__on_message_complete(llhttp_t * s,const char * p,const char * endp)435 int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
436 int err;
437 CALLBACK_MAYBE(s, on_message_complete);
438 return err;
439 }
440
441
llhttp__on_body(llhttp_t * s,const char * p,const char * endp)442 int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
443 int err;
444 SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
445 return err;
446 }
447
448
llhttp__on_chunk_header(llhttp_t * s,const char * p,const char * endp)449 int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
450 int err;
451 CALLBACK_MAYBE(s, on_chunk_header);
452 return err;
453 }
454
455
llhttp__on_chunk_extension_name(llhttp_t * s,const char * p,const char * endp)456 int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) {
457 int err;
458 SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p);
459 return err;
460 }
461
462
llhttp__on_chunk_extension_name_complete(llhttp_t * s,const char * p,const char * endp)463 int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) {
464 int err;
465 CALLBACK_MAYBE(s, on_chunk_extension_name_complete);
466 return err;
467 }
468
469
llhttp__on_chunk_extension_value(llhttp_t * s,const char * p,const char * endp)470 int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) {
471 int err;
472 SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p);
473 return err;
474 }
475
476
llhttp__on_chunk_extension_value_complete(llhttp_t * s,const char * p,const char * endp)477 int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) {
478 int err;
479 CALLBACK_MAYBE(s, on_chunk_extension_value_complete);
480 return err;
481 }
482
483
llhttp__on_chunk_complete(llhttp_t * s,const char * p,const char * endp)484 int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
485 int err;
486 CALLBACK_MAYBE(s, on_chunk_complete);
487 return err;
488 }
489
490
llhttp__on_reset(llhttp_t * s,const char * p,const char * endp)491 int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) {
492 int err;
493 CALLBACK_MAYBE(s, on_reset);
494 return err;
495 }
496
497
498 /* Private */
499
500
llhttp__debug(llhttp_t * s,const char * p,const char * endp,const char * msg)501 void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
502 const char* msg) {
503 if (p == endp) {
504 fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
505 s->flags, msg);
506 } else {
507 fprintf(stderr, "p=%p type=%d flags=%02x next=%02x debug=%s\n", s,
508 s->type, s->flags, *p, msg);
509 }
510 }
511