• 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   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 
llhttp_alloc(llhttp_type_t type)73 llhttp_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 
llhttp_free(llhttp_t * parser)79 void llhttp_free(llhttp_t* parser) {
80   free(parser);
81 }
82 
83 /* Some getters required to get stuff from the parser */
84 
llhttp_get_type(llhttp_t * parser)85 uint8_t llhttp_get_type(llhttp_t* parser) {
86   return parser->type;
87 }
88 
llhttp_get_http_major(llhttp_t * parser)89 uint8_t llhttp_get_http_major(llhttp_t* parser) {
90   return parser->http_major;
91 }
92 
llhttp_get_http_minor(llhttp_t * parser)93 uint8_t llhttp_get_http_minor(llhttp_t* parser) {
94   return parser->http_minor;
95 }
96 
llhttp_get_method(llhttp_t * parser)97 uint8_t llhttp_get_method(llhttp_t* parser) {
98   return parser->method;
99 }
100 
llhttp_get_status_code(llhttp_t * parser)101 int llhttp_get_status_code(llhttp_t* parser) {
102   return parser->status_code;
103 }
104 
llhttp_get_upgrade(llhttp_t * parser)105 uint8_t llhttp_get_upgrade(llhttp_t* parser) {
106   return parser->upgrade;
107 }
108 
109 #endif  // defined(__wasm__)
110 
111 
llhttp_reset(llhttp_t * parser)112 void 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 
llhttp_execute(llhttp_t * parser,const char * data,size_t len)127 llhttp_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 
llhttp_settings_init(llhttp_settings_t * settings)132 void llhttp_settings_init(llhttp_settings_t* settings) {
133   memset(settings, 0, sizeof(*settings));
134 }
135 
136 
llhttp_finish(llhttp_t * parser)137 llhttp_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 
llhttp_pause(llhttp_t * parser)162 void 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 
llhttp_resume(llhttp_t * parser)172 void llhttp_resume(llhttp_t* parser) {
173   if (parser->error != HPE_PAUSED) {
174     return;
175   }
176 
177   parser->error = 0;
178 }
179 
180 
llhttp_resume_after_upgrade(llhttp_t * parser)181 void 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 
llhttp_get_errno(const llhttp_t * parser)190 llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
191   return parser->error;
192 }
193 
194 
llhttp_get_error_reason(const llhttp_t * parser)195 const char* llhttp_get_error_reason(const llhttp_t* parser) {
196   return parser->reason;
197 }
198 
199 
llhttp_set_error_reason(llhttp_t * parser,const char * reason)200 void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
201   parser->reason = reason;
202 }
203 
204 
llhttp_get_error_pos(const llhttp_t * parser)205 const char* llhttp_get_error_pos(const llhttp_t* parser) {
206   return parser->error_pos;
207 }
208 
209 
llhttp_errno_name(llhttp_errno_t err)210 const 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 
llhttp_method_name(llhttp_method_t method)220 const 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 
llhttp_set_lenient_headers(llhttp_t * parser,int enabled)230 void 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 
llhttp_set_lenient_chunked_length(llhttp_t * parser,int enabled)239 void 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 
llhttp_set_lenient_keep_alive(llhttp_t * parser,int enabled)248 void 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 
llhttp_set_lenient_transfer_encoding(llhttp_t * parser,int enabled)256 void 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 
llhttp__on_message_begin(llhttp_t * s,const char * p,const char * endp)267 int 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 
llhttp__on_url(llhttp_t * s,const char * p,const char * endp)274 int 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 
llhttp__on_url_complete(llhttp_t * s,const char * p,const char * endp)281 int 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 
llhttp__on_status(llhttp_t * s,const char * p,const char * endp)288 int 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 
llhttp__on_status_complete(llhttp_t * s,const char * p,const char * endp)295 int 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 
llhttp__on_header_field(llhttp_t * s,const char * p,const char * endp)302 int 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 
llhttp__on_header_field_complete(llhttp_t * s,const char * p,const char * endp)309 int 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 
llhttp__on_header_value(llhttp_t * s,const char * p,const char * endp)316 int 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 
llhttp__on_header_value_complete(llhttp_t * s,const char * p,const char * endp)323 int 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 
llhttp__on_headers_complete(llhttp_t * s,const char * p,const char * endp)330 int 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 
llhttp__on_message_complete(llhttp_t * s,const char * p,const char * endp)337 int 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 
llhttp__on_body(llhttp_t * s,const char * p,const char * endp)344 int 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 
llhttp__on_chunk_header(llhttp_t * s,const char * p,const char * endp)351 int 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 
llhttp__on_chunk_parameters(llhttp_t * s,const char * p,const char * endp)358 int 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 
llhttp__on_chunk_complete(llhttp_t * s,const char * p,const char * endp)365 int 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 
llhttp__debug(llhttp_t * s,const char * p,const char * endp,const char * msg)375 void 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