16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <netinet/tcp.h>
19 #include <arpa/inet.h>
30 #include <event2/dns.h>
32 #include "evhtp/config.h"
61 #ifndef EVHTP_DISABLE_REGEX
71 #define SET_BIT(VAR, FLAG) VAR |= FLAG
72 #define UNSET_BIT(VAR, FLAG) VAR &= ~FLAG
74 #define HTP_FLAG_ON(PRE, FLAG) SET_BIT(PRE->flags, FLAG)
75 #define HTP_FLAG_OFF(PRE, FLAG) UNSET_BIT(PRE->flags, FLAG)
77 #define HTP_IS_READING(b) ((bufferevent_get_enabled(b) & \
78 EV_READ) ? true : false)
79 #define HTP_IS_WRITING(b) ((bufferevent_get_enabled(b) & \
80 EV_WRITE) ? true : false)
82 #define HTP_LEN_OUTPUT(b) (evbuffer_get_length(bufferevent_get_output(b)))
83 #define HTP_LEN_INPUT(b) (evbuffer_get_length(bufferevent_get_input(b)))
85 #define HOOK_AVAIL(var, hook_name) (var->hooks && var->hooks->hook_name)
86 #define HOOK_FUNC(var, hook_name) (var->hooks->hook_name)
87 #define HOOK_ARGS(var, hook_name) var->hooks->hook_name ## _arg
89 #define HOOK_REQUEST_RUN(request, hook_name, ...) do { \
90 if (HOOK_AVAIL(request, hook_name)) { \
91 return HOOK_FUNC(request, hook_name) (request, __VA_ARGS__, \
92 HOOK_ARGS(request, hook_name)); \
94 if (request->conn && HOOK_AVAIL(request->conn, hook_name)) { \
95 return HOOK_FUNC(request->conn, hook_name) (request, __VA_ARGS__, \
96 HOOK_ARGS(request->conn, hook_name)); \
100 #define HOOK_REQUEST_RUN_NARGS(__request, hook_name) do { \
101 if (HOOK_AVAIL(__request, hook_name)) { \
102 return HOOK_FUNC(__request, hook_name) (__request, \
103 HOOK_ARGS(__request, hook_name)); \
105 if (__request->conn && HOOK_AVAIL(__request->conn, hook_name)) { \
106 return HOOK_FUNC(__request->conn, hook_name) (request, \
107 HOOK_ARGS(__request->conn, hook_name)); \
111 #ifndef EVHTP_DISABLE_EVTHR
117 #define htp__lock_(h) do { \
119 pthread_mutex_lock(h->lock); \
128 #define htp__unlock_(h) do { \
130 pthread_mutex_unlock(h->lock); \
134 #define htp__lock_(h) do { \
136 #define htp__unlock_(h) do { \
140 #ifndef TAILQ_FOREACH_SAFE
141 #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
142 for ((var) = TAILQ_FIRST((head)); \
143 (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
148 #define rc_scratch conn->scratch_buf
149 #define rc_parser conn->parser
152 #define ch_fini_arg hooks->on_connection_fini_arg
153 #define ch_fini hooks->on_connection_fini
156 #define cr_status request->status
157 #define cr_flags request->flags
158 #define cr_proto request->proto
161 #define rh_err hooks->on_error
162 #define rh_err_arg hooks->on_error_arg
164 #ifndef EVHTP_DISABLE_MEMFUNCTIONS
166 static void * (*malloc_)(
size_t sz) = malloc;
167 static void * (* realloc_)(
void * d,
size_t sz) = realloc;
168 static void (*
free_)(
void * d) = free;
237 size_t len = nmemb * size;
240 if ((p =
malloc_(len)) == NULL) {
249 return calloc(nmemb, size);
269 if ((p =
malloc_(len + 1)) == NULL) {
273 memcpy(p, str, len + 1);
296 if ((p =
malloc_(len + 1)) != NULL) {
297 memcpy(p, str, len + 1);
307 return strndup(str, len);
311 #define htp__malloc_(sz) malloc(sz)
312 #define htp__calloc_(n, sz) calloc(n, sz)
313 #define htp__strdup_(s) strdup(s)
314 #define htp__strndup_(n, sz) strndup(n, sz)
315 #define htp__realloc_(p, sz) realloc(p, sz)
316 #define htp__free_(p) free(p)
322 void *(*reallocfn_)(
void * p,
size_t sz),
323 void (*freefn_)(
void * p))
325 #ifndef EVHTP_DISABLE_MEMFUNCTIONS
350 return "Bad Request";
351 case EVHTP_RES_NOTFOUND:
353 case EVHTP_RES_SERVERR:
354 return "Internal Server Error";
355 case EVHTP_RES_CONTINUE:
357 case EVHTP_RES_FORBIDDEN:
359 case EVHTP_RES_SWITCH_PROTO:
360 return "Switching Protocols";
361 case EVHTP_RES_MOVEDPERM:
362 return "Moved Permanently";
363 case EVHTP_RES_PROCESSING:
365 case EVHTP_RES_URI_TOOLONG:
366 return "URI Too Long";
367 case EVHTP_RES_CREATED:
369 case EVHTP_RES_ACCEPTED:
371 case EVHTP_RES_NAUTHINFO:
372 return "No Auth Info";
373 case EVHTP_RES_NOCONTENT:
375 case EVHTP_RES_RSTCONTENT:
376 return "Reset Content";
377 case EVHTP_RES_PARTIAL:
378 return "Partial Content";
379 case EVHTP_RES_MSTATUS:
380 return "Multi-Status";
381 case EVHTP_RES_IMUSED:
383 case EVHTP_RES_FOUND:
385 case EVHTP_RES_SEEOTHER:
387 case EVHTP_RES_NOTMOD:
388 return "Not Modified";
389 case EVHTP_RES_USEPROXY:
391 case EVHTP_RES_SWITCHPROXY:
392 return "Switch Proxy";
393 case EVHTP_RES_TMPREDIR:
394 return "Temporary Redirect";
395 case EVHTP_RES_UNAUTH:
396 return "Unauthorized";
397 case EVHTP_RES_PAYREQ:
398 return "Payment Required";
399 case EVHTP_RES_METHNALLOWED:
400 return "Not Allowed";
401 case EVHTP_RES_NACCEPTABLE:
402 return "Not Acceptable";
403 case EVHTP_RES_PROXYAUTHREQ:
404 return "Proxy Authentication Required";
405 case EVHTP_RES_TIMEOUT:
406 return "Request Timeout";
407 case EVHTP_RES_CONFLICT:
411 case EVHTP_RES_LENREQ:
412 return "Length Required";
413 case EVHTP_RES_PRECONDFAIL:
414 return "Precondition Failed";
415 case EVHTP_RES_ENTOOLARGE:
416 return "Entity Too Large";
417 case EVHTP_RES_URITOOLARGE:
418 return "Request-URI Too Long";
419 case EVHTP_RES_UNSUPPORTED:
420 return "Unsupported Media Type";
421 case EVHTP_RES_RANGENOTSC:
422 return "Requested Range Not Satisfiable";
423 case EVHTP_RES_EXPECTFAIL:
424 return "Expectation Failed";
425 case EVHTP_RES_IAMATEAPOT:
426 return "I'm a teapot";
427 case EVHTP_RES_NOTIMPL:
428 return "Not Implemented";
429 case EVHTP_RES_BADGATEWAY:
430 return "Bad Gateway";
431 case EVHTP_RES_SERVUNAVAIL:
432 return "Service Unavailable";
433 case EVHTP_RES_GWTIMEOUT:
434 return "Gateway Timeout";
435 case EVHTP_RES_VERNSUPPORT:
436 return "HTTP Version Not Supported";
437 case EVHTP_RES_BWEXEED:
438 return "Bandwidth Limit Exceeded";
444 #ifndef EVHTP_DISABLE_SSL
446 #ifndef EVHTP_DISABLE_EVTHR
468 strnlen(
const char * s,
size_t maxlen)
473 for (e = s, n = 0; *e && n < maxlen; e++, n++) {
493 strndup(
const char * s,
size_t n)
495 size_t len = strnlen(s, n);
529 #define htp__is_http_11_(_major, _minor) \
530 (_major >= 1 && _minor >= 1)
541 #define htp__is_http_10_(_major, _minor) \
542 (_major >= 1 && _minor <= 0)
632 if (request == NULL) {
633 return EVHTP_RES_500;
652 if (request == NULL) {
653 return EVHTP_RES_500;
733 if (connection->
hooks != NULL && connection->ch_fini != NULL) {
734 return (connection->ch_fini)(connection, connection->ch_fini_arg);
749 if (request && request->
hooks && request->rh_err) {
750 (*request->rh_err)(request, errtype, request->rh_err_arg);
763 if (connection == NULL) {
767 if (connection->
request != NULL) {
798 if (connection->
hooks && connection->
hooks->on_write) {
799 return (connection->
hooks->on_write)(connection,
800 connection->
hooks->on_write_arg);
818 const char *
string,
size_t str_len)
821 switch (pattern[0]) {
823 while (pattern[1] ==
'*') {
844 if (pattern[0] !=
string[0]) {
857 while (*pattern ==
'*') {
866 if (plen == 0 && str_len == 0) {
882 static evhtp_callback_t *
885 unsigned int * start_offset,
886 unsigned int * end_offset)
889 evhtp_callback_t * callback;
891 #ifndef EVHTP_DISABLE_REGEX
892 regmatch_t pmatch[28];
899 path_len = strlen(path);
901 TAILQ_FOREACH(callback, cbs, next) {
902 switch (callback->type) {
904 if (strncmp(path, callback->val.path, callback->len) == 0) {
906 *end_offset = path_len;
912 #ifndef EVHTP_DISABLE_REGEX
914 if (regexec(callback->val.regex,
916 callback->val.regex->re_nsub + 1,
918 *start_offset = pmatch[callback->val.regex->re_nsub].rm_so;
919 *end_offset = pmatch[callback->val.regex->re_nsub].rm_eo;
928 size_t glob_len = strlen(callback->val.glob);
935 *end_offset = path_len;
988 const char * data_end = (
const char *)(data + len);
996 if (req_path == NULL) {
1012 }
else if (*data !=
'/') {
1028 if (data[len - 1] !=
'/') {
1035 for (i = (len - 1); i != 0; i--) {
1036 if (data[i] ==
'/') {
1044 path_len = (size_t)(&data[i] - data) + 1;
1045 file_len = (size_t)(data_end - &data[i + 1]);
1048 if ((
const char *)(data + path_len) > data_end) {
1053 if ((
const char *)(&data[i + 1] + file_len) > data_end) {
1073 if (i == 0 && data[i] ==
'/' && !
file && !
path) {
1139 return (*out != NULL) ? 0 : -1;
1150 if (authority == NULL) {
1219 if (request == NULL) {
1229 if (request->conn && request->conn->request == request) {
1230 request->conn->request = NULL;
1233 if (request->buffer_in != NULL) {
1237 if (request->buffer_out != NULL) {
1252 static evhtp_request_t *
1264 req->
htp = c ? c->htp : NULL;
1268 if (!(req->
buffer_in = evbuffer_new())) {
1308 evhtp_connection_t * c;
1355 evhtp_uri_t *
uri = c->request->uri;
1356 const char * fragment;
1357 int ignore_fragment;
1369 ignore_fragment = (c->htp->parser_flags &
1373 if (!ignore_fragment && (fragment = memchr(data,
'#', len))) {
1380 ptrdiff_t frag_offset;
1382 frag_offset = fragment - data;
1384 if (frag_offset < len) {
1390 fraglen = len - frag_offset;
1395 memcpy(
uri->fragment, fragment, fraglen);
1397 uri->fragment[fraglen] =
'\0';
1413 memcpy(
uri->query_raw, data, len);
1414 uri->query_raw[len] =
'\0';
1436 evhtp_header_t * hdr;
1441 if (key_s == NULL) {
1448 memcpy(key_s, data, len);
1468 evhtp_header_t * header;
1474 memcpy(val_s, data, len);
1483 header->v_heaped = 1;
1492 static inline evhtp_t *
1495 evhtp_t * evhtp_vhost;
1498 TAILQ_FOREACH(evhtp_vhost, &
evhtp->vhosts, next_vhost) {
1504 strlen(evhtp_vhost->server_name), name,
1505 strlen(name)) == 1) {
1509 TAILQ_FOREACH(
evhtp_alias, &evhtp_vhost->aliases, next) {
1516 strlen(name)) == 1) {
1529 evhtp_connection_t *
conn;
1531 evhtp_path_t * path;
1532 evhtp_hooks_t *
hooks;
1533 evhtp_callback_t * callback;
1537 if (request == NULL) {
1541 if ((
evhtp = request->htp) == NULL) {
1545 if ((
conn = request->conn) == NULL) {
1549 if ((
uri = request->uri) == NULL) {
1553 if ((path =
uri->path) == NULL) {
1563 &path->matched_soff, &path->matched_eoff))) {
1566 cbarg = callback->cbarg;
1567 hooks = callback->hooks;
1569 &path->matched_soff, &path->matched_eoff))) {
1572 cbarg = callback->cbarg;
1573 hooks = callback->hooks;
1579 path->matched_soff = 0;
1580 path->matched_eoff = (
unsigned int)strlen(path->full);
1583 if (path->match_start == NULL) {
1584 path->match_start =
htp__calloc_(strlen(path->full) + 1, 1);
1588 if (path->match_end == NULL) {
1589 path->match_end =
htp__calloc_(strlen(path->full) + 1, 1);
1593 if (path->matched_soff != UINT_MAX ) {
1594 if (path->matched_eoff - path->matched_soff) {
1595 memcpy(path->match_start, (
void *)(path->full + path->matched_soff),
1596 path->matched_eoff - path->matched_soff);
1598 memcpy(path->match_start, (
void *)(path->full + path->matched_soff),
1599 strlen((
const char *)(path->full + path->matched_soff)));
1602 memcpy(path->match_end,
1603 (
void *)(path->full + path->matched_eoff),
1604 strlen(path->full) - path->matched_eoff);
1607 if (
hooks != NULL) {
1608 if (request->hooks == NULL) {
1613 memcpy(request->hooks,
hooks,
sizeof(evhtp_hooks_t));
1617 request->cbarg =
cbarg;
1627 evhtp_t * evhtp_vhost;
1629 #ifndef EVHTP_DISABLE_SSL
1634 host = SSL_get_servername(c->ssl, TLSEXT_NAMETYPE_host_name);
1659 c->htp = evhtp_vhost;
1660 c->request->htp = evhtp_vhost;
1679 if (c != NULL && c->request != NULL) {
1680 if (c->request->uri == NULL) {
1693 evhtp_connection_t * c;
1694 evhtp_authority_t * authority;
1709 authority = c->request->uri->authority;
1713 if (authority->hostname == NULL) {
1719 memcpy(authority->hostname, data, len);
1720 authority->hostname[len] =
'\0';
1729 evhtp_authority_t * authority;
1737 authority = c->request->uri->authority;
1738 port = strtoul(data, &endptr, 10);
1740 if (endptr - data != len || port > 65535) {
1746 authority->port = port;
1755 evhtp_path_t * path;
1771 c->request->uri->path = path;
1791 evhtp_connection_t * c;
1819 evbuffer_add_printf(bufferevent_get_output(c->bev),
1820 "HTTP/%c.%c 100 Continue\r\n\r\n",
1832 struct evbuffer * buf;
1835 if (c->max_body_size > 0 && c->body_bytes_read + len >= c->max_body_size) {
1842 if ((buf = c->scratch_buf) == NULL) {
1846 evbuffer_add(buf, data, len);
1852 if (evbuffer_get_length(buf)) {
1853 evbuffer_add_buffer(c->request->buffer_in, buf);
1856 evbuffer_drain(buf, -1);
1858 c->body_bytes_read += len;
1925 const char * content_type;
1931 if (req->uri == NULL || req->uri->query != NULL) {
1940 evbuffer_get_length(req->buffer_in)) {
1944 content_type =
evhtp_kv_find(req->headers_in,
"content-type");
1946 if (content_type == NULL) {
1950 if (strncasecmp(content_type,
"application/x-www-form-urlencoded", 33)) {
1979 struct evbuffer * buf_in;
1981 uri = c->request->uri;
1982 buf_in = c->request->buffer_in;
1984 body_len = evbuffer_get_length(buf_in);
1985 body = (
const char *)evbuffer_pullup(buf_in, body_len);
1994 memcpy(uri->query_raw, body, body_len);
2005 if (c->request && c->request->cb) {
2006 (c->request->cb)(c->request, c->request->cbarg);
2019 #if LIBEVENT_VERSION_NUMBER < 0x02010000
2026 for (n = 0; n < n_vec; n++) {
2027 to_alloc += vec[n].iov_len;
2030 evbuffer_expand(buf, to_alloc);
2032 for (n = 0; n < n_vec; n++) {
2033 evbuffer_add(buf, vec[n].iov_base, vec[n].iov_len);
2035 res += vec[n].iov_len;
2040 return evbuffer_add_iovec(buf, vec, n_vec);
2047 struct evbuffer * buf = arg;
2048 struct evbuffer_iovec iov[4] = {
2049 { header->key, header->klen },
2051 { header->val, header->vlen },
2060 static struct evbuffer *
2063 struct evbuffer * buf;
2064 const char * content_type;
2068 unsigned char major;
2069 unsigned char minor;
2073 && request->headers_out
2074 && request->buffer_out
2076 && request->rc_parser);
2078 request->status = code;
2080 out_len = evbuffer_get_length(request->buffer_out);
2082 if ((buf = request->rc_scratch) == NULL) {
2083 request->rc_scratch = evbuffer_new();
2087 evbuffer_drain(buf, -1);
2109 switch (request->proto) {
2142 if (!content_type) {
2165 struct evbuffer_iovec iov[9] = {
2167 { (
void *)&major, 1 },
2169 { (
void *)&minor, 1 },
2171 { out_buf, strlen(out_buf) },
2173 { (
void *)status_str, strlen(status_str) },
2181 evbuffer_add(buf,
"\r\n", 2);
2183 if (evbuffer_get_length(request->buffer_out)) {
2184 evbuffer_add_buffer(buf, request->buffer_out);
2217 evhtp_connection_t * c = arg;
2233 log_debug(
"connection is paused, returning");
2241 buf = evbuffer_pullup(bufferevent_get_input(bev), avail);
2256 log_debug(
"EVHTP_CONN_FLAG_OWNER set, removing contexts");
2258 evbuffer_drain(bufferevent_get_input(bev), nread);
2265 switch (c->cr_status) {
2276 evbuffer_drain(bufferevent_get_input(bev), nread);
2283 log_debug(
"error %d, freeing connection",
2287 }
else if (nread < avail) {
2289 log_debug(
"Reading more data via resumption");
2298 evhtp_connection_t * conn;
2299 uint64_t keepalive_max;
2300 const char * errstr;
2307 log_error(
"No data associated with the bufferevent %p", bev);
2314 conn = (evhtp_connection_t *)arg;
2318 errstr =
"no request associated with connection";
2323 errstr =
"no parser registered with connection";
2329 errstr =
"no context associated with the server-connection";
2333 keepalive_max = conn->htp->max_keepalive_requests;
2340 log_error(
"shutting down connection: %s", errstr);
2363 bufferevent_enable(bev, EV_READ);
2367 log_debug(
"have input data, will travel");
2389 if (keepalive_max > 0) {
2390 if (++conn->num_requests >= keepalive_max) {
2409 conn->body_bytes_read = 0;
2412 if (conn->htp->parent != NULL
2419 conn->htp = conn->htp->parent;
2423 switch (conn->type) {
2425 type = htp_type_response;
2428 type = htp_type_request;
2454 evhtp_connection_t * c = arg;
2456 log_debug(
"%p %p eventcb %s%s%s%s", arg, (
void *)bev,
2457 events & BEV_EVENT_CONNECTED ?
"connected" :
"",
2458 events & BEV_EVENT_ERROR ?
"error" :
"",
2459 events & BEV_EVENT_TIMEOUT ?
"timeout" :
"",
2460 events & BEV_EVENT_EOF ?
"eof" :
"");
2462 if (c->hooks && c->hooks->on_event) {
2463 (c->hooks->on_event)(c, events, c->hooks->on_event_arg);
2466 if ((events & BEV_EVENT_CONNECTED)) {
2472 bufferevent_setcb(bev,
2481 #ifndef EVHTP_DISABLE_SSL
2482 if (c->ssl && !(events & BEV_EVENT_EOF)) {
2484 unsigned long sslerr;
2486 while ((sslerr = bufferevent_get_openssl_error(bev))) {
2487 log_error(
"SSL ERROR %lu:%i:%s:%i:%s:%i:%s",
2489 ERR_GET_REASON(sslerr),
2490 ERR_reason_error_string(sslerr),
2491 ERR_GET_LIB(sslerr),
2492 ERR_lib_error_string(sslerr),
2493 ERR_GET_FUNC(sslerr),
2494 ERR_func_error_string(sslerr));
2508 if (events == (BEV_EVENT_EOF | BEV_EVENT_READING)) {
2511 if (errno == EAGAIN) {
2523 bufferevent_enable(bev, EV_READ);
2553 evhtp_connection_t * c = arg;
2561 log_debug(
"cr status = OK %d", c->cr_status);
2587 bufferevent_enable(c->bev, EV_WRITE);
2595 bufferevent_enable(c->bev, EV_READ | EV_WRITE);
2615 args = htp->defaults.pre_accept_cbarg;
2616 res = htp->defaults.pre_accept(conn,
args);
2628 struct timeval * c_recv_timeo;
2629 struct timeval * c_send_timeo;
2632 evutil_closesocket(connection->sock);
2637 #ifndef EVHTP_DISABLE_SSL
2638 if (connection->htp->ssl_ctx != NULL) {
2639 connection->ssl = SSL_new(connection->htp->ssl_ctx);
2640 connection->bev = bufferevent_openssl_socket_new(evbase,
2643 BUFFEREVENT_SSL_ACCEPTING,
2644 connection->htp->bev_flags);
2645 SSL_set_app_data(connection->ssl, connection);
2651 connection->bev = bufferevent_socket_new(evbase,
2653 connection->htp->bev_flags);
2655 log_debug(
"enter sock=%d\n", connection->sock);
2657 #ifndef EVHTP_DISABLE_SSL
2661 if (connection->recv_timeo.tv_sec || connection->recv_timeo.tv_usec) {
2662 c_recv_timeo = &connection->recv_timeo;
2663 }
else if (connection->htp->recv_timeo.tv_sec ||
2664 connection->htp->recv_timeo.tv_usec) {
2665 c_recv_timeo = &connection->htp->recv_timeo;
2667 c_recv_timeo = NULL;
2670 if (connection->send_timeo.tv_sec || connection->send_timeo.tv_usec) {
2671 c_send_timeo = &connection->send_timeo;
2672 }
else if (connection->htp->send_timeo.tv_sec ||
2673 connection->htp->send_timeo.tv_usec) {
2674 c_send_timeo = &connection->htp->send_timeo;
2676 c_send_timeo = NULL;
2681 connection->resume_ev = event_new(evbase, -1, EV_READ | EV_PERSIST,
2683 event_add(connection->resume_ev, NULL);
2685 bufferevent_setcb(connection->bev,
2690 bufferevent_enable(connection->bev, EV_READ);
2703 static evhtp_connection_t *
2706 evhtp_connection_t * connection;
2711 ptype = htp_type_response;
2714 ptype = htp_type_request;
2726 connection->scratch_buf = evbuffer_new();
2735 connection->max_body_size = htp->max_body_size;
2739 connection->sock = sock;
2740 connection->htp = htp;
2741 connection->type = type;
2756 #ifdef LIBEVENT_HAS_SHUTDOWN
2757 #ifndef EVHTP_DISABLE_SSL
2759 htp__shutdown_eventcb_(
struct bufferevent * bev,
short events,
void * arg)
2776 args = htp->defaults.post_accept_cbarg;
2777 res = htp->defaults.post_accept(connection,
args);
2786 #ifndef EVHTP_DISABLE_EVTHR
2790 evhtp_t * htp = shared;
2791 evhtp_connection_t * connection = arg;
2794 connection->thread = thr;
2812 htp__accept_cb_(
struct evconnlistener * serv,
int fd,
struct sockaddr * s,
int sl,
void * arg)
2814 evhtp_t * htp = arg;
2815 evhtp_connection_t * connection;
2825 log_debug(
"fd = %d, conn = %p", fd, connection);
2836 memcpy(connection->saddr, s, sl);
2838 #ifndef EVHTP_DISABLE_EVTHR
2839 if (htp->thr_pool != NULL) {
2842 evutil_closesocket(connection->sock);
2852 connection->evbase = htp->evbase;
2865 #ifndef EVHTP_DISABLE_SSL
2866 #ifndef EVHTP_DISABLE_EVTHR
2869 #define _HTP_tid (unsigned long)pthread_self()
2871 #define _HTP_tid pthread_self().p
2874 #if OPENSSL_VERSION_NUMBER < 0x10000000L
2875 static unsigned long
2886 CRYPTO_THREADID_set_numeric(
id,
_HTP_tid);
2895 if (mode & CRYPTO_LOCK) {
2898 pthread_mutex_unlock(&(
ssl_locks[type]));
2908 evhtp_ssl_cfg_t * cfg;
2912 htp = (evhtp_t *)SSL_CTX_get_app_data(ctx);
2916 if (cfg->scache_del) {
2917 (cfg->scache_del)(htp, sid, slen);
2924 evhtp_connection_t * connection;
2925 evhtp_ssl_cfg_t * cfg;
2929 connection = (evhtp_connection_t *)SSL_get_app_data(ssl);
2930 if (connection->htp == NULL) {
2934 cfg = connection->htp->ssl_cfg;
2937 SSL_set_timeout(sess, cfg->scache_timeout);
2939 if (cfg->scache_add) {
2940 return (cfg->scache_add)(connection, sid, slen, sess);
2949 evhtp_connection_t * connection;
2950 evhtp_ssl_cfg_t * cfg;
2953 connection = (evhtp_connection_t * )SSL_get_app_data(ssl);
2955 if (connection->htp == NULL) {
2959 cfg = connection->htp->ssl_cfg;
2962 if (cfg->scache_get) {
2963 sess = (cfg->scache_get)(connection, sid, sid_len);
2975 evhtp_connection_t * connection;
2977 evhtp_t * evhtp_vhost;
2980 return SSL_TLSEXT_ERR_NOACK;
2983 if (!(sname = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) {
2984 return SSL_TLSEXT_ERR_NOACK;
2987 if (!(connection = SSL_get_app_data(ssl))) {
2988 return SSL_TLSEXT_ERR_NOACK;
2991 if (!(
evhtp = connection->htp)) {
2992 return SSL_TLSEXT_ERR_NOACK;
2996 SSL_CTX * ctx = SSL_get_SSL_CTX(ssl);
2998 connection->htp = evhtp_vhost;
3002 SSL_set_SSL_CTX(ssl, evhtp_vhost->ssl_ctx);
3003 SSL_set_options(ssl, SSL_CTX_get_options(ctx));
3005 if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
3006 (SSL_num_renegotiations(ssl) == 0)) {
3007 SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx),
3008 SSL_CTX_get_verify_callback(ctx));
3011 return SSL_TLSEXT_ERR_OK;
3014 return SSL_TLSEXT_ERR_NOACK;
3039 log_debug(
"connection is already paused");
3049 bufferevent_disable(c->bev, EV_READ);
3061 log_error(
"ODDITY, resuming when not paused?!?");
3069 event_active(c->resume_ev, EV_WRITE, 1);
3094 evhtp_header_t * header;
3108 evhtp_header_t * header;
3114 if (!(header = TAILQ_LAST(headers, evhtp_kvs))) {
3118 if (header->val != NULL) {
3122 header->vlen = strlen(val);
3124 if (val_alloc == 1) {
3128 header->val[header->vlen] =
'\0';
3129 memcpy(header->val, val, header->vlen);
3131 header->val = (
char *)val;
3134 header->v_heaped = val_alloc;
3157 char key_alloc,
char val_alloc)
3167 kv->k_heaped = key_alloc;
3168 kv->v_heaped = val_alloc;
3175 kv->klen = strlen(key);
3177 if (key_alloc == 1) {
3186 memcpy(s, key, kv->klen);
3191 kv->key = (
char *)key;
3196 kv->vlen = strlen(val);
3198 if (val_alloc == 1) {
3208 memcpy(s, val, kv->vlen);
3211 kv->val = (
char *)val;
3225 if (kv->k_heaped == 1) {
3229 if (kv->v_heaped == 1) {
3243 TAILQ_REMOVE(kvs, kv, next);
3261 for (kv = TAILQ_FIRST(kvs); kv != NULL; kv = save) {
3262 save = TAILQ_NEXT(kv, next);
3264 TAILQ_REMOVE(kvs, kv, next);
3277 if (kvs == NULL ||
cb == NULL) {
3281 TAILQ_FOREACH(kv, kvs, next) {
3284 if ((res =
cb(kv, arg))) {
3301 TAILQ_FOREACH(kv, kvs, next) {
3302 if (strcasecmp(kv->key, key) == 0) {
3337 TAILQ_FOREACH(kv, kvs, next) {
3338 if (strcasecmp(kv->key, key) == 0) {
3353 TAILQ_INSERT_TAIL(kvs, kv, next);
3361 if (dst == NULL || src == NULL) {
3365 TAILQ_FOREACH(kv, src, next) {
3415 unsigned char * optr;
3416 unsigned char * sptr;
3428 for (i = 0; i < str_len; i++) {
3442 if (ch >=
'0' && ch <=
'9') {
3443 d = (
unsigned char)(ch -
'0');
3448 c = (
unsigned char)(ch | 0x20);
3450 if (c >=
'a' && c <=
'f') {
3451 d = (
unsigned char)(c -
'a' + 10);
3462 if (ch >=
'0' && ch <=
'9') {
3463 ch = (
unsigned char)((d << 4) + ch -
'0');
3469 c = (
unsigned char)(ch | 0x20);
3471 if (c >=
'a' && c <=
'f') {
3472 ch = (
unsigned char)((d << 4) + c -
'a' + 10);
3495 if (len > (SIZE_MAX - (len + 2))) {
3505 #ifdef EVHTP_HAS_C99
3506 char key_buf[len + 1];
3507 char val_buf[len + 1];
3530 for (i = 0; i < len; i++) {
3533 if (key_idx >= len || val_idx >= len) {
3553 key_buf[key_idx++] = ch;
3554 key_buf[key_idx] =
'\0';
3563 key_buf[key_idx++] = ch;
3564 key_buf[key_idx] =
'\0';
3589 key_buf[key_idx++] = ch;
3590 key_buf[key_idx] =
'\0';
3597 if ((key_idx + 2) >= len) {
3602 key_buf[key_idx - 1] =
'%';
3603 key_buf[key_idx++] = ch;
3604 key_buf[key_idx] =
'\0';
3610 key_buf[key_idx++] = ch;
3611 key_buf[key_idx] =
'\0';
3620 key_buf[key_idx++] = ch;
3621 key_buf[key_idx] =
'\0';
3629 val_buf[val_idx++] = ch;
3630 val_buf[val_idx] =
'\0';
3646 val_buf[val_idx++] = ch;
3647 val_buf[val_idx] =
'\0';
3655 val_buf[val_idx++] = ch;
3656 val_buf[val_idx] =
'\0';
3664 if ((val_idx + 2) >= len) {
3673 val_buf[val_idx - 1] =
'%';
3674 val_buf[val_idx++] = ch;
3675 val_buf[val_idx] =
'\0';
3681 val_buf[val_idx++] = ch;
3682 val_buf[val_idx] =
'\0';
3691 val_buf[val_idx++] = ch;
3692 val_buf[val_idx] =
'\0';
3727 #ifndef EVHTP_HAS_C99
3734 #ifndef EVHTP_HAS_C99
3754 evhtp_connection_t * c;
3755 struct evbuffer * reply_buf;
3764 bufferevent_write_buffer(c->bev, reply_buf);
3765 evbuffer_drain(reply_buf, -1);
3771 evhtp_connection_t * c;
3775 bufferevent_write_buffer(c->bev, buf);
3787 evhtp_connection_t * c;
3788 struct evbuffer * reply_buf;
3789 struct bufferevent * bev;
3805 bufferevent_write_buffer(bev, reply_buf);
3807 evbuffer_drain(reply_buf, -1);
3813 return code != EVHTP_RES_NOCONTENT &&
3814 code != EVHTP_RES_NOTMOD &&
3815 (code < 100 || code >= 200) &&
3816 method != htp_method_HEAD;
3822 evhtp_header_t * content_len;
3827 switch (request->proto) {
3865 if (evbuffer_get_length(request->buffer_out) > 0) {
3869 sres = snprintf(lstr,
sizeof(lstr),
"%x\r\n",
3870 (
unsigned)evbuffer_get_length(request->buffer_out));
3872 if (sres >=
sizeof(lstr) || sres < 0) {
3878 evbuffer_prepend(request->buffer_out, lstr, strlen(lstr));
3879 evbuffer_add(request->buffer_out,
"\r\n", 2);
3890 struct evbuffer * output;
3892 if (evbuffer_get_length(buf) == 0) {
3896 output = bufferevent_get_output(request->conn->bev);
3899 evbuffer_add_printf(output,
"%x\r\n",
3900 (
unsigned)evbuffer_get_length(buf));
3906 evbuffer_add(output,
"\r\n", 2);
3909 bufferevent_flush(request->conn->bev, EV_WRITE, BEV_FLUSH);
3926 if (htp == NULL || htp->server == NULL) {
3938 if (htp == NULL || sock == -1) {
3939 log_error(
"htp = %p && sock = %d", htp, sock);
3943 if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (
void *)&on,
sizeof(on)) == -1) {
3947 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (
void *)&on,
sizeof(on)) == -1) {
3951 #if defined(SO_REUSEPORT)
3953 if (setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (
void *)&on,
sizeof(on)) == -1) {
3954 if (errno != EOPNOTSUPP) {
3959 log_warn(
"SO_REUSEPORT NOT SUPPORTED");
3965 #if defined(TCP_NODELAY)
3967 if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (
void *)&on,
sizeof(on)) == -1) {
3968 if (errno != EOPNOTSUPP) {
3979 #if defined(TCP_DEFER_ACCEPT)
3981 if (setsockopt(sock, IPPROTO_TCP, TCP_DEFER_ACCEPT, (
void *)&on,
sizeof(on)) == -1) {
3982 if (errno != EOPNOTSUPP) {
3987 log_warn(
"DEFER_ACCEPT NOT SUPPORTED");
4001 if (htp == NULL || sock == -1) {
4002 log_error(
"htp = %p && sock = %d", htp, sock);
4007 htp->server = evconnlistener_new(htp->evbase,
4010 LEV_OPT_CLOSE_ON_FREE | LEV_OPT_REUSEABLE,
4014 if (htp->server == NULL) {
4018 #ifndef EVHTP_DISABLE_SSL
4019 if (htp->ssl_ctx != NULL) {
4025 if (TAILQ_FIRST(&htp->vhosts) != NULL) {
4026 SSL_CTX_set_tlsext_servername_callback(htp->ssl_ctx,
4036 if (htp->server != NULL) {
4048 struct sockaddr * sa,
4052 evutil_socket_t fd = -1;
4063 signal(SIGPIPE, SIG_IGN);
4067 if ((fd = socket(sa->sa_family, SOCK_STREAM, 0)) == -1) {
4072 evutil_make_socket_closeonexec(fd);
4073 evutil_make_socket_nonblocking(fd);
4079 if (sa->sa_family == AF_INET6) {
4080 if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &on,
sizeof(on)) == -1) {
4085 if (bind(fd, sa, sin_len) == -1) {
4095 evutil_closesocket(fd);
4105 evutil_closesocket(fd);
4117 struct sockaddr_un sockun = { 0 };
4119 struct sockaddr * sa;
4120 struct sockaddr_in6 sin6 = { 0 };
4121 struct sockaddr_in sin = { 0 };
4124 if (!strncmp(baddr,
"ipv6:", 5)) {
4126 sin_len =
sizeof(
struct sockaddr_in6);
4127 sin6.sin6_port = htons(port);
4128 sin6.sin6_family = AF_INET6;
4130 evutil_inet_pton(AF_INET6, baddr, &sin6.sin6_addr);
4131 sa = (
struct sockaddr *)&sin6;
4132 }
else if (!strncmp(baddr,
"unix:", 5)) {
4136 if (strlen(baddr) >=
sizeof(sockun.sun_path)) {
4140 sin_len =
sizeof(
struct sockaddr_un);
4141 sockun.sun_family = AF_UNIX;
4143 strncpy(sockun.sun_path, baddr, strlen(baddr));
4145 sa = (
struct sockaddr *)&sockun;
4151 if (!strncmp(baddr,
"ipv4:", 5)) {
4155 sin_len =
sizeof(
struct sockaddr_in);
4156 sin.sin_family = AF_INET;
4157 sin.sin_port = htons(port);
4158 sin.sin_addr.s_addr = inet_addr(baddr);
4160 sa = (
struct sockaddr *)&sin;
4169 evhtp_callback_t * callback;
4170 evhtp_callback_t * tmp;
4172 if (callbacks == NULL) {
4177 TAILQ_REMOVE(callbacks, callback, next);
4188 evhtp_callback_t * hcb;
4201 hcb->len = strlen(path);
4214 #ifndef EVHTP_DISABLE_REGEX
4224 if (regcomp(hcb->val.regex, (
char *)path, REG_EXTENDED) != 0) {
4255 if (callback == NULL) {
4259 switch (callback->type) {
4266 #ifndef EVHTP_DISABLE_REGEX
4273 if (callback->hooks) {
4285 TAILQ_INSERT_TAIL(cbs,
cb, next);
4293 if (*hooks == NULL) {
4294 if (!(*hooks =
htp__calloc_(
sizeof(evhtp_hooks_t), 1))) {
4302 (*hooks)->on_headers_start_arg = arg;
4306 (*hooks)->on_header_arg = arg;
4310 (*hooks)->on_headers_arg = arg;
4314 (*hooks)->on_path_arg = arg;
4318 (*hooks)->on_read_arg = arg;
4322 (*hooks)->on_request_fini_arg = arg;
4326 (*hooks)->on_connection_fini_arg = arg;
4330 (*hooks)->on_connection_error_arg = arg;
4334 (*hooks)->on_error_arg = arg;
4338 (*hooks)->on_new_chunk_arg = arg;
4342 (*hooks)->on_chunk_fini_arg = arg;
4346 (*hooks)->on_chunks_fini_arg = arg;
4350 (*hooks)->on_hostname_arg = arg;
4354 (*hooks)->on_write_arg = arg;
4358 (*hooks)->on_event_arg = arg;
4437 if (hooks == NULL) {
4491 evhtp_callback_t * hcb;
4495 if (htp->callbacks == NULL) {
4502 TAILQ_INIT(htp->callbacks);
4526 evhtp_callback_t * callback;
4534 TAILQ_FOREACH(callback, htp->callbacks, next) {
4535 if (strcmp(callback->val.path, path) == 0) {
4543 #ifndef EVHTP_DISABLE_EVTHR
4547 evhtp_t * htp = (evhtp_t *)arg;
4549 if (htp->thread_init_cb) {
4550 htp->thread_init_cb(htp, thr, htp->thread_cbarg);
4557 evhtp_t * htp = (evhtp_t *)arg;
4559 if (htp->thread_exit_cb) {
4560 htp->thread_exit_cb(htp, thr, htp->thread_cbarg);
4568 int nthreads,
void * arg)
4574 htp->thread_cbarg = arg;
4575 htp->thread_init_cb = init_cb;
4576 htp->thread_exit_cb = exit_cb;
4578 #ifndef EVHTP_DISABLE_SSL
4595 int nthreads,
void * arg)
4604 int nthreads,
void * arg)
4611 #ifndef EVHTP_DISABLE_EVTHR
4619 if (!(htp->lock =
htp__malloc_(
sizeof(pthread_mutex_t)))) {
4623 return pthread_mutex_init(htp->lock, NULL);
4628 #ifndef EVHTP_DISABLE_REGEX
4631 const char * pattern,
4635 evhtp_callback_t * hcb;
4639 if (htp->callbacks == NULL) {
4646 TAILQ_INIT(htp->callbacks);
4672 evhtp_callback_t * hcb;
4676 if (htp->callbacks == NULL) {
4683 TAILQ_INIT(htp->callbacks);
4707 htp->defaults.cb =
cb;
4708 htp->defaults.cbarg = arg;
4714 htp->defaults.pre_accept =
cb;
4715 htp->defaults.pre_accept_cbarg = arg;
4721 htp->defaults.post_accept =
cb;
4722 htp->defaults.post_accept_cbarg = arg;
4725 #ifndef EVHTP_DISABLE_SSL
4726 #ifndef EVHTP_DISABLE_EVTHR
4745 pthread_mutex_init(&(
ssl_locks[i]), NULL);
4748 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4767 if (cfg == NULL || htp == NULL || cfg->pemfile == NULL) {
4771 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4773 ERR_load_crypto_strings();
4774 SSL_load_error_strings();
4775 OpenSSL_add_all_algorithms();
4793 if (RAND_poll() != 1) {
4798 if (RAND_bytes(&c, 1) != 1) {
4803 #if OPENSSL_VERSION_NUMBER < 0x10000000L
4804 STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
4805 sk_SSL_COMP_zero(comp_methods);
4809 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4810 htp->ssl_ctx = SSL_CTX_new(SSLv23_server_method());
4812 htp->ssl_ctx = SSL_CTX_new(TLS_server_method());
4817 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
4818 SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS | SSL_OP_NO_COMPRESSION);
4819 SSL_CTX_set_timeout(htp->ssl_ctx, cfg->ssl_ctx_timeout);
4822 SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);
4824 #ifndef OPENSSL_NO_ECDH
4825 if (cfg->named_curve != NULL) {
4826 EC_KEY * ecdh = NULL;
4829 nid = OBJ_sn2nid(cfg->named_curve);
4832 log_error(
"ECDH initialization failed: unknown curve %s", cfg->named_curve);
4835 ecdh = EC_KEY_new_by_curve_name(nid);
4838 log_error(
"ECDH initialization failed for curve %s", cfg->named_curve);
4841 SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh);
4846 #ifndef OPENSSL_NO_DH
4847 if (cfg->dhparams != NULL) {
4851 fh = fopen(cfg->dhparams,
"r");
4854 dh = PEM_read_DHparams(fh, NULL, NULL, NULL);
4856 SSL_CTX_set_tmp_dh(htp->ssl_ctx, dh);
4859 log_error(
"DH initialization failed: unable to parse file %s", cfg->dhparams);
4864 log_error(
"DH initialization failed: unable to open file %s", cfg->dhparams);
4870 if (cfg->ciphers != NULL) {
4871 if (SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers) == 0) {
4877 SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
4878 X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
4879 SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);
4881 if (cfg->x509_chk_issued_cb != NULL) {
4882 #if OPENSSL_VERSION_NUMBER < 0x10100000L
4883 htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
4885 X509_STORE_set_check_issued(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->x509_chk_issued_cb);
4889 if (cfg->verify_depth) {
4890 SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
4893 switch (cfg->scache_type) {
4895 cache_mode = SSL_SESS_CACHE_OFF;
4898 cache_mode = SSL_SESS_CACHE_SERVER;
4902 SSL_CTX_use_certificate_chain_file(htp->ssl_ctx, cfg->pemfile);
4904 char *
const key = cfg->privfile ? cfg->privfile : cfg->pemfile;
4906 if (cfg->decrypt_cb != NULL) {
4907 EVP_PKEY * pkey = cfg->decrypt_cb(key);
4913 SSL_CTX_use_PrivateKey(htp->ssl_ctx, pkey);
4916 EVP_PKEY_free(pkey);
4918 SSL_CTX_use_PrivateKey_file(htp->ssl_ctx, key, SSL_FILETYPE_PEM);
4921 SSL_CTX_set_session_id_context(htp->ssl_ctx,
4925 SSL_CTX_set_app_data(htp->ssl_ctx, htp);
4926 SSL_CTX_set_session_cache_mode(htp->ssl_ctx, cache_mode);
4928 if (cache_mode != SSL_SESS_CACHE_OFF) {
4929 SSL_CTX_sess_set_cache_size(htp->ssl_ctx,
4930 cfg->scache_size ? cfg->scache_size : 1024);
4938 if (cfg->scache_init) {
4939 cfg->args = (cfg->scache_init)(htp);
4949 struct bufferevent *
4952 return connection->bev;
4955 struct bufferevent *
4960 if (connection->hooks) {
4964 if (connection->request && connection->request->hooks) {
4975 bufferevent_disable(bev, EV_READ);
4976 bufferevent_setcb(bev, NULL, NULL, NULL, NULL);
4981 struct bufferevent *
4987 struct bufferevent *
5013 evhtp_connection_t *
5016 return request->conn;
5022 return request->proto;
5028 return request->status;
5039 const struct timeval * rtimeo,
5040 const struct timeval * wtimeo)
5046 bufferevent_set_timeouts(c->bev, rtimeo, wtimeo);
5053 c->max_body_size = c->htp->max_body_size;
5055 c->max_body_size = len;
5080 if (connection->resume_ev) {
5084 if (connection->bev) {
5085 #ifdef LIBEVENT_HAS_SHUTDOWN
5086 bufferevent_shutdown(connection->bev, htp__shutdown_eventcb_);
5088 #ifndef EVHTP_DISABLE_SSL
5089 if (connection->ssl != NULL) {
5090 SSL_set_shutdown(connection->ssl, SSL_RECEIVED_SHUTDOWN);
5091 SSL_shutdown(connection->ssl);
5105 if (request == NULL) {
5115 if (r_timeo != NULL) {
5116 htp->recv_timeo = *r_timeo;
5119 if (w_timeo != NULL) {
5120 htp->send_timeo = *w_timeo;
5127 htp->max_keepalive_requests = num;
5133 htp->bev_flags = flags;
5139 htp->max_body_size = len;
5151 htp->parser_flags = flags;
5154 #define HTP_FLAG_FNGEN(NAME, TYPE) void \
5155 evhtp ## NAME ## _enable_flag(TYPE v, int flag) { \
5156 HTP_FLAG_ON(v, flag); \
5160 evhtp ## NAME ## _disable_flag(TYPE v, int flag) { \
5161 HTP_FLAG_OFF(v, flag); \
5165 evhtp ## NAME ## _get_flags(TYPE v) { \
5179 evhtp_alias_t * alias;
5185 if (!(alias =
htp__calloc_(
sizeof(evhtp_alias_t), 1))) {
5189 log_debug(
"Adding %s to aliases", name);
5199 TAILQ_INSERT_TAIL(&
evhtp->aliases, alias, next);
5213 va_start(argp, name);
5217 while ((p = va_arg(argp,
const char *)) != NULL) {
5234 if (
evhtp == NULL || name == NULL || vhost == NULL) {
5238 if (TAILQ_FIRST(&vhost->vhosts) != NULL) {
5255 vhost->parent =
evhtp;
5264 TAILQ_INSERT_TAIL(&
evhtp->vhosts, vhost, next_vhost);
5295 htp->evbase = evbase;
5297 htp->bev_flags = BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS;
5303 TAILQ_INIT(&htp->vhosts);
5304 TAILQ_INIT(&htp->aliases);
5334 if (
evhtp == NULL) {
5338 #ifndef EVHTP_DISABLE_EVTHR
5346 #ifndef EVHTP_DISABLE_SSL
5377 evhtp_connection_t *
5383 evhtp_connection_t *
5385 const char * addr, uint16_t port)
5387 evhtp_connection_t * conn;
5397 conn->evbase = evbase;
5398 conn->bev = bufferevent_socket_new(evbase, -1, BEV_OPT_CLOSE_ON_FREE);
5400 if (conn->bev == NULL) {
5406 bufferevent_enable(conn->bev, EV_READ);
5407 bufferevent_setcb(conn->bev, NULL, NULL,
5410 if (dns_base != NULL) {
5411 err = bufferevent_socket_connect_hostname(conn->bev, dns_base,
5412 AF_UNSPEC, addr, port);
5414 struct sockaddr_in sin4;
5415 struct sockaddr_in6 sin6;
5416 struct sockaddr * sin;
5419 if (inet_pton(AF_INET, addr, &sin4.sin_addr)) {
5420 sin4.sin_family = AF_INET;
5421 sin4.sin_port = htons(port);
5422 sin = (
struct sockaddr *)&sin4;
5423 salen =
sizeof(sin4);
5424 }
else if (inet_pton(AF_INET6, addr, &sin6.sin6_addr)) {
5425 sin6.sin6_family = AF_INET6;
5426 sin6.sin6_port = htons(port);
5427 sin = (
struct sockaddr *)&sin6;
5428 salen =
sizeof(sin6);
5436 err = bufferevent_socket_connect(conn->bev, sin, salen);
5449 #ifndef EVHTP_DISABLE_SSL
5451 #define ssl_sk_new_ bufferevent_openssl_socket_new
5452 #define ssl_sk_connect_ bufferevent_socket_connect
5454 evhtp_connection_t *
5460 evhtp_connection_t * conn;
5461 struct sockaddr_in sin;
5462 const char * errstr;
5464 if (evbase == NULL) {
5472 conn->evbase = evbase;
5476 if ((conn->ssl = SSL_new(ctx)) == NULL) {
5477 errstr =
"unable to allocate SSL context";
5482 if ((conn->bev =
ssl_sk_new_(evbase, -1, conn->ssl,
5483 BUFFEREVENT_SSL_CONNECTING,
5484 BEV_OPT_CLOSE_ON_FREE)) == NULL) {
5485 errstr =
"unable to allocate bev context";
5489 if (bufferevent_enable(conn->bev, EV_READ) == -1) {
5490 errstr =
"unable to enable reading";
5494 bufferevent_setcb(conn->bev, NULL, NULL,
5498 sin.sin_family = AF_INET;
5499 sin.sin_addr.s_addr = inet_addr(addr);
5500 sin.sin_port = htons(port);
5503 (
struct sockaddr *)&sin,
5504 sizeof(sin)) == -1) {
5505 errstr =
"sk_connect_ failure";
5511 if (errstr != NULL) {
5528 evhtp_request_t * r;
5542 htp_method meth,
const char * uri)
5544 struct evbuffer * obuf;
5547 obuf = bufferevent_get_output(c->bev);
5562 evbuffer_add_printf(obuf,
"%s %s HTTP/%s\r\n",
5565 if (evbuffer_get_length(r->buffer_out)) {
5567 char out_buf[64] = { 0 };
5568 size_t out_len = evbuffer_get_length(r->buffer_out);
5578 evbuffer_add_reference(obuf,
"\r\n", 2, NULL, NULL);
5581 if (evbuffer_get_length(r->buffer_out)) {
5582 evbuffer_add_buffer(obuf, r->buffer_out);