• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   uint8_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 
286 /* Callbacks */
287 
288 
llhttp__on_message_begin(llhttp_t * s,const char * p,const char * endp)289 int llhttp__on_message_begin(llhttp_t* s, const char* p, const char* endp) {
290   int err;
291   CALLBACK_MAYBE(s, on_message_begin);
292   return err;
293 }
294 
295 
llhttp__on_url(llhttp_t * s,const char * p,const char * endp)296 int llhttp__on_url(llhttp_t* s, const char* p, const char* endp) {
297   int err;
298   SPAN_CALLBACK_MAYBE(s, on_url, p, endp - p);
299   return err;
300 }
301 
302 
llhttp__on_url_complete(llhttp_t * s,const char * p,const char * endp)303 int llhttp__on_url_complete(llhttp_t* s, const char* p, const char* endp) {
304   int err;
305   CALLBACK_MAYBE(s, on_url_complete);
306   return err;
307 }
308 
309 
llhttp__on_status(llhttp_t * s,const char * p,const char * endp)310 int llhttp__on_status(llhttp_t* s, const char* p, const char* endp) {
311   int err;
312   SPAN_CALLBACK_MAYBE(s, on_status, p, endp - p);
313   return err;
314 }
315 
316 
llhttp__on_status_complete(llhttp_t * s,const char * p,const char * endp)317 int llhttp__on_status_complete(llhttp_t* s, const char* p, const char* endp) {
318   int err;
319   CALLBACK_MAYBE(s, on_status_complete);
320   return err;
321 }
322 
323 
llhttp__on_method(llhttp_t * s,const char * p,const char * endp)324 int llhttp__on_method(llhttp_t* s, const char* p, const char* endp) {
325   int err;
326   SPAN_CALLBACK_MAYBE(s, on_method, p, endp - p);
327   return err;
328 }
329 
330 
llhttp__on_method_complete(llhttp_t * s,const char * p,const char * endp)331 int llhttp__on_method_complete(llhttp_t* s, const char* p, const char* endp) {
332   int err;
333   CALLBACK_MAYBE(s, on_method_complete);
334   return err;
335 }
336 
337 
llhttp__on_version(llhttp_t * s,const char * p,const char * endp)338 int llhttp__on_version(llhttp_t* s, const char* p, const char* endp) {
339   int err;
340   SPAN_CALLBACK_MAYBE(s, on_version, p, endp - p);
341   return err;
342 }
343 
344 
llhttp__on_version_complete(llhttp_t * s,const char * p,const char * endp)345 int llhttp__on_version_complete(llhttp_t* s, const char* p, const char* endp) {
346   int err;
347   CALLBACK_MAYBE(s, on_version_complete);
348   return err;
349 }
350 
351 
llhttp__on_header_field(llhttp_t * s,const char * p,const char * endp)352 int llhttp__on_header_field(llhttp_t* s, const char* p, const char* endp) {
353   int err;
354   SPAN_CALLBACK_MAYBE(s, on_header_field, p, endp - p);
355   return err;
356 }
357 
358 
llhttp__on_header_field_complete(llhttp_t * s,const char * p,const char * endp)359 int llhttp__on_header_field_complete(llhttp_t* s, const char* p, const char* endp) {
360   int err;
361   CALLBACK_MAYBE(s, on_header_field_complete);
362   return err;
363 }
364 
365 
llhttp__on_header_value(llhttp_t * s,const char * p,const char * endp)366 int llhttp__on_header_value(llhttp_t* s, const char* p, const char* endp) {
367   int err;
368   SPAN_CALLBACK_MAYBE(s, on_header_value, p, endp - p);
369   return err;
370 }
371 
372 
llhttp__on_header_value_complete(llhttp_t * s,const char * p,const char * endp)373 int llhttp__on_header_value_complete(llhttp_t* s, const char* p, const char* endp) {
374   int err;
375   CALLBACK_MAYBE(s, on_header_value_complete);
376   return err;
377 }
378 
379 
llhttp__on_headers_complete(llhttp_t * s,const char * p,const char * endp)380 int llhttp__on_headers_complete(llhttp_t* s, const char* p, const char* endp) {
381   int err;
382   CALLBACK_MAYBE(s, on_headers_complete);
383   return err;
384 }
385 
386 
llhttp__on_message_complete(llhttp_t * s,const char * p,const char * endp)387 int llhttp__on_message_complete(llhttp_t* s, const char* p, const char* endp) {
388   int err;
389   CALLBACK_MAYBE(s, on_message_complete);
390   return err;
391 }
392 
393 
llhttp__on_body(llhttp_t * s,const char * p,const char * endp)394 int llhttp__on_body(llhttp_t* s, const char* p, const char* endp) {
395   int err;
396   SPAN_CALLBACK_MAYBE(s, on_body, p, endp - p);
397   return err;
398 }
399 
400 
llhttp__on_chunk_header(llhttp_t * s,const char * p,const char * endp)401 int llhttp__on_chunk_header(llhttp_t* s, const char* p, const char* endp) {
402   int err;
403   CALLBACK_MAYBE(s, on_chunk_header);
404   return err;
405 }
406 
407 
llhttp__on_chunk_extension_name(llhttp_t * s,const char * p,const char * endp)408 int llhttp__on_chunk_extension_name(llhttp_t* s, const char* p, const char* endp) {
409   int err;
410   SPAN_CALLBACK_MAYBE(s, on_chunk_extension_name, p, endp - p);
411   return err;
412 }
413 
414 
llhttp__on_chunk_extension_name_complete(llhttp_t * s,const char * p,const char * endp)415 int llhttp__on_chunk_extension_name_complete(llhttp_t* s, const char* p, const char* endp) {
416   int err;
417   CALLBACK_MAYBE(s, on_chunk_extension_name_complete);
418   return err;
419 }
420 
421 
llhttp__on_chunk_extension_value(llhttp_t * s,const char * p,const char * endp)422 int llhttp__on_chunk_extension_value(llhttp_t* s, const char* p, const char* endp) {
423   int err;
424   SPAN_CALLBACK_MAYBE(s, on_chunk_extension_value, p, endp - p);
425   return err;
426 }
427 
428 
llhttp__on_chunk_extension_value_complete(llhttp_t * s,const char * p,const char * endp)429 int llhttp__on_chunk_extension_value_complete(llhttp_t* s, const char* p, const char* endp) {
430   int err;
431   CALLBACK_MAYBE(s, on_chunk_extension_value_complete);
432   return err;
433 }
434 
435 
llhttp__on_chunk_complete(llhttp_t * s,const char * p,const char * endp)436 int llhttp__on_chunk_complete(llhttp_t* s, const char* p, const char* endp) {
437   int err;
438   CALLBACK_MAYBE(s, on_chunk_complete);
439   return err;
440 }
441 
442 
llhttp__on_reset(llhttp_t * s,const char * p,const char * endp)443 int llhttp__on_reset(llhttp_t* s, const char* p, const char* endp) {
444   int err;
445   CALLBACK_MAYBE(s, on_reset);
446   return err;
447 }
448 
449 
450 /* Private */
451 
452 
llhttp__debug(llhttp_t * s,const char * p,const char * endp,const char * msg)453 void llhttp__debug(llhttp_t* s, const char* p, const char* endp,
454                    const char* msg) {
455   if (p == endp) {
456     fprintf(stderr, "p=%p type=%d flags=%02x next=null debug=%s\n", s, s->type,
457             s->flags, msg);
458   } else {
459     fprintf(stderr, "p=%p type=%d flags=%02x next=%02x   debug=%s\n", s,
460             s->type, s->flags, *p, msg);
461   }
462 }
463