Merge branch 'release/1.2.15'
diff --git a/.travis.yml b/.travis.yml
index 840b997..56b6873 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -4,11 +4,11 @@
            - clang
 
 sudo: required
-iinstall:
+before_install:
         - sudo apt-get update -qq
-        - sudo apt-get install libevent-dev
+        - sudo apt-get install libevent-dev libonig-dev
 script:
-        - cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && cmake --build .
+        - cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. && make examples
 
 notifications:
         - irc "irc.oftc.net#libevhtp"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5ba3a6f..3617d97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,16 +24,19 @@
     add_definitions(-DEVTHR_SHARED_PIPE)
 endif()
 
-CHECK_include_FILES(strings.h   HAVE_STRINGS_H)
-CHECK_include_FILES(string.h    HAVE_STRING_H)
-CHECK_include_FILES(stdlib.h    HAVE_STDLIB_H)
-CHECK_include_FILES(sys/time.h  HAVE_SYS_TIME_H)
-CHECK_include_FILES(sys/times.h HAVE_SYS_TIMES_H)
-CHECK_include_FILES(unistd.h    HAVE_UNISTD_H)
-CHECK_include_FILES(stdarg.h    HAVE_STDARG_PROTOTYPES)
-CHECK_include_FILES(sys/tree.h  HAVE_SYS_TREE)
-CHECK_include_FILES(sys/queue.h HAVE_SYS_QUEUE)
-CHECK_include_FILES(sys/un.h    HAVE_SYS_UN)
+check_include_files (stdlib.h    HAVE_STDLIB_H)
+check_include_files (string.h    HAVE_STRING_H)
+check_include_files (stdint.h    HAVE_STDINT_H)
+check_include_files (errno.h     HAVE_ERRNO_H)
+check_include_files (strings.h   HAVE_STRINGS_H)
+check_include_files (inttypes.h  HAVE_INTTYPES_H)
+check_include_files (limits.h    HAVE_LIMITS_H)
+
+check_include_files (unistd.h    HAVE_UNISTD_H)
+check_include_files (stdarg.h    HAVE_STDARG_PROTOTYPES)
+check_include_files (sys/tree.h  HAVE_SYS_TREE)
+check_include_files (sys/queue.h HAVE_SYS_QUEUE)
+check_include_files (sys/un.h    HAVE_SYS_UN)
 
 CHECK_TYPE_SIZE("int" SIZEOF_INT)
 CHECK_TYPE_SIZE("long" SIZEOF_LONG)
@@ -189,11 +192,11 @@
     list (APPEND LIBEVHTP_EXTERNAL_LIBS pthread)
 endif()
 
-add_library(evhtp ${EVHTP_LIBTYPE} ${LIBEVHTP_SOURCE_FILES})
-target_link_libraries(evhtp ${LIBEVHTP_EXTERNAL_LIBS})
+add_library           (evhtp ${EVHTP_LIBTYPE} ${LIBEVHTP_SOURCE_FILES})
+target_link_libraries (evhtp ${LIBEVHTP_EXTERNAL_LIBS})
 
 if (EVHTP_BUILD_SHARED)
-        set_target_properties(evhtp PROPERTIES SOVERSION "${PROJECT_VERSION}")
+        set_target_properties(evhtp PROPERTIES VERSION "${PROJECT_VERSION}" 0 OUTPUT_NAME "evhtp")
 endif()
 
 add_subdirectory(examples)
@@ -212,6 +215,7 @@
     FILES
         ${PROJECT_SOURCE_DIR}/include/evhtp/evhtp.h
         ${PROJECT_SOURCE_DIR}/include/evhtp/parser.h
+        ${PROJECT_BINARY_DIR}/include/evhtp/config.h
     DESTINATION
         ${INCLUDE_INSTALL_DIR}/evhtp)
 
@@ -221,12 +225,6 @@
     DESTINATION
         ${INCLUDE_INSTALL_DIR})
 
-install (
-    FILES
-        ${CMAKE_CURRENT_BINARY_DIR}/include/evhtp/config.h
-    DESTINATION
-        ${INCLUDE_INSTALL_DIR}/evhtp)
-
 if (NOT EVHTP_DISABLE_EVTHR)
     install (
         FILES
diff --git a/ChangeLog b/ChangeLog
index 1f03277..8ada5aa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+v1.2.15
+ o deprecated unset_hook and set_hook / cleanup (f1d2bd1 Nathan French)
+ o updated travis configuration (45003e1 Nathan French)
+ o Latest revision to support multiple SSL versions (4e353ba Tony Lambiris)
+ o remove silly comment (d3da401 Nathan French)
+ o check for errors in SSL RAND_(poll|bytes) calls (018dec8 Nathan French)
+ o Added new virtualhost examples and functions (3467382 Nathan French)
+ o added example request pausing app (282a1c9 Nathan French)
+ o Added a more extensive SSL sandbox. (1e0c241 Nathan French)
+ o Add examples/https/README (6ecf7e7 Nathan French)
+ o exit failure in example_https when SSL is disabled (0848e08 Nathan French)
+ o [#26] Use SSL_CTX_use_certificate_chain_file (4c4eb3a Nathan French)
+
 v1.2.14 - !!!! SECURITY UPDATE !!!!
  o Added doxygen tags. Updated Doxyfile to include more sources and headers. (50ab41d Dan Henderson)
  o SSL logging on handshake errors (0fff6bc Nathan French)
diff --git a/README.markdown b/README.markdown
index fff71d4..c965a8a 100644
--- a/README.markdown
+++ b/README.markdown
@@ -1,7 +1,7 @@
 | ![LOGO](http://i.imgur.com/uBd4iIz.png) | <h1>Libevhtp</h1> |
 | :------------- | -------------: |
 
-[![Build Status](https://travis-ci.org/ellzey/libevhtp.svg?branch=develop)](https://travis-ci.org/ellzey/libevhtp)
+[![Build Status](https://travis-ci.org/criticalstack/libevhtp.svg?branch=develop)](https://travis-ci.org/criticalstack/libevhtp)
 <a href="https://scan.coverity.com/projects/ellzey-libevhtp">
   <img alt="Coverity Scan Build Status"
        src="https://scan.coverity.com/projects/5084/badge.svg"/>
@@ -17,6 +17,7 @@
 ## Optional Dependencies
 * [OpenSSL](http://openssl.org)
 * pthreads
+* [onig (regex)](https://github.com/kkos/oniguruma)
 
 ## Building
 * cd build
@@ -51,7 +52,7 @@
 1.	Create a parent evhtp_t structure.
 2.	Assign callbacks to the parent for specific URIs or posix-regex based URI's
 3.	Optionally assign per-connection hooks (see hooks) to the callbacks.
-4.	Optionally assign pre-accept and post-accept callbacks for incoming connections.	
+4.	Optionally assign pre-accept and post-accept callbacks for incoming connections.
 5.	Optionally enable built-in threadpool for connection handling (lock-free, and non-blocking).
 6.	Optionally morph your server to HTTPS.
 7.	Start the evhtp listener.
@@ -78,7 +79,7 @@
 	main(int argc, char ** argv) {
 	    evbase_t * evbase = event_base_new();
 	    evhtp_t  * htp    = evhtp_new(evbase, NULL);
-	
+
 	    evhtp_set_cb(htp, "/test", testcb, NULL);
 	    evhtp_bind_socket(htp, "0.0.0.0", 8080, 1024);
 	    event_base_loop(evbase, 0);
@@ -89,12 +90,12 @@
 ## Is evhtp thread-safe?
 
 For simple usage with evhtp_use_threads(), yes. But for more extreme cases:
-sorta, you are bound to the thread mechanisms of libevent itself. 
+sorta, you are bound to the thread mechanisms of libevent itself.
 
 But with proper design around libevhtp, thread issues can be out-of-sight,
-out-of-mind. 
+out-of-mind.
 
-What do you mean by this "proper design" statement? 
+What do you mean by this "proper design" statement?
 
 Refer to the code in ./examples/thread_design.c. The comments go into great detail
 of the hows and whys for proper design using libevhtp's threading model.
@@ -113,7 +114,7 @@
 
 ## Performance stuff
 
-While we never documented any benchmark publically, 
+While we never documented any benchmark publically,
 the popular open source project [ZIMG](http://zimg.buaa.us) did a bit of that
 for us.The ZIMG team decided to move away from NGINX to libevhtp for their
 software, and the results were pretty outstanding. Here is a graph showing their
diff --git a/cmake/version.cmake b/cmake/version.cmake
index d7c14ed..f88c98f 100644
--- a/cmake/version.cmake
+++ b/cmake/version.cmake
@@ -1,5 +1,5 @@
 set (PROJECT_MAJOR_VERSION 1)
 set (PROJECT_MINOR_VERSION 2)
-set (PROJECT_PATCH_VERSION 14)
+set (PROJECT_PATCH_VERSION 15)
 set (PROJECT_VERSION
     "${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION}")
diff --git a/evhtp.c b/evhtp.c
index c818a9f..d9e1bb1 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -2754,10 +2754,6 @@
     htparser_init(connection->parser, ptype);
     htparser_set_userdata(connection->parser, connection);
 
-#ifdef EVHTP_FUTURE_USE
-    TAILQ_INIT(&connection->pending);
-#endif
-
     return connection;
 }     /* htp__connection_new_ */
 
@@ -2904,16 +2900,14 @@
 static void
 htp__ssl_delete_scache_ent_(evhtp_ssl_ctx_t * ctx, evhtp_ssl_sess_t * sess)
 {
-    evhtp_t         * htp;
-    evhtp_ssl_cfg_t * cfg;
-    unsigned char   * sid;
-    unsigned int      slen;
+    evhtp_t          * htp;
+    evhtp_ssl_cfg_t  * cfg;
+    evhtp_ssl_data_t * sid;
+    unsigned int       slen;
 
-    htp  = (evhtp_t *)SSL_CTX_get_app_data(ctx);
-    cfg  = htp->ssl_cfg;
-
-    sid  = sess->session_id;
-    slen = sess->session_id_length;
+    htp = (evhtp_t *)SSL_CTX_get_app_data(ctx);
+    cfg = htp->ssl_cfg;
+    sid = (evhtp_ssl_data_t *)SSL_SESSION_get_id(sess, &slen);
 
     if (cfg->scache_del)
     {
@@ -2926,7 +2920,7 @@
 {
     evhtp_connection_t * connection;
     evhtp_ssl_cfg_t    * cfg;
-    unsigned char      * sid;
+    evhtp_ssl_data_t   * sid;
     int                  slen;
 
     connection = (evhtp_connection_t *)SSL_get_app_data(ssl);
@@ -2934,10 +2928,9 @@
     {
         return 0;     /* We cannot get the ssl_cfg */
     }
-    cfg        = connection->htp->ssl_cfg;
 
-    sid        = sess->session_id;
-    slen       = sess->session_id_length;
+    cfg = connection->htp->ssl_cfg;
+    sid = (evhtp_ssl_data_t *)SSL_SESSION_get_id(sess, &slen);
 
     SSL_set_timeout(sess, cfg->scache_timeout);
 
@@ -2950,19 +2943,20 @@
 }
 
 static evhtp_ssl_sess_t *
-htp__ssl_get_scache_ent_(evhtp_ssl_t * ssl, unsigned char * sid, int sid_len, int * copy)
+htp__ssl_get_scache_ent_(evhtp_ssl_t * ssl, evhtp_ssl_data_t * sid, int sid_len, int * copy)
 {
     evhtp_connection_t * connection;
     evhtp_ssl_cfg_t    * cfg;
     evhtp_ssl_sess_t   * sess;
 
     connection = (evhtp_connection_t * )SSL_get_app_data(ssl);
+
     if (connection->htp == NULL)
     {
         return NULL;     /* We have no way of getting ssl_cfg */
     }
-    cfg        = connection->htp->ssl_cfg;
-    sess       = NULL;
+    cfg  = connection->htp->ssl_cfg;
+    sess = NULL;
 
     if (cfg->scache_get)
     {
@@ -3004,18 +2998,20 @@
 
     if ((evhtp_vhost = htp__request_find_vhost_(evhtp, sname)))
     {
+        SSL_CTX * ctx = SSL_get_SSL_CTX(ssl);
+
         connection->htp = evhtp_vhost;
 
         HTP_FLAG_ON(connection, EVHTP_CONN_FLAG_VHOST_VIA_SNI);
 
         SSL_set_SSL_CTX(ssl, evhtp_vhost->ssl_ctx);
-        SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx));
+        SSL_set_options(ssl, SSL_CTX_get_options(ctx));
 
         if ((SSL_get_verify_mode(ssl) == SSL_VERIFY_NONE) ||
             (SSL_num_renegotiations(ssl) == 0))
         {
-            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx),
-                           SSL_CTX_get_verify_callback(ssl->ctx));
+            SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ctx),
+                           SSL_CTX_get_verify_callback(ctx));
         }
 
         return SSL_TLSEXT_ERR_OK;
@@ -4352,10 +4348,27 @@
     return 0;
 }         /* htp__set_hook_ */
 
+static int
+htp__unset_hook_(evhtp_hooks_t ** hooks, evhtp_hook_type type) {
+    return htp__set_hook_(hooks, type, NULL, NULL);
+}
+
 int
-evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
+evhtp_callback_unset_hook(evhtp_callback_t * callback, evhtp_hook_type type)
 {
-    return htp__set_hook_(hooks, type, cb, arg);
+    return htp__unset_hook_(&callback->hooks, type);
+}
+
+int
+evhtp_request_unset_hook(evhtp_request_t * req, evhtp_hook_type type)
+{
+    return htp__unset_hook_(&req->hooks, type);
+}
+
+int
+evhtp_connection_unset_hook(evhtp_connection_t * conn, evhtp_hook_type type)
+{
+    return htp__unset_hook_(&conn->hooks, type);
 }
 
 int
@@ -4377,12 +4390,6 @@
 }
 
 int
-evhtp_unset_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type)
-{
-    return evhtp_set_hook(hooks, type, NULL, NULL);
-}
-
-int
 evhtp_unset_all_hooks(evhtp_hooks_t ** hooks)
 {
     int i;
@@ -4413,7 +4420,7 @@
     }
 
     for (i = 0; hooklist_[i].type != -1; i++) {
-        if (evhtp_unset_hook(hooks, hooklist_[i].type) == -1) {
+        if (htp__unset_hook_(hooks, hooklist_[i].type) == -1) {
             return -1;
         }
     }
@@ -4752,13 +4759,8 @@
 int
 evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg)
 {
-#ifdef EVHTP_ENABLE_FUTURE_STUFF
-    evhtp_ssl_scache_init init_cb = NULL;
-    evhtp_ssl_scache_add  add_cb  = NULL;
-    evhtp_ssl_scache_get  get_cb  = NULL;
-    evhtp_ssl_scache_del  del_cb  = NULL;
-#endif
-    long cache_mode;
+    long          cache_mode;
+    unsigned char c;
 
     if (cfg == NULL || htp == NULL || cfg->pemfile == NULL)
     {
@@ -4769,7 +4771,16 @@
     ERR_load_crypto_strings();
     SSL_load_error_strings();
     OpenSSL_add_all_algorithms();
-    RAND_poll();
+
+    if (RAND_poll() != 1) {
+        log_error("RAND_poll");
+        return -1;
+    }
+
+    if (RAND_bytes(&c, 1) != 1) {
+        log_error("RAND_bytes");
+        return -1;
+    }
 
 #if OPENSSL_VERSION_NUMBER < 0x10000000L
     STACK_OF(SSL_COMP) * comp_methods = SSL_COMP_get_compression_methods();
@@ -4789,21 +4800,22 @@
     SSL_CTX_set_options(htp->ssl_ctx, cfg->ssl_opts);
 
 #ifndef OPENSSL_NO_ECDH
-    if (cfg->named_curve != NULL)
-    {
+    if (cfg->named_curve != NULL) {
         EC_KEY * ecdh = NULL;
         int      nid  = 0;
 
-        nid  = OBJ_sn2nid(cfg->named_curve);
-        if (nid == 0)
-        {
-            fprintf(stderr, "ECDH initialization failed: unknown curve %s\n", cfg->named_curve);
+        nid = OBJ_sn2nid(cfg->named_curve);
+
+        if (nid == 0) {
+            log_error("ECDH initialization failed: unknown curve %s", cfg->named_curve);
         }
+
         ecdh = EC_KEY_new_by_curve_name(nid);
-        if (ecdh == NULL)
-        {
-            fprintf(stderr, "ECDH initialization failed for curve %s\n", cfg->named_curve);
+
+        if (ecdh == NULL) {
+            log_error("ECDH initialization failed for curve %s", cfg->named_curve);
         }
+
         SSL_CTX_set_tmp_ecdh(htp->ssl_ctx, ecdh);
         EC_KEY_free(ecdh);
     }
@@ -4815,6 +4827,7 @@
         DH   * dh;
 
         fh = fopen(cfg->dhparams, "r");
+
         if (fh != NULL)
         {
             dh = PEM_read_DHparams(fh, NULL, NULL, NULL);
@@ -4823,30 +4836,36 @@
                 SSL_CTX_set_tmp_dh(htp->ssl_ctx, dh);
                 DH_free(dh);
             } else {
-                fprintf(stderr, "DH initialization failed: unable to parse file %s\n", cfg->dhparams);
+                log_error("DH initialization failed: unable to parse file %s", cfg->dhparams);
             }
+
             fclose(fh);
         } else {
-            fprintf(stderr, "DH initialization failed: unable to open file %s\n", cfg->dhparams);
+            log_error("DH initialization failed: unable to open file %s", cfg->dhparams);
         }
     }
 #endif  /* OPENSSL_NO_DH */
 
     if (cfg->ciphers != NULL) {
-        SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers);
+        if (SSL_CTX_set_cipher_list(htp->ssl_ctx, cfg->ciphers) == 0) {
+            log_error("set_cipher_list");
+            return -1;
+        }
     }
 
     SSL_CTX_load_verify_locations(htp->ssl_ctx, cfg->cafile, cfg->capath);
     X509_STORE_set_flags(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->store_flags);
     SSL_CTX_set_verify(htp->ssl_ctx, cfg->verify_peer, cfg->x509_verify_cb);
 
-    if (cfg->x509_chk_issued_cb != NULL)
-    {
+    if (cfg->x509_chk_issued_cb != NULL) {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
         htp->ssl_ctx->cert_store->check_issued = cfg->x509_chk_issued_cb;
+#else
+        X509_STORE_set_check_issued(SSL_CTX_get_cert_store(htp->ssl_ctx), cfg->x509_chk_issued_cb);
+#endif
     }
 
-    if (cfg->verify_depth)
-    {
+    if (cfg->verify_depth) {
         SSL_CTX_set_verify_depth(htp->ssl_ctx, cfg->verify_depth);
     }
 
@@ -4854,35 +4873,12 @@
         case evhtp_ssl_scache_type_disabled:
             cache_mode = SSL_SESS_CACHE_OFF;
             break;
-#ifdef EVHTP_ENABLE_FUTURE_STUFF
-        case evhtp_ssl_scache_type_user:
-            cache_mode = SSL_SESS_CACHE_SERVER |
-                         SSL_SESS_CACHE_NO_INTERNAL |
-                         SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
-
-            init_cb    = cfg->scache_init;
-            add_cb     = cfg->scache_add;
-            get_cb     = cfg->scache_get;
-            del_cb     = cfg->scache_del;
-            break;
-        case evhtp_ssl_scache_type_builtin:
-            cache_mode = SSL_SESS_CACHE_SERVER |
-                         SSL_SESS_CACHE_NO_INTERNAL |
-                         SSL_SESS_CACHE_NO_INTERNAL_LOOKUP;
-
-            init_cb    = htp__ssl_builtin_init_;
-            add_cb     = htp__ssl_builtin_add_;
-            get_cb     = htp__ssl_builtin_get_;
-            del_cb     = htp__ssl_builtin_del_;
-            break;
-#endif
-        case evhtp_ssl_scache_type_internal:
         default:
             cache_mode = SSL_SESS_CACHE_SERVER;
             break;
     }     /* switch */
 
-    SSL_CTX_use_certificate_file(htp->ssl_ctx, cfg->pemfile, SSL_FILETYPE_PEM);
+    SSL_CTX_use_certificate_chain_file(htp->ssl_ctx, cfg->pemfile);
 
     char * const key = cfg->privfile ?  cfg->privfile : cfg->pemfile;
 
@@ -5168,6 +5164,8 @@
         return -1;
     }
 
+    log_debug("Adding %s to aliases", name);
+
     alias->alias = htp__strdup_(name);
     evhtp_alloc_assert(alias->alias);
 
@@ -5177,6 +5175,31 @@
 }
 
 int
+evhtp_add_aliases(evhtp_t * htp, const char * name, ...) {
+    va_list      argp;
+    size_t       len;
+
+    if (evhtp_add_alias(htp, name) == -1) {
+        return -1;
+    }
+
+    va_start(argp, name);
+    {
+        const char * p;
+
+        while ((p = va_arg(argp, const char *)) != NULL) {
+            if (evhtp_add_alias(htp, p) == -1) {
+                log_error("Unable to add %s alias", p);
+                return -1;
+            }
+        }
+    }
+    va_end(argp);
+
+    return 0;
+}
+
+int
 evhtp_add_vhost(evhtp_t * evhtp, const char * name, evhtp_t * vhost)
 {
     if (evhtp == NULL || name == NULL || vhost == NULL)
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index c69aac5..31c3b8b 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -6,6 +6,9 @@
 add_executable(test_client EXCLUDE_FROM_ALL test_client.c)
 add_executable(test_query EXCLUDE_FROM_ALL test_query.c)
 add_executable(test_perf EXCLUDE_FROM_ALL test_perf.c)
+add_executable(example_vhost EXCLUDE_FROM_ALL example_vhost.c)
+add_executable(example_pause EXCLUDE_FROM_ALL example_pause.c)
+add_executable(example_https EXCLUDE_FROM_ALL https/example_https.c)
 
 if (NOT EVHTP_DISABLE_EVTHR)
 	add_executable(test_proxy EXCLUDE_FROM_ALL test_proxy.c)
@@ -19,7 +22,18 @@
 target_link_libraries(test_client  evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 target_link_libraries(test_query   evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 target_link_libraries(test_perf    evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
+target_link_libraries(example_vhost evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
+target_link_libraries(example_pause evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
+target_link_libraries(example_https evhtp ${LIBEVHTP_EXTERNAL_LIBS} ${SYS_LIBS})
 
-add_dependencies(examples test_extensive test_basic test_vhost test_client test_query test_perf)
+add_dependencies(examples example_https example_pause example_vhost test_extensive test_basic test_vhost test_client test_query test_perf)
 
+file (COPY
+    https/etc/ca.cnf
+    https/etc/client1.cnf
+    https/etc/client2.cnf
+    https/etc/server.cnf
+    DESTINATION
+    https/etc/)
 
+configure_file(https/bin/generate.sh.in https/bin/generate.sh @ONLY)
diff --git a/examples/example_pause.c b/examples/example_pause.c
new file mode 100644
index 0000000..247a7da
--- /dev/null
+++ b/examples/example_pause.c
@@ -0,0 +1,125 @@
+/*
+ * Quick example of how to pause a request, and in this case, simply
+ * set a timer to emit the response 10 seconds later.
+ *
+ * This is a good way to long running tasks before responding (thus
+ * not blocking any other processing).
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include "../log.h"
+#include "internal.h"
+#include "evhtp/evhtp.h"
+
+struct paused_request_ {
+    struct event    * _timeoutev;
+    struct timeval    _timeout;
+    evhtp_request_t * _request;
+};
+
+/* once 10 seconds has passed, this function is called, it will
+ * resume the request, and send the final response back to the
+ * client.
+ */
+static void
+http_resume__callback_(int sock, short events, void * arg) {
+    struct paused_request_ * preq;
+    evhtp_request_t        * req;
+
+    evhtp_assert(arg != NULL);
+
+    preq = (struct paused_request_ *)arg;
+    req  = preq->_request;
+    evhtp_assert(req != NULL);
+
+    event_free(preq->_timeoutev);
+    free(preq);
+
+    /* add the current time to our output buffer to the client */
+    evbuffer_add_printf(req->buffer_out, "time end %ld\n", time(NULL));
+
+    /* inform the evhtp API to resume this connection request */
+    evhtp_request_resume(req);
+
+    /* finally send the response to the client, YAY! */
+    evhtp_send_reply(req, EVHTP_RES_OK);
+}
+
+/* this is our default callback, it is the one who sets up the evtimer
+ * that triggers the response after 10 seconds.
+ */
+static void
+http_pause__callback_(evhtp_request_t * req, void * arg) {
+    struct timeval         * tv = (struct timeval *)arg;
+    struct paused_request_ * preq;
+
+    /* allocate a little structure that holds our evtimer and the
+     * pending request, se the timeout to 10 seconds.
+     */
+    preq                   = malloc(sizeof(*preq));
+    evhtp_alloc_assert(preq);
+
+    preq->_request         = req;
+    preq->_timeout.tv_sec  = tv->tv_sec;
+    preq->_timeout.tv_usec = tv->tv_usec;
+
+    /* when 10 seconds is up, the function http_resume__callback_ will
+     * be called, this function will actually send the response.
+     */
+    preq->_timeoutev       = evtimer_new(req->htp->evbase, http_resume__callback_, preq);
+    evhtp_alloc_assert(preq->_timeoutev);
+
+    /* just for debugging, add the time the request was first seen */
+    evbuffer_add_printf(req->buffer_out, "time start %ld\n", time(NULL));
+
+    /* add the timer to the event loop */
+    evtimer_add(preq->_timeoutev, &preq->_timeout);
+
+    /* notify the evhtp API to "pause" this request (meaning it will no
+     * longer do any work on this connection until it is "resumed".
+     */
+    evhtp_request_pause(req);
+}
+
+int
+main(int argc, char ** argv) {
+    evhtp_t           * htp;
+    struct event_base * evbase;
+    struct timeval      timeo = { 10, 0 };
+
+    evbase = event_base_new();
+    evhtp_alloc_assert(evbase);
+
+    htp    = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp);
+
+    /* we just set the default callback for any requests to
+     * the function that pauses the session, sets a timer,
+     * and 10 seconds later, sends the response.
+     */
+    evhtp_set_gencb(htp, http_pause__callback_, &timeo);
+
+    evhtp_bind_socket(htp, "127.0.0.1", 0, 128);
+    {
+        struct sockaddr_in sin;
+        socklen_t          len = sizeof(struct sockaddr);
+        uint16_t           port;
+
+        getsockname(
+            evconnlistener_get_fd(htp->server),
+            (struct sockaddr *)&sin, &len);
+
+        port = ntohs(sin.sin_port);
+
+        log_info("request will be delayed for 10 seconds with: curl http://127.0.0.1:%d/", port);
+    }
+
+    event_base_loop(evbase, 0);
+
+
+    return 0;
+}
diff --git a/examples/example_vhost.c b/examples/example_vhost.c
new file mode 100644
index 0000000..4a61003
--- /dev/null
+++ b/examples/example_vhost.c
@@ -0,0 +1,127 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+
+#include "internal.h"
+#include "../log.h"
+#include "evhtp/evhtp.h"
+
+#define make_response(cb) do {                                          \
+        evbuffer_add_printf(req->buffer_out,                            \
+                            "%s = host:%s, arg:%s\n", cb,               \
+                            evhtp_header_find(req->headers_in, "Host"), \
+                            (char *)arg);                               \
+} while (0)
+
+
+static void
+vhost_1__callback_(evhtp_request_t * req, void * arg) {
+    /* these should be our callbacks for our evhtp.io hosts */
+    make_response("vhost_1__callback_");
+
+    evhtp_send_reply(req, EVHTP_RES_OK);
+}
+
+static void
+vhost_2__callback_(evhtp_request_t * req, void * arg) {
+    /* these should be our callbacks for our google hosts */
+    make_response("vhost_2__callback_");
+
+    evhtp_send_reply(req, EVHTP_RES_OK);
+}
+
+int
+main(int argc, char ** argv) {
+    struct event_base * evbase;
+    evhtp_t           * htp;
+    evhtp_t           * htp_vhost_1;
+    evhtp_t           * htp_vhost_2;
+
+    evbase      = event_base_new();
+    evhtp_alloc_assert(evbase);
+
+    /* allocate our main evhtp structure which vhosts are
+     * nested under
+     */
+    htp         = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp);
+
+    /* create a evhtp structure for vhost_1 specific hostnames,
+     * this will match hostnames for 'evhtp.io'
+     * */
+    htp_vhost_1 = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp_vhost_1);
+
+    /* running a get on /vhost for htp_vhost_1 will be different
+     * from htp_vhost_2 due to the hostname we set below.
+     */
+    evhtp_set_cb(htp_vhost_1, "/vhost", vhost_1__callback_, "evhtp.io domains");
+
+    /* create a evhtp structure for vhost_2 specific hostnames,
+     * this will match hostnames for 'google.com'
+     */
+    htp_vhost_2 = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp_vhost_2);
+
+    /* running a get on /vhost for http_vhost_2 will be different
+     * from the http_vhost_1 due to the hostname we set below.
+     */
+    evhtp_set_cb(htp_vhost_2, "/vhost", vhost_2__callback_, "google.com domains");
+
+    /* if Host: evhtp.io is present, the callbacks fro htp_vhost_1 are
+     * used. We do this by adding the vhost_1 evhtp to the main htp ctx.
+     */
+    evhtp_add_vhost(htp, "evhtp.io", htp_vhost_1);
+
+    /* now lets set some virtual host aliases to evhtp.io */
+    evhtp_add_aliases(htp_vhost_1,
+                      "www.evhtp.io",
+                      "web.evhtp.io", NULL);
+
+    /* If Host: google.com is present, the callbacks for htp_vhost_2 are
+     * used instead. This must be attached to the main htp context.
+     */
+    evhtp_add_vhost(htp, "google.com", htp_vhost_2);
+
+    /* now add some virtual host aliases for google.com */
+    evhtp_add_aliases(htp_vhost_2,
+                      "www.google.com",
+                      "web.google.com",
+                      "inbox.google.com", NULL);
+
+    /* we can also append a single alias to vhost_2 like this */
+    evhtp_add_alias(htp_vhost_2, "gmail.google.com");
+
+    /* now bind and listen on our server */
+    evhtp_bind_socket(htp, "127.0.0.1", 0, 128);
+
+    {
+        struct sockaddr_in sin;
+        socklen_t          len = sizeof(struct sockaddr);
+        uint16_t           port;
+
+        getsockname(
+            evconnlistener_get_fd(htp->server),
+            (struct sockaddr *)&sin, &len);
+
+        port = ntohs(sin.sin_port);
+
+        log_info("[[ try the following commands and you should see 'evhtp.io domains' ]]");
+        log_info("=====================================================================");
+        log_info("curl -H'Host: evhtp.io' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: www.evhtp.io' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: web.evhtp.io' http://127.0.0.1:%d/vhost", port);
+        log_info("========================================================================");
+        log_info("[[ try the following commands and you should see 'google.com domains' ]]");
+        log_info("========================================================================");
+        log_info("curl -H'Host: google.com' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: www.google.com' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: web.google.com' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: inbox.google.com' http://127.0.0.1:%d/vhost", port);
+        log_info("curl -H'Host: gmail.google.com' http://127.0.0.1:%d/vhost", port);
+    }
+
+    event_base_loop(evbase, 0);
+} /* main */
diff --git a/examples/https/README.md b/examples/https/README.md
new file mode 100644
index 0000000..0e1b539
--- /dev/null
+++ b/examples/https/README.md
@@ -0,0 +1,32 @@
+After running `make examples`, if SSL is enabled, you can quickly test HTTPS, with optional client-based certificate authentication using the following process within the build directory:
+
+```
+# do all the stupid ssl generation
+./examples/https/bin/generate.sh
+
+# Test without client auth
+
+# Run the server
+./examples/example_https              \
+  -cert examples/https/server-crt.pem \
+  -key  examples/https/server-key.pem
+
+# Make a request
+curl -vk https://localhost:4443/
+
+# Test WITH client auth
+
+./examples/example_https              \
+  -cert examples/https/server-crt.pem \
+  -key  examples/https/server-key.pem \
+  -ca   examples/https/ca-crt.pem     \
+  -verify-peer                        \
+  -verify-depth 2                     \
+  -enforce-peer-cert
+
+# Make a request with the client key
+curl -kv \
+  --key  examples/https/client1-key.pem \
+  --cert examples/https/client1-crt.pem \
+  https://localhost:4443/
+```
diff --git a/examples/https/bin/generate.sh.in b/examples/https/bin/generate.sh.in
new file mode 100755
index 0000000..6f78154
--- /dev/null
+++ b/examples/https/bin/generate.sh.in
@@ -0,0 +1,58 @@
+#!/usr/bin/env bash
+
+CONFIG_DIR="@PROJECT_BINARY_DIR@/examples/https"
+
+# Create new CA
+openssl req -new -x509 -days 9999    \
+    -config "$CONFIG_DIR/etc/ca.cnf" \
+    -keyout "$CONFIG_DIR/ca-key.pem" \
+    -out    "$CONFIG_DIR/ca-crt.pem"
+
+# Generate private key for server
+openssl genrsa -out "$CONFIG_DIR/server-key.pem" 4096
+
+# Generate cert signing request
+openssl req -new \
+    -config "$CONFIG_DIR/etc/server.cnf" \
+    -key    "$CONFIG_DIR/server-key.pem" \
+    -out    "$CONFIG_DIR/server-csr.pem"
+
+# Sign the request
+openssl x509 -req                         \
+    -extfile "$CONFIG_DIR/etc/server.cnf" \
+    -days 999                             \
+    -passin "pass:password"               \
+    -in "$CONFIG_DIR/server-csr.pem"      \
+    -CA "$CONFIG_DIR/ca-crt.pem"          \
+    -CAkey "$CONFIG_DIR/ca-key.pem"       \
+    -CAcreateserial                       \
+    -out "$CONFIG_DIR/server-crt.pem"
+
+# Generate a few client certs
+openssl genrsa -out "$CONFIG_DIR/client1-key.pem" 4096
+openssl genrsa -out "$CONFIG_DIR/client2-key.pem" 4096
+
+# create two cert sign requests
+openssl req -new -config "$CONFIG_DIR/etc/client1.cnf" -key $CONFIG_DIR/client1-key.pem -out $CONFIG_DIR/client1-csr.pem
+openssl req -new -config $CONFIG_DIR/etc/client2.cnf -key $CONFIG_DIR/client2-key.pem -out $CONFIG_DIR/client2-csr.pem
+
+# sign the above client certs
+openssl x509 -req            \
+    -extfile $CONFIG_DIR/etc/client1.cnf \
+    -days 999                \
+    -passin "pass:password"  \
+    -in $CONFIG_DIR/client1-csr.pem      \
+    -CA $CONFIG_DIR/ca-crt.pem           \
+    -CAkey $CONFIG_DIR/ca-key.pem        \
+    -CAcreateserial          \
+    -out $CONFIG_DIR/client1-crt.pem
+
+openssl x509 -req            \
+    -extfile $CONFIG_DIR/etc/client2.cnf \
+    -days 999                \
+    -passin "pass:password"  \
+    -in $CONFIG_DIR/client2-csr.pem      \
+    -CA $CONFIG_DIR/ca-crt.pem           \
+    -CAkey $CONFIG_DIR/ca-key.pem        \
+    -CAcreateserial          \
+    -out $CONFIG_DIR/client2-crt.pem
diff --git a/examples/https/etc/ca.cnf b/examples/https/etc/ca.cnf
new file mode 100644
index 0000000..53eab64
--- /dev/null
+++ b/examples/https/etc/ca.cnf
@@ -0,0 +1,31 @@
+[ ca ]
+default_ca      = CA_default
+
+[ CA_default ]
+serial = ca-serial
+crl = ca-crl.pem
+database = ca-database.txt
+name_opt = CA_default
+cert_opt = CA_default
+default_crl_days = 9999
+default_md = md5
+
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+output_password        = password
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = ca
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = test
diff --git a/examples/https/etc/client1.cnf b/examples/https/etc/client1.cnf
new file mode 100644
index 0000000..6e881ff
--- /dev/null
+++ b/examples/https/etc/client1.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = client1
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/etc/client2.cnf b/examples/https/etc/client2.cnf
new file mode 100644
index 0000000..2cbf570
--- /dev/null
+++ b/examples/https/etc/client2.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = client2
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/etc/server.cnf b/examples/https/etc/server.cnf
new file mode 100644
index 0000000..2c36ee4
--- /dev/null
+++ b/examples/https/etc/server.cnf
@@ -0,0 +1,26 @@
+[ req ]
+default_bits           = 4096
+days                   = 9999
+distinguished_name     = req_distinguished_name
+attributes             = req_attributes
+prompt                 = no
+x509_extensions        = v3_ca
+
+[ req_distinguished_name ]
+C                      = US
+ST                     = MA
+L                      = Boston
+O                      = Critical Stack
+OU                     = evhtp
+CN                     = localhost
+emailAddress           = nate@cl0d.com
+
+[ req_attributes ]
+challengePassword      = password
+
+[ v3_ca ]
+authorityInfoAccess = @issuer_info
+
+[ issuer_info ]
+OCSP;URI.0 = http://ocsp.example.com/
+caIssuers;URI.0 = http://example.com/ca.cert
diff --git a/examples/https/example_https.c b/examples/https/example_https.c
new file mode 100644
index 0000000..18a4723
--- /dev/null
+++ b/examples/https/example_https.c
@@ -0,0 +1,261 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include "../log.h"
+#include "internal.h"
+#include "evhtp/evhtp.h"
+
+#ifndef EVHTP_DISABLE_SSL
+static void
+http__callback_(evhtp_request_t * req, void * arg) {
+    return evhtp_send_reply(req, EVHTP_RES_OK);
+}
+
+static int
+ssl__x509_verify_(int ok, X509_STORE_CTX * store) {
+    char                 buf[256];
+    X509               * err_cert;
+    int                  err;
+    int                  depth;
+    SSL                * ssl;
+    evhtp_connection_t * connection;
+    evhtp_ssl_cfg_t    * ssl_cfg;
+
+    err_cert   = X509_STORE_CTX_get_current_cert(store);
+    err        = X509_STORE_CTX_get_error(store);
+    depth      = X509_STORE_CTX_get_error_depth(store);
+    ssl        = X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx());
+
+    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
+
+    connection = SSL_get_app_data(ssl);
+    ssl_cfg    = connection->htp->ssl_cfg;
+
+    if (depth > ssl_cfg->verify_depth) {
+        ok  = 0;
+        err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
+
+        X509_STORE_CTX_set_error(store, err);
+    }
+
+    if (!ok) {
+        log_error("SSL: verify error:num=%d:%s:depth=%d:%s", err,
+                  X509_verify_cert_error_string(err), depth, buf);
+    }
+
+    return ok;
+}
+
+enum {
+    OPTARG_CERT = 1000,
+    OPTARG_KEY,
+    OPTARG_CA,
+    OPTARG_CAPATH,
+    OPTARG_CIPHERS,
+    OPTARG_VERIFY_PEER,
+    OPTARG_ENFORCE_PEER_CERT,
+    OPTARG_VERIFY_DEPTH,
+    OPTARG_ENABLE_CACHE,
+    OPTARG_CACHE_TIMEOUT,
+    OPTARG_CACHE_SIZE,
+    OPTARG_CTX_TIMEOUT,
+    OPTARG_ENABLE_PROTOCOL,
+    OPTARG_DISABLE_PROTOCOL
+};
+
+static const char * help =
+    "Usage %s [opts] <host>:<port>\n"
+    "  -cert          <file> : Server PEM-encoded X.509 Certificate file\n"
+    "  -key           <file> : Server PEM-encoded Private Key file\n"
+    "  -ca            <file> : File of PEM-encoded Server CA Certificates\n"
+    "  -capath        <path> : Directory of PEM-encoded CA Certificates for Client Auth\n"
+    "  -ciphers        <str> : Accepted SSL Ciphers\n"
+    "  -verify-peer          : Enable SSL client verification\n"
+    "  -enforce-peer-cert    : Reject clients without a cert\n"
+    "  -verify-depth     <n> : Maximum depth of CA Certificates in Client Certificate verification\n"
+    "  -enable-protocol  <p> : Enable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
+    "  -disable-protocol <p> : Disable one of the following protocols: SSLv2, SSLv3, TLSv1, or ALL\n"
+    "  -ctx-timeout      <n> : SSL Session Timeout (SSL >= 1.0)\n";
+
+evhtp_ssl_cfg_t *
+parse__ssl_opts_(int argc, char ** argv) {
+    int               opt               = 0;
+    int               long_index        = 0;
+    int               ssl_verify_mode   = 0;
+    struct stat       f_stat;
+    evhtp_ssl_cfg_t * ssl_config        = calloc(1, sizeof(evhtp_ssl_cfg_t));
+
+
+    ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
+
+    static struct option long_options[] = {
+        { "cert",              required_argument, 0, OPTARG_CERT              },
+        { "key",               required_argument, 0, OPTARG_KEY               },
+        { "ca",                required_argument, 0, OPTARG_CA                },
+        { "capath",            required_argument, 0, OPTARG_CAPATH            },
+        { "ciphers",           required_argument, 0, OPTARG_CIPHERS           },
+        { "verify-peer",       no_argument,       0, OPTARG_VERIFY_PEER       },
+        { "enforce-peer-cert", no_argument,       0, OPTARG_ENFORCE_PEER_CERT },
+        { "verify-depth",      required_argument, 0, OPTARG_VERIFY_DEPTH      },
+        { "enable-cache",      no_argument,       0, OPTARG_ENABLE_CACHE      },
+        { "cache-timeout",     required_argument, 0, OPTARG_CACHE_TIMEOUT     },
+        { "cache-size",        required_argument, 0, OPTARG_CACHE_SIZE        },
+        { "enable-protocol",   required_argument, 0, OPTARG_ENABLE_PROTOCOL   },
+        { "disable-protocol",  required_argument, 0, OPTARG_DISABLE_PROTOCOL  },
+        { "ctx-timeout",       required_argument, 0, OPTARG_CTX_TIMEOUT       },
+        { "help",              no_argument,       0, 'h'                      },
+        { NULL,                0,                 0, 0                        }
+    };
+
+    while ((opt = getopt_long_only(argc, argv, "", long_options, &long_index)) != -1) {
+        switch (opt) {
+            case 'h':
+                printf(help, argv[0]);
+                exit(EXIT_FAILURE);
+            case OPTARG_CERT:
+                ssl_config->pemfile         = strdup(optarg);
+                break;
+            case OPTARG_KEY:
+                ssl_config->privfile        = strdup(optarg);
+                break;
+            case OPTARG_CA:
+                ssl_config->cafile          = strdup(optarg);
+                break;
+            case OPTARG_CAPATH:
+                ssl_config->capath          = strdup(optarg);
+                break;
+            case OPTARG_CIPHERS:
+                ssl_config->ciphers         = strdup(optarg);
+                break;
+            case OPTARG_VERIFY_DEPTH:
+                ssl_config->verify_depth = atoi(optarg);
+                break;
+            case OPTARG_VERIFY_PEER:
+                ssl_verify_mode            |= SSL_VERIFY_PEER;
+                break;
+            case OPTARG_ENFORCE_PEER_CERT:
+                ssl_verify_mode            |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
+                break;
+            case OPTARG_ENABLE_CACHE:
+                ssl_config->scache_type     = evhtp_ssl_scache_type_internal;
+                break;
+            case OPTARG_CACHE_TIMEOUT:
+                ssl_config->scache_timeout  = atoi(optarg);
+                break;
+            case OPTARG_CACHE_SIZE:
+                ssl_config->scache_size     = atoi(optarg);
+                break;
+            case OPTARG_CTX_TIMEOUT:
+                ssl_config->ssl_ctx_timeout = atoi(optarg);
+                break;
+            case OPTARG_ENABLE_PROTOCOL:
+                if (!strcasecmp(optarg, "SSLv2")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv2;
+                } else if (!strcasecmp(optarg, "SSLv3")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_SSLv3;
+                } else if (!strcasecmp(optarg, "TLSv1")) {
+                    ssl_config->ssl_opts &= ~SSL_OP_NO_TLSv1;
+                } else if (!strcasecmp(optarg, "ALL")) {
+                    ssl_config->ssl_opts = 0;
+                }
+
+                break;
+            case OPTARG_DISABLE_PROTOCOL:
+                if (!strcasecmp(optarg, "SSLv2")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_SSLv2;
+                } else if (!strcasecmp(optarg, "SSLv3")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_SSLv3;
+                } else if (!strcasecmp(optarg, "TLSv1")) {
+                    ssl_config->ssl_opts |= SSL_OP_NO_TLSv1;
+                } else if (!strcasecmp(optarg, "ALL")) {
+                    ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
+                }
+                break;
+
+            default:
+                break;
+        } /* switch */
+    }
+
+    if (ssl_verify_mode != 0) {
+        ssl_config->verify_peer    = ssl_verify_mode;
+        ssl_config->x509_verify_cb = ssl__x509_verify_;
+    }
+
+
+    if (ssl_config->pemfile) {
+        if (stat(ssl_config->pemfile, &f_stat) != 0) {
+            log_error("Cannot load SSL cert '%s' (%s)", ssl_config->pemfile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->privfile) {
+        if (stat(ssl_config->privfile, &f_stat) != 0) {
+            log_error("Cannot load SSL key '%s' (%s)", ssl_config->privfile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->cafile) {
+        if (stat(ssl_config->cafile, &f_stat) != 0) {
+            log_error("Cannot find SSL CA File '%s' (%s)", ssl_config->cafile, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    if (ssl_config->capath) {
+        if (stat(ssl_config->capath, &f_stat) != 0) {
+            log_error("Cannot find SSL CA PATH '%s' (%s)", ssl_config->capath, strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    return ssl_config;
+} /* parse__ssl_opts_ */
+#endif
+
+int
+main(int argc, char ** argv) {
+#ifndef EVHTP_DISABLE_SSL
+    evhtp_t           * htp;
+    struct event_base * evbase;
+
+    evbase = event_base_new();
+    evhtp_alloc_assert(evbase);
+
+    htp    = evhtp_new(evbase, NULL);
+    evhtp_alloc_assert(htp);
+
+    evhtp_ssl_init(htp, parse__ssl_opts_(argc, argv));
+    evhtp_set_gencb(htp, http__callback_, NULL);
+
+    evhtp_bind_socket(htp, "127.0.0.1", 4443, 128);
+    {
+        struct sockaddr_in sin;
+        socklen_t          len = sizeof(struct sockaddr);
+        uint16_t           port;
+
+        getsockname(
+            evconnlistener_get_fd(htp->server),
+            (struct sockaddr *)&sin, &len);
+
+        port = ntohs(sin.sin_port);
+
+        log_info("curl https://127.0.0.1:%d/", port);
+    }
+
+    event_base_loop(evbase, 0);
+    return 0;
+#else
+    log_error("Not compiled with SSL support, go away");
+    return EXIT_FAILURE;
+#endif
+}
diff --git a/include/evhtp/evhtp.h b/include/evhtp/evhtp.h
index 0c66428..f7cd3d9 100644
--- a/include/evhtp/evhtp.h
+++ b/include/evhtp/evhtp.h
@@ -44,6 +44,11 @@
 typedef SSL_CTX                   evhtp_ssl_ctx_t;
 typedef X509                      evhtp_x509_t;
 typedef X509_STORE_CTX            evhtp_x509_store_ctx_t;
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+typedef unsigned char             evhtp_ssl_data_t;
+#else
+typedef const unsigned char       evhtp_ssl_data_t;
+#endif
 #else
 typedef void                      evhtp_ssl_sess_t;
 typedef void                      evhtp_ssl_t;
@@ -162,7 +167,7 @@
 typedef evhtp_res (* evhtp_hook_header_cb)(evhtp_request_t * req, evhtp_header_t * hdr, void * arg);
 typedef evhtp_res (* evhtp_hook_headers_cb)(evhtp_request_t * req, evhtp_headers_t * hdr, void * arg);
 typedef evhtp_res (* evhtp_hook_path_cb)(evhtp_request_t * req, evhtp_path_t * path, void * arg);
-typedef evhtp_res (* evhtp_hook_read_cb)(evhtp_request_t * req, evbuf_t * buf, void * arg);
+typedef evhtp_res (* evhtp_hook_read_cb)(evhtp_request_t * req, struct evbuffer * buf, void * arg);
 typedef evhtp_res (* evhtp_hook_request_fini_cb)(evhtp_request_t * req, void * arg);
 typedef evhtp_res (* evhtp_hook_connection_fini_cb)(evhtp_connection_t * connection, void * arg);
 typedef evhtp_res (* evhtp_hook_chunk_new_cb)(evhtp_request_t * r, uint64_t len, void * arg);
@@ -180,16 +185,17 @@
 typedef int (* evhtp_ssl_chk_issued_cb)(evhtp_x509_store_ctx_t * ctx, evhtp_x509_t * x, evhtp_x509_t * issuer);
 typedef EVP_PKEY * (* evhtp_ssl_decrypt_cb)(char * privfile);
 
-typedef int (* evhtp_ssl_scache_add)(evhtp_connection_t * connection, unsigned char * sid, int sid_len, evhtp_ssl_sess_t * sess);
-typedef void (* evhtp_ssl_scache_del)(evhtp_t * htp, unsigned char * sid, int sid_len);
-typedef evhtp_ssl_sess_t * (* evhtp_ssl_scache_get)(evhtp_connection_t * connection, unsigned char * sid, int sid_len);
+typedef int (* evhtp_ssl_scache_add)(evhtp_connection_t * connection, evhtp_ssl_data_t * sid, int sid_len, evhtp_ssl_sess_t * sess);
+typedef void (* evhtp_ssl_scache_del)(evhtp_t * htp, evhtp_ssl_data_t * sid, int sid_len);
+typedef evhtp_ssl_sess_t * (* evhtp_ssl_scache_get)(evhtp_connection_t * connection, evhtp_ssl_data_t * sid, int sid_len);
+
 typedef void * (* evhtp_ssl_scache_init)(evhtp_t *);
 #endif
 
-#define EVHTP_VERSION           "1.2.14"
+#define EVHTP_VERSION           "1.2.15"
 #define EVHTP_VERSION_MAJOR     1
 #define EVHTP_VERSION_MINOR     2
-#define EVHTP_VERSION_PATCH     14
+#define EVHTP_VERSION_PATCH     15
 
 #define evhtp_headers_iterator  evhtp_kvs_iterator
 
@@ -395,8 +401,8 @@
     evhtp_connection_t * conn;          /**< the associated connection */
     evhtp_hooks_t      * hooks;         /**< request specific hooks */
     evhtp_uri_t        * uri;           /**< request URI information */
-    evbuf_t            * buffer_in;     /**< buffer containing data from client */
-    evbuf_t            * buffer_out;    /**< buffer containing data to client */
+    struct evbuffer    * buffer_in;     /**< buffer containing data from client */
+    struct evbuffer    * buffer_out;    /**< buffer containing data to client */
     evhtp_headers_t    * headers_in;    /**< headers from client */
     evhtp_headers_t    * headers_out;   /**< headers to client */
     evhtp_proto          proto;         /**< HTTP protocol used */
@@ -765,25 +771,11 @@
  *
  * @return 0 on success, -1 on error (if hooks is NULL, it is allocated)
  */
-EVHTP_EXPORT int evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, evhtp_hook cb, void * arg)
-DEPRECATED("use evhtp_[connection|request|callback]_set_hook() instead of set_hook directly");
-
 EVHTP_EXPORT int evhtp_connection_set_hook(evhtp_connection_t * c, evhtp_hook_type type, evhtp_hook cb, void * arg);
 EVHTP_EXPORT int evhtp_request_set_hook(evhtp_request_t * r, evhtp_hook_type type, evhtp_hook cb, void * arg);
 EVHTP_EXPORT int evhtp_callback_set_hook(evhtp_callback_t * cb, evhtp_hook_type type, evhtp_hook hookcb, void * arg);
 
 /**
- * @brief remove a specific hook from being called.
- *
- * @param hooks
- * @param type
- *
- * @return
- */
-EVHTP_EXPORT int evhtp_unset_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type);
-
-
-/**
  * @brief removes all hooks.
  *
  * @param hooks
@@ -887,7 +879,7 @@
  * but for the weak of heart.
  */
 EVHTP_EXPORT void evhtp_send_reply_start(evhtp_request_t * request, evhtp_res code);
-EVHTP_EXPORT void evhtp_send_reply_body(evhtp_request_t * request, evbuf_t * buf);
+EVHTP_EXPORT void evhtp_send_reply_body(evhtp_request_t * request, struct evbuffer * buf);
 EVHTP_EXPORT void evhtp_send_reply_end(evhtp_request_t * request);
 
 /**
@@ -914,7 +906,7 @@
  * @param request
  * @param buf
  */
-EVHTP_EXPORT void evhtp_send_reply_chunk(evhtp_request_t * request, evbuf_t * buf);
+EVHTP_EXPORT void evhtp_send_reply_chunk(evhtp_request_t * request, struct evbuffer * buf);
 
 /**
  * @brief call when all chunks have been sent and you wish to send the last
@@ -996,6 +988,20 @@
  */
 EVHTP_EXPORT int evhtp_add_alias(evhtp_t * evhtp, const char * name);
 
+
+/**
+ * @brief set a variable number of aliases in one call
+ * @reference evhtp_add_alias
+ * @note last argument must be NULL terminated
+ *
+ * @param evhtp
+ * @param name
+ * @param ...
+ *
+ * @return 0 on success, -1 on error
+ */
+EVHTP_EXPORT int evhtp_add_aliases(evhtp_t * evhtp, const char * name, ...);
+
 /**
  * @brief Allocates a new key/value structure.
  *
diff --git a/parser.c b/parser.c
index f8dfeb3..cda246f 100644
--- a/parser.c
+++ b/parser.c
@@ -1,12 +1,6 @@
-#include <stdio.h>
-#include <time.h>
 #include <stdlib.h>
 #include <stddef.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
 #include <ctype.h>
-#include <unistd.h>
 
 #include "internal.h"
 #include "evhtp/parser.h"
diff --git a/thread.c b/thread.c
index 8f03832..7659cee 100644
--- a/thread.c
+++ b/thread.c
@@ -1,15 +1,9 @@
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
 #include <stdint.h>
-#include <inttypes.h>
 #include <limits.h>
-#include <errno.h>
-#include <fcntl.h>
 #ifndef WIN32
-#include <sys/syscall.h>
-#include <sys/ioctl.h>
 #include <sys/queue.h>
 #endif