kore

Kore is a web application platform for writing scalable, concurrent web based processes in C or Python.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

http.c (59817B)



      1 /*
      2  * Copyright (c) 2013-2022 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 #include <sys/param.h>
     18 #include <sys/types.h>
     19 
     20 #include <sys/socket.h>
     21 #include <netinet/in.h>
     22 
     23 #include <ctype.h>
     24 #include <fcntl.h>
     25 #include <inttypes.h>
     26 #include <float.h>
     27 #include <time.h>
     28 #include <stdio.h>
     29 #include <string.h>
     30 
     31 #include "kore.h"
     32 #include "http.h"
     33 
     34 #if defined(KORE_USE_PYTHON)
     35 #include "python_api.h"
     36 #endif
     37 
     38 #if defined(KORE_USE_PGSQL)
     39 #include "pgsql.h"
     40 #endif
     41 
     42 #if defined(KORE_USE_TASKS)
     43 #include "tasks.h"
     44 #endif
     45 
     46 #if defined(KORE_USE_CURL)
     47 #include "curl.h"
     48 #endif
     49 
     50 static struct {
     51 	const char	*ext;
     52 	const char	*type;
     53 } builtin_media[] = {
     54 	{ "gif",	"image/gif" },
     55 	{ "png",	"image/png" },
     56 	{ "jpeg",	"image/jpeg" },
     57 	{ "jpg",	"image/jpeg" },
     58 	{ "zip",	"application/zip" },
     59 	{ "pdf",	"application/pdf" },
     60 	{ "json",	"application/json" },
     61 	{ "js",		"application/javascript" },
     62 	{ "htm",	"text/html" },
     63 	{ "txt",	"text/plain" },
     64 	{ "css",	"text/css" },
     65 	{ "html",	"text/html" },
     66 	{ NULL,		NULL },
     67 };
     68 
     69 #define HTTP_MAP_LIMIT		127
     70 
     71 /*
     72  * token      = 1*<any CHAR except CTLs or separators>
     73  * separators = "(" | ")" | "<" | ">" | "@"
     74  *            | "," | ";" | ":" | "\" | <">
     75  *            | "/" | "[" | "]" | "?" | "="
     76  *            | "{" | "}" | SP | HT
     77  */
     78 static const char http_token[] = {
     79 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     80 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     81 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     82 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     83 	0x00, '!' , 0x00, '#' , '$' , '%' , '&' , '\'',
     84 	0x00, 0x00, '*' , '+' , 0x00, '-' , '.' , 0x00,
     85 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
     86 	'8' , '9' , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     87 	0x00, 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
     88 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
     89 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
     90 	'X' , 'Y' , 'Z' , 0x00, 0x00, 0x00, '^' , '_' ,
     91 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
     92 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
     93 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
     94 	'x' , 'y' , 'z' , 0x00, '|' , 0x00, '~' , 0x00
     95 };
     96 
     97 /*
     98  * field-content  = <the OCTETs making up the field-value
     99  *                   and consisting of either *TEXT or combinations
    100  *                   of token, separators, and quoted-string>
    101  */
    102 static const char http_field_content[] = {
    103 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    104 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    105 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    106 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    107 	' ' , '!' , '"' , '#' , '$' , '%' , '&' , '\'',
    108 	'(' , ')' , '*' , '+' , ',' , '-' , '.' , '/' ,
    109 	'0' , '1' , '2' , '3' , '4' , '5' , '6' , '7' ,
    110 	'8' , '9' , ':' , ';' , '<' , '=' , '>' , '?' ,
    111 	'@' , 'A' , 'B' , 'C' , 'D' , 'E' , 'F' , 'G' ,
    112 	'H' , 'I' , 'J' , 'K' , 'L' , 'M' , 'N' , 'O' ,
    113 	'P' , 'Q' , 'R' , 'S' , 'T' , 'U' , 'V' , 'W' ,
    114 	'X' , 'Y' , 'Z' , '[' , '\\', ']' , '^' , '_' ,
    115 	'`' , 'a' , 'b' , 'c' , 'd' , 'e' , 'f' , 'g' ,
    116 	'h' , 'i' , 'j' , 'k' , 'l' , 'm' , 'n' , 'o' ,
    117 	'p' , 'q' , 'r' , 's' , 't' , 'u' , 'v' , 'w' ,
    118 	'x' , 'y' , 'z' , '{' , '|' , '}' , '~' , 0x00
    119 };
    120 
    121 /*
    122  * Fixed "pretty" HTTP error HTML page.
    123  */
    124 static const char *pretty_error_fmt =
    125 	"<html>\n<head>\n\t<title>%d %s</title>"
    126 	"</head>\n<body>\n\t"
    127 	"<h1>%d %s</h1>\n"
    128 	"</body>\n</html>\n";
    129 
    130 static int	http_body_recv(struct netbuf *);
    131 static int	http_release_buffer(struct netbuf *);
    132 static void	http_error_response(struct connection *, int);
    133 static int	http_data_convert(void *, void **, void *, int);
    134 static void	http_write_response_cookie(struct http_cookie *);
    135 static int	http_body_update(struct http_request *, const void *, size_t);
    136 static void	http_argument_add(struct http_request *, char *, char *,
    137 		    int, int);
    138 static int	http_check_redirect(struct http_request *,
    139 		    struct kore_domain *);
    140 static void	http_response_normal(struct http_request *,
    141 		    struct connection *, int, const void *, size_t);
    142 static void	multipart_add_field(struct http_request *, struct kore_buf *,
    143 		    char *, const char *, const int);
    144 static void	multipart_file_add(struct http_request *, struct kore_buf *,
    145 		    const char *, const char *, const char *, const int);
    146 static int	multipart_find_data(struct kore_buf *, struct kore_buf *,
    147 		    size_t *, struct http_request *, const void *, size_t);
    148 static int	multipart_parse_headers(struct http_request *,
    149 		    struct kore_buf *, struct kore_buf *,
    150 		    const char *, const int);
    151 
    152 static struct http_request	*http_request_new(struct connection *,
    153 				    const char *, const char *, char *,
    154 				    const char *);
    155 
    156 static struct kore_buf			*header_buf;
    157 static struct kore_buf			*ckhdr_buf;
    158 static char				http_version[64];
    159 static u_int16_t			http_version_len;
    160 static TAILQ_HEAD(, http_request)	http_requests;
    161 static TAILQ_HEAD(, http_request)	http_requests_sleeping;
    162 static LIST_HEAD(, http_media_type)	http_media_types;
    163 static struct kore_pool			http_request_pool;
    164 static struct kore_pool			http_cookie_pool;
    165 static struct kore_pool			http_body_path;
    166 static struct kore_pool			http_rlq_pool;
    167 
    168 struct kore_pool			http_header_pool;
    169 
    170 int		http_pretty_error = 0;
    171 u_int32_t	http_request_count = 0;
    172 u_int32_t	http_request_ms = HTTP_REQUEST_MS;
    173 u_int16_t	http_body_timeout = HTTP_BODY_TIMEOUT;
    174 u_int32_t	http_request_limit = HTTP_REQUEST_LIMIT;
    175 u_int64_t	http_hsts_enable = HTTP_HSTS_ENABLE;
    176 u_int16_t	http_header_max = HTTP_HEADER_MAX_LEN;
    177 u_int16_t	http_keepalive_time = HTTP_KEEPALIVE_TIME;
    178 u_int16_t	http_header_timeout = HTTP_HEADER_TIMEOUT;
    179 
    180 size_t		http_body_max = HTTP_BODY_MAX_LEN;
    181 char		*http_body_disk_path = HTTP_BODY_DISK_PATH;
    182 u_int64_t	http_body_disk_offload = HTTP_BODY_DISK_OFFLOAD;
    183 
    184 void
    185 http_parent_init(void)
    186 {
    187 	LIST_INIT(&http_media_types);
    188 }
    189 
    190 void
    191 http_init(void)
    192 {
    193 	int		prealloc, l, i;
    194 
    195 	TAILQ_INIT(&http_requests);
    196 	TAILQ_INIT(&http_requests_sleeping);
    197 
    198 	header_buf = kore_buf_alloc(HTTP_HEADER_BUFSIZE);
    199 	ckhdr_buf = kore_buf_alloc(HTTP_COOKIE_BUFSIZE);
    200 
    201 	if (!http_version_len) {
    202 		l = snprintf(http_version, sizeof(http_version),
    203 		    "server: kore (%s)\r\n", kore_version);
    204 		if (l == -1 || (size_t)l >= sizeof(http_version))
    205 			fatal("http_init(): http_version buffer too small");
    206 
    207 		http_version_len = l;
    208 	}
    209 
    210 	prealloc = MIN((worker_max_connections / 10), 1000);
    211 	kore_pool_init(&http_request_pool, "http_request_pool",
    212 	    sizeof(struct http_request), http_request_limit);
    213 	kore_pool_init(&http_header_pool, "http_header_pool",
    214 	    sizeof(struct http_header), prealloc * HTTP_REQ_HEADER_MAX);
    215 	kore_pool_init(&http_cookie_pool, "http_cookie_pool",
    216 		sizeof(struct http_cookie), prealloc * HTTP_MAX_COOKIES);
    217 	kore_pool_init(&http_rlq_pool, "http_rlq_pool",
    218 		sizeof(struct http_runlock_queue), http_request_limit);
    219 
    220 	kore_pool_init(&http_body_path,
    221 	    "http_body_path", HTTP_BODY_PATH_MAX, prealloc);
    222 
    223 	for (i = 0; builtin_media[i].ext != NULL; i++) {
    224 		if (!http_media_register(builtin_media[i].ext,
    225 		    builtin_media[i].type)) {
    226 			fatal("duplicate media type for %s",
    227 			    builtin_media[i].ext);
    228 		}
    229 	}
    230 }
    231 
    232 void
    233 http_cleanup(void)
    234 {
    235 	if (header_buf != NULL) {
    236 		kore_buf_free(header_buf);
    237 		header_buf = NULL;
    238 	}
    239 
    240 	if (ckhdr_buf != NULL) {
    241 		kore_buf_free(ckhdr_buf);
    242 		ckhdr_buf = NULL;
    243 	}
    244 
    245 	kore_pool_cleanup(&http_request_pool);
    246 	kore_pool_cleanup(&http_header_pool);
    247 	kore_pool_cleanup(&http_body_path);
    248 }
    249 
    250 void
    251 http_server_version(const char *version)
    252 {
    253 	int		l;
    254 
    255 	l = snprintf(http_version, sizeof(http_version),
    256 	    "server: %s\r\n", version);
    257 	if (l == -1 || (size_t)l >= sizeof(http_version))
    258 		fatal("http_server_version(): http_version buffer too small");
    259 
    260 	http_version_len = l;
    261 }
    262 
    263 int
    264 http_check_timeout(struct connection *c, u_int64_t now)
    265 {
    266 	u_int64_t	d;
    267 
    268 	if (c->http_timeout == 0)
    269 		return (KORE_RESULT_OK);
    270 
    271 	if (now > c->http_start)
    272 		d = now - c->http_start;
    273 	else
    274 		d = 0;
    275 
    276 	if (d >= c->http_timeout) {
    277 		http_error_response(c, HTTP_STATUS_REQUEST_TIMEOUT);
    278 		kore_connection_disconnect(c);
    279 		return (KORE_RESULT_ERROR);
    280 	}
    281 
    282 	return (KORE_RESULT_OK);
    283 }
    284 
    285 void
    286 http_request_sleep(struct http_request *req)
    287 {
    288 	if (!(req->flags & HTTP_REQUEST_SLEEPING)) {
    289 		req->flags |= HTTP_REQUEST_SLEEPING;
    290 		TAILQ_REMOVE(&http_requests, req, list);
    291 		TAILQ_INSERT_TAIL(&http_requests_sleeping, req, list);
    292 	}
    293 }
    294 
    295 void
    296 http_request_wakeup(struct http_request *req)
    297 {
    298 	if (req->flags & HTTP_REQUEST_SLEEPING) {
    299 		req->flags &= ~HTTP_REQUEST_SLEEPING;
    300 		TAILQ_REMOVE(&http_requests_sleeping, req, list);
    301 		TAILQ_INSERT_TAIL(&http_requests, req, list);
    302 	}
    303 }
    304 
    305 void
    306 http_process(void)
    307 {
    308 	u_int64_t			total;
    309 	struct http_request		*req, *next;
    310 
    311 	total = 0;
    312 
    313 	for (req = TAILQ_FIRST(&http_requests); req != NULL; req = next) {
    314 		if (total >= http_request_ms)
    315 			break;
    316 
    317 		next = TAILQ_NEXT(req, list);
    318 		if (req->flags & HTTP_REQUEST_DELETE) {
    319 			http_request_free(req);
    320 			continue;
    321 		}
    322 
    323 		/* Sleeping requests should be in http_requests_sleeping. */
    324 		if (req->flags & HTTP_REQUEST_SLEEPING)
    325 			fatal("http_process: sleeping request on list");
    326 
    327 		if (!(req->flags & HTTP_REQUEST_COMPLETE))
    328 			continue;
    329 
    330 		http_process_request(req);
    331 		total += req->ms;
    332 
    333 		if (req->flags & HTTP_REQUEST_DELETE)
    334 			http_request_free(req);
    335 	}
    336 }
    337 
    338 void
    339 http_process_request(struct http_request *req)
    340 {
    341 	int		r;
    342 
    343 	if (req->flags & HTTP_REQUEST_DELETE || req->rt == NULL)
    344 		return;
    345 
    346 	req->start = kore_time_ms();
    347 	if (req->rt->auth != NULL && !(req->flags & HTTP_REQUEST_AUTHED))
    348 		r = kore_auth_run(req, req->rt->auth);
    349 	else
    350 		r = KORE_RESULT_OK;
    351 
    352 	switch (r) {
    353 	case KORE_RESULT_OK:
    354 		r = kore_runtime_http_request(req->rt->rcall, req);
    355 		break;
    356 	case KORE_RESULT_RETRY:
    357 		break;
    358 	case KORE_RESULT_ERROR:
    359 		/*
    360 		 * Set r to KORE_RESULT_OK so we can properly
    361 		 * flush the result from kore_auth_run().
    362 		 */
    363 		r = KORE_RESULT_OK;
    364 		break;
    365 	default:
    366 		fatal("kore_auth() returned unknown %d", r);
    367 	}
    368 	req->end = kore_time_ms();
    369 	req->ms = req->end - req->start;
    370 	req->total += req->ms;
    371 
    372 	switch (r) {
    373 	case KORE_RESULT_OK:
    374 		r = net_send_flush(req->owner);
    375 		if (r == KORE_RESULT_ERROR)
    376 			kore_connection_disconnect(req->owner);
    377 		break;
    378 	case KORE_RESULT_ERROR:
    379 		kore_connection_disconnect(req->owner);
    380 		break;
    381 	case KORE_RESULT_RETRY:
    382 		return;
    383 	default:
    384 		fatal("A page handler returned an unknown result: %d", r);
    385 	}
    386 
    387 	if (req->rt->dom->accesslog)
    388 		kore_accesslog(req);
    389 
    390 	req->flags |= HTTP_REQUEST_DELETE;
    391 }
    392 
    393 void
    394 http_response_header(struct http_request *req,
    395     const char *header, const char *value)
    396 {
    397 	struct http_header	*hdr;
    398 
    399 	hdr = NULL;
    400 
    401 	TAILQ_FOREACH(hdr, &req->resp_headers, list) {
    402 		if (!strcasecmp(hdr->header, header)) {
    403 			TAILQ_REMOVE(&req->resp_headers, hdr, list);
    404 			kore_free(hdr->header);
    405 			kore_free(hdr->value);
    406 			break;
    407 		}
    408 	}
    409 
    410 	if (hdr == NULL)
    411 		hdr = kore_pool_get(&http_header_pool);
    412 
    413 	hdr->header = kore_strdup(header);
    414 	hdr->value = kore_strdup(value);
    415 
    416 	TAILQ_INSERT_TAIL(&(req->resp_headers), hdr, list);
    417 }
    418 
    419 void
    420 http_request_free(struct http_request *req)
    421 {
    422 #if defined(KORE_USE_TASKS)
    423 	struct kore_task	*t, *nt;
    424 	int			pending_tasks;
    425 #endif
    426 #if defined(KORE_USE_PGSQL)
    427 	struct kore_pgsql	*pgsql;
    428 #endif
    429 #if defined(KORE_USE_CURL)
    430 	struct kore_curl	*client;
    431 #endif
    432 	struct http_file	*f, *fnext;
    433 	struct http_arg		*q, *qnext;
    434 	struct http_header	*hdr, *next;
    435 	struct http_cookie	*ck, *cknext;
    436 
    437 	if (req->rt != NULL && req->rt->on_free != NULL)
    438 		kore_runtime_http_request_free(req->rt->on_free, req);
    439 
    440 	if (req->runlock != NULL) {
    441 		LIST_REMOVE(req->runlock, list);
    442 		req->runlock = NULL;
    443 	}
    444 
    445 #if defined(KORE_USE_TASKS)
    446 	pending_tasks = 0;
    447 	for (t = LIST_FIRST(&(req->tasks)); t != NULL; t = nt) {
    448 		nt = LIST_NEXT(t, rlist);
    449 		if (!kore_task_finished(t)) {
    450 			pending_tasks++;
    451 		} else {
    452 			kore_task_destroy(t);
    453 		}
    454 	}
    455 
    456 	if (pending_tasks)
    457 		return;
    458 #endif
    459 
    460 #if defined(KORE_USE_PYTHON)
    461 	if (req->py_coro != NULL) {
    462 		kore_python_coro_delete(req->py_coro);
    463 		req->py_coro = NULL;
    464 	}
    465 	if (req->py_validator != NULL) {
    466 		kore_python_coro_delete(req->py_validator);
    467 		req->py_validator = NULL;
    468 	}
    469 	Py_XDECREF(req->py_req);
    470 #endif
    471 #if defined(KORE_USE_PGSQL)
    472 	while (!LIST_EMPTY(&(req->pgsqls))) {
    473 		pgsql = LIST_FIRST(&(req->pgsqls));
    474 		kore_pgsql_cleanup(pgsql);
    475 	}
    476 #endif
    477 #if defined(KORE_USE_CURL)
    478 	while (!LIST_EMPTY(&req->chandles)) {
    479 		client = LIST_FIRST(&req->chandles);
    480 		kore_curl_cleanup(client);
    481 	}
    482 #endif
    483 	kore_free(req->headers);
    484 
    485 	req->host = NULL;
    486 	req->path = NULL;
    487 	req->headers = NULL;
    488 
    489 	TAILQ_REMOVE(&http_requests, req, list);
    490 	if (req->owner != NULL)
    491 		TAILQ_REMOVE(&(req->owner->http_requests), req, olist);
    492 
    493 	for (hdr = TAILQ_FIRST(&(req->resp_headers)); hdr != NULL; hdr = next) {
    494 		next = TAILQ_NEXT(hdr, list);
    495 		TAILQ_REMOVE(&(req->resp_headers), hdr, list);
    496 		kore_free(hdr->header);
    497 		kore_free(hdr->value);
    498 		kore_pool_put(&http_header_pool, hdr);
    499 	}
    500 
    501 	for (hdr = TAILQ_FIRST(&(req->req_headers)); hdr != NULL; hdr = next) {
    502 		next = TAILQ_NEXT(hdr, list);
    503 		TAILQ_REMOVE(&(req->req_headers), hdr, list);
    504 		kore_pool_put(&http_header_pool, hdr);
    505 	}
    506 
    507 	for (ck = TAILQ_FIRST(&(req->resp_cookies)); ck != NULL; ck = cknext) {
    508 		cknext = TAILQ_NEXT(ck, list);
    509 		TAILQ_REMOVE(&(req->resp_cookies), ck, list);
    510 		kore_free(ck->name);
    511 		kore_free(ck->value);
    512 		kore_free(ck->path);
    513 		kore_free(ck->domain);
    514 		kore_pool_put(&http_cookie_pool, ck);
    515 	}
    516 
    517 	for (ck = TAILQ_FIRST(&(req->req_cookies)); ck != NULL; ck = cknext) {
    518 		cknext = TAILQ_NEXT(ck, list);
    519 		TAILQ_REMOVE(&(req->req_cookies), ck, list);
    520 		kore_free(ck->name);
    521 		kore_free(ck->value);
    522 		kore_pool_put(&http_cookie_pool, ck);
    523 	}
    524 
    525 	for (q = TAILQ_FIRST(&(req->arguments)); q != NULL; q = qnext) {
    526 		qnext = TAILQ_NEXT(q, list);
    527 		TAILQ_REMOVE(&(req->arguments), q, list);
    528 		kore_free(q->name);
    529 		kore_free(q->s_value);
    530 		kore_free(q);
    531 	}
    532 
    533 	for (f = TAILQ_FIRST(&(req->files)); f != NULL; f = fnext) {
    534 		fnext = TAILQ_NEXT(f, list);
    535 		TAILQ_REMOVE(&(req->files), f, list);
    536 		kore_free(f->filename);
    537 		kore_free(f->name);
    538 		kore_free(f);
    539 	}
    540 
    541 	if (req->http_body != NULL)
    542 		kore_buf_free(req->http_body);
    543 
    544 	if (req->http_body_fd != -1)
    545 		(void)close(req->http_body_fd);
    546 
    547 	if (req->http_body_path != NULL) {
    548 		if (unlink(req->http_body_path) == -1 && errno != ENOENT) {
    549 			kore_log(LOG_NOTICE, "failed to unlink %s: %s",
    550 			    req->http_body_path, errno_s);
    551 		}
    552 		kore_pool_put(&http_body_path, req->http_body_path);
    553 	}
    554 
    555 	if (req->hdlr_extra != NULL &&
    556 	    !(req->flags & HTTP_REQUEST_RETAIN_EXTRA))
    557 		kore_free(req->hdlr_extra);
    558 
    559 	kore_pool_put(&http_request_pool, req);
    560 	http_request_count--;
    561 }
    562 
    563 void
    564 http_serveable(struct http_request *req, const void *data, size_t len,
    565     const char *etag, const char *type)
    566 {
    567 	const char		*match;
    568 
    569 	if (req->method != HTTP_METHOD_GET) {
    570 		http_response_header(req, "allow", "get");
    571 		http_response(req, HTTP_STATUS_BAD_REQUEST, NULL, 0);
    572 		return;
    573 	}
    574 
    575 	if (http_request_header(req, "if-none-match", &match)) {
    576 		if (!strcmp(match, etag)) {
    577 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    578 			return;
    579 		}
    580 	}
    581 
    582 	http_response_header(req, "etag", etag);
    583 	http_response_header(req, "content-type", type);
    584 	http_response(req, HTTP_STATUS_OK, data, len);
    585 }
    586 
    587 void
    588 http_response(struct http_request *req, int code, const void *d, size_t l)
    589 {
    590 	if (req->owner == NULL)
    591 		return;
    592 
    593 	req->status = code;
    594 
    595 	switch (req->owner->proto) {
    596 	case CONN_PROTO_HTTP:
    597 	case CONN_PROTO_WEBSOCKET:
    598 		http_response_normal(req, req->owner, code, d, l);
    599 		break;
    600 	default:
    601 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    602 		/* NOTREACHED. */
    603 	}
    604 }
    605 
    606 void
    607 http_response_close(struct http_request *req, int code, const void *d, size_t l)
    608 {
    609 	if (req->owner == NULL)
    610 		return;
    611 
    612 	req->status = code;
    613 	req->owner->flags |= CONN_CLOSE_EMPTY;
    614 
    615 	switch (req->owner->proto) {
    616 	case CONN_PROTO_HTTP:
    617 	case CONN_PROTO_WEBSOCKET:
    618 		http_response_normal(req, req->owner, code, d, l);
    619 		break;
    620 	default:
    621 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    622 		/* NOTREACHED. */
    623 	}
    624 }
    625 
    626 void
    627 http_response_json(struct http_request *req, int status,
    628     struct kore_json_item *json)
    629 {
    630 	struct kore_buf		*buf;
    631 
    632 	if (req->owner == NULL)
    633 		return;
    634 
    635 	buf = kore_buf_alloc(1024);
    636 	kore_json_item_tobuf(json, buf);
    637 	kore_json_item_free(json);
    638 
    639 	req->status = status;
    640 	http_response_header(req, "content-type", "application/json");
    641 
    642 	switch (req->owner->proto) {
    643 	case CONN_PROTO_HTTP:
    644 		http_response_stream(req, status, buf->data, buf->offset,
    645 		    http_release_buffer, buf);
    646 		break;
    647 	default:
    648 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    649 		/* NOTREACHED. */
    650 	}
    651 }
    652 
    653 void
    654 http_response_stream(struct http_request *req, int status, void *base,
    655     size_t len, int (*cb)(struct netbuf *), void *arg)
    656 {
    657 	struct netbuf		*nb;
    658 
    659 	if (req->owner == NULL)
    660 		return;
    661 
    662 	req->status = status;
    663 
    664 	switch (req->owner->proto) {
    665 	case CONN_PROTO_HTTP:
    666 		http_response_normal(req, req->owner, status, NULL, len);
    667 		break;
    668 	default:
    669 		fatal("%s: bad proto %d", __func__, req->owner->proto);
    670 		/* NOTREACHED. */
    671 	}
    672 
    673 	net_send_stream(req->owner, base, len, cb, &nb);
    674 	nb->extra = arg;
    675 
    676 	if (req->method == HTTP_METHOD_HEAD) {
    677 		nb->s_off = nb->b_len;
    678 		net_remove_netbuf(req->owner, nb);
    679 	}
    680 }
    681 
    682 void
    683 http_response_fileref(struct http_request *req, int status,
    684     struct kore_fileref *ref)
    685 {
    686 	struct tm	*tm;
    687 	time_t		mtime;
    688 	char		tbuf[128];
    689 	const char	*media_type, *modified;
    690 
    691 	if (req->owner == NULL)
    692 		return;
    693 
    694 	media_type = http_media_type(ref->path);
    695 	if (media_type != NULL)
    696 		http_response_header(req, "content-type", media_type);
    697 
    698 	if (http_request_header(req, "if-modified-since", &modified)) {
    699 		mtime = kore_date_to_time(modified);
    700 		if (mtime == ref->mtime_sec) {
    701 			kore_fileref_release(ref);
    702 			http_response(req, HTTP_STATUS_NOT_MODIFIED, NULL, 0);
    703 			return;
    704 		}
    705 	}
    706 
    707 	if ((tm = gmtime(&ref->mtime_sec)) != NULL) {
    708 		if (strftime(tbuf, sizeof(tbuf),
    709 		    "%a, %d %b %Y %H:%M:%S GMT", tm) > 0) {
    710 			http_response_header(req, "last-modified", tbuf);
    711 		}
    712 	}
    713 
    714 	req->status = status;
    715 	switch (req->owner->proto) {
    716 	case CONN_PROTO_HTTP:
    717 		http_response_normal(req, req->owner, status, NULL, ref->size);
    718 		break;
    719 	default:
    720 		fatal("http_response_fd() bad proto %d", req->owner->proto);
    721 		/* NOTREACHED. */
    722 	}
    723 
    724 	if (req->method != HTTP_METHOD_HEAD)
    725 		net_send_fileref(req->owner, ref);
    726 	else
    727 		kore_fileref_release(ref);
    728 }
    729 
    730 int
    731 http_request_header(struct http_request *req, const char *header,
    732     const char **out)
    733 {
    734 	struct http_header	*hdr;
    735 
    736 	TAILQ_FOREACH(hdr, &(req->req_headers), list) {
    737 		if (!strcasecmp(hdr->header, header)) {
    738 			*out = hdr->value;
    739 			return (KORE_RESULT_OK);
    740 		}
    741 	}
    742 
    743 	if (!strcasecmp(header, "host")) {
    744 		*out = req->host;
    745 		return (KORE_RESULT_OK);
    746 	}
    747 
    748 	return (KORE_RESULT_ERROR);
    749 }
    750 
    751 int
    752 http_request_header_get(struct http_request *req, const char *header,
    753     void **out, void *nout, int type)
    754 {
    755 	struct http_header	*hdr;
    756 
    757 	if (type == HTTP_ARG_TYPE_STRING)
    758 		fatal("%s: cannot be called with type string", __func__);
    759 
    760 	TAILQ_FOREACH(hdr, &req->req_headers, list) {
    761 		if (strcasecmp(hdr->header, header))
    762 			continue;
    763 
    764 		if (http_data_convert(hdr->value, out, nout, type))
    765 			return (KORE_RESULT_OK);
    766 
    767 		return (KORE_RESULT_ERROR);
    768 	}
    769 
    770 	return (KORE_RESULT_ERROR);
    771 }
    772 
    773 int
    774 http_request_cookie(struct http_request *req, const char *cookie, char **out)
    775 {
    776 	struct http_cookie	*ck;
    777 
    778 	TAILQ_FOREACH(ck, &(req->req_cookies), list) {
    779 		if (!strcasecmp(ck->name, cookie)) {
    780 			*out = ck->value;
    781 			return (KORE_RESULT_OK);
    782 		}
    783 	}
    784 
    785 	return (KORE_RESULT_ERROR);
    786 }
    787 
    788 int
    789 http_header_recv(struct netbuf *nb)
    790 {
    791 	struct connection	*c;
    792 	size_t			len;
    793 	struct http_header	*hdr;
    794 	struct http_request	*req;
    795 	u_int8_t		*end_headers;
    796 	int			h, i, v, skip, l;
    797 	char			*headers[HTTP_REQ_HEADER_MAX];
    798 	char			*value, *host, *request[4], *hbuf;
    799 
    800 	c = nb->owner;
    801 
    802 	if (nb->s_off < 4)
    803 		return (KORE_RESULT_OK);
    804 
    805 	if (!isalpha(nb->buf[0])) {
    806 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    807 		return (KORE_RESULT_ERROR);
    808 	}
    809 
    810 	skip = 4;
    811 	end_headers = kore_mem_find(nb->buf, nb->s_off, "\r\n\r\n", 4);
    812 	if (end_headers == NULL) {
    813 		end_headers = kore_mem_find(nb->buf, nb->s_off, "\n\n", 2);
    814 		if (end_headers == NULL) {
    815 			if (nb->s_off == http_header_max) {
    816 				http_error_response(c,
    817 				    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    818 				return (KORE_RESULT_ERROR);
    819 			}
    820 			return (KORE_RESULT_OK);
    821 		}
    822 		skip = 2;
    823 	}
    824 
    825 	*end_headers = '\0';
    826 	end_headers += skip;
    827 	len = end_headers - nb->buf;
    828 	hbuf = (char *)nb->buf;
    829 
    830 	h = kore_split_string(hbuf, "\r\n", headers, HTTP_REQ_HEADER_MAX);
    831 	if (h < 2) {
    832 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    833 		return (KORE_RESULT_OK);
    834 	}
    835 
    836 	v = kore_split_string(headers[0], " ", request, 4);
    837 	if (v != 3) {
    838 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    839 		return (KORE_RESULT_OK);
    840 	}
    841 
    842 	skip = 0;
    843 	host = NULL;
    844 	for (i = 0; i < h; i++) {
    845 		if (strncasecmp(headers[i], "host", 4))
    846 			continue;
    847 
    848 		if ((host = http_validate_header(headers[i])) == NULL) {
    849 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    850 			return (KORE_RESULT_OK);
    851 		}
    852 
    853 		if (*host == '\0') {
    854 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    855 			return (KORE_RESULT_OK);
    856 		}
    857 
    858 		skip = i;
    859 		break;
    860 	}
    861 
    862 	if (host == NULL) {
    863 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    864 		return (KORE_RESULT_OK);
    865 	}
    866 
    867 	req = http_request_new(c, host, request[0], request[1], request[2]);
    868 	if (req == NULL)
    869 		return (KORE_RESULT_OK);
    870 
    871 	/* take full ownership of the buffer. */
    872 	req->headers = nb->buf;
    873 	nb->buf = NULL;
    874 	nb->m_len = 0;
    875 
    876 	for (i = 1; i < h; i++) {
    877 		if (i == skip)
    878 			continue;
    879 
    880 		if ((value = http_validate_header(headers[i])) == NULL) {
    881 			req->flags |= HTTP_REQUEST_DELETE;
    882 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    883 			return (KORE_RESULT_OK);
    884 		}
    885 
    886 		if (*value == '\0') {
    887 			req->flags |= HTTP_REQUEST_DELETE;
    888 			http_error_response(c, HTTP_STATUS_BAD_REQUEST);
    889 			return (KORE_RESULT_OK);
    890 		}
    891 
    892 		hdr = kore_pool_get(&http_header_pool);
    893 		hdr->header = headers[i];
    894 		hdr->value = value;
    895 		TAILQ_INSERT_TAIL(&(req->req_headers), hdr, list);
    896 
    897 		if (req->agent == NULL &&
    898 		    !strcasecmp(hdr->header, "user-agent"))
    899 			req->agent = hdr->value;
    900 
    901 		if (req->referer == NULL &&
    902 		    !strcasecmp(hdr->header, "referer"))
    903 			req->referer = hdr->value;
    904 	}
    905 
    906 	if (req->flags & HTTP_REQUEST_EXPECT_BODY) {
    907 		if (http_body_max == 0) {
    908 			req->flags |= HTTP_REQUEST_DELETE;
    909 			http_error_response(req->owner,
    910 			    HTTP_STATUS_METHOD_NOT_ALLOWED);
    911 			return (KORE_RESULT_OK);
    912 		}
    913 
    914 		if (!http_request_header_uint64(req, "content-length",
    915 		    &req->content_length)) {
    916 			if (req->method == HTTP_METHOD_DELETE) {
    917 				req->flags |= HTTP_REQUEST_COMPLETE;
    918 				return (KORE_RESULT_OK);
    919 			}
    920 
    921 			req->flags |= HTTP_REQUEST_DELETE;
    922 			http_error_response(req->owner,
    923 			    HTTP_STATUS_LENGTH_REQUIRED);
    924 			return (KORE_RESULT_OK);
    925 		}
    926 
    927 		if (req->content_length == 0) {
    928 			c->http_timeout = 0;
    929 			req->flags |= HTTP_REQUEST_COMPLETE;
    930 			req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
    931 			return (KORE_RESULT_OK);
    932 		}
    933 
    934 		if (req->content_length > http_body_max) {
    935 			req->flags |= HTTP_REQUEST_DELETE;
    936 			http_error_response(req->owner,
    937 			    HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE);
    938 			return (KORE_RESULT_OK);
    939 		}
    940 
    941 		req->http_body_length = req->content_length;
    942 
    943 		if (req->rt->on_body_chunk == NULL &&
    944 		    http_body_disk_offload > 0 &&
    945 		    req->content_length > http_body_disk_offload) {
    946 			req->http_body_path = kore_pool_get(&http_body_path);
    947 			l = snprintf(req->http_body_path, HTTP_BODY_PATH_MAX,
    948 			    "%s/http_body.XXXXXX", http_body_disk_path);
    949 			if (l == -1 || (size_t)l >= HTTP_BODY_PATH_MAX) {
    950 				req->flags |= HTTP_REQUEST_DELETE;
    951 				http_error_response(req->owner,
    952 				    HTTP_STATUS_INTERNAL_ERROR);
    953 				return (KORE_RESULT_ERROR);
    954 			}
    955 
    956 			req->http_body = NULL;
    957 			req->http_body_fd = mkstemp(req->http_body_path);
    958 			if (req->http_body_fd == -1) {
    959 				req->flags |= HTTP_REQUEST_DELETE;
    960 				http_error_response(req->owner,
    961 				    HTTP_STATUS_INTERNAL_ERROR);
    962 				return (KORE_RESULT_OK);
    963 			}
    964 		} else if (req->rt->on_body_chunk == NULL) {
    965 			req->http_body_fd = -1;
    966 			req->http_body = kore_buf_alloc(req->content_length);
    967 		}
    968 
    969 		SHA256Init(&req->hashctx);
    970 		c->http_timeout = http_body_timeout * 1000;
    971 
    972 		if (!http_body_update(req, end_headers, nb->s_off - len)) {
    973 			req->flags |= HTTP_REQUEST_DELETE;
    974 			http_error_response(req->owner,
    975 			    HTTP_STATUS_INTERNAL_ERROR);
    976 			return (KORE_RESULT_OK);
    977 		}
    978 	} else {
    979 		c->http_timeout = 0;
    980 	}
    981 
    982 	if (req->rt->on_headers != NULL) {
    983 		if (!kore_runtime_http_request(req->rt->on_headers, req)) {
    984 			req->flags |= HTTP_REQUEST_DELETE;
    985 			return (KORE_RESULT_OK);
    986 		}
    987 	}
    988 
    989 	return (KORE_RESULT_OK);
    990 }
    991 
    992 int
    993 http_argument_get(struct http_request *req, const char *name,
    994     void **out, void *nout, int type)
    995 {
    996 	struct http_arg		*q;
    997 
    998 	TAILQ_FOREACH(q, &(req->arguments), list) {
    999 		if (strcmp(q->name, name))
   1000 			continue;
   1001 
   1002 		if (http_data_convert(q->s_value, out, nout, type))
   1003 			return (KORE_RESULT_OK);
   1004 
   1005 		break;
   1006 	}
   1007 
   1008 	return (KORE_RESULT_ERROR);
   1009 }
   1010 
   1011 int
   1012 http_argument_urldecode(char *arg, int url)
   1013 {
   1014 	u_int8_t	v;
   1015 	int		err;
   1016 	size_t		len;
   1017 	char		*p, *in, h[5];
   1018 
   1019 	p = arg;
   1020 	in = arg;
   1021 	len = strlen(arg);
   1022 
   1023 	while (*p != '\0' && p < (arg + len)) {
   1024 		if (*p == '+')
   1025 			*p = ' ';
   1026 		if (*p != '%') {
   1027 			*in++ = *p++;
   1028 			continue;
   1029 		}
   1030 
   1031 		if ((p + 2) >= (arg + len))
   1032 			return (KORE_RESULT_ERROR);
   1033 
   1034 		if (!isxdigit((unsigned char)*(p + 1)) ||
   1035 		    !isxdigit((unsigned char)*(p + 2))) {
   1036 			*in++ = *p++;
   1037 			continue;
   1038 		}
   1039 
   1040 		h[0] = '0';
   1041 		h[1] = 'x';
   1042 		h[2] = *(p + 1);
   1043 		h[3] = *(p + 2);
   1044 		h[4] = '\0';
   1045 
   1046 		v = kore_strtonum(h, 16, 0x0, 0xff, &err);
   1047 		if (err != KORE_RESULT_OK)
   1048 			return (err);
   1049 
   1050 		if (url) {
   1051 			if (v <= 0x1f || v == 0x7f)
   1052 				return (KORE_RESULT_ERROR);
   1053 		} else {
   1054 			if ((v <= 0x1f || v == 0x7f) &&
   1055 			    (v != '\n' && v != '\r' && v != '\t'))
   1056 				return (KORE_RESULT_ERROR);
   1057 		}
   1058 
   1059 		*in++ = (char)v;
   1060 		p += 3;
   1061 	}
   1062 
   1063 	*in = '\0';
   1064 	return (KORE_RESULT_OK);
   1065 }
   1066 
   1067 struct http_file *
   1068 http_file_lookup(struct http_request *req, const char *name)
   1069 {
   1070 	struct http_file	*f;
   1071 
   1072 	TAILQ_FOREACH(f, &(req->files), list) {
   1073 		if (!strcmp(f->name, name))
   1074 			return (f);
   1075 	}
   1076 
   1077 	return (NULL);
   1078 }
   1079 
   1080 ssize_t
   1081 http_file_read(struct http_file *file, void *buf, size_t len)
   1082 {
   1083 	ssize_t		ret;
   1084 	size_t		toread, off;
   1085 
   1086 	if (file->length < file->offset)
   1087 		return (-1);
   1088 	if ((file->offset + len) < file->offset)
   1089 		return (-1);
   1090 	if ((file->position + file->offset) < file->position)
   1091 		return (-1);
   1092 
   1093 	off = file->position + file->offset;
   1094 	toread = MIN(len, (file->length - file->offset));
   1095 	if (toread == 0)
   1096 		return (0);
   1097 
   1098 	if (file->req->http_body_fd != -1) {
   1099 		if (lseek(file->req->http_body_fd, off, SEEK_SET) == -1) {
   1100 			kore_log(LOG_ERR, "http_file_read: lseek(%s): %s",
   1101 			    file->req->http_body_path, errno_s);
   1102 			return (-1);
   1103 		}
   1104 
   1105 		for (;;) {
   1106 			ret = read(file->req->http_body_fd, buf, toread);
   1107 			if (ret == -1) {
   1108 				if (errno == EINTR)
   1109 					continue;
   1110 				kore_log(LOG_ERR, "failed to read %s: %s",
   1111 				    file->req->http_body_path, errno_s);
   1112 				return (-1);
   1113 			}
   1114 			if (ret == 0)
   1115 				return (0);
   1116 			break;
   1117 		}
   1118 	} else if (file->req->http_body != NULL) {
   1119 		if (off > file->req->http_body->length)
   1120 			return (0);
   1121 		memcpy(buf, file->req->http_body->data + off, toread);
   1122 		ret = toread;
   1123 	} else {
   1124 		kore_log(LOG_ERR, "http_file_read: called without body");
   1125 		return (-1);
   1126 	}
   1127 
   1128 	file->offset += (size_t)ret;
   1129 	return (ret);
   1130 }
   1131 
   1132 void
   1133 http_file_rewind(struct http_file *file)
   1134 {
   1135 	file->offset = 0;
   1136 }
   1137 
   1138 void
   1139 http_response_cookie(struct http_request *req, const char *name,
   1140     const char *val, const char *path, time_t expires, u_int32_t maxage,
   1141     struct http_cookie **out)
   1142 {
   1143 	char			*p;
   1144 	struct http_cookie	*ck;
   1145 
   1146 	if (name == NULL || val == NULL)
   1147 		fatal("http_response_cookie: invalid parameters");
   1148 
   1149 	ck = kore_pool_get(&http_cookie_pool);
   1150 
   1151 	ck->maxage = maxage;
   1152 	ck->expires = expires;
   1153 	ck->name = kore_strdup(name);
   1154 	ck->value = kore_strdup(val);
   1155 	ck->domain = kore_strdup(req->host);
   1156 	ck->flags = HTTP_COOKIE_HTTPONLY | HTTP_COOKIE_SECURE;
   1157 
   1158 	if ((p = strrchr(ck->domain, ':')) != NULL)
   1159 		*p = '\0';
   1160 
   1161 	if (path != NULL)
   1162 		ck->path = kore_strdup(path);
   1163 	else
   1164 		ck->path = NULL;
   1165 
   1166 	TAILQ_INSERT_TAIL(&(req->resp_cookies), ck, list);
   1167 
   1168 	if (out != NULL)
   1169 		*out = ck;
   1170 }
   1171 
   1172 void
   1173 http_populate_cookies(struct http_request *req)
   1174 {
   1175 	struct http_cookie	*ck;
   1176 	const char		*hdr;
   1177 	int			 i, v, n;
   1178 	char			*c, *header, *pair[3];
   1179 	char			*cookies[HTTP_MAX_COOKIES];
   1180 
   1181 	if (!http_request_header(req, "cookie", &hdr))
   1182 		return;
   1183 
   1184 	header = kore_strdup(hdr);
   1185 	v = kore_split_string(header, ";", cookies, HTTP_MAX_COOKIES);
   1186 	for (i = 0; i < v; i++) {
   1187 		for (c = cookies[i]; isspace(*(unsigned char *)c); c++)
   1188 			;
   1189 
   1190 		n = kore_split_string(c, "=", pair, 3);
   1191 		if (n != 2)
   1192 			continue;
   1193 
   1194 		ck = kore_pool_get(&http_cookie_pool);
   1195 		ck->name = kore_strdup(pair[0]);
   1196 		ck->value = kore_strdup(pair[1]);
   1197 		TAILQ_INSERT_TAIL(&(req->req_cookies), ck, list);
   1198 	}
   1199 
   1200 	kore_free(header);
   1201 }
   1202 
   1203 void
   1204 http_populate_post(struct http_request *req)
   1205 {
   1206 	ssize_t			ret;
   1207 	int			i, v;
   1208 	struct kore_buf		*body;
   1209 	char			data[BUFSIZ];
   1210 	char			*args[HTTP_MAX_QUERY_ARGS], *val[3], *string;
   1211 
   1212 	if (req->method != HTTP_METHOD_POST)
   1213 		return;
   1214 
   1215 	if (req->http_body != NULL) {
   1216 		body = NULL;
   1217 		req->http_body->offset = req->content_length;
   1218 		string = kore_buf_stringify(req->http_body, NULL);
   1219 		req->http_body_length = 0;
   1220 		req->http_body_offset = 0;
   1221 	} else {
   1222 		body = kore_buf_alloc(128);
   1223 		for (;;) {
   1224 			ret = http_body_read(req, data, sizeof(data));
   1225 			if (ret == -1)
   1226 				goto out;
   1227 			if (ret == 0)
   1228 				break;
   1229 			kore_buf_append(body, data, ret);
   1230 		}
   1231 		string = kore_buf_stringify(body, NULL);
   1232 	}
   1233 
   1234 	v = kore_split_string(string, "&", args, HTTP_MAX_QUERY_ARGS);
   1235 	for (i = 0; i < v; i++) {
   1236 		kore_split_string(args[i], "=", val, 3);
   1237 		if (val[0] != NULL && val[1] != NULL)
   1238 			http_argument_add(req, val[0], val[1], 0, 1);
   1239 	}
   1240 
   1241 out:
   1242 	if (body != NULL)
   1243 		kore_buf_free(body);
   1244 }
   1245 
   1246 void
   1247 http_populate_qs(struct http_request *req)
   1248 {
   1249 	int		i, v;
   1250 	char		*query, *args[HTTP_MAX_QUERY_ARGS], *val[3];
   1251 
   1252 	if (req->query_string == NULL)
   1253 		return;
   1254 
   1255 	query = kore_strdup(req->query_string);
   1256 	v = kore_split_string(query, "&", args, HTTP_MAX_QUERY_ARGS);
   1257 	for (i = 0; i < v; i++) {
   1258 		kore_split_string(args[i], "=", val, 3);
   1259 		if (val[0] != NULL && val[1] != NULL)
   1260 			http_argument_add(req, val[0], val[1], 1, 1);
   1261 	}
   1262 
   1263 	kore_free(query);
   1264 }
   1265 
   1266 void
   1267 http_populate_multipart_form(struct http_request *req)
   1268 {
   1269 	const char		*hdr;
   1270 	int			h, blen;
   1271 	struct kore_buf		in, out;
   1272 	char			*type, *val, *args[3];
   1273 	char			boundary[HTTP_BOUNDARY_MAX];
   1274 
   1275 	if (req->method != HTTP_METHOD_POST)
   1276 		return;
   1277 
   1278 	if (!http_request_header(req, "content-type", &hdr))
   1279 		return;
   1280 
   1281 	kore_buf_init(&in, 128);
   1282 	kore_buf_init(&out, 128);
   1283 
   1284 	type = kore_strdup(hdr);
   1285 	h = kore_split_string(type, ";", args, 3);
   1286 	if (h != 2)
   1287 		goto cleanup;
   1288 
   1289 	if (strcasecmp(args[0], "multipart/form-data"))
   1290 		goto cleanup;
   1291 
   1292 	if ((val = strchr(args[1], '=')) == NULL)
   1293 		goto cleanup;
   1294 
   1295 	val++;
   1296 	blen = snprintf(boundary, sizeof(boundary), "--%s", val);
   1297 	if (blen == -1 || (size_t)blen >= sizeof(boundary))
   1298 		goto cleanup;
   1299 
   1300 	if (!multipart_find_data(&in, NULL, NULL, req, boundary, blen))
   1301 		goto cleanup;
   1302 
   1303 	for (;;) {
   1304 		if (!multipart_find_data(&in, NULL, NULL, req, "\r\n", 2))
   1305 			break;
   1306 		if (in.offset < 4 && req->http_body_length == 0)
   1307 			break;
   1308 		if (!multipart_find_data(&in, &out, NULL, req, "\r\n\r\n", 4))
   1309 			break;
   1310 		if (!multipart_parse_headers(req, &in, &out, boundary, blen))
   1311 			break;
   1312 
   1313 		kore_buf_reset(&out);
   1314 	}
   1315 
   1316 cleanup:
   1317 	kore_free(type);
   1318 	kore_buf_cleanup(&in);
   1319 	kore_buf_cleanup(&out);
   1320 }
   1321 
   1322 int
   1323 http_body_rewind(struct http_request *req)
   1324 {
   1325 	if (req->http_body_fd != -1) {
   1326 		if (lseek(req->http_body_fd, 0, SEEK_SET) == -1) {
   1327 			kore_log(LOG_ERR, "lseek(%s) failed: %s",
   1328 			    req->http_body_path, errno_s);
   1329 			return (KORE_RESULT_ERROR);
   1330 		}
   1331 	} else if (req->http_body != NULL) {
   1332 		kore_buf_reset(req->http_body);
   1333 	}
   1334 
   1335 	req->http_body_offset = 0;
   1336 	req->http_body_length = req->content_length;
   1337 
   1338 	return (KORE_RESULT_OK);
   1339 }
   1340 
   1341 int
   1342 http_body_digest(struct http_request *req, char *out, size_t len)
   1343 {
   1344 	size_t		idx;
   1345 	int		slen;
   1346 
   1347 	if (len != HTTP_BODY_DIGEST_STRLEN) {
   1348 		fatal("http_body_digest: bad len:%zu wanted:%u",
   1349 		    len, HTTP_BODY_DIGEST_STRLEN);
   1350 	}
   1351 
   1352 	if (!(req->flags & HTTP_REQUEST_COMPLETE))
   1353 		return (KORE_RESULT_ERROR);
   1354 
   1355 	for (idx = 0; idx < sizeof(req->http_body_digest); idx++) {
   1356 		slen = snprintf(out + (idx * 2), len - (idx * 2), "%02x",
   1357 		    req->http_body_digest[idx]);
   1358 		if (slen == -1 || (size_t)slen >= len)
   1359 			fatal("failed to create hex string");
   1360 	}
   1361 
   1362 	return (KORE_RESULT_OK);
   1363 }
   1364 
   1365 ssize_t
   1366 http_body_read(struct http_request *req, void *out, size_t len)
   1367 {
   1368 	ssize_t		ret;
   1369 	size_t		toread;
   1370 
   1371 	toread = MIN(req->http_body_length, len);
   1372 	if (toread == 0)
   1373 		return (0);
   1374 
   1375 	if (req->http_body_fd != -1) {
   1376 		for (;;) {
   1377 			ret = read(req->http_body_fd, out, toread);
   1378 			if (ret == -1) {
   1379 				if (errno == EINTR)
   1380 					continue;
   1381 				kore_log(LOG_ERR, "failed to read %s: %s",
   1382 				    req->http_body_path, errno_s);
   1383 				return (-1);
   1384 			}
   1385 			if (ret == 0)
   1386 				return (0);
   1387 			break;
   1388 		}
   1389 	} else if (req->http_body != NULL) {
   1390 		memcpy(out,
   1391 		    (req->http_body->data + req->http_body->offset), toread);
   1392 		req->http_body->offset += toread;
   1393 		ret = toread;
   1394 	} else {
   1395 		kore_log(LOG_ERR, "http_body_read: called without body");
   1396 		return (-1);
   1397 	}
   1398 
   1399 	req->http_body_length -= (size_t)ret;
   1400 	req->http_body_offset += (size_t)ret;
   1401 
   1402 	return (ret);
   1403 }
   1404 
   1405 int
   1406 http_state_run(struct http_state *states, u_int8_t elm,
   1407     struct http_request *req)
   1408 {
   1409 	int		r, done;
   1410 
   1411 	done = 0;
   1412 
   1413 	while (!done) {
   1414 		if (req->fsm_state >= elm) {
   1415 			fatal("http_state_run: fsm_state > elm (%d/%d)",
   1416 			    req->fsm_state, elm);
   1417 		}
   1418 
   1419 		r = states[req->fsm_state].cb(req);
   1420 		switch (r) {
   1421 		case HTTP_STATE_ERROR:
   1422 			return (KORE_RESULT_OK);
   1423 		case HTTP_STATE_RETRY:
   1424 			return (KORE_RESULT_RETRY);
   1425 		case HTTP_STATE_CONTINUE:
   1426 			break;
   1427 		case HTTP_STATE_COMPLETE:
   1428 			done = 1;
   1429 			break;
   1430 		default:
   1431 			fatal("http_state_run: unknown return value %d", r);
   1432 		}
   1433 	}
   1434 
   1435 	req->fsm_state = 0;
   1436 
   1437 	return (KORE_RESULT_OK);
   1438 }
   1439 
   1440 int
   1441 http_state_exists(struct http_request *req)
   1442 {
   1443 	return (req->hdlr_extra != NULL);
   1444 }
   1445 
   1446 void *
   1447 http_state_create(struct http_request *req, size_t len)
   1448 {
   1449 	if (req->hdlr_extra != NULL)
   1450 		fatal("http_state_create: state already exists");
   1451 
   1452 	req->state_len = len;
   1453 	req->hdlr_extra = kore_calloc(1, len);
   1454 
   1455 	return (req->hdlr_extra);
   1456 }
   1457 
   1458 void *
   1459 http_state_get(struct http_request *req)
   1460 {
   1461 	return (req->hdlr_extra);
   1462 }
   1463 
   1464 void
   1465 http_state_cleanup(struct http_request *req)
   1466 {
   1467 	kore_free(req->hdlr_extra);
   1468 	req->hdlr_extra = NULL;
   1469 }
   1470 
   1471 void
   1472 http_start_recv(struct connection *c)
   1473 {
   1474 	c->http_start = kore_time_ms();
   1475 	c->http_timeout = http_header_timeout * 1000;
   1476 	net_recv_reset(c, http_header_max, http_header_recv);
   1477 }
   1478 
   1479 void
   1480 http_runlock_init(struct http_runlock *lock)
   1481 {
   1482 	lock->owner = NULL;
   1483 	LIST_INIT(&lock->queue);
   1484 }
   1485 
   1486 int
   1487 http_runlock_acquire(struct http_runlock *lock, struct http_request *req)
   1488 {
   1489 	if (lock->owner != NULL) {
   1490 		if (req->runlock != NULL)
   1491 			fatal("%s: request already waiting on lock", __func__);
   1492 
   1493 		req->runlock = kore_pool_get(&http_rlq_pool);
   1494 		req->runlock->req = req;
   1495 		LIST_INSERT_HEAD(&lock->queue, req->runlock, list);
   1496 
   1497 		http_request_sleep(req);
   1498 		return (KORE_RESULT_ERROR);
   1499 	}
   1500 
   1501 	lock->owner = req;
   1502 
   1503 	return (KORE_RESULT_OK);
   1504 }
   1505 
   1506 void
   1507 http_runlock_release(struct http_runlock *lock, struct http_request *req)
   1508 {
   1509 	struct http_runlock_queue	*next;
   1510 	struct http_request		*nextreq;
   1511 
   1512 	if (lock->owner != req)
   1513 		fatal("%s: calling request != owner of runlock", __func__);
   1514 
   1515 	lock->owner = NULL;
   1516 
   1517 	if ((next = LIST_FIRST(&lock->queue)) != NULL) {
   1518 		LIST_REMOVE(next, list);
   1519 
   1520 		nextreq = next->req;
   1521 		nextreq->runlock = NULL;
   1522 
   1523 		http_request_wakeup(nextreq);
   1524 		kore_pool_put(&http_rlq_pool, next);
   1525 	}
   1526 }
   1527 
   1528 int
   1529 http_redirect_add(struct kore_domain *dom, const char *path, int status,
   1530     const char *target)
   1531 {
   1532 	struct http_redirect	*rdr;
   1533 
   1534 	rdr = kore_calloc(1, sizeof(*rdr));
   1535 
   1536 	if (regcomp(&(rdr->rctx), path, REG_EXTENDED)) {
   1537 		kore_free(rdr);
   1538 		return (KORE_RESULT_ERROR);
   1539 	}
   1540 
   1541 	rdr->status = status;
   1542 
   1543 	if (target != NULL)
   1544 		rdr->target = kore_strdup(target);
   1545 	else
   1546 		rdr->target = NULL;
   1547 
   1548 	TAILQ_INSERT_TAIL(&dom->redirects, rdr, list);
   1549 
   1550 	return (KORE_RESULT_OK);
   1551 }
   1552 
   1553 const char *
   1554 http_status_text(int status)
   1555 {
   1556 	const char	*r;
   1557 
   1558 	switch (status) {
   1559 	case HTTP_STATUS_CONTINUE:
   1560 		r = "Continue";
   1561 		break;
   1562 	case HTTP_STATUS_SWITCHING_PROTOCOLS:
   1563 		r = "Switching Protocols";
   1564 		break;
   1565 	case HTTP_STATUS_OK:
   1566 		r = "OK";
   1567 		break;
   1568 	case HTTP_STATUS_CREATED:
   1569 		r = "Created";
   1570 		break;
   1571 	case HTTP_STATUS_ACCEPTED:
   1572 		r = "Accepted";
   1573 		break;
   1574 	case HTTP_STATUS_NON_AUTHORITATIVE:
   1575 		r = "Non-Authoritative Information";
   1576 		break;
   1577 	case HTTP_STATUS_NO_CONTENT:
   1578 		r = "No Content";
   1579 		break;
   1580 	case HTTP_STATUS_RESET_CONTENT:
   1581 		r = "Reset Content";
   1582 		break;
   1583 	case HTTP_STATUS_PARTIAL_CONTENT:
   1584 		r = "Partial Content";
   1585 		break;
   1586 	case HTTP_STATUS_MULTIPLE_CHOICES:
   1587 		r = "Multiple Choices";
   1588 		break;
   1589 	case HTTP_STATUS_MOVED_PERMANENTLY:
   1590 		r = "Moved Permanently";
   1591 		break;
   1592 	case HTTP_STATUS_FOUND:
   1593 		r = "Found";
   1594 		break;
   1595 	case HTTP_STATUS_SEE_OTHER:
   1596 		r = "See Other";
   1597 		break;
   1598 	case HTTP_STATUS_NOT_MODIFIED:
   1599 		r = "Not Modified";
   1600 		break;
   1601 	case HTTP_STATUS_USE_PROXY:
   1602 		r = "Use Proxy";
   1603 		break;
   1604 	case HTTP_STATUS_TEMPORARY_REDIRECT:
   1605 		r = "Temporary Redirect";
   1606 		break;
   1607 	case HTTP_STATUS_BAD_REQUEST:
   1608 		r = "Bad Request";
   1609 		break;
   1610 	case HTTP_STATUS_UNAUTHORIZED:
   1611 		r = "Unauthorized";
   1612 		break;
   1613 	case HTTP_STATUS_PAYMENT_REQUIRED:
   1614 		r = "Payment Required";
   1615 		break;
   1616 	case HTTP_STATUS_FORBIDDEN:
   1617 		r = "Forbidden";
   1618 		break;
   1619 	case HTTP_STATUS_NOT_FOUND:
   1620 		r = "Not Found";
   1621 		break;
   1622 	case HTTP_STATUS_METHOD_NOT_ALLOWED:
   1623 		r = "Method Not Allowed";
   1624 		break;
   1625 	case HTTP_STATUS_NOT_ACCEPTABLE:
   1626 		r = "Not Acceptable";
   1627 		break;
   1628 	case HTTP_STATUS_PROXY_AUTH_REQUIRED:
   1629 		r = "Proxy Authentication Required";
   1630 		break;
   1631 	case HTTP_STATUS_REQUEST_TIMEOUT:
   1632 		r = "Request Time-out";
   1633 		break;
   1634 	case HTTP_STATUS_CONFLICT:
   1635 		r = "Conflict";
   1636 		break;
   1637 	case HTTP_STATUS_GONE:
   1638 		r = "Gone";
   1639 		break;
   1640 	case HTTP_STATUS_LENGTH_REQUIRED:
   1641 		r = "Length Required";
   1642 		break;
   1643 	case HTTP_STATUS_PRECONDITION_FAILED:
   1644 		r = "Precondition Failed";
   1645 		break;
   1646 	case HTTP_STATUS_REQUEST_ENTITY_TOO_LARGE:
   1647 		r = "Request Entity Too Large";
   1648 		break;
   1649 	case HTTP_STATUS_REQUEST_URI_TOO_LARGE:
   1650 		r = "Request-URI Too Large";
   1651 		break;
   1652 	case HTTP_STATUS_UNSUPPORTED_MEDIA_TYPE:
   1653 		r = "Unsupported Media Type";
   1654 		break;
   1655 	case HTTP_STATUS_REQUEST_RANGE_INVALID:
   1656 		r = "Requested range not satisfiable";
   1657 		break;
   1658 	case HTTP_STATUS_EXPECTATION_FAILED:
   1659 		r = "Expectation Failed";
   1660 		break;
   1661 	case HTTP_STATUS_MISDIRECTED_REQUEST:
   1662 		r = "Misdirected Request";
   1663 		break;
   1664 	case HTTP_STATUS_INTERNAL_ERROR:
   1665 		r = "Internal Server Error";
   1666 		break;
   1667 	case HTTP_STATUS_NOT_IMPLEMENTED:
   1668 		r = "Not Implemented";
   1669 		break;
   1670 	case HTTP_STATUS_BAD_GATEWAY:
   1671 		r = "Bad Gateway";
   1672 		break;
   1673 	case HTTP_STATUS_SERVICE_UNAVAILABLE:
   1674 		r = "Service Unavailable";
   1675 		break;
   1676 	case HTTP_STATUS_GATEWAY_TIMEOUT:
   1677 		r = "Gateway Time-out";
   1678 		break;
   1679 	case HTTP_STATUS_BAD_VERSION:
   1680 		r = "HTTP Version not supported";
   1681 		break;
   1682 	default:
   1683 		r = "";
   1684 		break;
   1685 	}
   1686 
   1687 	return (r);
   1688 }
   1689 
   1690 const char *
   1691 http_method_text(int method)
   1692 {
   1693 	char		*r;
   1694 
   1695 	switch(method) {
   1696 	case HTTP_METHOD_GET:
   1697 		r = "GET";
   1698 		break;
   1699 	case HTTP_METHOD_POST:
   1700 		r = "POST";
   1701 		break;
   1702 	case HTTP_METHOD_PUT:
   1703 		r = "PUT";
   1704 		break;
   1705 	case HTTP_METHOD_DELETE:
   1706 		r = "DELETE";
   1707 		break;
   1708 	case HTTP_METHOD_HEAD:
   1709 		r = "HEAD";
   1710 		break;
   1711 	case HTTP_METHOD_OPTIONS:
   1712 		r = "OPTIONS";
   1713 		break;
   1714 	case HTTP_METHOD_PATCH:
   1715 		r = "PATCH";
   1716 		break;
   1717 	default:
   1718 		r = "";
   1719 		break;
   1720 	}
   1721 
   1722 	return (r);
   1723 }
   1724 
   1725 int
   1726 http_method_value(const char *method)
   1727 {
   1728 	if (!strcasecmp(method, "GET"))
   1729 		return (HTTP_METHOD_GET);
   1730 
   1731 	if (!strcasecmp(method, "POST"))
   1732 		return (HTTP_METHOD_POST);
   1733 
   1734 	if (!strcasecmp(method, "PUT"))
   1735 		return (HTTP_METHOD_PUT);
   1736 
   1737 	if (!strcasecmp(method, "DELETE"))
   1738 		return (HTTP_METHOD_DELETE);
   1739 
   1740 	if (!strcasecmp(method, "HEAD"))
   1741 		return (HTTP_METHOD_HEAD);
   1742 
   1743 	if (!strcasecmp(method, "OPTIONS"))
   1744 		return (HTTP_METHOD_OPTIONS);
   1745 
   1746 	if (!strcasecmp(method, "PATCH"))
   1747 		return (HTTP_METHOD_PATCH);
   1748 
   1749 	return (0);
   1750 }
   1751 
   1752 int
   1753 http_media_register(const char *ext, const char *type)
   1754 {
   1755 	struct http_media_type	*media;
   1756 
   1757 	LIST_FOREACH(media, &http_media_types, list) {
   1758 		if (!strcasecmp(media->ext, ext))
   1759 			return (KORE_RESULT_ERROR);
   1760 	}
   1761 
   1762 	media = kore_calloc(1, sizeof(*media));
   1763 	media->ext = kore_strdup(ext);
   1764 	media->type = kore_strdup(type);
   1765 
   1766 	LIST_INSERT_HEAD(&http_media_types, media, list);
   1767 
   1768 	return (KORE_RESULT_OK);
   1769 }
   1770 
   1771 const char *
   1772 http_media_type(const char *path)
   1773 {
   1774 	const char		*p;
   1775 	struct http_media_type	*media;
   1776 
   1777 	if ((p = strrchr(path, '.')) == NULL)
   1778 		return (NULL);
   1779 
   1780 	p++;
   1781 	if (*p == '\0')
   1782 		return (NULL);
   1783 
   1784 	LIST_FOREACH(media, &http_media_types, list) {
   1785 		if (!strcasecmp(media->ext, p))
   1786 			return (media->type);
   1787 	}
   1788 
   1789 	return (NULL);
   1790 }
   1791 
   1792 char *
   1793 http_validate_header(char *header)
   1794 {
   1795 	u_int8_t	idx;
   1796 	char		*p, *value;
   1797 
   1798 	for (p = header; *p != '\0'; p++) {
   1799 		idx = *p;
   1800 		if (idx > HTTP_MAP_LIMIT)
   1801 			return (NULL);
   1802 
   1803 		if (*p == ':') {
   1804 			*(p)++ = '\0';
   1805 			break;
   1806 		}
   1807 
   1808 		if (*p >= 'A' && *p <= 'Z')
   1809 			*p += 32;
   1810 
   1811 		if (http_token[idx] == 0x00)
   1812 			return (NULL);
   1813 	}
   1814 
   1815 	while (isspace(*(unsigned char *)p))
   1816 		p++;
   1817 
   1818 	if (*p == '\0')
   1819 		return (NULL);
   1820 
   1821 	value = p;
   1822 	while (*p != '\0') {
   1823 		idx = *p;
   1824 		if (idx > HTTP_MAP_LIMIT)
   1825 			return (NULL);
   1826 		if (http_field_content[idx] == 0x00)
   1827 			return (NULL);
   1828 		p++;
   1829 	}
   1830 
   1831 	return (value);
   1832 }
   1833 
   1834 static int
   1835 http_release_buffer(struct netbuf *nb)
   1836 {
   1837 	kore_buf_free(nb->extra);
   1838 
   1839 	return (KORE_RESULT_OK);
   1840 }
   1841 
   1842 static int
   1843 http_check_redirect(struct http_request *req, struct kore_domain *dom)
   1844 {
   1845 	int			idx;
   1846 	struct http_redirect	*rdr;
   1847 	const char		*uri;
   1848 	char			key[4];
   1849 	struct kore_buf		location;
   1850 
   1851 	TAILQ_FOREACH(rdr, &dom->redirects, list) {
   1852 		if (!regexec(&(rdr->rctx), req->path,
   1853 		    HTTP_CAPTURE_GROUPS, req->cgroups, 0))
   1854 			break;
   1855 	}
   1856 
   1857 	if (rdr == NULL)
   1858 		return (KORE_RESULT_ERROR);
   1859 
   1860 	uri = NULL;
   1861 	kore_buf_init(&location, 128);
   1862 
   1863 	if (rdr->target) {
   1864 		kore_buf_appendf(&location, "%s", rdr->target);
   1865 
   1866 		if (req->query_string != NULL) {
   1867 			kore_buf_replace_string(&location, "$qs",
   1868 			    req->query_string, strlen(req->query_string));
   1869 		}
   1870 
   1871 		/* Starts at 1 to skip the full path. */
   1872 		for (idx = 1; idx < HTTP_CAPTURE_GROUPS - 1; idx++) {
   1873 			if (req->cgroups[idx].rm_so == -1 ||
   1874 			    req->cgroups[idx].rm_eo == -1)
   1875 				break;
   1876 
   1877 			(void)snprintf(key, sizeof(key), "$%d", idx);
   1878 
   1879 			kore_buf_replace_string(&location, key,
   1880 			    req->path + req->cgroups[idx].rm_so,
   1881 			    req->cgroups[idx].rm_eo - req->cgroups[idx].rm_so);
   1882 		}
   1883 
   1884 		uri = kore_buf_stringify(&location, NULL);
   1885 	}
   1886 
   1887 	if (uri)
   1888 		http_response_header(req, "location", uri);
   1889 
   1890 	http_response(req, rdr->status, NULL, 0);
   1891 	kore_buf_cleanup(&location);
   1892 
   1893 	if (dom->accesslog)
   1894 		kore_accesslog(req);
   1895 
   1896 	return (KORE_RESULT_OK);
   1897 }
   1898 
   1899 static struct http_request *
   1900 http_request_new(struct connection *c, const char *host,
   1901     const char *method, char *path, const char *version)
   1902 {
   1903 	struct kore_domain		*dom;
   1904 	struct http_request		*req;
   1905 	size_t				qsoff;
   1906 	char				*p, *hp;
   1907 	int				m, flags, exists;
   1908 
   1909 	if (http_request_count >= http_request_limit) {
   1910 		http_error_response(c, HTTP_STATUS_SERVICE_UNAVAILABLE);
   1911 		return (NULL);
   1912 	}
   1913 
   1914 	if (strlen(host) >= KORE_DOMAINNAME_LEN - 1) {
   1915 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1916 		return (NULL);
   1917 	}
   1918 
   1919 	if (strlen(path) >= HTTP_URI_LEN - 1) {
   1920 		http_error_response(c, HTTP_STATUS_REQUEST_URI_TOO_LARGE);
   1921 		return (NULL);
   1922 	}
   1923 
   1924 	if (strcasecmp(version, "http/1.1")) {
   1925 		if (strcasecmp(version, "http/1.0")) {
   1926 			http_error_response(c, HTTP_STATUS_BAD_VERSION);
   1927 			return (NULL);
   1928 		}
   1929 
   1930 		flags = HTTP_VERSION_1_0;
   1931 	} else {
   1932 		flags = HTTP_VERSION_1_1;
   1933 	}
   1934 
   1935 	if ((p = strchr(path, '?')) != NULL) {
   1936 		qsoff = p - path;
   1937 	} else {
   1938 		qsoff = 0;
   1939 	}
   1940 
   1941 	hp = NULL;
   1942 
   1943 	switch (c->family) {
   1944 	case AF_INET6:
   1945 		if (*host == '[') {
   1946 			if ((hp = strrchr(host, ']')) == NULL) {
   1947 				http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   1948 				return (NULL);
   1949 			}
   1950 			hp++;
   1951 			if (*hp == ':')
   1952 				*hp = '\0';
   1953 			else
   1954 				hp = NULL;
   1955 		}
   1956 		break;
   1957 	default:
   1958 		if ((hp = strrchr(host, ':')) != NULL)
   1959 			*hp = '\0';
   1960 		break;
   1961 	}
   1962 
   1963 	if (c->owner->server->tls && c->tls_sni != NULL) {
   1964 		if (strcasecmp(c->tls_sni, host)) {
   1965 			http_error_response(c, HTTP_STATUS_MISDIRECTED_REQUEST);
   1966 			return (NULL);
   1967 		}
   1968 	}
   1969 
   1970 	if ((dom = kore_domain_lookup(c->owner->server, host)) == NULL) {
   1971 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   1972 		return (NULL);
   1973 	}
   1974 
   1975 	if (dom->cafile != NULL && c->tls_cert == NULL) {
   1976 		http_error_response(c, HTTP_STATUS_FORBIDDEN);
   1977 		return (NULL);
   1978 	}
   1979 
   1980 	if (hp != NULL)
   1981 		*hp = ':';
   1982 
   1983 	if (!strcasecmp(method, "get")) {
   1984 		m = HTTP_METHOD_GET;
   1985 		flags |= HTTP_REQUEST_COMPLETE;
   1986 	} else if (!strcasecmp(method, "delete")) {
   1987 		m = HTTP_METHOD_DELETE;
   1988 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1989 	} else if (!strcasecmp(method, "post")) {
   1990 		m = HTTP_METHOD_POST;
   1991 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1992 	} else if (!strcasecmp(method, "put")) {
   1993 		m = HTTP_METHOD_PUT;
   1994 		flags |= HTTP_REQUEST_EXPECT_BODY;
   1995 	} else if (!strcasecmp(method, "head")) {
   1996 		m = HTTP_METHOD_HEAD;
   1997 		flags |= HTTP_REQUEST_COMPLETE;
   1998 	} else if (!strcasecmp(method, "options")) {
   1999 		m = HTTP_METHOD_OPTIONS;
   2000 		flags |= HTTP_REQUEST_COMPLETE;
   2001 	} else if (!strcasecmp(method, "patch")) {
   2002 		m = HTTP_METHOD_PATCH;
   2003 		flags |= HTTP_REQUEST_EXPECT_BODY;
   2004 	} else {
   2005 		http_error_response(c, HTTP_STATUS_BAD_REQUEST);
   2006 		return (NULL);
   2007 	}
   2008 
   2009 	if (flags & HTTP_VERSION_1_0) {
   2010 		if (m != HTTP_METHOD_GET && m != HTTP_METHOD_POST &&
   2011 		    m != HTTP_METHOD_HEAD) {
   2012 			http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2013 			return (NULL);
   2014 		}
   2015 	}
   2016 
   2017 	req = kore_pool_get(&http_request_pool);
   2018 
   2019 	req->end = 0;
   2020 	req->total = 0;
   2021 	req->start = 0;
   2022 	req->owner = c;
   2023 	req->status = 0;
   2024 	req->method = m;
   2025 	req->agent = NULL;
   2026 	req->referer = NULL;
   2027 	req->runlock = NULL;
   2028 	req->flags = flags;
   2029 	req->fsm_state = 0;
   2030 	req->http_body = NULL;
   2031 	req->http_body_fd = -1;
   2032 	req->hdlr_extra = NULL;
   2033 	req->content_length = 0;
   2034 	req->query_string = NULL;
   2035 	req->http_body_length = 0;
   2036 	req->http_body_offset = 0;
   2037 	req->http_body_path = NULL;
   2038 
   2039 	req->host = host;
   2040 	req->path = path;
   2041 
   2042 #if defined(KORE_USE_PYTHON)
   2043 	req->py_req = NULL;
   2044 	req->py_coro = NULL;
   2045 	req->py_rqnext = NULL;
   2046 	req->py_validator = NULL;
   2047 #endif
   2048 
   2049 	if (qsoff > 0) {
   2050 		req->query_string = path + qsoff;
   2051 		*(req->query_string)++ = '\0';
   2052 	} else {
   2053 		req->query_string = NULL;
   2054 	}
   2055 
   2056 	/* Checked further down below if we need to 404. */
   2057 	exists = kore_route_lookup(req, dom, m, &req->rt);
   2058 
   2059 	TAILQ_INIT(&(req->resp_headers));
   2060 	TAILQ_INIT(&(req->req_headers));
   2061 	TAILQ_INIT(&(req->resp_cookies));
   2062 	TAILQ_INIT(&(req->req_cookies));
   2063 	TAILQ_INIT(&(req->arguments));
   2064 	TAILQ_INIT(&(req->files));
   2065 
   2066 #if defined(KORE_USE_TASKS)
   2067 	LIST_INIT(&(req->tasks));
   2068 #endif
   2069 
   2070 #if defined(KORE_USE_PGSQL)
   2071 	LIST_INIT(&(req->pgsqls));
   2072 #endif
   2073 
   2074 	http_request_count++;
   2075 	TAILQ_INSERT_HEAD(&http_requests, req, list);
   2076 	TAILQ_INSERT_TAIL(&(c->http_requests), req, olist);
   2077 
   2078 	if (http_check_redirect(req, dom)) {
   2079 		http_request_free(req);
   2080 		return (NULL);
   2081 	}
   2082 
   2083 	if (exists == 0) {
   2084 		http_request_free(req);
   2085 		http_error_response(c, HTTP_STATUS_NOT_FOUND);
   2086 		return (NULL);
   2087 	}
   2088 
   2089 	if (req->rt == NULL) {
   2090 		http_request_free(req);
   2091 		http_error_response(c, HTTP_STATUS_METHOD_NOT_ALLOWED);
   2092 		return (NULL);
   2093 	}
   2094 
   2095 	return (req);
   2096 }
   2097 
   2098 static int
   2099 multipart_find_data(struct kore_buf *in, struct kore_buf *out,
   2100     size_t *olen, struct http_request *req, const void *needle, size_t len)
   2101 {
   2102 	ssize_t			ret;
   2103 	size_t			left;
   2104 	u_int8_t		*p, first, data[4096];
   2105 
   2106 	if (olen != NULL)
   2107 		*olen = 0;
   2108 
   2109 	first = *(const u_int8_t *)needle;
   2110 	for (;;) {
   2111 		if (in->offset < len) {
   2112 			ret = http_body_read(req, data, sizeof(data));
   2113 			if (ret == -1)
   2114 				return (KORE_RESULT_ERROR);
   2115 			if (ret == 0)
   2116 				return (KORE_RESULT_ERROR);
   2117 
   2118 			kore_buf_append(in, data, ret);
   2119 			continue;
   2120 		}
   2121 
   2122 		p = kore_mem_find(in->data, in->offset, &first, 1);
   2123 		if (p == NULL) {
   2124 			if (out != NULL)
   2125 				kore_buf_append(out, in->data, in->offset);
   2126 			if (olen != NULL)
   2127 				*olen += in->offset;
   2128 			kore_buf_reset(in);
   2129 			continue;
   2130 		}
   2131 
   2132 		left = in->offset - (p - in->data);
   2133 		if (left < len) {
   2134 			if (out != NULL)
   2135 				kore_buf_append(out, in->data, (p - in->data));
   2136 			if (olen != NULL)
   2137 				*olen += (p - in->data);
   2138 			memmove(in->data, p, left);
   2139 			in->offset = left;
   2140 			continue;
   2141 		}
   2142 
   2143 		if (!memcmp(p, needle, len)) {
   2144 			if (out != NULL)
   2145 				kore_buf_append(out, in->data, p - in->data);
   2146 			if (olen != NULL)
   2147 				*olen += (p - in->data);
   2148 
   2149 			in->offset = left - len;
   2150 			if (in->offset > 0)
   2151 				memmove(in->data, p + len, in->offset);
   2152 			return (KORE_RESULT_OK);
   2153 		}
   2154 
   2155 		if (out != NULL)
   2156 			kore_buf_append(out, in->data, (p - in->data) + 1);
   2157 		if (olen != NULL)
   2158 			*olen += (p - in->data) + 1;
   2159 
   2160 		in->offset = left - 1;
   2161 		if (in->offset > 0)
   2162 			memmove(in->data, p + 1, in->offset);
   2163 	}
   2164 
   2165 	return (KORE_RESULT_ERROR);
   2166 }
   2167 
   2168 static int
   2169 multipart_parse_headers(struct http_request *req, struct kore_buf *in,
   2170     struct kore_buf *hbuf, const char *boundary, const int blen)
   2171 {
   2172 	int		h, c, i;
   2173 	char		*headers[5], *args[5], *opt[5];
   2174 	char		*d, *val, *name, *fname, *string;
   2175 
   2176 	string = kore_buf_stringify(hbuf, NULL);
   2177 	h = kore_split_string(string, "\r\n", headers, 5);
   2178 	for (i = 0; i < h; i++) {
   2179 		c = kore_split_string(headers[i], ":", args, 5);
   2180 		if (c != 2)
   2181 			continue;
   2182 
   2183 		/* Ignore other headers for now. */
   2184 		if (strcasecmp(args[0], "content-disposition"))
   2185 			continue;
   2186 
   2187 		for (d = args[1]; isspace(*(unsigned char *)d); d++)
   2188 			;
   2189 
   2190 		c = kore_split_string(d, ";", opt, 5);
   2191 		if (c < 2)
   2192 			continue;
   2193 
   2194 		if (strcasecmp(opt[0], "form-data"))
   2195 			continue;
   2196 
   2197 		if ((val = strchr(opt[1], '=')) == NULL)
   2198 			continue;
   2199 		if (strlen(val) < 3)
   2200 			continue;
   2201 
   2202 		val++;
   2203 		kore_strip_chars(val, '"', &name);
   2204 
   2205 		if (opt[2] == NULL) {
   2206 			multipart_add_field(req, in, name, boundary, blen);
   2207 			kore_free(name);
   2208 			continue;
   2209 		}
   2210 
   2211 		for (d = opt[2]; isspace(*(unsigned char *)d); d++)
   2212 			;
   2213 
   2214 		if (!strncasecmp(d, "filename=", 9)) {
   2215 			if ((val = strchr(d, '=')) == NULL) {
   2216 				kore_free(name);
   2217 				continue;
   2218 			}
   2219 
   2220 			val++;
   2221 			kore_strip_chars(val, '"', &fname);
   2222 			if (strlen(fname) > 0) {
   2223 				multipart_file_add(req,
   2224 				    in, name, fname, boundary, blen);
   2225 			}
   2226 			kore_free(fname);
   2227 		}
   2228 
   2229 		kore_free(name);
   2230 	}
   2231 
   2232 	return (KORE_RESULT_OK);
   2233 }
   2234 
   2235 static void
   2236 multipart_add_field(struct http_request *req, struct kore_buf *in,
   2237     char *name, const char *boundary, const int blen)
   2238 {
   2239 	struct kore_buf		*data;
   2240 	char			*string;
   2241 
   2242 	data = kore_buf_alloc(128);
   2243 
   2244 	if (!multipart_find_data(in, data, NULL, req, boundary, blen)) {
   2245 		kore_buf_free(data);
   2246 		return;
   2247 	}
   2248 
   2249 	if (data->offset < 3) {
   2250 		kore_buf_free(data);
   2251 		return;
   2252 	}
   2253 
   2254 	data->offset -= 2;
   2255 	string = kore_buf_stringify(data, NULL);
   2256 	http_argument_add(req, name, string, 0, 0);
   2257 	kore_buf_free(data);
   2258 }
   2259 
   2260 static void
   2261 multipart_file_add(struct http_request *req, struct kore_buf *in,
   2262     const char *name, const char *fname, const char *boundary, const int blen)
   2263 {
   2264 	struct http_file	*f;
   2265 	size_t			position, len;
   2266 
   2267 	position = req->http_body_offset - in->offset;
   2268 	if (!multipart_find_data(in, NULL, &len, req, boundary, blen))
   2269 		return;
   2270 
   2271 	if (len < 3)
   2272 		return;
   2273 	len -= 2;
   2274 
   2275 	f = kore_malloc(sizeof(struct http_file));
   2276 	f->req = req;
   2277 	f->offset = 0;
   2278 	f->length = len;
   2279 	f->position = position;
   2280 	f->name = kore_strdup(name);
   2281 	f->filename = kore_strdup(fname);
   2282 
   2283 	TAILQ_INSERT_TAIL(&(req->files), f, list);
   2284 }
   2285 
   2286 static void
   2287 http_argument_add(struct http_request *req, char *name, char *value, int qs,
   2288     int decode)
   2289 {
   2290 	struct http_arg			*q;
   2291 	struct kore_route_params	*p;
   2292 
   2293 	if (decode) {
   2294 		if (!http_argument_urldecode(name, qs))
   2295 			return;
   2296 	}
   2297 
   2298 	TAILQ_FOREACH(p, &req->rt->params, list) {
   2299 		if (qs == 1 && !(p->flags & KORE_PARAMS_QUERY_STRING))
   2300 			continue;
   2301 		if (qs == 0 && (p->flags & KORE_PARAMS_QUERY_STRING))
   2302 			continue;
   2303 
   2304 		if (p->method != req->method)
   2305 			continue;
   2306 
   2307 		if (strcmp(p->name, name))
   2308 			continue;
   2309 
   2310 		if (decode) {
   2311 			if (!http_argument_urldecode(value, qs))
   2312 				return;
   2313 		}
   2314 
   2315 		if (!kore_validator_check(req, p->validator, value))
   2316 			break;
   2317 
   2318 		q = kore_malloc(sizeof(struct http_arg));
   2319 		q->name = kore_strdup(name);
   2320 		q->s_value = kore_strdup(value);
   2321 		TAILQ_INSERT_TAIL(&(req->arguments), q, list);
   2322 		break;
   2323 	}
   2324 }
   2325 
   2326 static int
   2327 http_body_recv(struct netbuf *nb)
   2328 {
   2329 	struct http_request	*req = (struct http_request *)nb->extra;
   2330 
   2331 	return (http_body_update(req, nb->buf, nb->s_off));
   2332 }
   2333 
   2334 static int
   2335 http_body_update(struct http_request *req, const void *data, size_t len)
   2336 {
   2337 	ssize_t			ret;
   2338 	u_int64_t		bytes_left;
   2339 
   2340 	SHA256Update(&req->hashctx, data, len);
   2341 
   2342 	if (req->rt->on_body_chunk != NULL) {
   2343 		if (kore_runtime_http_body_chunk(req->rt->on_body_chunk,
   2344 		    req, data, len) != KORE_RESULT_OK) {
   2345 			req->flags |= HTTP_REQUEST_DELETE;
   2346 			http_error_response(req->owner,
   2347 			    HTTP_STATUS_INTERNAL_ERROR);
   2348 			return (KORE_RESULT_ERROR);
   2349 		}
   2350 	} else if (req->http_body_fd != -1) {
   2351 		ret = write(req->http_body_fd, data, len);
   2352 		if (ret == -1 || (size_t)ret != len) {
   2353 			req->flags |= HTTP_REQUEST_DELETE;
   2354 			http_error_response(req->owner,
   2355 			    HTTP_STATUS_INTERNAL_ERROR);
   2356 			return (KORE_RESULT_ERROR);
   2357 		}
   2358 	} else if (req->http_body != NULL) {
   2359 		kore_buf_append(req->http_body, data, len);
   2360 	} else {
   2361 		req->flags |= HTTP_REQUEST_DELETE;
   2362 		http_error_response(req->owner,
   2363 		    HTTP_STATUS_INTERNAL_ERROR);
   2364 		return (KORE_RESULT_ERROR);
   2365 	}
   2366 
   2367 	req->content_length -= len;
   2368 
   2369 	if (req->content_length == 0) {
   2370 		req->owner->http_timeout = 0;
   2371 		req->owner->rnb->extra = NULL;
   2372 		http_request_wakeup(req);
   2373 		req->flags |= HTTP_REQUEST_COMPLETE;
   2374 		req->flags &= ~HTTP_REQUEST_EXPECT_BODY;
   2375 		req->content_length = req->http_body_length;
   2376 		if (!http_body_rewind(req)) {
   2377 			req->flags |= HTTP_REQUEST_DELETE;
   2378 			http_error_response(req->owner,
   2379 			    HTTP_STATUS_INTERNAL_ERROR);
   2380 			return (KORE_RESULT_ERROR);
   2381 		}
   2382 		SHA256Final(req->http_body_digest, &req->hashctx);
   2383 	} else {
   2384 		bytes_left = req->content_length;
   2385 		net_recv_reset(req->owner,
   2386 		    MIN(bytes_left, NETBUF_SEND_PAYLOAD_MAX),
   2387 		    http_body_recv);
   2388 		req->owner->rnb->extra = req;
   2389 	}
   2390 
   2391 	return (KORE_RESULT_OK);
   2392 }
   2393 
   2394 static void
   2395 http_error_response(struct connection *c, int status)
   2396 {
   2397 	c->flags |= CONN_CLOSE_EMPTY;
   2398 
   2399 	switch (c->proto) {
   2400 	case CONN_PROTO_HTTP:
   2401 		http_response_normal(NULL, c, status, NULL, 0);
   2402 		break;
   2403 	default:
   2404 		fatal("http_error_response() bad proto %d", c->proto);
   2405 		/* NOTREACHED. */
   2406 	}
   2407 
   2408 	if (!net_send_flush(c))
   2409 		kore_connection_disconnect(c);
   2410 }
   2411 
   2412 static void
   2413 http_response_normal(struct http_request *req, struct connection *c,
   2414     int status, const void *d, size_t len)
   2415 {
   2416 	struct kore_buf		buf;
   2417 	struct http_cookie	*ck;
   2418 	struct http_header	*hdr;
   2419 	char			version;
   2420 	const char		*conn, *text;
   2421 	int			connection_close, send_body;
   2422 
   2423 	send_body = 1;
   2424 	text = http_status_text(status);
   2425 
   2426 	kore_buf_reset(header_buf);
   2427 
   2428 	if (req != NULL) {
   2429 		if (req->flags & HTTP_VERSION_1_0)
   2430 			version = '0';
   2431 		else
   2432 			version = '1';
   2433 	} else {
   2434 		version = '1';
   2435 	}
   2436 
   2437 	kore_buf_appendf(header_buf, "HTTP/1.%c %d %s\r\n",
   2438 	    version, status, text);
   2439 
   2440 	if (status == 100) {
   2441 		kore_buf_append(header_buf, "\r\n", 2);
   2442 		net_send_queue(c, header_buf->data, header_buf->offset);
   2443 		return;
   2444 	}
   2445 
   2446 	kore_buf_append(header_buf, http_version, http_version_len);
   2447 
   2448 	if ((c->flags & CONN_CLOSE_EMPTY) ||
   2449 	    (req != NULL && (req->flags & HTTP_VERSION_1_0))) {
   2450 		connection_close = 1;
   2451 	} else {
   2452 		connection_close = 0;
   2453 	}
   2454 
   2455 	if (connection_close == 0 && req != NULL) {
   2456 		if (http_request_header(req, "connection", &conn)) {
   2457 			if ((*conn == 'c' || *conn == 'C') &&
   2458 			    !strcasecmp(conn, "close")) {
   2459 				connection_close = 1;
   2460 			}
   2461 		}
   2462 	}
   2463 
   2464 	kore_buf_init(&buf, 1024);
   2465 
   2466 	/* Note that req CAN be NULL. */
   2467 	if (req == NULL || req->owner->proto != CONN_PROTO_WEBSOCKET) {
   2468 		if (http_keepalive_time && connection_close == 0) {
   2469 			kore_buf_appendf(header_buf,
   2470 			    "connection: keep-alive\r\n");
   2471 			kore_buf_appendf(header_buf,
   2472 			    "keep-alive: timeout=%d\r\n", http_keepalive_time);
   2473 		} else {
   2474 			c->flags |= CONN_CLOSE_EMPTY;
   2475 			kore_buf_appendf(header_buf, "connection: close\r\n");
   2476 		}
   2477 	}
   2478 
   2479 	if (c->tls && http_hsts_enable) {
   2480 		kore_buf_appendf(header_buf, "strict-transport-security: ");
   2481 		kore_buf_appendf(header_buf,
   2482 		    "max-age=%" PRIu64 "; includeSubDomains\r\n",
   2483 		    http_hsts_enable);
   2484 	}
   2485 
   2486 	if (http_pretty_error && d == NULL && status >= 400) {
   2487 		kore_buf_appendf(&buf, pretty_error_fmt,
   2488 		    status, text, status, text);
   2489 
   2490 		d = buf.data;
   2491 		len = buf.offset;
   2492 	}
   2493 
   2494 	if (req != NULL) {
   2495 		TAILQ_FOREACH(ck, &(req->resp_cookies), list)
   2496 			http_write_response_cookie(ck);
   2497 
   2498 		TAILQ_FOREACH(hdr, &(req->resp_headers), list) {
   2499 			kore_buf_appendf(header_buf, "%s: %s\r\n",
   2500 			    hdr->header, hdr->value);
   2501 		}
   2502 
   2503 		if (status != 204 && status >= 200 &&
   2504 		    !(req->flags & HTTP_REQUEST_NO_CONTENT_LENGTH)) {
   2505 			kore_buf_appendf(header_buf,
   2506 			    "content-length: %zu\r\n", len);
   2507 		}
   2508 	} else {
   2509 		if (status != 204 && status >= 200) {
   2510 			kore_buf_appendf(header_buf,
   2511 			    "content-length: %zu\r\n", len);
   2512 		}
   2513 	}
   2514 
   2515 	kore_buf_append(header_buf, "\r\n", 2);
   2516 	net_send_queue(c, header_buf->data, header_buf->offset);
   2517 
   2518 	if (req != NULL && req->method == HTTP_METHOD_HEAD)
   2519 		send_body = 0;
   2520 
   2521 	if (d != NULL && send_body)
   2522 		net_send_queue(c, d, len);
   2523 
   2524 	if (!(c->flags & CONN_CLOSE_EMPTY) && !(c->flags & CONN_IS_BUSY))
   2525 		http_start_recv(c);
   2526 
   2527 	if (req != NULL)
   2528 		req->content_length = len;
   2529 
   2530 	kore_buf_cleanup(&buf);
   2531 }
   2532 
   2533 static void
   2534 http_write_response_cookie(struct http_cookie *ck)
   2535 {
   2536 	struct tm		tm;
   2537 	char			expires[HTTP_DATE_MAXSIZE];
   2538 
   2539 	kore_buf_reset(ckhdr_buf);
   2540 	kore_buf_appendf(ckhdr_buf, "%s=%s", ck->name, ck->value);
   2541 
   2542 	if (ck->path != NULL)
   2543 		kore_buf_appendf(ckhdr_buf, "; Path=%s", ck->path);
   2544 	if (ck->domain != NULL)
   2545 		kore_buf_appendf(ckhdr_buf, "; Domain=%s", ck->domain);
   2546 
   2547 	if (ck->expires > 0) {
   2548 		if (gmtime_r(&ck->expires, &tm) == NULL) {
   2549 			kore_log(LOG_ERR, "gmtime_r(): %s", errno_s);
   2550 			return;
   2551 		}
   2552 
   2553 		if (strftime(expires, sizeof(expires),
   2554 		    "%a, %d %b %y %H:%M:%S GMT", &tm) == 0) {
   2555 			kore_log(LOG_ERR, "strftime(): %s", errno_s);
   2556 			return;
   2557 		}
   2558 
   2559 		kore_buf_appendf(ckhdr_buf, "; Expires=%s", expires);
   2560 	}
   2561 
   2562 	if (ck->maxage > 0)
   2563 		kore_buf_appendf(ckhdr_buf, "; Max-Age=%u", ck->maxage);
   2564 
   2565 	if (ck->flags & HTTP_COOKIE_HTTPONLY)
   2566 		kore_buf_appendf(ckhdr_buf, "; HttpOnly");
   2567 	if (ck->flags & HTTP_COOKIE_SECURE)
   2568 		kore_buf_appendf(ckhdr_buf, "; Secure");
   2569 
   2570 	kore_buf_appendf(header_buf, "set-cookie: %s\r\n",
   2571 	    kore_buf_stringify(ckhdr_buf, NULL));
   2572 }
   2573 
   2574 static int
   2575 http_data_convert(void *data, void **out, void *nout, int type)
   2576 {
   2577 	switch (type) {
   2578 	case HTTP_ARG_TYPE_RAW:
   2579 	case HTTP_ARG_TYPE_STRING:
   2580 		*out = data;
   2581 		return (KORE_RESULT_OK);
   2582 	case HTTP_ARG_TYPE_BYTE:
   2583 		COPY_ARG_TYPE(*(u_int8_t *)data, u_int8_t);
   2584 		return (KORE_RESULT_OK);
   2585 	case HTTP_ARG_TYPE_INT16:
   2586 		COPY_AS_INTTYPE(SHRT_MIN, SHRT_MAX, int16_t);
   2587 		return (KORE_RESULT_OK);
   2588 	case HTTP_ARG_TYPE_UINT16:
   2589 		COPY_AS_INTTYPE(0, USHRT_MAX, u_int16_t);
   2590 		return (KORE_RESULT_OK);
   2591 	case HTTP_ARG_TYPE_INT32:
   2592 		COPY_AS_INTTYPE(INT_MIN, INT_MAX, int32_t);
   2593 		return (KORE_RESULT_OK);
   2594 	case HTTP_ARG_TYPE_UINT32:
   2595 		COPY_AS_INTTYPE(0, UINT_MAX, u_int32_t);
   2596 		return (KORE_RESULT_OK);
   2597 	case HTTP_ARG_TYPE_INT64:
   2598 		COPY_AS_INTTYPE_64(int64_t, 1);
   2599 		return (KORE_RESULT_OK);
   2600 	case HTTP_ARG_TYPE_UINT64:
   2601 		COPY_AS_INTTYPE_64(u_int64_t, 0);
   2602 		return (KORE_RESULT_OK);
   2603 	case HTTP_ARG_TYPE_FLOAT:
   2604 		COPY_ARG_DOUBLE(-FLT_MAX, FLT_MAX, float);
   2605 		return (KORE_RESULT_OK);
   2606 	case HTTP_ARG_TYPE_DOUBLE:
   2607 		COPY_ARG_DOUBLE(-DBL_MAX, DBL_MAX, double);
   2608 		return (KORE_RESULT_OK);
   2609 	default:
   2610 		break;
   2611 	}
   2612 
   2613 	return (KORE_RESULT_ERROR);
   2614 }