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