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