http.h (14148B)
1 /*
2 * Copyright (c) 2013 Joris Vink <joris@coders.se>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #if !defined(KORE_NO_HTTP)
18
19 #ifndef __H_HTTP_H
20 #define __H_HTTP_H
21
22 #include <sys/types.h>
23 #include <sys/queue.h>
24
25 #include "sha2.h"
26
27 #if defined(__cplusplus)
28 extern "C" {
29 #endif
30
31 /* Keep the http_populate_get symbol around. */
32 #define http_populate_get http_populate_qs
33
34 #define HTTP_KEEPALIVE_TIME 20
35 #define HTTP_HSTS_ENABLE 31536000
36 #define HTTP_HEADER_MAX_LEN 4096
37 #define HTTP_BODY_MAX_LEN 1024000
38 #define HTTP_URI_LEN 2000
39 #define HTTP_USERAGENT_LEN 256
40 #define HTTP_REFERER_LEN 256
41 #define HTTP_REQ_HEADER_MAX 25
42 #define HTTP_MAX_QUERY_ARGS 20
43 #define HTTP_MAX_COOKIES 10
44 #define HTTP_MAX_COOKIENAME 255
45 #define HTTP_HEADER_BUFSIZE 1024
46 #define HTTP_COOKIE_BUFSIZE 1024
47 #define HTTP_DATE_MAXSIZE 255
48 #define HTTP_REQUEST_LIMIT 1000
49 #define HTTP_REQUEST_MS 10
50 #define HTTP_BODY_DISK_PATH "tmp_files"
51 #define HTTP_BODY_DISK_OFFLOAD 0
52 #define HTTP_BODY_PATH_MAX 256
53 #define HTTP_BOUNDARY_MAX 80
54 #define HTTP_HEADER_TIMEOUT 10
55 #define HTTP_BODY_TIMEOUT 60
56
57 #define HTTP_ARG_TYPE_RAW 0
58 #define HTTP_ARG_TYPE_BYTE 1
59 #define HTTP_ARG_TYPE_INT16 2
60 #define HTTP_ARG_TYPE_UINT16 3
61 #define HTTP_ARG_TYPE_INT32 4
62 #define HTTP_ARG_TYPE_UINT32 5
63 #define HTTP_ARG_TYPE_STRING 6
64 #define HTTP_ARG_TYPE_INT64 7
65 #define HTTP_ARG_TYPE_UINT64 8
66 #define HTTP_ARG_TYPE_FLOAT 9
67 #define HTTP_ARG_TYPE_DOUBLE 10
68
69 #define HTTP_STATE_ERROR 0
70 #define HTTP_STATE_CONTINUE 1
71 #define HTTP_STATE_COMPLETE 2
72 #define HTTP_STATE_RETRY 3
73
74 struct http_runlock_queue {
75 struct http_request *req;
76 LIST_ENTRY(http_runlock_queue) list;
77 };
78
79 struct http_runlock {
80 struct http_request *owner;
81 LIST_HEAD(, http_runlock_queue) queue;
82 };
83
84 struct http_header {
85 char *header;
86 char *value;
87
88 TAILQ_ENTRY(http_header) list;
89 };
90
91 #define HTTP_COOKIE_HTTPONLY 0x0001
92 #define HTTP_COOKIE_SECURE 0x0002
93
94 struct http_cookie {
95 char *name;
96 char *value;
97 char *path;
98 char *domain;
99 u_int32_t maxage;
100 time_t expires;
101 u_int16_t flags;
102
103 TAILQ_ENTRY(http_cookie) list;
104 };
105
106 struct http_arg {
107 char *name;
108 char *s_value;
109
110 TAILQ_ENTRY(http_arg) list;
111 };
112
113 #define COPY_ARG_TYPE(v, t) \
114 do { \
115 *(t *)nout = v; \
116 } while (0)
117
118 #define COPY_ARG_INT64(type, sign) \
119 do { \
120 int err; \
121 type nval; \
122 nval = (type)kore_strtonum64(data, sign, &err); \
123 if (err != KORE_RESULT_OK) \
124 return (KORE_RESULT_ERROR); \
125 COPY_ARG_TYPE(nval, type); \
126 } while (0)
127
128 #define COPY_ARG_DOUBLE(min, max, type) \
129 do { \
130 int err; \
131 type nval; \
132 nval = kore_strtodouble(data, min, max, &err); \
133 if (err != KORE_RESULT_OK) \
134 return (KORE_RESULT_ERROR); \
135 COPY_ARG_TYPE(nval, type); \
136 } while (0)
137
138 #define COPY_ARG_INT(min, max, type) \
139 do { \
140 int err; \
141 int64_t nval; \
142 nval = kore_strtonum(data, 10, min, max, &err); \
143 if (err != KORE_RESULT_OK) \
144 return (KORE_RESULT_ERROR); \
145 COPY_ARG_TYPE(nval, type); \
146 } while (0)
147
148 #define COPY_AS_INTTYPE_64(type, sign) \
149 do { \
150 if (nout == NULL) \
151 return (KORE_RESULT_ERROR); \
152 COPY_ARG_INT64(type, sign); \
153 } while (0)
154
155 #define COPY_AS_INTTYPE(min, max, type) \
156 do { \
157 if (nout == NULL) \
158 return (KORE_RESULT_ERROR); \
159 COPY_ARG_INT(min, max, type); \
160 } while (0)
161
162 #define http_argument_get_string(r, n, o) \
163 http_argument_get(r, n, (void **)o, NULL, HTTP_ARG_TYPE_STRING)
164
165 #define http_argument_get_byte(r, n, o) \
166 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
167
168 #define http_argument_get_uint16(r, n, o) \
169 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
170
171 #define http_argument_get_int16(r, n, o) \
172 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
173
174 #define http_argument_get_uint32(r, n, o) \
175 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
176
177 #define http_argument_get_int32(r, n, o) \
178 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
179
180 #define http_argument_get_uint64(r, n, o) \
181 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
182
183 #define http_argument_get_int64(r, n, o) \
184 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
185
186 #define http_argument_get_float(r, n, o) \
187 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT)
188
189 #define http_argument_get_double(r, n, o) \
190 http_argument_get(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE)
191
192 #define http_request_header_byte(r, n, o) \
193 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_BYTE)
194
195 #define http_request_header_uint16(r, n, o) \
196 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT16)
197
198 #define http_request_header_int16(r, n, o) \
199 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT16)
200
201 #define http_request_header_uint32(r, n, o) \
202 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT32)
203
204 #define http_request_header_int32(r, n, o) \
205 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT32)
206
207 #define http_request_header_uint64(r, n, o) \
208 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_UINT64)
209
210 #define http_request_header_int64(r, n, o) \
211 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_INT64)
212
213 #define http_request_header_float(r, n, o) \
214 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_FLOAT)
215
216 #define http_request_header_double(r, n, o) \
217 http_request_header_get(r, n, NULL, o, HTTP_ARG_TYPE_DOUBLE)
218
219 struct http_file {
220 char *name;
221 char *filename;
222 size_t position;
223 size_t offset;
224 size_t length;
225 struct http_request *req;
226 TAILQ_ENTRY(http_file) list;
227 };
228
229 #define HTTP_METHOD_GET 0x0001
230 #define HTTP_METHOD_POST 0x0002
231 #define HTTP_METHOD_PUT 0x0004
232 #define HTTP_METHOD_DELETE 0x0010
233 #define HTTP_METHOD_HEAD 0x0020
234 #define HTTP_METHOD_OPTIONS 0x0040
235 #define HTTP_METHOD_PATCH 0x0080
236
237 #define HTTP_METHOD_ALL (HTTP_METHOD_GET | HTTP_METHOD_POST | \
238 HTTP_METHOD_PUT | HTTP_METHOD_DELETE | HTTP_METHOD_HEAD | \
239 HTTP_METHOD_OPTIONS | HTTP_METHOD_PATCH)
240
241 #define HTTP_REQUEST_COMPLETE 0x0001
242 #define HTTP_REQUEST_DELETE 0x0002
243 #define HTTP_REQUEST_SLEEPING 0x0004
244 #define HTTP_REQUEST_EXPECT_BODY 0x0020
245 #define HTTP_REQUEST_RETAIN_EXTRA 0x0040
246 #define HTTP_REQUEST_NO_CONTENT_LENGTH 0x0080
247 #define HTTP_REQUEST_AUTHED 0x0100
248
249 #define HTTP_VERSION_1_1 0x1000
250 #define HTTP_VERSION_1_0 0x2000
251
252 #define HTTP_VALIDATOR_IS_REQUEST 0x8000
253
254 #define HTTP_BODY_DIGEST_LEN 32
255 #define HTTP_BODY_DIGEST_STRLEN ((HTTP_BODY_DIGEST_LEN * 2) + 1)
256
257 #define HTTP_CAPTURE_GROUPS 17
258
259 struct reqcall;
260 struct kore_task;
261 struct http_client;
262
263 struct http_redirect {
264 regex_t rctx;
265 int status;
266 char *target;
267 TAILQ_ENTRY(http_redirect) list;
268 };
269
270 struct http_request {
271 u_int8_t method;
272 u_int8_t fsm_state;
273 u_int16_t flags;
274 u_int16_t status;
275 u_int64_t ms;
276 u_int64_t start;
277 u_int64_t end;
278 u_int64_t total;
279 const char *path;
280 const char *host;
281 const char *agent;
282 const char *referer;
283 struct connection *owner;
284 SHA2_CTX hashctx;
285 u_int8_t *headers;
286 struct kore_buf *http_body;
287 int http_body_fd;
288 char *http_body_path;
289 u_int64_t http_body_length;
290 u_int64_t http_body_offset;
291 u_int64_t content_length;
292 void *hdlr_extra;
293 size_t state_len;
294 char *query_string;
295 struct kore_route *rt;
296 struct http_runlock_queue *runlock;
297 void (*onfree)(struct http_request *);
298
299 #if defined(KORE_USE_PYTHON)
300 void *py_req;
301 void *py_coro;
302 void *py_validator;
303 struct reqcall *py_rqnext;
304 #endif
305
306 regmatch_t cgroups[HTTP_CAPTURE_GROUPS];
307 u_int8_t http_body_digest[HTTP_BODY_DIGEST_LEN];
308
309 #if defined(KORE_USE_CURL)
310 LIST_HEAD(, kore_curl) chandles;
311 #endif
312
313 #if defined(KORE_USE_TASKS)
314 LIST_HEAD(, kore_task) tasks;
315 #endif
316
317 #if defined(KORE_USE_PGSQL)
318 LIST_HEAD(, kore_pgsql) pgsqls;
319 #endif
320
321 TAILQ_HEAD(, http_cookie) req_cookies;
322 TAILQ_HEAD(, http_cookie) resp_cookies;
323 TAILQ_HEAD(, http_header) req_headers;
324 TAILQ_HEAD(, http_header) resp_headers;
325 TAILQ_HEAD(, http_arg) arguments;
326 TAILQ_HEAD(, http_file) files;
327 TAILQ_ENTRY(http_request) list;
328 TAILQ_ENTRY(http_request) olist;
329 };
330
331 #define KORE_HTTP_STATE(f) { #f, f }
332
333 struct http_state {
334 const char *name;
335 int (*cb)(struct http_request *);
336 };
337
338 struct http_media_type {
339 char *ext;
340 char *type;
341 LIST_ENTRY(http_media_type) list;
342 };
343
344 extern size_t http_body_max;
345 extern u_int16_t http_body_timeout;
346 extern u_int16_t http_header_max;
347 extern u_int16_t http_header_timeout;
348 extern u_int32_t http_request_ms;
349 extern u_int64_t http_hsts_enable;
350 extern u_int16_t http_keepalive_time;
351 extern u_int32_t http_request_limit;
352 extern u_int32_t http_request_count;
353 extern u_int64_t http_body_disk_offload;
354 extern int http_pretty_error;
355 extern char *http_body_disk_path;
356 extern struct kore_pool http_header_pool;
357
358 void kore_accesslog(struct http_request *);
359
360 void http_init(void);
361 void http_parent_init(void);
362 void http_cleanup(void);
363 void http_server_version(const char *);
364 void http_process(void);
365 const char *http_status_text(int);
366 const char *http_method_text(int);
367 time_t http_date_to_time(char *);
368 char *http_validate_header(char *);
369 int http_method_value(const char *);
370 void http_start_recv(struct connection *);
371 void http_request_free(struct http_request *);
372 void http_request_sleep(struct http_request *);
373 void http_request_wakeup(struct http_request *);
374 void http_process_request(struct http_request *);
375 int http_body_rewind(struct http_request *);
376 int http_media_register(const char *, const char *);
377 int http_check_timeout(struct connection *, u_int64_t);
378 ssize_t http_body_read(struct http_request *, void *, size_t);
379 int http_body_digest(struct http_request *, char *, size_t);
380
381 int http_redirect_add(struct kore_domain *,
382 const char *, int, const char *);
383 void http_response(struct http_request *, int, const void *, size_t);
384 void http_response_json(struct http_request *, int,
385 struct kore_json_item *);
386 void http_response_close(struct http_request *, int,
387 const void *, size_t);
388 void http_response_fileref(struct http_request *, int,
389 struct kore_fileref *);
390 void http_serveable(struct http_request *, const void *,
391 size_t, const char *, const char *);
392 void http_response_stream(struct http_request *, int, void *,
393 size_t, int (*cb)(struct netbuf *), void *);
394 int http_request_header(struct http_request *,
395 const char *, const char **);
396 void http_response_header(struct http_request *,
397 const char *, const char *);
398 int http_state_run(struct http_state *, u_int8_t,
399 struct http_request *);
400 int http_request_cookie(struct http_request *,
401 const char *, char **);
402 void http_response_cookie(struct http_request *, const char *,
403 const char *, const char *, time_t, u_int32_t,
404 struct http_cookie **);
405
406 void http_runlock_init(struct http_runlock *);
407 void http_runlock_release(struct http_runlock *,
408 struct http_request *);
409 int http_runlock_acquire(struct http_runlock *,
410 struct http_request *);
411
412 const char *http_media_type(const char *);
413 void *http_state_get(struct http_request *);
414 int http_state_exists(struct http_request *);
415 void http_state_cleanup(struct http_request *);
416 void *http_state_create(struct http_request *, size_t);
417
418 int http_header_recv(struct netbuf *);
419 int http_argument_urldecode(char *, int);
420 void http_populate_qs(struct http_request *);
421 void http_populate_post(struct http_request *);
422 void http_populate_multipart_form(struct http_request *);
423 void http_populate_cookies(struct http_request *);
424 int http_argument_get(struct http_request *,
425 const char *, void **, void *, int);
426 int http_request_header_get(struct http_request *,
427 const char *, void **, void *, int);
428
429 void http_file_rewind(struct http_file *);
430 ssize_t http_file_read(struct http_file *, void *, size_t);
431 struct http_file *http_file_lookup(struct http_request *, const char *);
432
433 enum http_status_code {
434 HTTP_STATUS_CONTINUE = 100,
435 HTTP_STATUS_SWITCHING_PROTOCOLS = 101,
436 HTTP_STATUS_OK = 200,
437 HTTP_STATUS_CREATED = 201,
438 HTTP_STATUS_ACCEPTED = 202,
439 HTTP_STATUS_NON_AUTHORITATIVE = 203,
440 HTTP_STATUS_NO_CONTENT = 204,
441 HTTP_STATUS_RESET_CONTENT = 205,
442 HTTP_STATUS_PARTIAL_CONTENT = 206,
443 HTTP_STATUS_MULTIPLE_CHOICES = 300,
444 HTTP_STATUS_MOVED_PERMANENTLY = 301,
445 HTTP_STATUS_FOUND = 302,
446 HTTP_STATUS_SEE_OTHER = 303,
447 HTTP_STATUS_NOT_MODIFIED = 304,
448 HTTP_STATUS_USE_PROXY = 305,
449 HTTP_STATUS_TEMPORARY_REDIRECT = 307,
450 HTTP_STATUS_BAD_REQUEST = 400,
451 HTTP_STATUS_UNAUTHORIZED = 401,
452 HTTP_STATUS_PAYMENT_REQUIRED = 402,
453 HTTP_STATUS_FORBIDDEN = 403,
454 HTTP_STATUS_NOT_FOUND = 404,
455 HTTP_STATUS_METHOD_NOT_ALLOWED = 405,
456 HTTP_STATUS_NOT_ACCEPTABLE = 406,
457 HTTP_STATUS_PROXY_AUTH_REQUIRED = 407,
458 HTTP_STATUS_REQUEST_TIMEOUT = 408,
459 HTTP_STATUS_CONFLICT = 409,
460 HTTP_STATUS_GONE = 410,
461 HTTP_STATUS_LENGTH_REQUIRED = 411,
462 HTTP_STATUS_PRECONDITION_FAILED = 412,
463 HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE = 413,
464 HTTP_STATUS_REQUEST_URI_TOO_LARGE = 414,
465 HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE = 415,
466 HTTP_STATUS_REQUEST_RANGE_INVALID = 416,
467 HTTP_STATUS_EXPECTATION_FAILED = 417,
468 HTTP_STATUS_MISDIRECTED_REQUEST = 421,
469 HTTP_STATUS_INTERNAL_ERROR = 500,
470 HTTP_STATUS_NOT_IMPLEMENTED = 501,
471 HTTP_STATUS_BAD_GATEWAY = 502,
472 HTTP_STATUS_SERVICE_UNAVAILABLE = 503,
473 HTTP_STATUS_GATEWAY_TIMEOUT = 504,
474 HTTP_STATUS_BAD_VERSION = 505
475 };
476 #if defined(__cplusplus)
477 }
478 #endif
479 #endif /* !__H_HTTP_H */
480
481 #endif /* ! KORE_NO_HTTP */