Merge branch 'release/0.4.12'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f862b8b..4b7b2ac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 set(PROJECT_MAJOR_VERSION 0)
 set(PROJECT_MINOR_VERSION 4)
-set(PROJECT_PATCH_VERSION 7)
+set(PROJECT_PATCH_VERSION 12)
 
 set (PROJECT_VERSION ${PROJECT_MAJOR_VERSION}.${PROJECT_MINOR_VERSION}.${PROJECT_PATCH_VERSION})
 set (CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules)
diff --git a/ChangeLog b/ChangeLog
index bba65f9..cd36ee3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,9 +1,20 @@
-v0.4.11
+v0.4.12
+ o Added #ifndef EVHTP_DISABLE_EVTHR flags for compilation withotu threading support (d5bcc33 Thibaut Le Guilly)
+ o Modify evthr_lock() macro previous patch for less ifdefs. (c800fe9 Mark Ellzey)
+ o Took out more disable thread ifdefs. (b5de21e Mark Ellzey)
+ o Remove use of bev_flush for evhtp_send_reply_end (9f2f31f Mark Ellzey)
+ o Modify evthr_lock() macro previous patch for less ifdefs. (aa24e6a Mark Ellzey)
+ o Took out more disable thread ifdefs. (accbe88 Mark Ellzey)
+ o Bugfixes, additions, cleanup, see full commit msg. (e6155d8 Mark Ellzey)
+ o Added evhtp_set_bev_flags() (a342903 Mark Ellzey)
+
+v0.4.10
  o Add compile time EVHTP_DISABLE_REGEX option. (eab0d0f Andy Hochhaus)
  o Use evbuffer_add in lieu of add_reference for short writes. (2df5fbd Joe Nardone)
  o Added take_ownership functionality which frees resources but gives the underlying bufferevent to the caller. (75050f8 Mark Ellzey)
+ o Release v0.4.11 (5d6339f Mark Ellzey)
 
-v0.4.10
+v0.4.9
  o Fixed memleak with evthr_free() (10ad15a Mark Ellzey)
  o Correct SSL_Shutdown() usage. (f5f97ee Mark Ellzey)
  o Added total bytes read function in htparser. (4a9eefb Mark Ellzey)
@@ -11,12 +22,13 @@
  o Don't add aux headers if content-type is multipart. (6be91ca Mark Ellzey)
  o Removed silly compile-time flags for OSX (0dd14a9 Mark Ellzey)
  o Ignore deprecated ssl warnings on OSX until further notice. (0aa4fb6 Mark Ellzey)
+ o Prep release v0.4.10 (60d0f25 Mark Ellzey)
 
-v0.4.9
+v0.4.8
  o Fix for non-system strndup. (d7486b4 Mark Ellzey)
  o Prepping release v0.4.9 (4ef6362 Mark Ellzey)
 
-v0.4.8
+v0.4.7
  o Place _evhtp_run_pre_accept() into _evhtp_connection_accept() (e45adbd Mark Ellzey)
  o pre_accept_cb argument changes. (c2fbb86 Mark Ellzey)
  o Fixed test.c for pre_accept changes. (671a911 Mark Ellzey)
@@ -30,7 +42,7 @@
  o Remove debug msg. (9a41148 Mark Ellzey)
  o Prepping release v0.4.8 (c140e2f Mark Ellzey)
 
-v0.4.7
+v0.4.6
  o Fix to be able to set a verification "mode" to the SSL_CTX_set_verify() function without having to set a custom (*verify_callback). (f3c3f37 Oscar Koeroo)
  o Allow SSL_CTX_set_timeout value to be passed in via config. (4f775bd Stephen Cox)
  o Fixed issue with _evhtp_request_parser_path with no matched callbacks where the end offset was never being set. (Reported by snnn119@gmail.com) (0d20de9 Mark Ellzey)
@@ -38,7 +50,7 @@
  o set request status to PAUSE if evhtp_request_pause() is called manually. (4d64111 Mark Ellzey)
  o Prepping release v0.4.7 (12d7cc4 Mark Ellzey)
 
-v0.4.6
+v0.4.5
  o Don't treat EOF eventcb flags for ssl enabled connections as errors. (49c98b1 Mark Ellzey)
  o Add HTTP/1.1 chunked encoding interface. (69a29d3 Andy Hochhaus)
  o Added test-case for chunking API usage. (939517a Mark Ellzey)
@@ -46,24 +58,7 @@
  o Added SSL_CTX_set_timeout() for openssl >= 1.0 (e6fa029 Mark Ellzey)
  o Prepping release 0.4.6 (81c493d Mark Ellzey)
 
-v0.4.5
- o Fixing size_t printf format issues. (c75bc5b Mark Ellzey)
- o Added support for the -C option in the test.c The internals were there, it just covers the getops. (e3636d5 Oscar Koeroo)
- o The struct evhtp_connection_s has a member ssl_ctx of type evhtp_ssl_t (a typedef of an SSL*) which by name is confusing with respect to the evhtp_ssl_ctx_t (a typedef of an SSL_CTX*). The member of stru
- o Initial markdown-based API documentation. (c16b551 Mark Ellzey)
- o Documentation updates. (f097558 Mark Ellzey)
- o Documentation updates (98c8ff0 Mark Ellzey)
- o Added evhtp_unescape_string() to unescape query type strings. (d75904f Mark Ellzey)
- o added on_headers_start hook (before header parsing, post requestline parsing). (7076b8e Mark Ellzey)
- o Added htparser_set_(major|minor). fixed edgecase where major/minor is not yet set. (137aa19 Mark Ellzey)
- o Fix C++/clang++ build. (af2a0dd Andy Hochhaus)
- o Added #ifndef _GNU_SOURCE before setting it again. (f8a2308 Mark Ellzey)
- o Changes to DISABLE to EVHTP_DISABLE, also fixed enum hook missing from last merge. (0ab23de Mark Ellzey)
- o inline enum's should not be static. (5efd199 Mark Ellzey)
- o Set libevent as a required dependency (d08f4fd Mark Ellzey)
- o Prepping release v0.4.5 (a3731d7 Mark Ellzey)
-
-v0.4.4
+v0.4.3
  o Added api docs (57370c1 Mark Ellzey)
  o Added various accessor functions, see full commitlog (16d3fdc Mark Ellzey)
  o Added evhtp_request_get_connection() (db1f023 Mark Ellzey)
@@ -83,8 +78,23 @@
  o Removed README and added changelog generator. (219f2eb Mark Ellzey)
  o Prepping release v0.4.4 (d335798 Mark Ellzey)
  o ChangeLog for v0.4.4 (c5c6d19 Mark Ellzey)
+ o Fixing size_t printf format issues. (c75bc5b Mark Ellzey)
+ o Added support for the -C option in the test.c The internals were there, it just covers the getops. (e3636d5 Oscar Koeroo)
+ o The struct evhtp_connection_s has a member ssl_ctx of type evhtp_ssl_t (a typedef of an SSL*) which by name is confusing with respect to the evhtp_ssl_ctx_t (a typedef of an SSL_CTX*). The member of struct evhtp_connection_s is now rename from ssl_ctx to ssl. (ca42b4d Oscar Koeroo)
+ o Initial markdown-based API documentation. (c16b551 Mark Ellzey)
+ o Documentation updates. (f097558 Mark Ellzey)
+ o Documentation updates (98c8ff0 Mark Ellzey)
+ o Added evhtp_unescape_string() to unescape query type strings. (d75904f Mark Ellzey)
+ o added on_headers_start hook (before header parsing, post requestline parsing). (7076b8e Mark Ellzey)
+ o Added htparser_set_(major|minor). fixed edgecase where major/minor is not yet set. (137aa19 Mark Ellzey)
+ o Fix C++/clang++ build. (af2a0dd Andy Hochhaus)
+ o Added #ifndef _GNU_SOURCE before setting it again. (f8a2308 Mark Ellzey)
+ o Changes to DISABLE to EVHTP_DISABLE, also fixed enum hook missing from last merge. (0ab23de Mark Ellzey)
+ o inline enum's should not be static. (5efd199 Mark Ellzey)
+ o Set libevent as a required dependency (d08f4fd Mark Ellzey)
+ o Prepping release v0.4.5 (a3731d7 Mark Ellzey)
 
-v0.4.3
+v0.4.2
  o Moving libhtparse to just htparse (bf2e43a Mark Ellzey)
  o Thread-safe add/remove callback additions. (d916366 Mark Ellzey)
  o strn* compat functions set to static (cab9503 Mark Ellzey)
@@ -94,7 +104,7 @@
  o Added IPv6 listener support. (c1482a2 Mark Ellzey)
  o Prepping release v0.4.3 (952baa9 Mark Ellzey)
 
-v0.4.2
+v0.4.1
  o Removing tabs from ChangeLog (3f6f220 Mark Ellzey)
  o Add checks for sys/tree.h and compat when missing (40c87e5 Jason L. Shiffer)
  o Fix strdup build warnings/errors on OSX (84e17c1 Jason L. Shiffer)
@@ -112,7 +122,7 @@
  o Moved ./libhtparse to ./htparse (44c77d3 Mark Ellzey)
  o Prepping release v0.4.2 (815b023 Mark Ellzey)
 
-v0.4.1
+v0.4.0
  o Deal with 100 return status with responses correctly (bb86d09 Mark Ellzey)
  o more 100 fixes (3ef168a Mark Ellzey)
  o hert pup (a637672 Mark Ellzey)
@@ -145,3 +155,153 @@
  o Include RT and DL if avail when linking test. SSL needs them. (29e35fb Mark Ellzey)
  o default cb now returns 404 (fd4e3cb Mark Ellzey)
  o Prepping release v0.4.1 (246a5da Mark Ellzey)
+
+v0.3.7
+ o linking ChangeLog to README (4da3a26 Mark Ellzey)
+ o updated htparse (1706b82 Mark Ellzey)
+ o removing cruft (ac3b4f4 Mark Ellzey)
+ o killkillkill (45d0dfa Mark Ellzey)
+ o More logical structure (3ee2531 Mark Ellzey)
+ o cleanup (f7e3af2 Mark Ellzey)
+ o blerp (2833315 Mark Ellzey)
+ o getting better (6daf3ca Mark Ellzey)
+ o Request pipeline now functional. (99554e3 Mark Ellzey)
+ o derpityderp (1bd1b4e Mark Ellzey)
+ o cruft (45e5a33 Mark Ellzey)
+ o Fixed an issue with the body parser callback (f130965 Mark Ellzey)
+ o Major cleanup / re-factor (0752eef Mark Ellzey)
+ o fixups (0cc0980 Mark Ellzey)
+ o Added some more documentation (56c08d6 Mark Ellzey)
+ o documentation updates (3715c81 Mark Ellzey)
+ o Added better functionality, more docs - see full commit log (8a8e555 Mark Ellzey)
+ o Added Basic reply functions (b5434de Mark Ellzey)
+ o More updates - perf updates - bug fixes (0b050cc Mark Ellzey)
+ o updating ssl and test.c (37191f9 Mark Ellzey)
+ o bugfix in kv_add (3a18380 Mark Ellzey)
+ o pausing / fixes / request and connection fini hooks (3e98351 Mark Ellzey)
+ o fixed all the pause issues.. (658650e Mark Ellzey)
+ o threading fixes (97f18c5 Mark Ellzey)
+ o some optimizations (6a747c6 Mark Ellzey)
+ o blerp (f04c39a Mark Ellzey)
+ o Added CA Path option for ssl_cfg. (Thanks Oscar Koeroo) (8ace875 Mark Ellzey)
+ o Added x509_verify_cb, max_verify_depth, verify_peer and store_flags option to the struct evhtp_ssl_cfg_s. And also added HTTP return code 418 (e92e882 Oscar Koeroo)
+ o Adding dummy callbacks and values to the test.c program. (e703100 Oscar Koeroo)
+ o max_verify_depth -> verify_depth (556d722 Mark Ellzey)
+ o OSX Compat / fixes (e844f9a Mark Ellzey)
+ o cleanup (f7f25ef Mark Ellzey)
+ o docs, cleanup (022d424 Mark Ellzey)
+ o created verify and verify depth callbacks types (instead of using void *) (8a2f6d8 Mark Ellzey)
+ o cleanup (aee4707 Mark Ellzey)
+ o HTTP response parsing in libhtparser (6855a08 Mark Ellzey)
+ o fix with evthr (d4a63d8 Mark Ellzey)
+ o Added htparser_get_status (dae487a Mark Ellzey)
+ o fixes (7c6f5ab Mark Ellzey)
+ o send_reply start/body/end (33bfade Mark Ellzey)
+ o thread initialization functionality (362f902 Mark Ellzey)
+ o Content-Length duplicate header fix (8f74408 Mark Ellzey)
+ o Added chunk_complete and chunks_complete callback hooks (f391855 Mark Ellzey)
+ o Added some documentation (7853017 Mark Ellzey)
+ o fixed issue with bufferevent SSL events (a34b413 Mark Ellzey)
+ o on_new_chunk bugfix (de39114 Mark Ellzey)
+ o Additions for HTTP/1.1 / other additions / fixes (f865ff4 Mark Ellzey)
+ o Fixed conditional bug (c5c4aa4 Mark Ellzey)
+ o fixed some bugs dealing with parsing and schemes (258cbec Mark Ellzey)
+ o SSL shutdown / bugfixes / see commit log (c850692 Mark Ellzey)
+ o Making static (add8058 Mark Ellzey)
+ o linking ChangeLog to README (61866b8 Mark Ellzey)
+ o fixes, docs, features: (see full commit log) (01e61e2 Mark Ellzey)
+ o SSL updates (see full commit log) (b3cfb24 Mark Ellzey)
+ o bugfix in kv_add (ed5699e Mark Ellzey)
+ o Hook macros, fixes, additions (see full commit log) (ef3fee3 Mark Ellzey)
+ o Added CA Path option for ssl_cfg. (Thanks Oscar Koeroo) (7b79640 Mark Ellzey)
+ o SSL verification configuration options (62c07ff Oscar Koeroo)
+ o OSX Compatability fixes (955133d Mark Ellzey)
+ o Created verify and verify depth callbacks types (instead of using void *) (a2a0f09 Mark Ellzey)
+ o HTTP response parsing in libhtparser (29ac2e7 Mark Ellzey)
+ o evthr bugfix in evthr_new() args (17aede7 Mark Ellzey)
+ o Added htparser_get_status to libhtparse (7b16bd1 Mark Ellzey)
+ o Added streaming reply functionality (f0a8ed3 Mark Ellzey)
+ o thread initialization functionality (78a6863 Mark Ellzey)
+ o Content-Length duplicate header fix (b7d283f Mark Ellzey)
+ o Additional libevhtparse chunk-specific hooks and documentation. (c0c6e59 Mark Ellzey)
+ o fixed issue with bufferevent SSL events (fbe3c8b Mark Ellzey)
+ o libhtparse on_new_chunk bugfix (d352dd1 Mark Ellzey)
+ o Additions for HTTP/1.1 / other additions / fixes (c2883eb Mark Ellzey)
+ o Fixed conditional bug for chunked responses (b159c32 Mark Ellzey)
+ o libhtparse fixes when dealing with requests with schema data. (efdc171 Mark Ellzey)
+ o SSL shutdown / bugfixes / see commit log (482d0bd Mark Ellzey)
+ o Modified so that libevhtp creates a static library instead of shared. (ba170f1 Mark Ellzey)
+ o Rebase fix for htparser_init() (ce446b0 Mark Ellzey)
+ o Updating for release 0.4.0 (872c243 Mark Ellzey)
+
+v0.3.6
+ o Matched callback hooking (5b385a6 Mark Ellzey)
+ o Drop connection with invalid requests. (e4cd611 Mark Ellzey)
+ o added some more requests accessors (d9cf7d5 Mark Ellzey)
+ o added a finished hook (c04e61b Mark Ellzey)
+ o added evhtp_request_set_cbargs() (28a22dd Mark Ellzey)
+ o Bunch of stuff - see full commit message. (ae49ecf Mark Ellzey)
+ o If compiling as debug, http-parser will be pre-processed then compiled. (easier to debug the shitty and unnecessary macro-based function prototypes). (c378db3 Mark Ellzey)
+ o Mods to pass -Wextra (2b44c46 Mark Ellzey)
+ o More -Wextra mods (f2d6c9e Mark Ellzey)
+ o a bit broken (17d1572 Mark Ellzey)
+ o adding gitignore (b8eba44 Mark Ellzey)
+ o Removing dep for http_parser over to my libhtparse codebase (11b484e Mark Ellzey)
+ o Adding libhtparse.... (dd61c20 Mark Ellzey)
+ o Prepping release v0.3.7 (64db298 Mark Ellzey)
+
+v0.3.5
+ o Added various SSL information accessors (8db938e Mark Ellzey)
+ o evhtp_hdr functions / default 404 cb / fixes (37dbe4f Mark Ellzey)
+ o Prepping the removal of submodules (354e71d Mark Ellzey)
+ o No more submodules (1e0ec98 Mark Ellzey)
+ o updating release_prep (5a5e495 Mark Ellzey)
+ o Prepping release v0.3.6 (e582c7c Mark Ellzey)
+ o Updated ChangeLog (03a8536 Mark Ellzey)
+
+v0.3.4
+ o Added evhtp_set_regex_cb for matching URI with a regex. (99e8e64 Mark Ellzey)
+ o Adding oniguruma submodule (30adea5 Mark Ellzey)
+ o .. (2161264 Mark Ellzey)
+ o Switched over to oniguruma for regex (b80820b Mark Ellzey)
+ o updates (f2bb622 Mark Ellzey)
+ o httparser updates (1befd5c Mark Ellzey)
+ o make install rules, cleanup of dependencies (68cb269 Mark Ellzey)
+ o cmake onig test compile (75ede66 Mark Ellzey)
+ o Added find_callbacks_woffsets (0174055 Mark Ellzey)
+ o evhtp_request_t is now private. (c2cadcd Mark Ellzey)
+ o added various request accessors (6964387 Mark Ellzey)
+ o Even more evhtp_request_t accessors. (8c45457 Mark Ellzey)
+ o Better error / response handling. (6e869fc Mark Ellzey)
+ o Prepping release v0.3.5 (6a84efe Mark Ellzey)
+
+v0.3.3
+ o SSL and other various changes (see commit log) (76dc58d Mark Ellzey)
+ o Added ChangeLog (33bab50 Mark Ellzey)
+ o Updated version information. (df80701 Mark Ellzey)
+ o Added contrib section with misc patches. (0b2bb36 Mark Ellzey)
+ o And place it in the right directory :) (e337cb7 Mark Ellzey)
+ o Fixing up problems with the conflict resolution (6a606a4 Mark Ellzey)
+
+v0.3.2
+ o initial SSL support, junk is brizzoke (fbbc2fa Mark Ellzey)
+ o cleanup (57e309c Mark Ellzey)
+ o not working as intended, REBASE THIS JUNK (f645813 Mark Ellzey)
+ o SSL session caching. (590e226 Mark Ellzey)
+ o Adding a builtin cache (0e1d01e Mark Ellzey)
+ o Added SSL thread-safe functionality. (a9db78b Mark Ellzey)
+ o cleanup (6f71526 Mark Ellzey)
+ o Properly expire cache entries. (65f017b Mark Ellzey)
+ o Cleanup (edd1b44 Mark Ellzey)
+ o Prepping v0.3.3 (67307f1 Mark Ellzey)
+
+v0.3.1
+ o Modifying to use bufferevents (0c4b22e Mark Ellzey)
+ o Converting back to bevents after perf issue solved (6771104 Mark Ellzey)
+ o Prepping release 0.3.2 (758bb16 Mark Ellzey)
+
+v0.3.0
+ o Optional evthr support (5392bc9 Mark Ellzey)
+ o Prep v0.3.1 (8a6c836 Mark Ellzey)
+ o Prep release 0.3.1 (33f1a82 Mark Ellzey)
+
diff --git a/evhtp.c b/evhtp.c
index 65947bd..1aedc1b 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -68,6 +68,7 @@
         }                                                                                     \
 } while (0);
 
+#ifndef EVHTP_DISABLE_EVTHR
 #define _evhtp_lock(h)                             do { \
         if (h->lock) {                                  \
             pthread_mutex_lock(h->lock);                \
@@ -79,7 +80,10 @@
             pthread_mutex_unlock(h->lock);              \
         }                                               \
 } while (0)
-
+#else
+#define _evhtp_lock(h)                             do {} while (0)
+#define _evhtp_unlock(h)                           do {} while (0)
+#endif
 
 static int scode_tree_initialized = 0;
 
@@ -541,6 +545,7 @@
 
     return NULL;
 }
+
 #endif
 
 /**
@@ -999,12 +1004,6 @@
         return -1;
     }
 
-#if 0
-    if (!evhtp_header_find(c->request->headers_in, "Content-Length")) {
-        return 0;
-    }
-#endif
-
     if (!(expect_val = evhtp_header_find(c->request->headers_in, "Expect"))) {
         return 0;
     }
@@ -1271,6 +1270,12 @@
     }
 
     c->error = 1;
+
+    if (c->request && c->request->hooks && c->request->hooks->on_error) {
+        (*c->request->hooks->on_error)(c->request, events,
+                                       c->request->hooks->on_error_arg);
+    }
+
     return evhtp_connection_free((evhtp_connection_t *)arg);
 }
 
@@ -1304,16 +1309,18 @@
     if (connection->htp->ssl_ctx != NULL) {
         connection->ssl = SSL_new(connection->htp->ssl_ctx);
         connection->bev = bufferevent_openssl_socket_new(evbase,
-                                                         connection->sock, connection->ssl,
+                                                         connection->sock,
+                                                         connection->ssl,
                                                          BUFFEREVENT_SSL_ACCEPTING,
-                                                         BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+                                                         connection->htp->bev_flags);
         SSL_set_app_data(connection->ssl, connection);
         goto end;
     }
 #endif
 
-    connection->bev = bufferevent_socket_new(evbase, connection->sock,
-                                             BEV_OPT_CLOSE_ON_FREE | BEV_OPT_DEFER_CALLBACKS);
+    connection->bev = bufferevent_socket_new(evbase,
+                                             connection->sock,
+                                             connection->htp->bev_flags);
 #ifndef DISABLE_SSL
 end:
 #endif
@@ -1330,8 +1337,7 @@
     bufferevent_setcb(connection->bev,
                       _evhtp_connection_readcb,
                       _evhtp_connection_writecb,
-                      _evhtp_connection_eventcb,
-                      connection);
+                      _evhtp_connection_eventcb, connection);
 
     return 0;
 }     /* _evhtp_connection_accept */
@@ -1394,6 +1400,7 @@
     return 0;
 }
 
+#ifndef EVHTP_DISABLE_EVTHR
 static void
 _evhtp_run_in_thread(evthr_t * thr, void * arg, void * shared) {
     evhtp_t            * htp        = shared;
@@ -1413,6 +1420,8 @@
     }
 }
 
+#endif
+
 static void
 _evhtp_accept_cb(evserv_t * serv, int fd, struct sockaddr * s, int sl, void * arg) {
     evhtp_t            * htp = arg;
@@ -1425,11 +1434,15 @@
     connection->saddr = malloc(sl);
     memcpy(connection->saddr, s, sl);
 
+#ifndef EVHTP_DISABLE_EVTHR
     if (htp->thr_pool != NULL) {
-        evthr_pool_defer(htp->thr_pool, _evhtp_run_in_thread, connection);
+        if (evthr_pool_defer(htp->thr_pool, _evhtp_run_in_thread, connection) != EVTHR_RES_OK) {
+            evutil_closesocket(connection->sock);
+            return evhtp_connection_free(connection);
+        }
         return;
     }
-
+#endif
     connection->evbase = htp->evbase;
 
     if (_evhtp_connection_accept(htp->evbase, connection) < 0) {
@@ -1442,6 +1455,8 @@
 }
 
 #ifndef DISABLE_SSL
+
+#ifndef EVHTP_DISABLE_EVTHR
 static unsigned long
 _evhtp_ssl_get_thread_id(void) {
     return (unsigned long)pthread_self();
@@ -1458,6 +1473,7 @@
     }
 }
 
+#endif
 static void
 _evhtp_ssl_delete_scache_ent(evhtp_ssl_ctx_t * ctx, evhtp_ssl_sess_t * sess) {
     evhtp_t         * htp;
@@ -2108,7 +2124,9 @@
 void
 evhtp_send_reply_end(evhtp_request_t * request) {
     request->finished = 1;
-    bufferevent_flush(evhtp_request_get_bev(request), EV_WRITE, BEV_FLUSH);
+
+    return _evhtp_connection_writecb(evhtp_request_get_bev(request),
+                                     evhtp_request_get_connection(request));
 }
 
 void
@@ -2230,6 +2248,7 @@
         evbuffer_add(bufferevent_get_output(evhtp_request_get_bev(request)),
                      "0\r\n\r\n", 5);
     }
+
     evhtp_send_reply_end(request);
 }
 
@@ -2593,10 +2612,10 @@
     }
 
     _evhtp_unlock(htp);
-
     return hcb;
 }
 
+#ifndef EVHTP_DISABLE_EVTHR
 static void
 _evhtp_thread_init(evthr_t * thr, void * arg) {
     evhtp_t * htp = (evhtp_t *)arg;
@@ -2623,6 +2642,9 @@
     return 0;
 }
 
+#endif
+
+#ifndef EVHTP_DISABLE_EVTHR
 int
 evhtp_use_callback_locks(evhtp_t * htp) {
     if (htp == NULL) {
@@ -2636,6 +2658,8 @@
     return pthread_mutex_init(htp->lock, NULL);
 }
 
+#endif
+
 #ifndef EVHTP_DISABLE_REGEX
 evhtp_callback_t *
 evhtp_set_regex_cb(evhtp_t * htp, const char * pattern, evhtp_callback_cb cb, void * arg) {
@@ -2664,6 +2688,7 @@
     _evhtp_unlock(htp);
     return hcb;
 }
+
 #endif
 
 void
@@ -2685,6 +2710,7 @@
 }
 
 #ifndef DISABLE_SSL
+#ifndef EVHTP_DISABLE_EVTHR
 int
 evhtp_ssl_use_threads(void) {
     int i;
@@ -2708,6 +2734,8 @@
     return 0;
 }
 
+#endif
+
 int
 evhtp_ssl_init(evhtp_t * htp, evhtp_ssl_cfg_t * cfg) {
     long                  cache_mode;
@@ -2732,6 +2760,7 @@
 
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
     SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
+    /* SSL_CTX_set_options(htp->ssl_ctx, SSL_MODE_AUTO_RETRY); */
     SSL_CTX_set_timeout(htp->ssl_ctx, cfg->ssl_ctx_timeout);
 #endif
 
@@ -2892,7 +2921,7 @@
 #else
 #ifndef DISABLE_SSL
         if (connection->ssl != NULL) {
-            SSL_set_shutdown(connection->ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
+            SSL_set_shutdown(connection->ssl, SSL_RECEIVED_SHUTDOWN);
             SSL_shutdown(connection->ssl);
         }
 #endif
@@ -2903,11 +2932,11 @@
     if (connection->hooks) {
         free(connection->hooks);
     }
-
+#ifndef EVHTP_DISABLE_EVTHR
     if (connection->thread) {
         evthr_dec_backlog(connection->thread);
     }
-
+#endif
     if (connection->saddr) {
         free(connection->saddr);
     }
@@ -2928,6 +2957,11 @@
     }
 }
 
+void
+evhtp_set_bev_flags(evhtp_t * htp, int flags) {
+    htp->bev_flags = flags;
+}
+
 evhtp_t *
 evhtp_new(evbase_t * evbase, void * arg) {
     evhtp_t * htp;
@@ -2945,6 +2979,7 @@
     htp->arg         = arg;
     htp->evbase      = evbase;
     htp->server_name = "evhtp, sucka";
+    htp->bev_flags   = BEV_OPT_CLOSE_ON_FREE;
 
     evhtp_set_gencb(htp, _evhtp_default_request_cb, (void *)htp);
 
diff --git a/evhtp.h b/evhtp.h
index 7bf0d45..e98da59 100644
--- a/evhtp.h
+++ b/evhtp.h
@@ -151,10 +151,10 @@
 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          "0.4.11"
+#define EVHTP_VERSION          "0.4.12"
 #define EVHTP_VERSION_MAJOR    0
 #define EVHTP_VERSION_MINOR    4
-#define EVHTP_VERSION_PATCH    11
+#define EVHTP_VERSION_PATCH    12
 
 #define evhtp_headers_iterator evhtp_kvs_iterator
 
@@ -232,16 +232,19 @@
  * @brief main structure containing all configuration information
  */
 struct evhtp_s {
-    evbase_t * evbase;            /**< the initialized event_base */
-    evserv_t * server;            /**< the libevent listener struct */
-    char     * server_name;       /**< the name included in Host: responses */
-    void     * arg;               /**< user-defined evhtp_t specific arguments */
+    evbase_t * evbase;         /**< the initialized event_base */
+    evserv_t * server;         /**< the libevent listener struct */
+    char     * server_name;    /**< the name included in Host: responses */
+    void     * arg;            /**< user-defined evhtp_t specific arguments */
+    int        bev_flags;      /**< bufferevent flags to use on bufferevent_*_socket_new() */
 
-    evhtp_ssl_ctx_t * ssl_ctx;    /**< if ssl enabled, this is the servers CTX */
+    evhtp_ssl_ctx_t * ssl_ctx; /**< if ssl enabled, this is the servers CTX */
     evhtp_ssl_cfg_t * ssl_cfg;
 
-    evthr_pool_t      * thr_pool; /**< connection threadpool */
-    pthread_mutex_t   * lock;     /**< parent lock for add/del cbs in threads */
+    evthr_pool_t * thr_pool;   /**< connection threadpool */
+#ifndef EVHTP_DISABLE_EVTHR
+    pthread_mutex_t * lock;    /**< parent lock for add/del cbs in threads */
+#endif
     evhtp_callbacks_t * callbacks;
     evhtp_defaults_t    defaults;
 
@@ -262,10 +265,10 @@
 struct evhtp_callbacks_s {
     evhtp_callback_t ** callbacks;       /**< hash of path callbacks */
 #ifndef EVHTP_DISABLE_REGEX
-    evhtp_callback_t  * regex_callbacks; /**< list of regex callbacks */
+    evhtp_callback_t * regex_callbacks;  /**< list of regex callbacks */
 #endif
-    unsigned int        count;           /**< number of callbacks defined */
-    unsigned int        buckets;         /**< buckets allocated for hash */
+    unsigned int count;                  /**< number of callbacks defined */
+    unsigned int buckets;                /**< buckets allocated for hash */
 };
 
 /**
@@ -290,7 +293,7 @@
     evhtp_hooks_t     * hooks;           /**< per-callback hooks */
 
     union {
-        char    * path;
+        char * path;
 #ifndef EVHTP_DISABLE_REGEX
         regex_t * regex;
 #endif
@@ -464,6 +467,7 @@
 evhtp_t * evhtp_new(evbase_t * evbase, void * arg);
 
 void      evhtp_set_timeouts(evhtp_t * htp, struct timeval * r, 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);
 
@@ -557,7 +561,28 @@
  *
  * @return 0 on success, -1 on error (if hooks is NULL, it is allocated)
  */
-int  evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, void * cb, void * arg);
+int evhtp_set_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type, void * cb, void * arg);
+
+
+/**
+ * @brief remove a specific hook from being called.
+ *
+ * @param hooks
+ * @param type
+ *
+ * @return
+ */
+int evhtp_unset_hook(evhtp_hooks_t ** hooks, evhtp_hook_type type);
+
+
+/**
+ * @brief removes all hooks.
+ *
+ * @param hooks
+ *
+ * @return
+ */
+int  evhtp_unset_all_hooks(evhtp_hooks_t ** hooks);
 
 int  evhtp_bind_socket(evhtp_t * htp, const char * addr, uint16_t port, int backlog);
 int  evhtp_bind_sockaddr(evhtp_t * htp, struct sockaddr *, size_t sin_len, int backlog);
diff --git a/evthr/evthr.c b/evthr/evthr.c
index 671f3c6..4f7bb36 100644
--- a/evthr/evthr.c
+++ b/evthr/evthr.c
@@ -261,6 +261,9 @@
         return NULL;
     }
 
+    evutil_make_socket_nonblocking(fds[0]);
+    evutil_make_socket_nonblocking(fds[1]);
+
     if (!(thread = calloc(sizeof(evthr_t), sizeof(char)))) {
         return NULL;
     }
@@ -289,9 +292,6 @@
         return NULL;
     }
 
-    fcntl(thread->rdr, F_SETFL, O_NONBLOCK);
-    fcntl(thread->wdr, F_SETFL, O_NONBLOCK);
-
     return thread;
 } /* evthr_new */
 
diff --git a/htparse/htparse.c b/htparse/htparse.c
index 1933278..68aec46 100644
--- a/htparse/htparse.c
+++ b/htparse/htparse.c
@@ -1129,11 +1129,14 @@
             case s_status:
                 /* http response status code */
                 if (ch == ' ') {
+		    if (p->status) {
+			p->state = s_status_text;
+		    }
                     break;
                 }
 
                 if (ch < '0' || ch > '9') {
-                    p->error = htparse_error_generic;
+                    p->error = htparse_error_status;
                     return i + 1;
                 }
 
diff --git a/htparse/htparse.h b/htparse/htparse.h
index a9e7a1d..685015a 100644
--- a/htparse/htparse.h
+++ b/htparse/htparse.h
@@ -48,6 +48,7 @@
     htparse_error_inval_chunk,
     htparse_error_inval_state,
     htparse_error_user,
+    htparse_error_status,
     htparse_error_generic
 };
 
diff --git a/test.c b/test.c
index 90a2942..d1516c8 100644
--- a/test.c
+++ b/test.c
@@ -8,7 +8,7 @@
 #include <inttypes.h>
 #include <evhtp.h>
 
-#ifndef DISABLE_EVTHR
+#ifndef EVHTP_DISABLE_EVTHR
 int      use_threads = 0;
 int      num_threads = 0;
 #endif
@@ -373,7 +373,7 @@
 const char * help   =
     "Options: \n"
     "  -h       : This help text\n"
-#ifndef DISABLE_EVTHR
+#ifndef EVHTP_DISABLE_EVTHR
     "  -t       : Run requests in a thread (default: off)\n"
     "  -n <int> : Number of threads        (default: 0 if -t is off, 4 if -t is on)\n"
 #endif
@@ -407,7 +407,7 @@
             case 'p':
                 bind_port   = atoi(optarg);
                 break;
-#ifndef DISABLE_EVTHR
+#ifndef EVHTP_DISABLE_EVTHR
             case 't':
                 use_threads = 1;
                 break;
@@ -435,7 +435,7 @@
         } /* switch */
     }
 
-#ifndef DISABLE_EVTHR
+#ifndef EVHTP_DISABLE_EVTHR
     if (use_threads && num_threads == 0) {
         num_threads = 4;
     }
@@ -533,7 +533,7 @@
         };
 
         evhtp_ssl_init(htp, &scfg);
-
+#ifndef EVHTP_DISABLE_EVTHR
         if (use_threads) {
             #define OPENSSL_THREAD_DEFINES
 #include <openssl/opensslconf.h>
@@ -543,10 +543,11 @@
             exit(-1);
 #endif
         }
+#endif
     }
 #endif
 
-#ifndef DISABLE_EVTHR
+#ifndef EVHTP_DISABLE_EVTHR
     if (use_threads) {
         evhtp_use_threads(htp, NULL, num_threads, NULL);
     }
@@ -560,6 +561,7 @@
     signal(SIGINT, sigint);
 
     event_base_loop(evbase, 0);
+
     return 0;
 } /* main */
 
diff --git a/test_basic.c b/test_basic.c
index 0272688..043b859 100644
--- a/test_basic.c
+++ b/test_basic.c
@@ -17,8 +17,10 @@
     evhtp_t  * htp    = evhtp_new(evbase, NULL);
 
     evhtp_set_cb(htp, "/test", testcb, NULL);
+#ifndef EVHTP_DISABLE_EVTHR
     evhtp_use_threads(htp, NULL, 4, NULL);
-    evhtp_bind_socket(htp, "0.0.0.0", 8080, 1024);
+#endif
+    evhtp_bind_socket(htp, "0.0.0.0", 8081, 1024);
     event_base_loop(evbase, 0);
     return 0;
 }