xref: /third_party/node/deps/llhttp/src/api.c (revision 1cb0ef41)
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
33void 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
44extern int wasm_on_message_begin(llhttp_t * p);
45extern int wasm_on_url(llhttp_t* p, const char* at, size_t length);
46extern int wasm_on_status(llhttp_t* p, const char* at, size_t length);
47extern int wasm_on_header_field(llhttp_t* p, const char* at, size_t length);
48extern int wasm_on_header_value(llhttp_t* p, const char* at, size_t length);
49extern int wasm_on_headers_complete(llhttp_t * p, int status_code,
50                                    uint8_t upgrade, int should_keep_alive);
51extern int wasm_on_body(llhttp_t* p, const char* at, size_t length);
52extern int wasm_on_message_complete(llhttp_t * p);
53
54static 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
59const 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
73llhttp_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
79void llhttp_free(llhttp_t* parser) {
80  free(parser);
81}
82
83/* Some getters required to get stuff from the parser */
84
85uint8_t llhttp_get_type(llhttp_t* parser) {
86  return parser->type;
87}
88
89uint8_t llhttp_get_http_major(llhttp_t* parser) {
90  return parser->http_major;
91}
92
93uint8_t llhttp_get_http_minor(llhttp_t* parser) {
94  return parser->http_minor;
95}
96
97uint8_t llhttp_get_method(llhttp_t* parser) {
98  return parser->method;
99}
100
101int llhttp_get_status_code(llhttp_t* parser) {
102  return parser->status_code;
103}
104
105uint8_t llhttp_get_upgrade(llhttp_t* parser) {
106  return parser->upgrade;
107}
108
109#endif  // defined(__wasm__)
110
111
112void 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
127llhttp_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
132void llhttp_settings_init(llhttp_settings_t* settings) {
133  memset(settings, 0, sizeof(*settings));
134}
135
136
137llhttp_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
162void 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
172void llhttp_resume(llhttp_t* parser) {
173  if (parser->error != HPE_PAUSED) {
174    return;
175  }
176
177  parser->error = 0;
178}
179
180
181void 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
190llhttp_errno_t llhttp_get_errno(const llhttp_t* parser) {
191  return parser->error;
192}
193
194
195const char* llhttp_get_error_reason(const llhttp_t* parser) {
196  return parser->reason;
197}
198
199
200void llhttp_set_error_reason(llhttp_t* parser, const char* reason) {
201  parser->reason = reason;
202}
203
204
205const char* llhttp_get_error_pos(const llhttp_t* parser) {
206  return parser->error_pos;
207}
208
209
210const 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
220const 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
230void 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
239void 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
248void 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
256void 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
267int 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
274int 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
281int 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
288int 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
295int 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
302int 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
309int 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
316int 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
323int 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
330int 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
337int 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
344int 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
351int 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
358int 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
365int 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
375void 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