Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'release/1.1.5'

  • Loading branch information...
commit 921248d79cfd24b0a79a2e130f55ee4326553012 2 parents 36bebd3 + a02a382
Mark Ellzey authored
View
1  .gitignore
@@ -15,4 +15,5 @@
/libevhtp.a
/test
/test_basic
+/test_vhost
View
11 CMakeLists.txt
@@ -3,7 +3,7 @@ project(reason)
set(PROJECT_MAJOR_VERSION 1)
set(PROJECT_MINOR_VERSION 1)
-set(PROJECT_PATCH_VERSION 4)
+set(PROJECT_PATCH_VERSION 5)
set (PROJECT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION})
set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
@@ -79,7 +79,12 @@ find_package(OpenSSL)
find_path(LIBEVENT_INCLUDE_DIR event2/event.h REQUIRED)
if (NOT OPENSSL_FOUND)
+ message("Diabling SSL")
set (EVHTP_DISABLE_SSL ON)
+ set (OPENSSL_CRYPTO_LIBRARY "")
+ set (OPENSSL_INCLUDE_DIR "")
+ set (OPENSSL_LIBRARIES "")
+ set (LIBEVENT_OPENSSL_LIBRARY "")
endif()
@@ -170,6 +175,10 @@ if (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNDEBUG")
endif (NOT ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+if (EVHTP_DISABLE_SSL)
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DEVHTP_DISABLE_SSL")
+endif()
+
add_library(libevhtp STATIC ${LIBEVHTP_SOURCES} ${ONIG_SOURCES})
set_target_properties(libevhtp PROPERTIES OUTPUT_NAME "evhtp")
View
19 ChangeLog
@@ -1,3 +1,22 @@
+v1.1.5
+ o Don't treat non hex chars as errors. (d8c584d Mark Ellzey)
+ o If non hex, replace idx-1 with % (2783983 Mark Ellzey)
+ o Fix off-by-one in parse_query. (86881c1 Mark Ellzey)
+ o Do not use dynamically allocated timevals in evhtp_t. (3398442 Marcus Sundberg)
+ o Only initialize status_code_tree once. (da64395 Marcus Sundberg)
+ o Add evhtp_free() matching evhtp_new(). (60b141a Marcus Sundberg)
+ o (evhtp_callback_free): Free hooks as well, if set. (6fff598 Marcus Sundberg)
+ o (evhtp_callback_free): Free regexp pointer, not only regexp. (ab9adc6 Marcus Sundberg)
+ o (evthr_pool_stop): Do not read queue entry after freeing. (f7cc5f2 Marcus Sundberg)
+ o Use TAILQ_FOREACH_SAFE() in evhthr_pool_free() as well. (5c2adcc Marcus Sundberg)
+ o (evhtp_free): Stop and free thread pool, if started. (f13c207 Marcus Sundberg)
+ o Use libevent signal handling instead of signal() in test.c (e0b68b4 Marcus Sundberg)
+ o Properly deallocate resources in test programs. (ea1bd57 Marcus Sundberg)
+ o Add test_vhost to .gitignore (2a596c2 Marcus Sundberg)
+ o Fix issue where SSL is not disabled if not found. (6f25292 Mark Ellzey)
+ o Forgot LIBEVENT_OPENSSL_LIBRARY (5a933c7 Mark Ellzey)
+ o add upport multiline header values. (325c5c7 Mark Ellzey)
+
v1.1.4
o Fixed potential deadlock - reported by zhangpeihao (36ee722 Mark Ellzey)
o Removing conflicting code from master branch. (51feaa9 Mark Ellzey)
View
104 evhtp.c
@@ -86,6 +86,15 @@ static void _evhtp_path_free(evhtp_path_t * path);
#define _evhtp_unlock(h) do {} while (0)
#endif
+#ifndef TAILQ_FOREACH_SAFE
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+#endif
+
+static int scode_tree_initialized = 0;
+
/**
* @brief An RBTREE entry for the status code -> str matcher
*/
@@ -119,6 +128,11 @@ RB_GENERATE(status_code_tree, status_code, entry, status_code_cmp);
static void
status_code_init(void) {
+ if (scode_tree_initialized) {
+ /* Already initialized. */
+ return;
+ }
+
/* 100 codes */
scode_add(EVHTP_RES_CONTINUE, "Continue");
scode_add(EVHTP_RES_SWITCH_PROTO, "Switching Protocols");
@@ -175,6 +189,8 @@ status_code_init(void) {
scode_add(EVHTP_RES_GWTIMEOUT, "Gateway Timeout");
scode_add(EVHTP_RES_VERNSUPPORT, "HTTP Version Not Supported");
scode_add(EVHTP_RES_BWEXEED, "Bandwidth Limit Exceeded");
+
+ scode_tree_initialized = 1;
} /* status_code_init */
const char *
@@ -1501,14 +1517,20 @@ _evhtp_connection_accept(evbase_t * evbase, evhtp_connection_t * connection) {
if (connection->recv_timeo.tv_sec || connection->recv_timeo.tv_usec) {
c_recv_timeo = &connection->recv_timeo;
+ } else if (connection->htp->recv_timeo.tv_sec ||
+ connection->htp->recv_timeo.tv_usec) {
+ c_recv_timeo = &connection->htp->recv_timeo;
} else {
- c_recv_timeo = connection->htp->recv_timeo;
+ c_recv_timeo = NULL;
}
if (connection->send_timeo.tv_sec || connection->send_timeo.tv_usec) {
c_send_timeo = &connection->send_timeo;
+ } else if (connection->htp->send_timeo.tv_sec ||
+ connection->htp->send_timeo.tv_usec) {
+ c_send_timeo = &connection->htp->send_timeo;
} else {
- c_send_timeo = connection->htp->send_timeo;
+ c_send_timeo = NULL;
}
evhtp_connection_set_timeouts(connection, c_recv_timeo, c_send_timeo);
@@ -2137,11 +2159,11 @@ evhtp_parse_query(const char * query, size_t len) {
query_args = evhtp_query_new();
- if (!(key_buf = malloc(len))) {
+ if (!(key_buf = malloc(len+1))) {
return NULL;
}
- if (!(val_buf = malloc(len))) {
+ if (!(val_buf = malloc(len+1))) {
free(key_buf);
return NULL;
}
@@ -2212,8 +2234,15 @@ evhtp_parse_query(const char * query, size_t len) {
case s_query_key_hex_1:
if (!evhtp_is_hex_query_char(ch)) {
/* not hex, so we treat as a normal key */
- key_buf[key_idx++] = ch;
- key_buf[key_idx] = '\0';
+ if ((key_idx + 2) >= len) {
+ /* we need to insert \%<ch>, but not enough space */
+ res = -1;
+ goto error;
+ }
+
+ key_buf[key_idx - 1] = '%';
+ key_buf[key_idx++] = ch;
+ key_buf[key_idx] = '\0';
state = s_query_key;
break;
}
@@ -2265,8 +2294,17 @@ evhtp_parse_query(const char * query, size_t len) {
case s_query_val_hex_1:
if (!evhtp_is_hex_query_char(ch)) {
/* not really a hex val */
- val_buf[val_idx++] = ch;
- val_buf[val_idx] = '\0';
+ if ((val_idx + 2) >= len) {
+ /* we need to insert \%<ch>, but not enough space */
+ res = -1;
+ goto error;
+ }
+
+
+ val_buf[val_idx - 1] = '%';
+ val_buf[val_idx++] = ch;
+ val_buf[val_idx] = '\0';
+
state = s_query_val;
break;
}
@@ -2627,10 +2665,15 @@ evhtp_callback_free(evhtp_callback_t * callback) {
#ifndef EVHTP_DISABLE_REGEX
case evhtp_callback_type_regex:
regfree(callback->val.regex);
+ free(callback->val.regex);
break;
#endif
}
+ if (callback->hooks) {
+ free(callback->hooks);
+ }
+
free(callback);
return;
@@ -3130,9 +3173,9 @@ evhtp_request_get_connection(evhtp_request_t * request) {
}
void
-evhtp_connection_set_timeouts(evhtp_connection_t * c,
- struct timeval * rtimeo,
- struct timeval * wtimeo) {
+evhtp_connection_set_timeouts(evhtp_connection_t * c,
+ const struct timeval * rtimeo,
+ const struct timeval * wtimeo) {
if (!c) {
return;
}
@@ -3200,15 +3243,13 @@ evhtp_request_free(evhtp_request_t * request) {
}
void
-evhtp_set_timeouts(evhtp_t * htp, struct timeval * r_timeo, struct timeval * w_timeo) {
+evhtp_set_timeouts(evhtp_t * htp, const struct timeval * r_timeo, const struct timeval * w_timeo) {
if (r_timeo != NULL) {
- htp->recv_timeo = malloc(sizeof(struct timeval));
- memcpy(htp->recv_timeo, r_timeo, sizeof(struct timeval));
+ htp->recv_timeo = *r_timeo;
}
if (w_timeo != NULL) {
- htp->send_timeo = malloc(sizeof(struct timeval));
- memcpy(htp->send_timeo, w_timeo, sizeof(struct timeval));
+ htp->send_timeo = *w_timeo;
}
}
@@ -3329,3 +3370,34 @@ evhtp_new(evbase_t * evbase, void * arg) {
return htp;
}
+void
+evhtp_free(evhtp_t * evhtp) {
+ evhtp_alias_t * evhtp_alias, * tmp;
+
+ if (evhtp == NULL) {
+ return;
+ }
+
+ if (evhtp->thr_pool) {
+ evthr_pool_stop(evhtp->thr_pool);
+ evthr_pool_free(evhtp->thr_pool);
+ }
+
+ if (evhtp->callbacks) {
+ free(evhtp->callbacks);
+ }
+
+ if (evhtp->server_name) {
+ free(evhtp->server_name);
+ }
+
+ TAILQ_FOREACH_SAFE(evhtp_alias, &evhtp->aliases, next, tmp) {
+ if (evhtp_alias->alias != NULL) {
+ free(evhtp_alias->alias);
+ }
+ TAILQ_REMOVE(&evhtp->aliases, evhtp_alias, next);
+ free(evhtp_alias);
+ }
+
+ free(evhtp);
+}
View
13 evhtp.h
@@ -155,10 +155,10 @@ typedef void (*evhtp_ssl_scache_del)(evhtp_t * htp, unsigned char * sid, int sid
typedef evhtp_ssl_sess_t * (*evhtp_ssl_scache_get)(evhtp_connection_t * connection, unsigned char * sid, int sid_len);
typedef void * (*evhtp_ssl_scache_init)(evhtp_t *);
-#define EVHTP_VERSION "1.1.4"
+#define EVHTP_VERSION "1.1.5"
#define EVHTP_VERSION_MAJOR 1
#define EVHTP_VERSION_MINOR 1
-#define EVHTP_VERSION_PATCH 4
+#define EVHTP_VERSION_PATCH 5
#define evhtp_headers_iterator evhtp_kvs_iterator
@@ -270,8 +270,8 @@ struct evhtp_s {
evhtp_callbacks_t * callbacks;
evhtp_defaults_t defaults;
- struct timeval * recv_timeo;
- struct timeval * send_timeo;
+ struct timeval recv_timeo;
+ struct timeval send_timeo;
TAILQ_HEAD(, evhtp_alias_s) aliases;
TAILQ_HEAD(, evhtp_s) vhosts;
@@ -483,6 +483,7 @@ struct evhtp_ssl_cfg_s {
* @return a new evhtp_t structure or NULL on error
*/
evhtp_t * evhtp_new(evbase_t * evbase, void * arg);
+void evhtp_free(evhtp_t * evhtp);
/**
@@ -494,7 +495,7 @@ evhtp_t * evhtp_new(evbase_t * evbase, void * arg);
* @param r read-timeout in timeval
* @param w write-timeout in timeval.
*/
-void evhtp_set_timeouts(evhtp_t * htp, struct timeval * r, struct timeval * w);
+void evhtp_set_timeouts(evhtp_t * htp, const struct timeval * r, const struct timeval * w);
void evhtp_set_bev_flags(evhtp_t * htp, int flags);
int evhtp_ssl_use_threads(void);
int evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * ssl_cfg);
@@ -950,7 +951,7 @@ evbev_t * evhtp_connection_get_bev(evhtp_connection_t * conn);
* @param r timeval for read
* @param w timeval for write
*/
-void evhtp_connection_set_timeouts(evhtp_connection_t * conn, struct timeval * r, struct timeval * w);
+void evhtp_connection_set_timeouts(evhtp_connection_t * conn, const struct timeval * r, const struct timeval * w);
/**
* @brief returns the underlying requests bufferevent
View
14 evthr/evthr.c
@@ -61,6 +61,13 @@ struct evthr {
TAILQ_ENTRY(evthr) next;
};
+#ifndef TAILQ_FOREACH_SAFE
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+#endif
+
inline void
evthr_inc_backlog(evthr_t * evthr) {
__sync_fetch_and_add(&evthr->cur_backlog, 1);
@@ -347,9 +354,7 @@ evthr_pool_free(evthr_pool_t * pool) {
return;
}
- for (thread = TAILQ_FIRST(&pool->threads); thread != NULL; thread = save) {
- save = TAILQ_NEXT(thread, next);
-
+ TAILQ_FOREACH_SAFE(thread, &pool->threads, next, save) {
TAILQ_REMOVE(&pool->threads, thread, next);
evthr_free(thread);
@@ -361,12 +366,13 @@ evthr_pool_free(evthr_pool_t * pool) {
evthr_res
evthr_pool_stop(evthr_pool_t * pool) {
evthr_t * thr;
+ evthr_t * save;
if (pool == NULL) {
return EVTHR_RES_FATAL;
}
- TAILQ_FOREACH(thr, &pool->threads, next) {
+ TAILQ_FOREACH_SAFE(thr, &pool->threads, next, save) {
evthr_stop(thr);
}
View
25 htparse/htparse.c
@@ -1375,8 +1375,6 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
switch (ch) {
case CR:
- res = hook_hdr_val_run(p, hooks, p->buf, p->buf_idx);
-
switch (p->heval) {
case eval_hdr_val_none:
break;
@@ -1426,8 +1424,6 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
} /* switch */
p->state = s_hdrline_hdr_almost_done;
- p->buf_idx = 0;
-
break;
case LF:
/* LF before CR? invalid */
@@ -1475,6 +1471,13 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
switch (ch) {
case CR:
+ res = hook_hdr_val_run(p, hooks, p->buf, p->buf_idx);
+
+ if (res) {
+ p->error = htparse_error_user;
+ return i + 1;
+ }
+
p->state = s_hdrline_almost_done;
res = hook_on_hdrs_complete_run(p, hooks);
@@ -1486,8 +1489,22 @@ htparser_run(htparser * p, htparse_hooks * hooks, const char * data, size_t len)
break;
case LF:
/* got LFLF? is this valid? */
+ p->error = htparse_error_inval_hdr;
+
return i + 1;
+ case '\t':
+ /* this is a multiline header value, we must go back to
+ * reading as a header value */
+ p->state = s_hdrline_hdr_val;
+ break;
default:
+ res = hook_hdr_val_run(p, hooks, p->buf, p->buf_idx);
+
+ if (res) {
+ p->error = htparse_error_user;
+ return i + 1;
+ }
+
p->buf_idx = 0;
p->buf[p->buf_idx++] = ch;
p->buf[p->buf_idx] = '\0';
View
18 htparse/test.c
@@ -229,24 +229,27 @@ main(int argc, char ** argv) {
const char * test_fail = "GET /JF HfD]\r\n\r\n";
const char * test_resp_1 = "HTTP/1.0 200 OK\r\n"
"Stuff: junk\r\n\r\n";
- const char * test_empty_header = "GET /blah HTTP/1.1\r\n"
+ const char * test_empty_header = "GET /empty_header HTTP/1.1\r\n"
"Empty: \r\n"
"Stuff: junk\r\n\r\n";
const char * test_resp_empty_header = "HTTP/1.1 200 OK\r\n"
- "Empty: \r\n"
+ "response Empty: \r\n"
"Things: junk\r\n\r\n";
- const char * test_no_cr = "GET / HTTP/1.1\n"
+ const char * test_no_cr = "GET /no_cr HTTP/1.1\n"
"Host: stuff\n"
"Things: blah\n\n";
- const char * test_no_hdr_cr = "GET / HTTP/1.1\r\n"
+ const char * test_no_hdr_cr = "GET /no_hdr_cr HTTP/1.1\r\n"
"Host: things\n"
"Stuff: blah\n\n";
- const char * test_no_hdr_cr_end = "GET / HTTP/1.1\r\n"
+ const char * test_no_hdr_cr_end = "GET /no_hdr_cr_end HTTP/1.1\r\n"
"Host: blah\r\n"
"things: stuff\n\n\r\n";
-
-
+ const char * test_multiline = "GET /multi HTTP/1.1\r\n"
+ "Header: foo\r\n"
+ "\tbar\r\n"
+ "\tbaz\r\n"
+ "key: val\r\n\r\n";
_test(p, &hooks, test_resp_1, htp_type_response);
_test(p, &hooks, test_1, htp_type_request);
@@ -262,6 +265,7 @@ main(int argc, char ** argv) {
_test(p, &hooks, test_no_cr, htp_type_request);
_test(p, &hooks, test_no_hdr_cr, htp_type_request);
_test(p, &hooks, test_no_hdr_cr_end, htp_type_request);
+ _test(p, &hooks, test_multiline, htp_type_request);
_test_fragments(p, &hooks, test_fragment_1, htp_type_request);
_test_fragments(p, &hooks, test_fragment_2, htp_type_request);
View
40 test.c
@@ -7,6 +7,7 @@
#include <signal.h>
#include <inttypes.h>
#include <evhtp.h>
+#include <event2/event.h>
#ifndef EVHTP_DISABLE_EVTHR
int use_threads = 0;
@@ -293,7 +294,7 @@ print_data(evhtp_request_t * req, evbuf_t * buf, void * arg) {
evbuffer_add_printf(req->buffer_out,
"got %zu bytes of data\n",
evbuffer_get_length(buf));
- printf("%.*s", evbuffer_get_length(buf), (char *)evbuffer_pullup(buf, evbuffer_get_length(buf)));
+ printf("%.*s", (int)evbuffer_get_length(buf), (char *)evbuffer_pullup(buf, evbuffer_get_length(buf)));
#endif
evbuffer_drain(buf, -1);
return EVHTP_RES_OK;
@@ -492,13 +493,14 @@ parse_args(int argc, char ** argv) {
return 0;
} /* parse_args */
-void
-sigint(int s) {
- exit(0);
+static void
+sigint(int sig, short why, void * data) {
+ event_base_loopexit(data, NULL);
}
int
main(int argc, char ** argv) {
+ struct event * ev_sigint;
evbase_t * evbase = NULL;
evhtp_t * htp = NULL;
evhtp_callback_t * cb_1 = NULL;
@@ -511,6 +513,8 @@ main(int argc, char ** argv) {
evhtp_callback_t * cb_8 = NULL;
evhtp_callback_t * cb_9 = NULL;
evhtp_callback_t * cb_10 = NULL;
+ evhtp_callback_t * cb_11 = NULL;
+ evhtp_callback_t * cb_12 = NULL;
if (parse_args(argc, argv) < 0) {
exit(1);
@@ -539,12 +543,12 @@ main(int argc, char ** argv) {
cb_10 = evhtp_set_cb(htp, "/max_body_size", test_max_body, NULL);
/* set a callback to test out chunking API */
- evhtp_set_cb(htp, "/chunkme", test_chunking, NULL);
+ cb_11 = evhtp_set_cb(htp, "/chunkme", test_chunking, NULL);
/* set a callback which takes ownership of the underlying bufferevent and
* just starts echoing things
*/
- evhtp_set_cb(htp, "/ownme", test_ownership, NULL);
+ cb_12 = evhtp_set_cb(htp, "/ownme", test_ownership, NULL);
/* set a callback to pause on each header for cb_7 */
evhtp_set_hook(&cb_7->hooks, evhtp_hook_on_path, pause_init_cb, NULL);
@@ -614,10 +618,32 @@ main(int argc, char ** argv) {
exit(-1);
}
- signal(SIGINT, sigint);
+ ev_sigint = evsignal_new(evbase, SIGINT, sigint, evbase);
+ evsignal_add(ev_sigint, NULL);
event_base_loop(evbase, 0);
+ event_free(ev_sigint);
+ evhtp_unbind_socket(htp);
+ evhtp_callback_free(cb_12);
+ evhtp_callback_free(cb_11);
+ evhtp_callback_free(cb_10);
+ evhtp_callback_free(cb_9);
+#ifndef EVHTP_DISABLE_REGEX
+ evhtp_callback_free(cb_8);
+#endif
+ evhtp_callback_free(cb_7);
+#ifndef EVHTP_DISABLE_REGEX
+ evhtp_callback_free(cb_6);
+#endif
+ evhtp_callback_free(cb_5);
+ evhtp_callback_free(cb_4);
+ evhtp_callback_free(cb_3);
+ evhtp_callback_free(cb_2);
+ evhtp_callback_free(cb_1);
+ evhtp_free(htp);
+ event_base_free(evbase);
+
return 0;
} /* main */
View
18 test_basic.c
@@ -15,16 +15,26 @@ testcb(evhtp_request_t * req, void * a) {
int
main(int argc, char ** argv) {
- evbase_t * evbase = event_base_new();
- evhtp_t * htp = evhtp_new(evbase, NULL);
+ evbase_t * evbase = event_base_new();
+ evhtp_t * htp = evhtp_new(evbase, NULL);
+ evhtp_callback_t * cb_1 = NULL;
+ evhtp_callback_t * cb_2 = NULL;
- evhtp_set_cb(htp, "/1/ping", testcb, "one");
- evhtp_set_cb(htp, "/1/ping.json", testcb, "two");
+ cb_1 = evhtp_set_cb(htp, "/1/ping", testcb, "one");
+ cb_2 = evhtp_set_cb(htp, "/1/ping.json", testcb, "two");
#ifndef EVHTP_DISABLE_EVTHR
evhtp_use_threads(htp, NULL, 4, NULL);
#endif
evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024);
+
event_base_loop(evbase, 0);
+
+ evhtp_unbind_socket(htp);
+ evhtp_callback_free(cb_2);
+ evhtp_callback_free(cb_1);
+ evhtp_free(htp);
+ event_base_free(evbase);
+
return 0;
}
View
24 test_vhost.c
@@ -13,13 +13,15 @@ testcb(evhtp_request_t * req, void * a) {
int
main(int argc, char ** argv) {
- evbase_t * evbase = event_base_new();
- evhtp_t * evhtp = evhtp_new(evbase, NULL);
- evhtp_t * v1 = evhtp_new(evbase, NULL);
- evhtp_t * v2 = evhtp_new(evbase, NULL);
+ evbase_t * evbase = event_base_new();
+ evhtp_t * evhtp = evhtp_new(evbase, NULL);
+ evhtp_t * v1 = evhtp_new(evbase, NULL);
+ evhtp_t * v2 = evhtp_new(evbase, NULL);
+ evhtp_callback_t * cb_1 = NULL;
+ evhtp_callback_t * cb_2 = NULL;
- evhtp_set_cb(v1, "/host1", NULL, "host1.com");
- evhtp_set_cb(v2, "/localhost", testcb, "localhost");
+ cb_1 = evhtp_set_cb(v1, "/host1", NULL, "host1.com");
+ cb_2 = evhtp_set_cb(v2, "/localhost", testcb, "localhost");
evhtp_add_vhost(evhtp, "host1.com", v1);
evhtp_add_vhost(evhtp, "localhost", v2);
@@ -40,7 +42,17 @@ main(int argc, char ** argv) {
#endif
evhtp_bind_socket(evhtp, "0.0.0.0", 8081, 1024);
+
event_base_loop(evbase, 0);
+
+ evhtp_unbind_socket(evhtp);
+ evhtp_callback_free(cb_2);
+ evhtp_callback_free(cb_1);
+ evhtp_free(v2);
+ evhtp_free(v1);
+ evhtp_free(evhtp);
+ event_base_free(evbase);
+
return 0;
}
Please sign in to comment.
Something went wrong with that request. Please try again.