llhttp-ffi 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,462 @@
1
+ // This software is licensed under the MIT License.
2
+
3
+ // Copyright Fedor Indutny, 2018.
4
+
5
+ // Permission is hereby granted, free of charge, to any person obtaining a
6
+ // copy of this software and associated documentation files (the
7
+ // "Software"), to deal in the Software without restriction, including
8
+ // without limitation the rights to use, copy, modify, merge, publish,
9
+ // distribute, sublicense, and/or sell copies of the Software, and to permit
10
+ // persons to whom the Software is furnished to do so, subject to the
11
+ // following conditions:
12
+
13
+ // The above copyright notice and this permission notice shall be included
14
+ // in all copies or substantial portions of the Software.
15
+
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17
+ // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
19
+ // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20
+ // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21
+ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22
+ // USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ #ifndef INCLUDE_LLHTTP_H_
25
+ #define INCLUDE_LLHTTP_H_
26
+
27
+ #define LLHTTP_VERSION_MAJOR 4
28
+ #define LLHTTP_VERSION_MINOR 0
29
+ #define LLHTTP_VERSION_PATCH 0
30
+
31
+ #ifndef LLHTTP_STRICT_MODE
32
+ # define LLHTTP_STRICT_MODE 0
33
+ #endif
34
+
35
+ #ifndef INCLUDE_LLHTTP_ITSELF_H_
36
+ #define INCLUDE_LLHTTP_ITSELF_H_
37
+ #ifdef __cplusplus
38
+ extern "C" {
39
+ #endif
40
+
41
+ #include <stdint.h>
42
+
43
+ typedef struct llhttp__internal_s llhttp__internal_t;
44
+ struct llhttp__internal_s {
45
+ int32_t _index;
46
+ void* _span_pos0;
47
+ void* _span_cb0;
48
+ int32_t error;
49
+ const char* reason;
50
+ const char* error_pos;
51
+ void* data;
52
+ void* _current;
53
+ uint64_t content_length;
54
+ uint8_t type;
55
+ uint8_t method;
56
+ uint8_t http_major;
57
+ uint8_t http_minor;
58
+ uint8_t header_state;
59
+ uint8_t lenient_flags;
60
+ uint8_t upgrade;
61
+ uint8_t finish;
62
+ uint16_t flags;
63
+ uint16_t status_code;
64
+ void* settings;
65
+ };
66
+
67
+ int llhttp__internal_init(llhttp__internal_t* s);
68
+ int llhttp__internal_execute(llhttp__internal_t* s, const char* p, const char* endp);
69
+
70
+ #ifdef __cplusplus
71
+ } /* extern "C" */
72
+ #endif
73
+ #endif /* INCLUDE_LLHTTP_ITSELF_H_ */
74
+
75
+ #ifndef LLLLHTTP_C_HEADERS_
76
+ #define LLLLHTTP_C_HEADERS_
77
+ #ifdef __cplusplus
78
+ extern "C" {
79
+ #endif
80
+
81
+ enum llhttp_errno {
82
+ HPE_OK = 0,
83
+ HPE_INTERNAL = 1,
84
+ HPE_STRICT = 2,
85
+ HPE_LF_EXPECTED = 3,
86
+ HPE_UNEXPECTED_CONTENT_LENGTH = 4,
87
+ HPE_CLOSED_CONNECTION = 5,
88
+ HPE_INVALID_METHOD = 6,
89
+ HPE_INVALID_URL = 7,
90
+ HPE_INVALID_CONSTANT = 8,
91
+ HPE_INVALID_VERSION = 9,
92
+ HPE_INVALID_HEADER_TOKEN = 10,
93
+ HPE_INVALID_CONTENT_LENGTH = 11,
94
+ HPE_INVALID_CHUNK_SIZE = 12,
95
+ HPE_INVALID_STATUS = 13,
96
+ HPE_INVALID_EOF_STATE = 14,
97
+ HPE_INVALID_TRANSFER_ENCODING = 15,
98
+ HPE_CB_MESSAGE_BEGIN = 16,
99
+ HPE_CB_HEADERS_COMPLETE = 17,
100
+ HPE_CB_MESSAGE_COMPLETE = 18,
101
+ HPE_CB_CHUNK_HEADER = 19,
102
+ HPE_CB_CHUNK_COMPLETE = 20,
103
+ HPE_PAUSED = 21,
104
+ HPE_PAUSED_UPGRADE = 22,
105
+ HPE_USER = 23
106
+ };
107
+ typedef enum llhttp_errno llhttp_errno_t;
108
+
109
+ enum llhttp_flags {
110
+ F_CONNECTION_KEEP_ALIVE = 0x1,
111
+ F_CONNECTION_CLOSE = 0x2,
112
+ F_CONNECTION_UPGRADE = 0x4,
113
+ F_CHUNKED = 0x8,
114
+ F_UPGRADE = 0x10,
115
+ F_CONTENT_LENGTH = 0x20,
116
+ F_SKIPBODY = 0x40,
117
+ F_TRAILING = 0x80,
118
+ F_TRANSFER_ENCODING = 0x200
119
+ };
120
+ typedef enum llhttp_flags llhttp_flags_t;
121
+
122
+ enum llhttp_lenient_flags {
123
+ LENIENT_HEADERS = 0x1,
124
+ LENIENT_CHUNKED_LENGTH = 0x2
125
+ };
126
+ typedef enum llhttp_lenient_flags llhttp_lenient_flags_t;
127
+
128
+ enum llhttp_type {
129
+ HTTP_BOTH = 0,
130
+ HTTP_REQUEST = 1,
131
+ HTTP_RESPONSE = 2
132
+ };
133
+ typedef enum llhttp_type llhttp_type_t;
134
+
135
+ enum llhttp_finish {
136
+ HTTP_FINISH_SAFE = 0,
137
+ HTTP_FINISH_SAFE_WITH_CB = 1,
138
+ HTTP_FINISH_UNSAFE = 2
139
+ };
140
+ typedef enum llhttp_finish llhttp_finish_t;
141
+
142
+ enum llhttp_method {
143
+ HTTP_DELETE = 0,
144
+ HTTP_GET = 1,
145
+ HTTP_HEAD = 2,
146
+ HTTP_POST = 3,
147
+ HTTP_PUT = 4,
148
+ HTTP_CONNECT = 5,
149
+ HTTP_OPTIONS = 6,
150
+ HTTP_TRACE = 7,
151
+ HTTP_COPY = 8,
152
+ HTTP_LOCK = 9,
153
+ HTTP_MKCOL = 10,
154
+ HTTP_MOVE = 11,
155
+ HTTP_PROPFIND = 12,
156
+ HTTP_PROPPATCH = 13,
157
+ HTTP_SEARCH = 14,
158
+ HTTP_UNLOCK = 15,
159
+ HTTP_BIND = 16,
160
+ HTTP_REBIND = 17,
161
+ HTTP_UNBIND = 18,
162
+ HTTP_ACL = 19,
163
+ HTTP_REPORT = 20,
164
+ HTTP_MKACTIVITY = 21,
165
+ HTTP_CHECKOUT = 22,
166
+ HTTP_MERGE = 23,
167
+ HTTP_MSEARCH = 24,
168
+ HTTP_NOTIFY = 25,
169
+ HTTP_SUBSCRIBE = 26,
170
+ HTTP_UNSUBSCRIBE = 27,
171
+ HTTP_PATCH = 28,
172
+ HTTP_PURGE = 29,
173
+ HTTP_MKCALENDAR = 30,
174
+ HTTP_LINK = 31,
175
+ HTTP_UNLINK = 32,
176
+ HTTP_SOURCE = 33,
177
+ HTTP_PRI = 34,
178
+ HTTP_DESCRIBE = 35,
179
+ HTTP_ANNOUNCE = 36,
180
+ HTTP_SETUP = 37,
181
+ HTTP_PLAY = 38,
182
+ HTTP_PAUSE = 39,
183
+ HTTP_TEARDOWN = 40,
184
+ HTTP_GET_PARAMETER = 41,
185
+ HTTP_SET_PARAMETER = 42,
186
+ HTTP_REDIRECT = 43,
187
+ HTTP_RECORD = 44,
188
+ HTTP_FLUSH = 45
189
+ };
190
+ typedef enum llhttp_method llhttp_method_t;
191
+
192
+ #define HTTP_ERRNO_MAP(XX) \
193
+ XX(0, OK, OK) \
194
+ XX(1, INTERNAL, INTERNAL) \
195
+ XX(2, STRICT, STRICT) \
196
+ XX(3, LF_EXPECTED, LF_EXPECTED) \
197
+ XX(4, UNEXPECTED_CONTENT_LENGTH, UNEXPECTED_CONTENT_LENGTH) \
198
+ XX(5, CLOSED_CONNECTION, CLOSED_CONNECTION) \
199
+ XX(6, INVALID_METHOD, INVALID_METHOD) \
200
+ XX(7, INVALID_URL, INVALID_URL) \
201
+ XX(8, INVALID_CONSTANT, INVALID_CONSTANT) \
202
+ XX(9, INVALID_VERSION, INVALID_VERSION) \
203
+ XX(10, INVALID_HEADER_TOKEN, INVALID_HEADER_TOKEN) \
204
+ XX(11, INVALID_CONTENT_LENGTH, INVALID_CONTENT_LENGTH) \
205
+ XX(12, INVALID_CHUNK_SIZE, INVALID_CHUNK_SIZE) \
206
+ XX(13, INVALID_STATUS, INVALID_STATUS) \
207
+ XX(14, INVALID_EOF_STATE, INVALID_EOF_STATE) \
208
+ XX(15, INVALID_TRANSFER_ENCODING, INVALID_TRANSFER_ENCODING) \
209
+ XX(16, CB_MESSAGE_BEGIN, CB_MESSAGE_BEGIN) \
210
+ XX(17, CB_HEADERS_COMPLETE, CB_HEADERS_COMPLETE) \
211
+ XX(18, CB_MESSAGE_COMPLETE, CB_MESSAGE_COMPLETE) \
212
+ XX(19, CB_CHUNK_HEADER, CB_CHUNK_HEADER) \
213
+ XX(20, CB_CHUNK_COMPLETE, CB_CHUNK_COMPLETE) \
214
+ XX(21, PAUSED, PAUSED) \
215
+ XX(22, PAUSED_UPGRADE, PAUSED_UPGRADE) \
216
+ XX(23, USER, USER) \
217
+
218
+
219
+ #define HTTP_METHOD_MAP(XX) \
220
+ XX(0, DELETE, DELETE) \
221
+ XX(1, GET, GET) \
222
+ XX(2, HEAD, HEAD) \
223
+ XX(3, POST, POST) \
224
+ XX(4, PUT, PUT) \
225
+ XX(5, CONNECT, CONNECT) \
226
+ XX(6, OPTIONS, OPTIONS) \
227
+ XX(7, TRACE, TRACE) \
228
+ XX(8, COPY, COPY) \
229
+ XX(9, LOCK, LOCK) \
230
+ XX(10, MKCOL, MKCOL) \
231
+ XX(11, MOVE, MOVE) \
232
+ XX(12, PROPFIND, PROPFIND) \
233
+ XX(13, PROPPATCH, PROPPATCH) \
234
+ XX(14, SEARCH, SEARCH) \
235
+ XX(15, UNLOCK, UNLOCK) \
236
+ XX(16, BIND, BIND) \
237
+ XX(17, REBIND, REBIND) \
238
+ XX(18, UNBIND, UNBIND) \
239
+ XX(19, ACL, ACL) \
240
+ XX(20, REPORT, REPORT) \
241
+ XX(21, MKACTIVITY, MKACTIVITY) \
242
+ XX(22, CHECKOUT, CHECKOUT) \
243
+ XX(23, MERGE, MERGE) \
244
+ XX(24, MSEARCH, M-SEARCH) \
245
+ XX(25, NOTIFY, NOTIFY) \
246
+ XX(26, SUBSCRIBE, SUBSCRIBE) \
247
+ XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
248
+ XX(28, PATCH, PATCH) \
249
+ XX(29, PURGE, PURGE) \
250
+ XX(30, MKCALENDAR, MKCALENDAR) \
251
+ XX(31, LINK, LINK) \
252
+ XX(32, UNLINK, UNLINK) \
253
+ XX(33, SOURCE, SOURCE) \
254
+ XX(34, PRI, PRI) \
255
+ XX(35, DESCRIBE, DESCRIBE) \
256
+ XX(36, ANNOUNCE, ANNOUNCE) \
257
+ XX(37, SETUP, SETUP) \
258
+ XX(38, PLAY, PLAY) \
259
+ XX(39, PAUSE, PAUSE) \
260
+ XX(40, TEARDOWN, TEARDOWN) \
261
+ XX(41, GET_PARAMETER, GET_PARAMETER) \
262
+ XX(42, SET_PARAMETER, SET_PARAMETER) \
263
+ XX(43, REDIRECT, REDIRECT) \
264
+ XX(44, RECORD, RECORD) \
265
+ XX(45, FLUSH, FLUSH) \
266
+
267
+
268
+
269
+ #ifdef __cplusplus
270
+ } /* extern "C" */
271
+ #endif
272
+ #endif /* LLLLHTTP_C_HEADERS_ */
273
+
274
+ #ifndef INCLUDE_LLHTTP_API_H_
275
+ #define INCLUDE_LLHTTP_API_H_
276
+ #ifdef __cplusplus
277
+ extern "C" {
278
+ #endif
279
+ #include <stddef.h>
280
+
281
+ typedef llhttp__internal_t llhttp_t;
282
+ typedef struct llhttp_settings_s llhttp_settings_t;
283
+
284
+ typedef int (*llhttp_data_cb)(llhttp_t*, const char *at, size_t length);
285
+ typedef int (*llhttp_cb)(llhttp_t*);
286
+
287
+ struct llhttp_settings_s {
288
+ /* Possible return values 0, -1, `HPE_PAUSED` */
289
+ llhttp_cb on_message_begin;
290
+
291
+ llhttp_data_cb on_url;
292
+ llhttp_data_cb on_status;
293
+ llhttp_data_cb on_header_field;
294
+ llhttp_data_cb on_header_value;
295
+
296
+ /* Possible return values:
297
+ * 0 - Proceed normally
298
+ * 1 - Assume that request/response has no body, and proceed to parsing the
299
+ * next message
300
+ * 2 - Assume absence of body (as above) and make `llhttp_execute()` return
301
+ * `HPE_PAUSED_UPGRADE`
302
+ * -1 - Error
303
+ * `HPE_PAUSED`
304
+ */
305
+ llhttp_cb on_headers_complete;
306
+
307
+ llhttp_data_cb on_body;
308
+
309
+ /* Possible return values 0, -1, `HPE_PAUSED` */
310
+ llhttp_cb on_message_complete;
311
+
312
+ /* When on_chunk_header is called, the current chunk length is stored
313
+ * in parser->content_length.
314
+ * Possible return values 0, -1, `HPE_PAUSED`
315
+ */
316
+ llhttp_cb on_chunk_header;
317
+ llhttp_cb on_chunk_complete;
318
+
319
+ llhttp_cb on_url_complete;
320
+ llhttp_cb on_status_complete;
321
+ llhttp_cb on_header_field_complete;
322
+ llhttp_cb on_header_value_complete;
323
+ };
324
+
325
+ /* Initialize the parser with specific type and user settings.
326
+ *
327
+ * NOTE: lifetime of `settings` has to be at least the same as the lifetime of
328
+ * the `parser` here. In practice, `settings` has to be either a static
329
+ * variable or be allocated with `malloc`, `new`, etc.
330
+ */
331
+ void llhttp_init(llhttp_t* parser, llhttp_type_t type,
332
+ const llhttp_settings_t* settings);
333
+
334
+ /* Reset an already initialized parser back to the start state, preserving the
335
+ * existing parser type, callback settings, user data, and lenient flags.
336
+ */
337
+ void llhttp_reset(llhttp_t* parser);
338
+
339
+ /* Initialize the settings object */
340
+ void llhttp_settings_init(llhttp_settings_t* settings);
341
+
342
+ /* Parse full or partial request/response, invoking user callbacks along the
343
+ * way.
344
+ *
345
+ * If any of `llhttp_data_cb` returns errno not equal to `HPE_OK` - the parsing
346
+ * interrupts, and such errno is returned from `llhttp_execute()`. If
347
+ * `HPE_PAUSED` was used as a errno, the execution can be resumed with
348
+ * `llhttp_resume()` call.
349
+ *
350
+ * In a special case of CONNECT/Upgrade request/response `HPE_PAUSED_UPGRADE`
351
+ * is returned after fully parsing the request/response. If the user wishes to
352
+ * continue parsing, they need to invoke `llhttp_resume_after_upgrade()`.
353
+ *
354
+ * NOTE: if this function ever returns a non-pause type error, it will continue
355
+ * to return the same error upon each successive call up until `llhttp_init()`
356
+ * is called.
357
+ */
358
+ llhttp_errno_t llhttp_execute(llhttp_t* parser, const char* data, size_t len);
359
+
360
+ /* This method should be called when the other side has no further bytes to
361
+ * send (e.g. shutdown of readable side of the TCP connection.)
362
+ *
363
+ * Requests without `Content-Length` and other messages might require treating
364
+ * all incoming bytes as the part of the body, up to the last byte of the
365
+ * connection. This method will invoke `on_message_complete()` callback if the
366
+ * request was terminated safely. Otherwise a error code would be returned.
367
+ */
368
+ llhttp_errno_t llhttp_finish(llhttp_t* parser);
369
+
370
+ /* Returns `1` if the incoming message is parsed until the last byte, and has
371
+ * to be completed by calling `llhttp_finish()` on EOF
372
+ */
373
+ int llhttp_message_needs_eof(const llhttp_t* parser);
374
+
375
+ /* Returns `1` if there might be any other messages following the last that was
376
+ * successfully parsed.
377
+ */
378
+ int llhttp_should_keep_alive(const llhttp_t* parser);
379
+
380
+ /* Make further calls of `llhttp_execute()` return `HPE_PAUSED` and set
381
+ * appropriate error reason.
382
+ *
383
+ * Important: do not call this from user callbacks! User callbacks must return
384
+ * `HPE_PAUSED` if pausing is required.
385
+ */
386
+ void llhttp_pause(llhttp_t* parser);
387
+
388
+ /* Might be called to resume the execution after the pause in user's callback.
389
+ * See `llhttp_execute()` above for details.
390
+ *
391
+ * Call this only if `llhttp_execute()` returns `HPE_PAUSED`.
392
+ */
393
+ void llhttp_resume(llhttp_t* parser);
394
+
395
+ /* Might be called to resume the execution after the pause in user's callback.
396
+ * See `llhttp_execute()` above for details.
397
+ *
398
+ * Call this only if `llhttp_execute()` returns `HPE_PAUSED_UPGRADE`
399
+ */
400
+ void llhttp_resume_after_upgrade(llhttp_t* parser);
401
+
402
+ /* Returns the latest return error */
403
+ llhttp_errno_t llhttp_get_errno(const llhttp_t* parser);
404
+
405
+ /* Returns the verbal explanation of the latest returned error.
406
+ *
407
+ * Note: User callback should set error reason when returning the error. See
408
+ * `llhttp_set_error_reason()` for details.
409
+ */
410
+ const char* llhttp_get_error_reason(const llhttp_t* parser);
411
+
412
+ /* Assign verbal description to the returned error. Must be called in user
413
+ * callbacks right before returning the errno.
414
+ *
415
+ * Note: `HPE_USER` error code might be useful in user callbacks.
416
+ */
417
+ void llhttp_set_error_reason(llhttp_t* parser, const char* reason);
418
+
419
+ /* Returns the pointer to the last parsed byte before the returned error. The
420
+ * pointer is relative to the `data` argument of `llhttp_execute()`.
421
+ *
422
+ * Note: this method might be useful for counting the number of parsed bytes.
423
+ */
424
+ const char* llhttp_get_error_pos(const llhttp_t* parser);
425
+
426
+ /* Returns textual name of error code */
427
+ const char* llhttp_errno_name(llhttp_errno_t err);
428
+
429
+ /* Returns textual name of HTTP method */
430
+ const char* llhttp_method_name(llhttp_method_t method);
431
+
432
+
433
+ /* Enables/disables lenient header value parsing (disabled by default).
434
+ *
435
+ * Lenient parsing disables header value token checks, extending llhttp's
436
+ * protocol support to highly non-compliant clients/server. No
437
+ * `HPE_INVALID_HEADER_TOKEN` will be raised for incorrect header values when
438
+ * lenient parsing is "on".
439
+ *
440
+ * **(USE AT YOUR OWN RISK)**
441
+ */
442
+ void llhttp_set_lenient_headers(llhttp_t* parser, int enabled);
443
+
444
+
445
+ /* Enables/disables lenient handling of conflicting `Transfer-Encoding` and
446
+ * `Content-Length` headers (disabled by default).
447
+ *
448
+ * Normally `llhttp` would error when `Transfer-Encoding` is present in
449
+ * conjunction with `Content-Length`. This error is important to prevent HTTP
450
+ * request smuggling, but may be less desirable for small number of cases
451
+ * involving legacy servers.
452
+ *
453
+ * **(USE AT YOUR OWN RISK)**
454
+ */
455
+ void llhttp_set_lenient_chunked_length(llhttp_t* parser, int enabled);
456
+
457
+ #ifdef __cplusplus
458
+ } /* extern "C" */
459
+ #endif
460
+ #endif /* INCLUDE_LLHTTP_API_H_ */
461
+
462
+ #endif /* INCLUDE_LLHTTP_H_ */