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 | |
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 | |
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 | |
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 | |
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 | |
100 | uint8_t llhttp_get_type(llhttp_t* parser) { |
101 | return parser->type; |
102 | } |
103 | |
104 | uint8_t llhttp_get_http_major(llhttp_t* parser) { |
105 | return parser->http_major; |
106 | } |
107 | |
108 | uint8_t llhttp_get_http_minor(llhttp_t* parser) { |
109 | return parser->http_minor; |
110 | } |
111 | |
112 | uint8_t llhttp_get_method(llhttp_t* parser) { |
113 | return parser->method; |
114 | } |
115 | |
116 | int llhttp_get_status_code(llhttp_t* parser) { |
117 | return parser->status_code; |
118 | } |
119 | |
120 | uint8_t llhttp_get_upgrade(llhttp_t* parser) { |
121 | return parser->upgrade; |
122 | } |
123 | |
124 | |
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 | |
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 | |
145 | void llhttp_settings_init(llhttp_settings_t* settings) { |
146 | memset(settings, 0, sizeof(*settings)); |
147 | } |
148 | |
149 | |
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 | |
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 | |
185 | void llhttp_resume(llhttp_t* parser) { |
186 | if (parser->error != HPE_PAUSED) { |
187 | return; |
188 | } |
189 | |
190 | parser->error = 0; |
191 | } |
192 | |
193 | |
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 | |
203 | llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) { |
204 | return parser->error; |
205 | } |
206 | |
207 | |
208 | const char* llhttp_get_error_reason(const llhttp_t* parser) { |
209 | return parser->reason; |
210 | } |
211 | |
212 | |
213 | void llhttp_set_error_reason(llhttp_t* parser, const char* reason) { |
214 | parser->reason = reason; |
215 | } |
216 | |
217 | |
218 | const char* llhttp_get_error_pos(const llhttp_t* parser) { |
219 | return parser->error_pos; |
220 | } |
221 | |
222 | |
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 | |
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 | |
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 | |
252 | void (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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
400 | int (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 | |
407 | int (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 | |
414 | int (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 | |
421 | int (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 | |
428 | int (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 | |
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 | |
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 | |
449 | int (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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |