diff -u -r -N squid-4.0.10/acinclude/lib-checks.m4 squid-4.0.11/acinclude/lib-checks.m4
--- squid-4.0.10/acinclude/lib-checks.m4	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/acinclude/lib-checks.m4	2016-06-10 08:32:57.000000000 +1200
@@ -297,11 +297,12 @@
     ssl->init_num = 0;
     ssl->s3->wpend_ret = 0;
     ssl->s3->wpend_tot = 0;
+    SSL_CIPHER *cipher = 0;
+    assert(SSL_CIPHER_get_id(cipher));
     ])
   ],
   [
-   AC_DEFINE(SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK, 1)
-   AC_MSG_RESULT([yes])
+   AC_MSG_RESULT([possibly; to try, set SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK macro value to 1])
   ],
   [
    AC_MSG_RESULT([no])
diff -u -r -N squid-4.0.10/ChangeLog squid-4.0.11/ChangeLog
--- squid-4.0.10/ChangeLog	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/ChangeLog	2016-06-10 08:32:57.000000000 +1200
@@ -1,3 +1,20 @@
+Changes to squid-4.0.11 (09 Jun 2016):
+
+	- Bug 4517: error: comparison between signed and unsigned integer
+	- Bug 4492: chunked parser needs to accept BWS after chunk size
+	- HTTP/1.1: allow chunking the last HTTP response on a connection
+	- HTTP/1.1: unfold mime header blocks
+	- TLS: fast SNI peek
+	- TLS: check for SSL_CIPHER_get_id() support required in adjustSSL()
+	- TLS: never enable OPENSSL_HELLO_OVERWRITE_HACK automatically
+	- squidclient: improve shell-escape support in -H option
+	- Do not allow low-level debugging to hide important/critical messages
+	- Replace new/delete operators using modern C++ rules
+	- Remove ie_refresh configuration option
+	- Deprecating SMB LanMan helpers
+	- Mark refresh-waiting transactions with REFRESH
+	- ... and some code cleanup and polishing
+
 Changes to squid-4.0.10 (06 May 2016):
 
 	- Accumulate fewer unknown-size responses to avoid overwhelming disks.
diff -u -r -N squid-4.0.10/compat/os/macosx.h squid-4.0.11/compat/os/macosx.h
--- squid-4.0.10/compat/os/macosx.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/compat/os/macosx.h	2016-06-10 08:32:57.000000000 +1200
@@ -28,11 +28,6 @@
 
 #include "compat/cmsg.h"
 
-// MacOS GCC 4.0.1 and 4.2.1 supply __GNUC_GNU_INLINE__ but do not actually define  __attribute__((gnu_inline))
-#if defined(__cplusplus) && !defined(_SQUID_EXTERNNEW_)
-#define _SQUID_EXTERNNEW_ extern inline
-#endif
-
 #endif /* _SQUID_APPLE_ */
 #endif /* SQUID_OS_MACOSX_H */
 
diff -u -r -N squid-4.0.10/compat/os/sgi.h squid-4.0.11/compat/os/sgi.h
--- squid-4.0.10/compat/os/sgi.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/compat/os/sgi.h	2016-06-10 08:32:57.000000000 +1200
@@ -25,15 +25,6 @@
 #define _ABI_SOURCE
 #endif /* USE_ASYNC_IO */
 
-#if defined(__cplusplus) && !defined(_SQUID_EXTERNNEW_) && !defined(_GNUC_)
-/*
- * The gcc compiler treats extern inline functions as being extern,
- * while the SGI MIPSpro compilers treat them as inline. To get equivalent
- * behavior, remove the inline keyword.
- */
-#define _SQUID_EXTERNNEW_ extern
-#endif
-
 #endif /* _SQUID_SGI_ */
 #endif /* SQUID_OS_SGI_H */
 
diff -u -r -N squid-4.0.10/compat/os/solaris.h squid-4.0.11/compat/os/solaris.h
--- squid-4.0.10/compat/os/solaris.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/compat/os/solaris.h	2016-06-10 08:32:57.000000000 +1200
@@ -59,13 +59,6 @@
 #endif
 
 /*
- * SunPro CC handles extern inline as inline, PLUS extern symbols.
- */
-#if !defined(_SQUID_EXTERNNEW_) && defined(__SUNPRO_CC)
-#define _SQUID_EXTERNNEW_ extern
-#endif
-
-/*
  * SunStudio CC does not define C++ portability API __FUNCTION__
  */
 #if defined(__SUNPRO_CC) && !defined(__FUNCTION__)
diff -u -r -N squid-4.0.10/configure squid-4.0.11/configure
--- squid-4.0.10/configure	2016-05-06 23:37:23.000000000 +1200
+++ squid-4.0.11/configure	2016-06-10 08:35:21.000000000 +1200
@@ -1,7 +1,7 @@
 #! /bin/sh
 # From configure.ac Revision.
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.10.
+# Generated by GNU Autoconf 2.69 for Squid Web Proxy 4.0.11.
 #
 # Report bugs to <http://bugs.squid-cache.org/>.
 #
@@ -595,8 +595,8 @@
 # Identity of this package.
 PACKAGE_NAME='Squid Web Proxy'
 PACKAGE_TARNAME='squid'
-PACKAGE_VERSION='4.0.10'
-PACKAGE_STRING='Squid Web Proxy 4.0.10'
+PACKAGE_VERSION='4.0.11'
+PACKAGE_STRING='Squid Web Proxy 4.0.11'
 PACKAGE_BUGREPORT='http://bugs.squid-cache.org/'
 PACKAGE_URL=''
 
@@ -652,18 +652,18 @@
 PO2TEXT
 PO2HTML
 REGEXLIB
-USE_DEVPOLL_FALSE
-USE_DEVPOLL_TRUE
-USE_KQUEUE_FALSE
-USE_KQUEUE_TRUE
-USE_SELECT_WIN32_FALSE
-USE_SELECT_WIN32_TRUE
-USE_SELECT_FALSE
-USE_SELECT_TRUE
-USE_EPOLL_FALSE
-USE_EPOLL_TRUE
-USE_POLL_FALSE
-USE_POLL_TRUE
+ENABLE_DEVPOLL_FALSE
+ENABLE_DEVPOLL_TRUE
+ENABLE_KQUEUE_FALSE
+ENABLE_KQUEUE_TRUE
+ENABLE_SELECT_WIN32_FALSE
+ENABLE_SELECT_WIN32_TRUE
+ENABLE_SELECT_FALSE
+ENABLE_SELECT_TRUE
+ENABLE_EPOLL_FALSE
+ENABLE_EPOLL_TRUE
+ENABLE_POLL_FALSE
+ENABLE_POLL_TRUE
 LIBOBJS
 LIB_DB
 ALLOCA
@@ -681,6 +681,8 @@
 EXTERNAL_ACL_HELPERS
 WBINFO
 LOG_DAEMON_HELPERS
+ENABLE_SMBLIB_FALSE
+ENABLE_SMBLIB_TRUE
 AUTH_LIBS_TO_BUILD
 AUTH_MODULES
 NTLM_AUTH_HELPERS
@@ -700,13 +702,11 @@
 ENABLE_AUTH_FALSE
 ENABLE_AUTH_TRUE
 DEFAULT_HOSTS
-MAKE_LEAKFINDER_FALSE
-MAKE_LEAKFINDER_TRUE
+ENABLE_LEAKFINDER_FALSE
+ENABLE_LEAKFINDER_TRUE
 EPOLL_LIBS
 LBERLIB
 LDAPLIB
-HAVE_SPNEGO_FALSE
-HAVE_SPNEGO_TRUE
 KRB5LIBS
 KRB5INCS
 LIB_KRB5_LIBS
@@ -723,34 +723,34 @@
 NETTLELIB
 ENABLE_HTCP_FALSE
 ENABLE_HTCP_TRUE
-USE_SQUID_EUI_FALSE
-USE_SQUID_EUI_TRUE
+ENABLE_EUI_FALSE
+ENABLE_EUI_TRUE
 EUILIB
 SNMPLIB
 ENABLE_SNMP_FALSE
 ENABLE_SNMP_TRUE
 ADAPTATION_LIBS
-USE_ADAPTATION_FALSE
-USE_ADAPTATION_TRUE
+ENABLE_ADAPTATION_FALSE
+ENABLE_ADAPTATION_TRUE
 ECAP_LIBS
-USE_ECAP_FALSE
-USE_ECAP_TRUE
+ENABLE_ECAP_FALSE
+ENABLE_ECAP_TRUE
 EXT_LIBECAP_LIBS
 EXT_LIBECAP_CFLAGS
 PKG_CONFIG_LIBDIR
 PKG_CONFIG_PATH
 PKG_CONFIG
 ICAP_LIBS
-USE_ICAP_CLIENT_FALSE
-USE_ICAP_CLIENT_TRUE
+ENABLE_ICAP_CLIENT_FALSE
+ENABLE_ICAP_CLIENT_TRUE
 XMLLIB
-HAVE_LIBXML2_FALSE
-HAVE_LIBXML2_TRUE
+ENABLE_LIBXML2_FALSE
+ENABLE_LIBXML2_TRUE
 EXPATLIB
-HAVE_LIBEXPAT_FALSE
-HAVE_LIBEXPAT_TRUE
-USE_ESI_FALSE
-USE_ESI_TRUE
+ENABLE_LIBEXPAT_FALSE
+ENABLE_LIBEXPAT_TRUE
+ENABLE_ESI_FALSE
+ENABLE_ESI_TRUE
 ENABLE_DELAY_POOLS_FALSE
 ENABLE_DELAY_POOLS_TRUE
 ENABLE_PINGER_FALSE
@@ -761,10 +761,10 @@
 STORE_TESTS
 STORE_LIBS_TO_ADD
 STORE_LIBS_TO_BUILD
-HAVE_FS_ROCK_FALSE
-HAVE_FS_ROCK_TRUE
-HAVE_FS_UFS_FALSE
-HAVE_FS_UFS_TRUE
+ENABLE_FS_ROCK_FALSE
+ENABLE_FS_ROCK_TRUE
+ENABLE_FS_UFS_FALSE
+ENABLE_FS_UFS_TRUE
 ENABLE_DISKIO_MMAPPED_FALSE
 ENABLE_DISKIO_MMAPPED_TRUE
 ENABLE_DISKIO_IPCIO_FALSE
@@ -1650,7 +1650,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures Squid Web Proxy 4.0.10 to adapt to many kinds of systems.
+\`configure' configures Squid Web Proxy 4.0.11 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1721,7 +1721,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of Squid Web Proxy 4.0.10:";;
+     short | recursive ) echo "Configuration of Squid Web Proxy 4.0.11:";;
    esac
   cat <<\_ACEOF
 
@@ -2148,7 +2148,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-Squid Web Proxy configure 4.0.10
+Squid Web Proxy configure 4.0.11
 generated by GNU Autoconf 2.69
 
 Copyright (C) 2012 Free Software Foundation, Inc.
@@ -3252,7 +3252,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by Squid Web Proxy $as_me 4.0.10, which was
+It was created by Squid Web Proxy $as_me 4.0.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   $ $0 $@
@@ -4119,7 +4119,7 @@
 
 # Define the identity of the package.
  PACKAGE='squid'
- VERSION='4.0.10'
+ VERSION='4.0.11'
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6809,8 +6809,11 @@
 
 fi
 
-# Check for C++11 compiler support
-    ax_cxx_compile_cxx11_required=true
+# If the user did not specify a C++ version.
+user_cxx=`echo "$PRESET_CXXFLAGS" | grep -o -E "\-std="`
+if test "x$user_cxx" = "x"; then
+  # Check for C++11 compiler support
+      ax_cxx_compile_cxx11_required=true
   ac_ext=cpp
 ac_cpp='$CXXCPP $CPPFLAGS'
 ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -6956,6 +6959,7 @@
 
   fi
 
+fi
 
 # test for programs
 if test -n "$ac_tool_prefix"; then
@@ -21857,7 +21861,6 @@
 fi
 
 
-
 squid_opt_enable_storeio=auto
 # Check whether --enable-storeio was given.
 if test "${enable_storeio+set}" = set; then :
@@ -21964,20 +21967,20 @@
     esac
 done
 
- if test "x$squid_do_build_ufs" = "xtrue" ; then
-  HAVE_FS_UFS_TRUE=
-  HAVE_FS_UFS_FALSE='#'
+ if test "x$squid_do_build_ufs" = "xtrue"; then
+  ENABLE_FS_UFS_TRUE=
+  ENABLE_FS_UFS_FALSE='#'
 else
-  HAVE_FS_UFS_TRUE='#'
-  HAVE_FS_UFS_FALSE=
+  ENABLE_FS_UFS_TRUE='#'
+  ENABLE_FS_UFS_FALSE=
 fi
 
- if test "x$squid_do_build_rock" = "xtrue" ; then
-  HAVE_FS_ROCK_TRUE=
-  HAVE_FS_ROCK_FALSE='#'
+ if test "x$squid_do_build_rock" = "xtrue"; then
+  ENABLE_FS_ROCK_TRUE=
+  ENABLE_FS_ROCK_FALSE='#'
 else
-  HAVE_FS_ROCK_TRUE='#'
-  HAVE_FS_ROCK_FALSE=
+  ENABLE_FS_ROCK_TRUE='#'
+  ENABLE_FS_ROCK_FALSE=
 fi
 
 
@@ -22336,28 +22339,28 @@
 fi
 
  if test "x$squid_opt_use_esi" = "xyes"; then
-  USE_ESI_TRUE=
-  USE_ESI_FALSE='#'
+  ENABLE_ESI_TRUE=
+  ENABLE_ESI_FALSE='#'
 else
-  USE_ESI_TRUE='#'
-  USE_ESI_FALSE=
+  ENABLE_ESI_TRUE='#'
+  ENABLE_ESI_FALSE=
 fi
 
  if test "$HAVE_LIBEXPAT" = 1; then
-  HAVE_LIBEXPAT_TRUE=
-  HAVE_LIBEXPAT_FALSE='#'
+  ENABLE_LIBEXPAT_TRUE=
+  ENABLE_LIBEXPAT_FALSE='#'
 else
-  HAVE_LIBEXPAT_TRUE='#'
-  HAVE_LIBEXPAT_FALSE=
+  ENABLE_LIBEXPAT_TRUE='#'
+  ENABLE_LIBEXPAT_FALSE=
 fi
 
 
  if test "$HAVE_LIBXML2" = 1; then
-  HAVE_LIBXML2_TRUE=
-  HAVE_LIBXML2_FALSE='#'
+  ENABLE_LIBXML2_TRUE=
+  ENABLE_LIBXML2_FALSE='#'
 else
-  HAVE_LIBXML2_TRUE='#'
-  HAVE_LIBXML2_FALSE=
+  ENABLE_LIBXML2_TRUE='#'
+  ENABLE_LIBXML2_FALSE=
 fi
 
 
@@ -22388,22 +22391,21 @@
 
 unset squid_tmp_define
 
- if test "x$enable_icap_client" != "xno" ; then
-  USE_ICAP_CLIENT_TRUE=
-  USE_ICAP_CLIENT_FALSE='#'
-else
-  USE_ICAP_CLIENT_TRUE='#'
-  USE_ICAP_CLIENT_FALSE=
-fi
-
+ICAP_LIBS=""
 if test "x$enable_icap_client" != "xno" ; then
   ICAP_LIBS="icap/libicap.la"
   squid_opt_use_adaptation=yes
+fi
+ if test "x$enable_icap_client" != "xno"; then
+  ENABLE_ICAP_CLIENT_TRUE=
+  ENABLE_ICAP_CLIENT_FALSE='#'
 else
-  ICAP_LIBS=""
+  ENABLE_ICAP_CLIENT_TRUE='#'
+  ENABLE_ICAP_CLIENT_FALSE=
 fi
 
 
+
 squid_opt_use_ecap=1
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support eCAP" >&5
 $as_echo_n "checking whether to support eCAP... " >&6; }
@@ -22650,52 +22652,63 @@
   fi
 fi
 
- if test "x$squid_opt_use_ecap" = "xyes"; then
-  USE_ECAP_TRUE=
-  USE_ECAP_FALSE='#'
-else
-  USE_ECAP_TRUE='#'
-  USE_ECAP_FALSE=
-fi
-
-if test "x$squid_opt_use_ecap" = "xyes";
-then
-
-$as_echo "#define USE_ECAP 1" >>confdefs.h
-
+ECAP_LIBS=""
+if test "x$squid_opt_use_ecap" = "xyes"; then
     ECAP_LIBS="ecap/libecapsquid.la"
     squid_opt_use_adaptation=yes
-else
-
-$as_echo "#define USE_ECAP 0" >>confdefs.h
-
-    ECAP_LIBS=""
 fi
 
+squid_tmp_define=""
+case "${squid_opt_use_ecap:=no}" in
+  yes|true|1) squid_tmp_define="1" ;;
+  no|false|0|"") squid_tmp_define="0" ;;
+  *) as_fn_error $? "SQUID_DEFINE_BOOL: unrecognized value for USE_ECAP: '${squid_opt_use_ecap:=no}'" "$LINENO" 5 ;;
+esac
 
+cat >>confdefs.h <<_ACEOF
+#define USE_ECAP $squid_tmp_define
+_ACEOF
 
- if test "x$squid_opt_use_adaptation" = "xyes"; then
-  USE_ADAPTATION_TRUE=
-  USE_ADAPTATION_FALSE='#'
+unset squid_tmp_define
+
+ if test "x$squid_opt_use_ecap" = "xyes"; then
+  ENABLE_ECAP_TRUE=
+  ENABLE_ECAP_FALSE='#'
 else
-  USE_ADAPTATION_TRUE='#'
-  USE_ADAPTATION_FALSE=
+  ENABLE_ECAP_TRUE='#'
+  ENABLE_ECAP_FALSE=
 fi
 
-if test "x$squid_opt_use_adaptation" = "xyes"
-then
 
-$as_echo "#define USE_ADAPTATION 1" >>confdefs.h
 
+ADAPTATION_LIBS=""
+if test "x$squid_opt_use_adaptation" = "xyes"; then
     ADAPTATION_LIBS="adaptation/libadaptation.la"
-else
+fi
+
+squid_tmp_define=""
+case "${squid_opt_use_adaptation:=no}" in
+  yes|true|1) squid_tmp_define="1" ;;
+  no|false|0|"") squid_tmp_define="0" ;;
+  *) as_fn_error $? "SQUID_DEFINE_BOOL: unrecognized value for USE_ADAPTATION: '${squid_opt_use_adaptation:=no}'" "$LINENO" 5 ;;
+esac
 
-$as_echo "#define USE_ADAPTATION 0" >>confdefs.h
+cat >>confdefs.h <<_ACEOF
+#define USE_ADAPTATION $squid_tmp_define
+_ACEOF
+
+unset squid_tmp_define
 
-    ADAPTATION_LIBS=""
+ if test "x$squid_opt_use_adaptation" = "xyes"; then
+  ENABLE_ADAPTATION_TRUE=
+  ENABLE_ADAPTATION_FALSE='#'
+else
+  ENABLE_ADAPTATION_TRUE='#'
+  ENABLE_ADAPTATION_FALSE=
 fi
 
 
+
 test "x$squid_host_os" = "xmingw" && enable_wccp=no
 # Check whether --enable-wccp was given.
 if test "${enable_wccp+set}" = set; then :
@@ -22956,11 +22969,11 @@
 unset squid_tmp_define
 
  if test "x$enable_eui" = "xyes" ; then
-  USE_SQUID_EUI_TRUE=
-  USE_SQUID_EUI_FALSE='#'
+  ENABLE_EUI_TRUE=
+  ENABLE_EUI_FALSE='#'
 else
-  USE_SQUID_EUI_TRUE='#'
-  USE_SQUID_EUI_FALSE=
+  ENABLE_EUI_TRUE='#'
+  ENABLE_EUI_FALSE=
 fi
 
 
@@ -23624,7 +23637,7 @@
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto  $LIBS"
+LIBS="-lcrypto $LIBOPENSSL_LIBS $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -23668,7 +23681,7 @@
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lssl  $LIBS"
+LIBS="-lssl $LIBOPENSSL_LIBS $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -23727,7 +23740,7 @@
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcrypto  $LIBS"
+LIBS="-lcrypto $LIBOPENSSL_LIBS $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -23771,7 +23784,7 @@
   $as_echo_n "(cached) " >&6
 else
   ac_check_lib_save_LIBS=$LIBS
-LIBS="-lssl  $LIBS"
+LIBS="-lssl $LIBOPENSSL_LIBS $LIBS"
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
 /* end confdefs.h.  */
 
@@ -24327,6 +24340,8 @@
     ssl->init_num = 0;
     ssl->s3->wpend_ret = 0;
     ssl->s3->wpend_tot = 0;
+    SSL_CIPHER *cipher = 0;
+    assert(SSL_CIPHER_get_id(cipher));
 
   ;
   return 0;
@@ -24335,10 +24350,8 @@
 _ACEOF
 if ac_fn_cxx_try_compile "$LINENO"; then :
 
-   $as_echo "#define SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK 1" >>confdefs.h
-
-   { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
+   { $as_echo "$as_me:${as_lineno-$LINENO}: result: possibly; to try, set SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK macro value to 1" >&5
+$as_echo "possibly; to try, set SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK macro value to 1" >&6; }
 
 else
 
@@ -31100,14 +31113,6 @@
 $as_echo "$as_me: $KRB5_FLAVOUR Kerberos library support: ${with_krb5:=no} ${LIB_KRB5_PATH} ${LIB_KRB5_LIBS}" >&6;}
 
 
- if test x"$squid_cv_have_spnego" = x"yes" ; then
-  HAVE_SPNEGO_TRUE=
-  HAVE_SPNEGO_FALSE='#'
-else
-  HAVE_SPNEGO_TRUE='#'
-  HAVE_SPNEGO_FALSE=
-fi
-
 
 case "$squid_host_os" in
 	mingw)
@@ -32695,11 +32700,11 @@
 unset squid_tmp_define
 
  if test "x$enable_leakfinder" = "xyes"; then
-  MAKE_LEAKFINDER_TRUE=
-  MAKE_LEAKFINDER_FALSE='#'
+  ENABLE_LEAKFINDER_TRUE=
+  ENABLE_LEAKFINDER_FALSE='#'
 else
-  MAKE_LEAKFINDER_TRUE='#'
-  MAKE_LEAKFINDER_FALSE=
+  ENABLE_LEAKFINDER_TRUE='#'
+  ENABLE_LEAKFINDER_FALSE=
 fi
 
 
@@ -32817,6 +32822,7 @@
 fi
 
 AUTH_MODULES=""
+require_smblib=0
 
 # Check whether --enable-auth-basic was given.
 if test "${enable_auth_basic+set}" = set; then :
@@ -33351,10 +33357,11 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-BUILD_HELPER="SMB_LM"
-
 # DONT build this helper on Windows
-for ac_header in w32api/windows.h windows.h
+# DONT build this helper by default
+if test "x$auto_auth_basic_modules" != "xyes";then
+  BUILD_HELPER="SMB_LM"
+  for ac_header in w32api/windows.h windows.h
 do :
   as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
 ac_fn_cxx_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
@@ -33367,6 +33374,8 @@
 
 done
 
+  require_smblib=`test "x$BUILD_HELPER" = "xSMB_LM"`
+fi
 
 
       elif test "x$helper" = "xSSPI" ; then
@@ -33920,9 +33929,10 @@
 
 #
 # DONT build this helper on Windows
+# DONT build this helper by default
 #
 # XXX: do we really need the mingw check?
-if test "$squid_host_os" != "mingw"; then
+if test "$squid_host_os" != "mingw" -a "x$auto_auth_ntlm_modules" != "xyes"; then
   BUILD_HELPER="SMB_LM"
   for ac_header in w32api/windows.h windows.h
 do :
@@ -33937,6 +33947,7 @@
 
 done
 
+  require_smblib=`test "x$BUILD_HELPER" = "xSMB_LM"`
 fi
 
 
@@ -34041,6 +34052,14 @@
 done
 
 
+ if $require_smblib; then
+  ENABLE_SMBLIB_TRUE=
+  ENABLE_SMBLIB_FALSE='#'
+else
+  ENABLE_SMBLIB_TRUE='#'
+  ENABLE_SMBLIB_FALSE=
+fi
+
 
 # Check whether --enable-log-daemon-helpers was given.
 if test "${enable_log_daemon_helpers+set}" = set; then :
@@ -39783,52 +39802,52 @@
 { $as_echo "$as_me:${as_lineno-$LINENO}: Using ${squid_opt_io_loop_engine} for the IO loop." >&5
 $as_echo "$as_me: Using ${squid_opt_io_loop_engine} for the IO loop." >&6;}
 
- if test $squid_opt_io_loop_engine = poll; then
-  USE_POLL_TRUE=
-  USE_POLL_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xpoll"; then
+  ENABLE_POLL_TRUE=
+  ENABLE_POLL_FALSE='#'
 else
-  USE_POLL_TRUE='#'
-  USE_POLL_FALSE=
+  ENABLE_POLL_TRUE='#'
+  ENABLE_POLL_FALSE=
 fi
 
- if test $squid_opt_io_loop_engine = epoll; then
-  USE_EPOLL_TRUE=
-  USE_EPOLL_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xepoll"; then
+  ENABLE_EPOLL_TRUE=
+  ENABLE_EPOLL_FALSE='#'
 else
-  USE_EPOLL_TRUE='#'
-  USE_EPOLL_FALSE=
+  ENABLE_EPOLL_TRUE='#'
+  ENABLE_EPOLL_FALSE=
 fi
 
- if test $squid_opt_io_loop_engine = select; then
-  USE_SELECT_TRUE=
-  USE_SELECT_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xselect"; then
+  ENABLE_SELECT_TRUE=
+  ENABLE_SELECT_FALSE='#'
 else
-  USE_SELECT_TRUE='#'
-  USE_SELECT_FALSE=
+  ENABLE_SELECT_TRUE='#'
+  ENABLE_SELECT_FALSE=
 fi
 
- if test $squid_opt_io_loop_engine = select_win32; then
-  USE_SELECT_WIN32_TRUE=
-  USE_SELECT_WIN32_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xselect_win32"; then
+  ENABLE_SELECT_WIN32_TRUE=
+  ENABLE_SELECT_WIN32_FALSE='#'
 else
-  USE_SELECT_WIN32_TRUE='#'
-  USE_SELECT_WIN32_FALSE=
+  ENABLE_SELECT_WIN32_TRUE='#'
+  ENABLE_SELECT_WIN32_FALSE=
 fi
 
- if test $squid_opt_io_loop_engine = kqueue; then
-  USE_KQUEUE_TRUE=
-  USE_KQUEUE_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xkqueue"; then
+  ENABLE_KQUEUE_TRUE=
+  ENABLE_KQUEUE_FALSE='#'
 else
-  USE_KQUEUE_TRUE='#'
-  USE_KQUEUE_FALSE=
+  ENABLE_KQUEUE_TRUE='#'
+  ENABLE_KQUEUE_FALSE=
 fi
 
- if test $squid_opt_io_loop_engine = devpoll; then
-  USE_DEVPOLL_TRUE=
-  USE_DEVPOLL_FALSE='#'
+ if test "x$squid_opt_io_loop_engine" = "xdevpoll"; then
+  ENABLE_DEVPOLL_TRUE=
+  ENABLE_DEVPOLL_FALSE='#'
 else
-  USE_DEVPOLL_TRUE='#'
-  USE_DEVPOLL_FALSE=
+  ENABLE_DEVPOLL_TRUE='#'
+  ENABLE_DEVPOLL_FALSE=
 fi
 
 
@@ -41951,12 +41970,12 @@
   as_fn_error $? "conditional \"ENABLE_DISKIO_MMAPPED\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_FS_UFS_TRUE}" && test -z "${HAVE_FS_UFS_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_FS_UFS\" was never defined.
+if test -z "${ENABLE_FS_UFS_TRUE}" && test -z "${ENABLE_FS_UFS_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_FS_UFS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_FS_ROCK_TRUE}" && test -z "${HAVE_FS_ROCK_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_FS_ROCK\" was never defined.
+if test -z "${ENABLE_FS_ROCK_TRUE}" && test -z "${ENABLE_FS_ROCK_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_FS_ROCK\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${ENABLE_PINGER_TRUE}" && test -z "${ENABLE_PINGER_FALSE}"; then
@@ -41975,36 +41994,36 @@
   as_fn_error $? "conditional \"ENABLE_DELAY_POOLS\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_ESI_TRUE}" && test -z "${USE_ESI_FALSE}"; then
-  as_fn_error $? "conditional \"USE_ESI\" was never defined.
+if test -z "${ENABLE_ESI_TRUE}" && test -z "${ENABLE_ESI_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_ESI\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_LIBEXPAT_TRUE}" && test -z "${HAVE_LIBEXPAT_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_LIBEXPAT\" was never defined.
+if test -z "${ENABLE_LIBEXPAT_TRUE}" && test -z "${ENABLE_LIBEXPAT_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_LIBEXPAT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_LIBXML2_TRUE}" && test -z "${HAVE_LIBXML2_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_LIBXML2\" was never defined.
+if test -z "${ENABLE_LIBXML2_TRUE}" && test -z "${ENABLE_LIBXML2_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_LIBXML2\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_ICAP_CLIENT_TRUE}" && test -z "${USE_ICAP_CLIENT_FALSE}"; then
-  as_fn_error $? "conditional \"USE_ICAP_CLIENT\" was never defined.
+if test -z "${ENABLE_ICAP_CLIENT_TRUE}" && test -z "${ENABLE_ICAP_CLIENT_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_ICAP_CLIENT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_ECAP_TRUE}" && test -z "${USE_ECAP_FALSE}"; then
-  as_fn_error $? "conditional \"USE_ECAP\" was never defined.
+if test -z "${ENABLE_ECAP_TRUE}" && test -z "${ENABLE_ECAP_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_ECAP\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_ADAPTATION_TRUE}" && test -z "${USE_ADAPTATION_FALSE}"; then
-  as_fn_error $? "conditional \"USE_ADAPTATION\" was never defined.
+if test -z "${ENABLE_ADAPTATION_TRUE}" && test -z "${ENABLE_ADAPTATION_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_ADAPTATION\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${ENABLE_SNMP_TRUE}" && test -z "${ENABLE_SNMP_FALSE}"; then
   as_fn_error $? "conditional \"ENABLE_SNMP\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_SQUID_EUI_TRUE}" && test -z "${USE_SQUID_EUI_FALSE}"; then
-  as_fn_error $? "conditional \"USE_SQUID_EUI\" was never defined.
+if test -z "${ENABLE_EUI_TRUE}" && test -z "${ENABLE_EUI_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_EUI\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${ENABLE_HTCP_TRUE}" && test -z "${ENABLE_HTCP_FALSE}"; then
@@ -42015,12 +42034,8 @@
   as_fn_error $? "conditional \"ENABLE_SSL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${HAVE_SPNEGO_TRUE}" && test -z "${HAVE_SPNEGO_FALSE}"; then
-  as_fn_error $? "conditional \"HAVE_SPNEGO\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
-if test -z "${MAKE_LEAKFINDER_TRUE}" && test -z "${MAKE_LEAKFINDER_FALSE}"; then
-  as_fn_error $? "conditional \"MAKE_LEAKFINDER\" was never defined.
+if test -z "${ENABLE_LEAKFINDER_TRUE}" && test -z "${ENABLE_LEAKFINDER_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_LEAKFINDER\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 if test -z "${ENABLE_AUTH_TRUE}" && test -z "${ENABLE_AUTH_FALSE}"; then
@@ -42043,6 +42058,10 @@
   as_fn_error $? "conditional \"ENABLE_AUTH_NTLM\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
+if test -z "${ENABLE_SMBLIB_TRUE}" && test -z "${ENABLE_SMBLIB_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_SMBLIB\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
 if test -z "${ENABLE_UNLINKD_TRUE}" && test -z "${ENABLE_UNLINKD_FALSE}"; then
   as_fn_error $? "conditional \"ENABLE_UNLINKD\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -42052,28 +42071,28 @@
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 
-if test -z "${USE_POLL_TRUE}" && test -z "${USE_POLL_FALSE}"; then
-  as_fn_error $? "conditional \"USE_POLL\" was never defined.
+if test -z "${ENABLE_POLL_TRUE}" && test -z "${ENABLE_POLL_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_POLL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_EPOLL_TRUE}" && test -z "${USE_EPOLL_FALSE}"; then
-  as_fn_error $? "conditional \"USE_EPOLL\" was never defined.
+if test -z "${ENABLE_EPOLL_TRUE}" && test -z "${ENABLE_EPOLL_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_EPOLL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_SELECT_TRUE}" && test -z "${USE_SELECT_FALSE}"; then
-  as_fn_error $? "conditional \"USE_SELECT\" was never defined.
+if test -z "${ENABLE_SELECT_TRUE}" && test -z "${ENABLE_SELECT_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_SELECT\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_SELECT_WIN32_TRUE}" && test -z "${USE_SELECT_WIN32_FALSE}"; then
-  as_fn_error $? "conditional \"USE_SELECT_WIN32\" was never defined.
+if test -z "${ENABLE_SELECT_WIN32_TRUE}" && test -z "${ENABLE_SELECT_WIN32_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_SELECT_WIN32\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_KQUEUE_TRUE}" && test -z "${USE_KQUEUE_FALSE}"; then
-  as_fn_error $? "conditional \"USE_KQUEUE\" was never defined.
+if test -z "${ENABLE_KQUEUE_TRUE}" && test -z "${ENABLE_KQUEUE_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_KQUEUE\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
-if test -z "${USE_DEVPOLL_TRUE}" && test -z "${USE_DEVPOLL_FALSE}"; then
-  as_fn_error $? "conditional \"USE_DEVPOLL\" was never defined.
+if test -z "${ENABLE_DEVPOLL_TRUE}" && test -z "${ENABLE_DEVPOLL_FALSE}"; then
+  as_fn_error $? "conditional \"ENABLE_DEVPOLL\" was never defined.
 Usually this means the macro was only invoked conditionally." "$LINENO" 5
 fi
 
@@ -42473,7 +42492,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by Squid Web Proxy $as_me 4.0.10, which was
+This file was extended by Squid Web Proxy $as_me 4.0.11, which was
 generated by GNU Autoconf 2.69.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -42539,7 +42558,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
 ac_cs_version="\\
-Squid Web Proxy config.status 4.0.10
+Squid Web Proxy config.status 4.0.11
 configured by $0, generated by GNU Autoconf 2.69,
   with options \\"\$ac_cs_config\\"
 
diff -u -r -N squid-4.0.10/configure.ac squid-4.0.11/configure.ac
--- squid-4.0.10/configure.ac	2016-05-06 23:37:23.000000000 +1200
+++ squid-4.0.11/configure.ac	2016-06-10 08:35:21.000000000 +1200
@@ -5,7 +5,7 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-AC_INIT([Squid Web Proxy],[4.0.10],[http://bugs.squid-cache.org/],[squid])
+AC_INIT([Squid Web Proxy],[4.0.11],[http://bugs.squid-cache.org/],[squid])
 AC_PREREQ(2.61)
 AC_CONFIG_HEADERS([include/autoconf.h])
 AC_CONFIG_AUX_DIR(cfgaux)
@@ -92,8 +92,12 @@
 	AC_USE_SYSTEM_EXTENSIONS
 fi
 
-# Check for C++11 compiler support
-AX_CXX_COMPILE_STDCXX_11([noext],[mandatory])
+# If the user did not specify a C++ version.
+user_cxx=`echo "$PRESET_CXXFLAGS" | grep -o -E "\-std="`
+if test "x$user_cxx" = "x"; then
+  # Check for C++11 compiler support
+  AX_CXX_COMPILE_STDCXX_11([noext],[mandatory])
+fi
 
 # test for programs
 AC_PROG_RANLIB
@@ -724,17 +728,16 @@
 AC_MSG_NOTICE([IO Modules built: $DISK_MODULES])
 AC_SUBST(DISK_MODULES)
 AC_SUBST(DISK_LIBS)
-AM_CONDITIONAL([ENABLE_DISKIO_AIO], [test "x$squid_disk_module_candidates_AIO" = "xyes"])
+AM_CONDITIONAL(ENABLE_DISKIO_AIO, test "x$squid_disk_module_candidates_AIO" = "xyes")
 AC_SUBST(AIOLIB)
-AM_CONDITIONAL([ENABLE_WIN32_AIO], [test "x$squid_disk_module_candidates_AIO" = "xyes" -a "x$ENABLE_WIN32_AIO" = "x1"])
-AM_CONDITIONAL([ENABLE_DISKIO_BLOCKING], [test "x$squid_disk_module_candidates_Blocking" = "xyes"])
-AM_CONDITIONAL([ENABLE_DISKIO_DISKDAEMON], [test "x$squid_disk_module_candidates_DiskDaemon" = "xyes"])
-AM_CONDITIONAL([ENABLE_DISKIO_DISKTHREADS], [test "x$squid_disk_module_candidates_DiskThreads" = "xyes"])
+AM_CONDITIONAL(ENABLE_WIN32_AIO, test "x$squid_disk_module_candidates_AIO" = "xyes" -a "x$ENABLE_WIN32_AIO" = "x1")
+AM_CONDITIONAL(ENABLE_DISKIO_BLOCKING, test "x$squid_disk_module_candidates_Blocking" = "xyes")
+AM_CONDITIONAL(ENABLE_DISKIO_DISKDAEMON, test "x$squid_disk_module_candidates_DiskDaemon" = "xyes")
+AM_CONDITIONAL(ENABLE_DISKIO_DISKTHREADS, test "x$squid_disk_module_candidates_DiskThreads" = "xyes")
 AC_SUBST(LIBPTHREADS)
-AM_CONDITIONAL([ENABLE_WIN32_AIOPS], [test "x$squid_disk_module_candidates_DiskThreads" = "xyes" -a "x$ENABLE_WIN32_AIOPS" = "x1"])
-AM_CONDITIONAL([ENABLE_DISKIO_IPCIO], [test "x$squid_disk_module_candidates_IpcIo" = "xyes"])
-AM_CONDITIONAL([ENABLE_DISKIO_MMAPPED], [test "x$squid_disk_module_candidates_Mmapped" = "xyes"])
-
+AM_CONDITIONAL(ENABLE_WIN32_AIOPS, test "x$squid_disk_module_candidates_DiskThreads" = "xyes" -a "x$ENABLE_WIN32_AIOPS" = "x1")
+AM_CONDITIONAL(ENABLE_DISKIO_IPCIO, test "x$squid_disk_module_candidates_IpcIo" = "xyes")
+AM_CONDITIONAL(ENABLE_DISKIO_MMAPPED, test "x$squid_disk_module_candidates_Mmapped" = "xyes")
 
 dnl Check what Storage formats are wanted.
 dnl This version will error out with a message saying why if a required DiskIO is missing.
@@ -803,8 +806,8 @@
     esac
 done
 
-AM_CONDITIONAL(HAVE_FS_UFS,[test "x$squid_do_build_ufs" = "xtrue" ])
-AM_CONDITIONAL(HAVE_FS_ROCK,[test "x$squid_do_build_rock" = "xtrue" ])
+AM_CONDITIONAL(ENABLE_FS_UFS, test "x$squid_do_build_ufs" = "xtrue")
+AM_CONDITIONAL(ENABLE_FS_ROCK, test "x$squid_do_build_rock" = "xtrue")
 dnl hack: need to define those even if not used in the build system to
 dnl make sure that global FS objects are linked to the squid binary.
 AH_TEMPLATE(HAVE_FS_UFS, "Define to 1 if ufs filesystem module is build")
@@ -951,10 +954,10 @@
   fi
 fi
 
-AM_CONDITIONAL(USE_ESI, test "x$squid_opt_use_esi" = "xyes")
-AM_CONDITIONAL(HAVE_LIBEXPAT, test "$HAVE_LIBEXPAT" = 1)
+AM_CONDITIONAL(ENABLE_ESI, test "x$squid_opt_use_esi" = "xyes")
+AM_CONDITIONAL(ENABLE_LIBEXPAT, test "$HAVE_LIBEXPAT" = 1)
 AC_SUBST(EXPATLIB)
-AM_CONDITIONAL(HAVE_LIBXML2, test "$HAVE_LIBXML2" = 1)
+AM_CONDITIONAL(ENABLE_LIBXML2, test "$HAVE_LIBXML2" = 1)
 AC_SUBST(XMLLIB)
 
 # icap argument handling
@@ -963,13 +966,12 @@
   SQUID_YESNO([$enableval],[Unrecognized argument to --disable-icap-client: $enableval])
 ])
 SQUID_DEFINE_BOOL(ICAP_CLIENT,${enable_icap_client:=yes}, [Enable ICAP client features in Squid])
-AM_CONDITIONAL(USE_ICAP_CLIENT, [test "x$enable_icap_client" != "xno" ])
+ICAP_LIBS=""
 if test "x$enable_icap_client" != "xno" ; then
   ICAP_LIBS="icap/libicap.la"
   squid_opt_use_adaptation=yes
-else
-  ICAP_LIBS=""
 fi
+AM_CONDITIONAL(ENABLE_ICAP_CLIENT, test "x$enable_icap_client" != "xno")
 AC_SUBST(ICAP_LIBS)
 
 squid_opt_use_ecap=1
@@ -1010,30 +1012,22 @@
   fi
 fi
 
-AM_CONDITIONAL(USE_ECAP, test "x$squid_opt_use_ecap" = "xyes")
-if test "x$squid_opt_use_ecap" = "xyes";
-then
-    AC_DEFINE(USE_ECAP,1,[Enable eCAP support])
+ECAP_LIBS=""
+if test "x$squid_opt_use_ecap" = "xyes"; then
     ECAP_LIBS="ecap/libecapsquid.la"
     squid_opt_use_adaptation=yes
-else
-    AC_DEFINE(USE_ECAP,0,[Disable eCAP support])
-    ECAP_LIBS=""
 fi
-dnl convenience library
+SQUID_DEFINE_BOOL(USE_ECAP,${squid_opt_use_ecap:=no},[Whether to use eCAP support])
+AM_CONDITIONAL(ENABLE_ECAP, test "x$squid_opt_use_ecap" = "xyes")
 AC_SUBST(ECAP_LIBS)
 
-
 dnl enable adaptation if requested by specific adaptation mechanisms
-AM_CONDITIONAL(USE_ADAPTATION, test "x$squid_opt_use_adaptation" = "xyes")
-if test "x$squid_opt_use_adaptation" = "xyes"
-then
-    AC_DEFINE(USE_ADAPTATION,1,[common adaptation support])
+ADAPTATION_LIBS=""
+if test "x$squid_opt_use_adaptation" = "xyes"; then
     ADAPTATION_LIBS="adaptation/libadaptation.la"
-else
-    AC_DEFINE(USE_ADAPTATION,0,[common adaptation support])
-    ADAPTATION_LIBS=""
 fi
+SQUID_DEFINE_BOOL(USE_ADAPTATION,${squid_opt_use_adaptation:=no}, [common adaptation support])
+AM_CONDITIONAL(ENABLE_ADAPTATION, test "x$squid_opt_use_adaptation" = "xyes")
 AC_SUBST(ADAPTATION_LIBS)
 
 test "x$squid_host_os" = "xmingw" && enable_wccp=no
@@ -1150,7 +1144,7 @@
 AC_MSG_NOTICE([EUI (MAC address) controls enabled: $enable_eui])
 SQUID_DEFINE_BOOL(USE_SQUID_EUI,$enable_eui,
    [Define this to include code which lets you use ethernet addresses. This code uses API initially defined in 4.4-BSD.])
-AM_CONDITIONAL(USE_SQUID_EUI, [test "x$enable_eui" = "xyes" ])
+AM_CONDITIONAL(ENABLE_EUI, [test "x$enable_eui" = "xyes" ])
 
 
 AC_ARG_ENABLE(htcp,
@@ -1324,10 +1318,10 @@
 
     AC_CHECK_LIB(crypto,[CRYPTO_new_ex_data],[LIBOPENSSL_LIBS="-lcrypto $LIBOPENSSL_LIBS"],[
       AC_MSG_ERROR([library 'crypto' is required for OpenSSL])
-    ])
+    ],$LIBOPENSSL_LIBS)
     AC_CHECK_LIB(ssl,[SSL_library_init],[LIBOPENSSL_LIBS="-lssl $LIBOPENSSL_LIBS"],[
       AC_MSG_ERROR([library 'ssl' is required for OpenSSL])
-    ])
+    ],$LIBOPENSSL_LIBS)
   ])
 
   # This is a workaround for RedHat 9 brain damage..
@@ -1839,9 +1833,8 @@
 AC_MSG_NOTICE([$KRB5_FLAVOUR Kerberos library support: ${with_krb5:=no} ${LIB_KRB5_PATH} ${LIB_KRB5_LIBS}])
 AC_SUBST(KRB5INCS)
 AC_SUBST(KRB5LIBS)
-AM_CONDITIONAL(HAVE_SPNEGO, test x"$squid_cv_have_spnego" = x"yes" )
 
-dnl On MinGW OpenLDAP is not available, so LDAP helpers can be linked 
+dnl On MinGW OpenLDAP is not available, so LDAP helpers can be linked
 dnl only with Windows LDAP libraries using -lwldap32
 case "$squid_host_os" in
 	mingw)
@@ -2425,7 +2418,7 @@
 AC_MSG_NOTICE([Leak Finder enabled: ${enable_leakfinder:=no}])
 SQUID_DEFINE_BOOL(USE_LEAKFINDER,$enable_leakfinder,
   [Enable code for assisting in finding memory leaks. Not for the faint of heart])
-AM_CONDITIONAL(MAKE_LEAKFINDER, [test "x$enable_leakfinder" = "xyes"])
+AM_CONDITIONAL(ENABLE_LEAKFINDER, [test "x$enable_leakfinder" = "xyes"])
 
 
 AC_ARG_ENABLE(follow-x-forwarded-for,
@@ -2479,6 +2472,7 @@
 SQUID_DEFINE_BOOL(USE_AUTH,$enable_auth,[Enable support for authentication])
 AM_CONDITIONAL(ENABLE_AUTH, test "x$enable_auth" != "xno")
 AUTH_MODULES=""
+require_smblib=0
 
 AC_ARG_ENABLE(auth-basic,
   AS_HELP_STRING([--enable-auth-basic="list of helpers"],
@@ -2538,6 +2532,7 @@
 done
 AC_SUBST(AUTH_MODULES)
 AC_SUBST(AUTH_LIBS_TO_BUILD)
+AM_CONDITIONAL(ENABLE_SMBLIB, $require_smblib)
 
 dnl Select logging daemon helpers to build
 AC_ARG_ENABLE(log-daemon-helpers,
@@ -3438,12 +3433,12 @@
 
 AC_MSG_NOTICE([Using ${squid_opt_io_loop_engine} for the IO loop.])
 
-AM_CONDITIONAL([USE_POLL], [test $squid_opt_io_loop_engine = poll])
-AM_CONDITIONAL([USE_EPOLL], [test $squid_opt_io_loop_engine = epoll])
-AM_CONDITIONAL([USE_SELECT], [test $squid_opt_io_loop_engine = select])
-AM_CONDITIONAL([USE_SELECT_WIN32], [test $squid_opt_io_loop_engine = select_win32])
-AM_CONDITIONAL([USE_KQUEUE], [test $squid_opt_io_loop_engine = kqueue])
-AM_CONDITIONAL([USE_DEVPOLL], [test $squid_opt_io_loop_engine = devpoll])
+AM_CONDITIONAL(ENABLE_POLL, test "x$squid_opt_io_loop_engine" = "xpoll")
+AM_CONDITIONAL(ENABLE_EPOLL, test "x$squid_opt_io_loop_engine" = "xepoll")
+AM_CONDITIONAL(ENABLE_SELECT, test "x$squid_opt_io_loop_engine" = "xselect")
+AM_CONDITIONAL(ENABLE_SELECT_WIN32, test "x$squid_opt_io_loop_engine" = "xselect_win32")
+AM_CONDITIONAL(ENABLE_KQUEUE, test "x$squid_opt_io_loop_engine" = "xkqueue")
+AM_CONDITIONAL(ENABLE_DEVPOLL, test "x$squid_opt_io_loop_engine" = "xdevpoll")
 
 case $squid_opt_io_loop_engine in
   epoll) AC_DEFINE(USE_EPOLL,1,[Use epoll() for the IO loop]) ;;
diff -u -r -N squid-4.0.10/doc/release-notes/release-4.html squid-4.0.11/doc/release-notes/release-4.html
--- squid-4.0.10/doc/release-notes/release-4.html	2016-05-07 00:29:29.000000000 +1200
+++ squid-4.0.11/doc/release-notes/release-4.html	2016-06-10 09:27:51.000000000 +1200
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <HTML>
 <HEAD>
- <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 4.0.10 release notes</TITLE>
+ <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
+ <TITLE>Squid 4.0.11 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.10 release notes</H1>
+<H1>Squid 4.0.11 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -61,7 +61,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-4.0.10 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.0.11 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
@@ -425,6 +425,9 @@
 <P>Superceded by <EM>cache_peer_access</EM>. Use dstdomain ACL
 in the access control list to restrict domains requested.</P>
 
+<DT><B>ie_refresh</B><DD>
+<P>Removed. MSIE 3.x, 4.x, 5.0 and 5.01 are no longer popular browsers.</P>
+
 <DT><B>sslproxy_cafile</B><DD>
 <P>Replaced by <EM>tls_outgoing_options cafile=</EM>.
 Which now takes multiple entries.</P>
@@ -482,8 +485,8 @@
 <DT><B>--enable-security-cert-generators</B><DD>
 <P>New option to control which TLS/SSL dynamic certificate generator
 helpers are built and installed.</P>
-<P>Helper <EM>ssl_crtd<EM> has been renamed to <EM>security_file_certgen</EM>
-and built with module name <EM>file</EM>. Requires <EM>--with-openssl</EM>.</EM></EM></P>
+<P>Helper <EM>ssl_crtd</EM> has been renamed to <EM>security_file_certgen</EM>
+and built with module name <EM>file</EM>. Requires <EM>--with-openssl</EM>.</P>
 
 <DT><B>--enable-security-cert-validators</B><DD>
 <P>New option to control which TLS/SSL certificate validation
@@ -502,10 +505,14 @@
 <DL>
 <DT><B>--enable-auth-basic</B><DD>
 <P>The <EM>MSNT-multi-domain</EM> helper has been removed.</P>
+<P>The SMB LanMan helper <EM>SMB_LM</EM> is no longer built by default.
+It needs to be explicitly listed to be built.</P>
 
 <DT><B>--enable-auth-ntlm</B><DD>
 <P>The SMB LanMan helper is now built using <EM>SMB_LM</EM>
 (was lower case <EM>smb_lm</EM>).</P>
+<P>The SMB LanMan helper <EM>SMB_LM</EM> is no longer built by default.
+It needs to be explicitly listed to be built.</P>
 
 <DT><B>--enable-diskio</B><DD>
 <P>Auto-detection of SMP related modules has been fixed to
diff -u -r -N squid-4.0.10/include/autoconf.h.in squid-4.0.11/include/autoconf.h.in
--- squid-4.0.10/include/autoconf.h.in	2016-05-06 23:35:46.000000000 +1200
+++ squid-4.0.11/include/autoconf.h.in	2016-06-10 08:33:50.000000000 +1200
@@ -1367,7 +1367,7 @@
 /* DiskIO modules are expected to be available. */
 #undef USE_DISKIO
 
-/* Disable eCAP support */
+/* Whether to use eCAP support */
 #undef USE_ECAP
 
 /* Use epoll() for the IO loop */
diff -u -r -N squid-4.0.10/include/SquidNew.h squid-4.0.11/include/SquidNew.h
--- squid-4.0.10/include/SquidNew.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/include/SquidNew.h	1970-01-01 12:00:00.000000000 +1200
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
- *
- * Squid software is distributed under GPLv2+ license and includes
- * contributions from numerous individuals and organizations.
- * Please see the COPYING and CONTRIBUTORS files for details.
- */
-
-#ifndef SQUID_NEW_H
-#define SQUID_NEW_H
-
-#if !defined(__SUNPRO_CC) && !defined(__clang__)
-/* Any code using libstdc++ must have externally resolvable overloads
- * for void * operator new - which means in the .o for the binary,
- * or in a shared library. static libs don't propogate the symbol
- * so, look in the translation unit containing main() in squid
- * for the extern version in squid
- */
-#include <new>
-
-_SQUID_EXTERNNEW_ void *operator new(size_t size) throw (std::bad_alloc)
-{
-    return xmalloc(size);
-}
-_SQUID_EXTERNNEW_ void operator delete (void *address) throw()
-{
-    xfree(address);
-}
-_SQUID_EXTERNNEW_ void *operator new[] (size_t size) throw (std::bad_alloc)
-{
-    return xmalloc(size);
-}
-_SQUID_EXTERNNEW_ void operator delete[] (void *address) throw()
-{
-    xfree(address);
-}
-
-#endif /* !__SUNPRO_CC && !__clang__*/
-
-#endif /* SQUID_NEW_H */
-
diff -u -r -N squid-4.0.10/include/util.h squid-4.0.11/include/util.h
--- squid-4.0.10/include/util.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/include/util.h	2016-06-10 08:32:57.000000000 +1200
@@ -19,23 +19,6 @@
 SQUIDCEXTERN int tvSubUsec(struct timeval, struct timeval);
 SQUIDCEXTERN double tvSubDsec(struct timeval, struct timeval);
 SQUIDCEXTERN void Tolower(char *);
-#if defined(__cplusplus)
-/*
- * Any code using libstdc++ must have externally resolvable overloads
- * for void * operator new - which means in the .o for the binary,
- * or in a shared library. static libs don't propogate the symbol
- * so, look in the translation unit containing main() in squid
- * for the extern version in squid
- */
-#if !defined(_SQUID_EXTERNNEW_)
-#if defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__)
-#define _SQUID_EXTERNNEW_ extern inline __attribute__((gnu_inline))
-#else
-#define _SQUID_EXTERNNEW_ extern inline
-#endif
-#endif
-#include "SquidNew.h"
-#endif
 
 SQUIDCEXTERN time_t parse_iso3307_time(const char *buf);
 
diff -u -r -N squid-4.0.10/include/version.h squid-4.0.11/include/version.h
--- squid-4.0.10/include/version.h	2016-05-06 23:37:24.000000000 +1200
+++ squid-4.0.11/include/version.h	2016-06-10 08:35:21.000000000 +1200
@@ -7,7 +7,7 @@
  */
 
 #ifndef SQUID_RELEASE_TIME
-#define SQUID_RELEASE_TIME 1462534506
+#define SQUID_RELEASE_TIME 1465504370
 #endif
 
 /*
diff -u -r -N squid-4.0.10/lib/Makefile.am squid-4.0.11/lib/Makefile.am
--- squid-4.0.10/lib/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/lib/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -11,7 +11,7 @@
 SUBDIRS=
 EXTRA_DIST=
 
-if USE_ESI
+if ENABLE_ESI
 SUBDIRS += libTrie
 endif
 if ENABLE_SNMP
@@ -37,9 +37,12 @@
 noinst_LTLIBRARIES += libsspwin32.la
 libsspwin32_la_SOURCES = sspwin32.cc
 else
-SUBDIRS += rfcnb smblib
 EXTRA_DIST += sspwin32.cc
 endif
+if ENABLE_SMBLIB
+# smblib is the only user of the rfcnb library
+SUBDIRS += rfcnb smblib
+endif
 if ENABLE_AUTH_NTLM
 SUBDIRS += ntlmauth
 endif
diff -u -r -N squid-4.0.10/lib/Makefile.in squid-4.0.11/lib/Makefile.in
--- squid-4.0.10/lib/Makefile.in	2016-05-06 23:36:23.000000000 +1200
+++ squid-4.0.11/lib/Makefile.in	2016-06-10 08:34:22.000000000 +1200
@@ -91,7 +91,7 @@
 check_PROGRAMS = tests/testRFC1738$(EXEEXT)
 TESTS = tests/testRFC1738$(EXEEXT) testHeaders
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL)
-@USE_ESI_TRUE@am__append_2 = libTrie
+@ENABLE_ESI_TRUE@am__append_2 = libTrie
 @ENABLE_SNMP_TRUE@am__append_3 = snmplib
 @ENABLE_XPROF_STATS_TRUE@am__append_4 = profiler
 
@@ -100,8 +100,9 @@
 # and others are unable to be built.
 #
 @ENABLE_WIN32SPECIFIC_TRUE@am__append_5 = libsspwin32.la
-@ENABLE_WIN32SPECIFIC_FALSE@am__append_6 = rfcnb smblib
-@ENABLE_WIN32SPECIFIC_FALSE@am__append_7 = sspwin32.cc
+@ENABLE_WIN32SPECIFIC_FALSE@am__append_6 = sspwin32.cc
+# smblib is the only user of the rfcnb library
+@ENABLE_SMBLIB_TRUE@am__append_7 = rfcnb smblib
 @ENABLE_AUTH_NTLM_TRUE@am__append_8 = ntlmauth
 subdir = lib
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -804,8 +805,8 @@
 subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1)
 DIST_SUBDIRS = ntlmauth profiler rfcnb smblib libTrie snmplib
 SUBDIRS = $(am__append_2) $(am__append_3) $(am__append_4) \
-	$(am__append_6) $(am__append_8)
-EXTRA_DIST = $(am__append_7)
+	$(am__append_7) $(am__append_8)
+EXTRA_DIST = $(am__append_6)
 noinst_LTLIBRARIES = libmiscencoding.la libmisccontainers.la \
 	libmiscutil.la $(am__append_5)
 @ENABLE_WIN32SPECIFIC_TRUE@libsspwin32_la_SOURCES = sspwin32.cc
diff -u -r -N squid-4.0.10/RELEASENOTES.html squid-4.0.11/RELEASENOTES.html
--- squid-4.0.10/RELEASENOTES.html	2016-05-07 00:29:29.000000000 +1200
+++ squid-4.0.11/RELEASENOTES.html	2016-06-10 09:27:51.000000000 +1200
@@ -1,11 +1,11 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
 <HTML>
 <HEAD>
- <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.71">
- <TITLE>Squid 4.0.10 release notes</TITLE>
+ <META NAME="GENERATOR" CONTENT="LinuxDoc-Tools 0.9.72">
+ <TITLE>Squid 4.0.11 release notes</TITLE>
 </HEAD>
 <BODY>
-<H1>Squid 4.0.10 release notes</H1>
+<H1>Squid 4.0.11 release notes</H1>
 
 <H2>Squid Developers</H2>
 <HR>
@@ -61,7 +61,7 @@
 <HR>
 <H2><A NAME="s1">1.</A> <A HREF="#toc1">Notice</A></H2>
 
-<P>The Squid Team are pleased to announce the release of Squid-4.0.10 for testing.</P>
+<P>The Squid Team are pleased to announce the release of Squid-4.0.11 for testing.</P>
 <P>This new release is available for download from 
 <A HREF="http://www.squid-cache.org/Versions/v4/">http://www.squid-cache.org/Versions/v4/</A> or the
 <A HREF="http://www.squid-cache.org/Download/http-mirrors.html">mirrors</A>.</P>
@@ -425,6 +425,9 @@
 <P>Superceded by <EM>cache_peer_access</EM>. Use dstdomain ACL
 in the access control list to restrict domains requested.</P>
 
+<DT><B>ie_refresh</B><DD>
+<P>Removed. MSIE 3.x, 4.x, 5.0 and 5.01 are no longer popular browsers.</P>
+
 <DT><B>sslproxy_cafile</B><DD>
 <P>Replaced by <EM>tls_outgoing_options cafile=</EM>.
 Which now takes multiple entries.</P>
@@ -482,8 +485,8 @@
 <DT><B>--enable-security-cert-generators</B><DD>
 <P>New option to control which TLS/SSL dynamic certificate generator
 helpers are built and installed.</P>
-<P>Helper <EM>ssl_crtd<EM> has been renamed to <EM>security_file_certgen</EM>
-and built with module name <EM>file</EM>. Requires <EM>--with-openssl</EM>.</EM></EM></P>
+<P>Helper <EM>ssl_crtd</EM> has been renamed to <EM>security_file_certgen</EM>
+and built with module name <EM>file</EM>. Requires <EM>--with-openssl</EM>.</P>
 
 <DT><B>--enable-security-cert-validators</B><DD>
 <P>New option to control which TLS/SSL certificate validation
@@ -502,10 +505,14 @@
 <DL>
 <DT><B>--enable-auth-basic</B><DD>
 <P>The <EM>MSNT-multi-domain</EM> helper has been removed.</P>
+<P>The SMB LanMan helper <EM>SMB_LM</EM> is no longer built by default.
+It needs to be explicitly listed to be built.</P>
 
 <DT><B>--enable-auth-ntlm</B><DD>
 <P>The SMB LanMan helper is now built using <EM>SMB_LM</EM>
 (was lower case <EM>smb_lm</EM>).</P>
+<P>The SMB LanMan helper <EM>SMB_LM</EM> is no longer built by default.
+It needs to be explicitly listed to be built.</P>
 
 <DT><B>--enable-diskio</B><DD>
 <P>Auto-detection of SMP related modules has been fixed to
diff -u -r -N squid-4.0.10/scripts/find-alive.pl squid-4.0.11/scripts/find-alive.pl
--- squid-4.0.10/scripts/find-alive.pl	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/scripts/find-alive.pl	2016-06-10 08:32:57.000000000 +1200
@@ -55,8 +55,8 @@
 		'HttpStateData (\S+) destroyed',
 	],
 	cbdata => [
-		'cbdataAlloc: (\S+)',
-		'(?:cbdataFree|cbdataUnlock): Freeing (\S+)',
+		'cbdataInternalAlloc: Allocating (\S+)',
+		'cbdataRealFree: Freeing (\S+)',
 	],
 	FD => [
 		'fd_open.*\sFD (\d+)',
diff -u -r -N squid-4.0.10/SPONSORS squid-4.0.11/SPONSORS
--- squid-4.0.10/SPONSORS	2016-05-06 23:37:22.000000000 +1200
+++ squid-4.0.11/SPONSORS	2016-06-10 08:35:20.000000000 +1200
@@ -24,6 +24,11 @@
 	testing infrastructure, and since late 2014 to host many of the
 	Squid Project services.
 
+RM Education - http://www.rm.com/
+ 
+	RM Education has sponsored Squid performance optimizations and
+	stability improvements.
+
 Squid Software Foundation - http://foundation.squid-cache.org/
 
 	The Foundation governs and facilitates Squid project activities,
@@ -32,7 +37,7 @@
 
 The Measurement Factory - http://www.measurement-factory.com/
 
-	Measurement Factory has constributed significant resources
+	Measurement Factory has contributed significant resources
 	toward Squid-3+ development and server maintenance.
 
 Treehouse Networks, NZ - http://treenet.co.nz/
@@ -90,7 +95,7 @@
 
 BBC (UK) and Siemens IT Solutions and Services (UK)
 
-	Provided developement and testing resources for Solaris /dev/poll
+	Provided development and testing resources for Solaris /dev/poll
 	support in Squid-3.1.
 
 webwasher AG - http://www.webwasher.com/
@@ -131,7 +136,7 @@
 Yahoo! Inc. - http://www.yahoo.com/
 
 	Yahoo! Inc. supported the development of improved refresh
-	logics. Many thanks to Yahoo! Inc. for supporting the development
+	logic. Many thanks to Yahoo! Inc. for supporting the development
 	of these features.
 
 
diff -u -r -N squid-4.0.10/src/acl/external/delayer/ext_delayer_acl.8 squid-4.0.11/src/acl/external/delayer/ext_delayer_acl.8
--- squid-4.0.10/src/acl/external/delayer/ext_delayer_acl.8	2016-05-07 00:30:34.000000000 +1200
+++ squid-4.0.11/src/acl/external/delayer/ext_delayer_acl.8	2016-06-10 09:28:37.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_DELAYER_ACL 8"
-.TH EXT_DELAYER_ACL 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_DELAYER_ACL 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/acl/external/SQL_session/ext_sql_session_acl.8 squid-4.0.11/src/acl/external/SQL_session/ext_sql_session_acl.8
--- squid-4.0.10/src/acl/external/SQL_session/ext_sql_session_acl.8	2016-05-07 00:30:46.000000000 +1200
+++ squid-4.0.11/src/acl/external/SQL_session/ext_sql_session_acl.8	2016-06-10 09:28:45.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_SQL_SESSION_ACL 8"
-.TH EXT_SQL_SESSION_ACL 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_SQL_SESSION_ACL 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8 squid-4.0.11/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8
--- squid-4.0.10/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8	2016-05-07 00:30:51.000000000 +1200
+++ squid-4.0.11/src/acl/external/wbinfo_group/ext_wbinfo_group_acl.8	2016-06-10 09:28:48.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "EXT_WBINFO_GROUP_ACL 8"
-.TH EXT_WBINFO_GROUP_ACL 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH EXT_WBINFO_GROUP_ACL 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/acl/Makefile.am squid-4.0.11/src/acl/Makefile.am
--- squid-4.0.10/src/acl/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/acl/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -177,14 +177,14 @@
 	AdaptationServiceData.h \
 	AdaptationServiceData.cc
 
-if USE_ADAPTATION
+if ENABLE_ADAPTATION
 libacls_la_SOURCES += $(ADAPT_ACLS)
 endif
 EXTRA_libacls_la_SOURCES += $(ADAPT_ACLS)
 
 ARP_ACLS = Arp.cc Arp.h Eui64.cc Eui64.h
 
-if USE_SQUID_EUI
+if ENABLE_EUI
 libacls_la_SOURCES += $(ARP_ACLS)
 endif
 EXTRA_libacls_la_SOURCES += $(ARP_ACLS)
diff -u -r -N squid-4.0.10/src/acl/Makefile.in squid-4.0.11/src/acl/Makefile.in
--- squid-4.0.10/src/acl/Makefile.in	2016-05-06 23:36:32.000000000 +1200
+++ squid-4.0.11/src/acl/Makefile.in	2016-06-10 08:34:31.000000000 +1200
@@ -91,8 +91,8 @@
 check_PROGRAMS =
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL)
 @ENABLE_SSL_TRUE@am__append_2 = $(SSL_ACLS)
-@USE_ADAPTATION_TRUE@am__append_3 = $(ADAPT_ACLS)
-@USE_SQUID_EUI_TRUE@am__append_4 = $(ARP_ACLS)
+@ENABLE_ADAPTATION_TRUE@am__append_3 = $(ADAPT_ACLS)
+@ENABLE_EUI_TRUE@am__append_4 = $(ARP_ACLS)
 subdir = src/acl
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude/ax_with_prog.m4 \
@@ -202,9 +202,9 @@
 	SslErrorData.lo
 @ENABLE_SSL_TRUE@am__objects_2 = $(am__objects_1)
 am__objects_3 = AdaptationService.lo AdaptationServiceData.lo
-@USE_ADAPTATION_TRUE@am__objects_4 = $(am__objects_3)
+@ENABLE_ADAPTATION_TRUE@am__objects_4 = $(am__objects_3)
 am__objects_5 = Arp.lo Eui64.lo
-@USE_SQUID_EUI_TRUE@am__objects_6 = $(am__objects_5)
+@ENABLE_EUI_TRUE@am__objects_6 = $(am__objects_5)
 am_libacls_la_OBJECTS = IntRange.lo RegexData.lo StringData.lo Time.lo \
 	TimeData.lo AllOf.lo AnyOf.lo Asn.lo Browser.lo \
 	ConnectionsEncrypted.lo DestinationDomain.lo DestinationIp.lo \
diff -u -r -N squid-4.0.10/src/adaptation/ecap/Host.cc squid-4.0.11/src/adaptation/ecap/Host.cc
--- squid-4.0.10/src/adaptation/ecap/Host.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/adaptation/ecap/Host.cc	2016-06-10 08:32:57.000000000 +1200
@@ -147,18 +147,16 @@
 {
     const int squidLevel = SquidLogLevel(lv);
     const int squidSection = 93; // XXX: this should be a global constant
-    // XXX: Debug.h should provide this to us
-    if ((Debug::level = squidLevel) <= Debug::Levels[squidSection])
-        return &Debug::getDebugOut();
-    else
-        return NULL;
+    return Debug::Enabled(squidSection, squidLevel) ?
+           &Debug::Start(squidSection, squidLevel) :
+           nullptr;
 }
 
 void
 Adaptation::Ecap::Host::closeDebug(std::ostream *debug)
 {
     if (debug)
-        Debug::finishDebug();
+        Debug::Finish();
 }
 
 Adaptation::Ecap::Host::MessagePtr
diff -u -r -N squid-4.0.10/src/adaptation/Makefile.am squid-4.0.11/src/adaptation/Makefile.am
--- squid-4.0.10/src/adaptation/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/adaptation/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -11,11 +11,11 @@
 ## make a list of directories for configured adaptation schemes
 SUBDIRS =
 
-if USE_ICAP_CLIENT
+if ENABLE_ICAP_CLIENT
 SUBDIRS += icap
 endif
 
-if USE_ECAP
+if ENABLE_ECAP
 SUBDIRS += ecap
 endif
 
@@ -53,7 +53,7 @@
 	ServiceFilter.cc \
 	ServiceFilter.h \
 	History.cc \
-	History.h 
+	History.h
 
 # add libraries for specific adaptation schemes
 libadaptation_la_LIBADD = $(ECAP_LIBS) $(ICAP_LIBS)
diff -u -r -N squid-4.0.10/src/adaptation/Makefile.in squid-4.0.11/src/adaptation/Makefile.in
--- squid-4.0.10/src/adaptation/Makefile.in	2016-05-06 23:36:38.000000000 +1200
+++ squid-4.0.11/src/adaptation/Makefile.in	2016-06-10 08:34:37.000000000 +1200
@@ -90,8 +90,8 @@
 host_triplet = @host@
 check_PROGRAMS =
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL)
-@USE_ICAP_CLIENT_TRUE@am__append_2 = icap
-@USE_ECAP_TRUE@am__append_3 = ecap
+@ENABLE_ICAP_CLIENT_TRUE@am__append_2 = icap
+@ENABLE_ECAP_TRUE@am__append_3 = ecap
 subdir = src/adaptation
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude/ax_with_prog.m4 \
@@ -795,7 +795,7 @@
 	ServiceFilter.cc \
 	ServiceFilter.h \
 	History.cc \
-	History.h 
+	History.h
 
 
 # add libraries for specific adaptation schemes
diff -u -r -N squid-4.0.10/src/anyp/PortCfg.cc squid-4.0.11/src/anyp/PortCfg.cc
--- squid-4.0.10/src/anyp/PortCfg.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/anyp/PortCfg.cc	2016-06-10 08:32:57.000000000 +1200
@@ -143,9 +143,7 @@
         }
     }
 
-    secure.updateTlsVersionLimits();
-    secure.staticContext.reset(sslCreateServerContext(*this));
-
+    secure.staticContext.reset(secure.createStaticServerContext(*this));
     if (!secure.staticContext) {
         char buf[128];
         fatalf("%s_port %s initialization error", AnyP::ProtocolType_str[transport.protocol], s.toUrl(buf, sizeof(buf)));
diff -u -r -N squid-4.0.10/src/anyp/ProtocolType.cc squid-4.0.11/src/anyp/ProtocolType.cc
--- squid-4.0.10/src/anyp/ProtocolType.cc	2016-05-07 00:30:08.000000000 +1200
+++ squid-4.0.11/src/anyp/ProtocolType.cc	2016-06-10 09:28:14.000000000 +1200
@@ -23,6 +23,8 @@
 	"URN",
 	"WHOIS",
 	"ICY",
+	"TLS",
+	"SSL",
 	"UNKNOWN",
 	"MAX"
 };
diff -u -r -N squid-4.0.10/src/anyp/ProtocolType.h squid-4.0.11/src/anyp/ProtocolType.h
--- squid-4.0.10/src/anyp/ProtocolType.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/anyp/ProtocolType.h	2016-06-10 08:32:57.000000000 +1200
@@ -36,6 +36,8 @@
     PROTO_URN,
     PROTO_WHOIS,
     PROTO_ICY,
+    PROTO_TLS,
+    PROTO_SSL,
     PROTO_UNKNOWN,
     PROTO_MAX
 } ProtocolType;
diff -u -r -N squid-4.0.10/src/auth/basic/DB/basic_db_auth.8 squid-4.0.11/src/auth/basic/DB/basic_db_auth.8
--- squid-4.0.10/src/auth/basic/DB/basic_db_auth.8	2016-05-07 00:31:30.000000000 +1200
+++ squid-4.0.11/src/auth/basic/DB/basic_db_auth.8	2016-06-10 09:29:13.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_DB_AUTH 8"
-.TH BASIC_DB_AUTH 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH BASIC_DB_AUTH 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/auth/basic/POP3/basic_pop3_auth.8 squid-4.0.11/src/auth/basic/POP3/basic_pop3_auth.8
--- squid-4.0.10/src/auth/basic/POP3/basic_pop3_auth.8	2016-05-07 00:31:41.000000000 +1200
+++ squid-4.0.11/src/auth/basic/POP3/basic_pop3_auth.8	2016-06-10 09:29:20.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "BASIC_POP3_AUTH 8"
-.TH BASIC_POP3_AUTH 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH BASIC_POP3_AUTH 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/auth/basic/SMB_LM/required.m4 squid-4.0.11/src/auth/basic/SMB_LM/required.m4
--- squid-4.0.10/src/auth/basic/SMB_LM/required.m4	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/auth/basic/SMB_LM/required.m4	2016-06-10 08:32:57.000000000 +1200
@@ -5,7 +5,10 @@
 ## Please see the COPYING and CONTRIBUTORS files for details.
 ##
 
-BUILD_HELPER="SMB_LM"
-
 # DONT build this helper on Windows
-AC_CHECK_HEADERS([w32api/windows.h windows.h],[BUILD_HELPER=""])
+# DONT build this helper by default
+if test "x$auto_auth_basic_modules" != "xyes";then
+  BUILD_HELPER="SMB_LM"
+  AC_CHECK_HEADERS([w32api/windows.h windows.h],[BUILD_HELPER=""])
+  require_smblib=`test "x$BUILD_HELPER" = "xSMB_LM"`
+fi
diff -u -r -N squid-4.0.10/src/auth/ntlm/SMB_LM/required.m4 squid-4.0.11/src/auth/ntlm/SMB_LM/required.m4
--- squid-4.0.10/src/auth/ntlm/SMB_LM/required.m4	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/auth/ntlm/SMB_LM/required.m4	2016-06-10 08:32:57.000000000 +1200
@@ -7,9 +7,11 @@
 
 #
 # DONT build this helper on Windows
+# DONT build this helper by default
 #
 # XXX: do we really need the mingw check?
-if test "$squid_host_os" != "mingw"; then
+if test "$squid_host_os" != "mingw" -a "x$auto_auth_ntlm_modules" != "xyes"; then
   BUILD_HELPER="SMB_LM"
   AC_CHECK_HEADERS([w32api/windows.h windows.h],[BUILD_HELPER=""])
+  require_smblib=`test "x$BUILD_HELPER" = "xSMB_LM"`
 fi
diff -u -r -N squid-4.0.10/src/base/Lock.h squid-4.0.11/src/base/Lock.h
--- squid-4.0.10/src/base/Lock.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/base/Lock.h	2016-06-10 08:32:57.000000000 +1200
@@ -33,7 +33,7 @@
     /// All locks must be cleared before it may be destroyed.
     void lock() const {
 #if defined(LOCKCOUNT_DEBUG)
-        old_debug(0,1)("Incrementing this %p from count %u\n",this,count_);
+        debugs(0,1, "Incrementing this " << static_cast<void*>(this) << " from count " << count_);
 #endif
         assert(count_ < UINT32_MAX);
         ++count_;
@@ -43,7 +43,7 @@
     /// All locks must be cleared before it may be destroyed.
     uint32_t unlock() const {
 #if defined(LOCKCOUNT_DEBUG)
-        old_debug(0,1)("Decrementing this %p from count %u\n",this,count_);
+        debugs(0,1, "Decrementing this " << static_cast<void*>(this) << " from count " << count_);
 #endif
         assert(count_ > 0);
         return --count_;
diff -u -r -N squid-4.0.10/src/cbdata.cc squid-4.0.11/src/cbdata.cc
--- squid-4.0.10/src/cbdata.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/cbdata.cc	2016-06-10 08:32:57.000000000 +1200
@@ -162,6 +162,13 @@
     }
 
 #endif
+
+#if WITH_VALGRIND
+    void *p = data;
+#else
+    void *p = this;
+#endif
+    cbdata_index[type].pool->freeOne(p);
 }
 
 static void
@@ -255,25 +262,24 @@
 void
 cbdataRealFree(cbdata *c, const char *file, const int line)
 {
-    void *p = c;
+#if WITH_VALGRIND
+    void *p = c->data;
+#else
+    void *p = (void *)&c->data;
+#endif
 
     --cbdataCount;
-    debugs(45, 9, "Freeing " << p);
 #if USE_CBDATA_DEBUG
+    debugs(45, 3, "Freeing " << p << ' ' << file << ':' << line);
     dlinkDelete(&c->link, &cbdataEntries);
+#else
+    debugs(45, 9, "Freeing " << p);
 #endif
 
 #if WITH_VALGRIND
-    cbdata_htable.erase(c->data);
-#if USE_CBDATA_DEBUG
-    debugs(45, 3, "Call delete " << p << " " << file << ":" << line);
-#endif
+    cbdata_htable.erase(p);
     delete c;
 #else
-#if USE_CBDATA_DEBUG
-    debugs(45, 3, "Call cbdata::~cbdata() " << p << " " << file << ":" << line);
-#endif
-
     /* This is ugly. But: operator delete doesn't get
      * the type parameter, so we can't use that
      * to free the memory.
@@ -284,9 +290,7 @@
      * we could use the normal delete operator
      * and it would Just Work. RBC 20030902
      */
-    cbdata_type theType = c->type;
     c->cbdata::~cbdata();
-    cbdata_index[theType].pool->freeOne(p);
 #endif
 }
 
diff -u -r -N squid-4.0.10/src/cf.data.pre squid-4.0.11/src/cf.data.pre
--- squid-4.0.10/src/cf.data.pre	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/cf.data.pre	2016-06-10 08:32:57.000000000 +1200
@@ -163,13 +163,19 @@
 	This option is not yet supported by Squid-3.
 DOC_END
 
-# Options removed in 3.6
+# Options removed in 4.x
 NAME: cache_peer_domain cache_host_domain
 TYPE: obsolete
 DOC_START
 	Replace with dstdomain ACLs and cache_peer_access.
 DOC_END
 
+NAME: ie_refresh
+TYPE: obsolete
+DOC_START
+	Remove this line. The behaviour enabled by this is no longer needed.
+DOC_END
+
 NAME: sslproxy_cafile
 TYPE: obsolete
 DOC_START
@@ -5889,30 +5895,6 @@
 	replies as required by RFC2616.
 DOC_END
 
-NAME: ie_refresh
-COMMENT: on|off
-TYPE: onoff
-LOC: Config.onoff.ie_refresh
-DEFAULT: off
-DOC_START
-	Microsoft Internet Explorer up until version 5.5 Service
-	Pack 1 has an issue with transparent proxies, wherein it
-	is impossible to force a refresh.  Turning this on provides
-	a partial fix to the problem, by causing all IMS-REFRESH
-	requests from older IE versions to check the origin server
-	for fresh content.  This reduces hit ratio by some amount
-	(~10% in my experience), but allows users to actually get
-	fresh content when they want it.  Note because Squid
-	cannot tell if the user is using 5.5 or 5.5SP1, the behavior
-	of 5.5 is unchanged from old versions of Squid (i.e. a
-	forced refresh is impossible).  Newer versions of IE will,
-	hopefully, continue to have the new behavior and will be
-	handled based on that assumption.  This option defaults to
-	the old Squid behavior, which is better for hit ratios but
-	worse for clients using IE, if they need to be able to
-	force fresh content.
-DOC_END
-
 NAME: vary_ignore_expire
 COMMENT: on|off
 TYPE: onoff
diff -u -r -N squid-4.0.10/src/client_side.cc squid-4.0.11/src/client_side.cc
--- squid-4.0.10/src/client_side.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/client_side.cc	2016-06-10 08:32:57.000000000 +1200
@@ -2185,6 +2185,13 @@
 void
 ConnStateData::afterClientRead()
 {
+#if USE_OPENSSL
+    if (parsingTlsHandshake) {
+        parseTlsHandshake();
+        return;
+    }
+#endif
+
     /* Process next request */
     if (pipeline.empty())
         fd_note(clientConnection->fd, "Reading next request");
@@ -2417,6 +2424,7 @@
     needProxyProtocolHeader_(false),
 #if USE_OPENSSL
     switchedToHttps_(false),
+    parsingTlsHandshake(false),
     sslServerBump(NULL),
     signAlgorithm(Ssl::algSignTrusted),
 #endif
@@ -2602,11 +2610,11 @@
         switch (ssl_error) {
 
         case SSL_ERROR_WANT_READ:
-            Comm::SetSelect(fd, COMM_SELECT_READ, callback, conn, 0);
+            Comm::SetSelect(fd, COMM_SELECT_READ, callback, (callback != NULL ? conn : NULL), 0);
             return 0;
 
         case SSL_ERROR_WANT_WRITE:
-            Comm::SetSelect(fd, COMM_SELECT_WRITE, callback, conn, 0);
+            Comm::SetSelect(fd, COMM_SELECT_WRITE, callback, (callback != NULL ? conn : NULL), 0);
             return 0;
 
         case SSL_ERROR_SYSCALL:
@@ -2653,7 +2661,7 @@
         debugs(83, 2, "clientNegotiateSSL: Session " << SSL_get_session(ssl) <<
                " reused on FD " << fd << " (" << fd_table[fd].ipaddr << ":" << (int)fd_table[fd].remote_port << ")");
     } else {
-        if (do_debug(83, 4)) {
+        if (Debug::Enabled(83, 4)) {
             /* Write out the SSL session details.. actually the call below, but
              * OpenSSL headers do strange typecasts confusing GCC.. */
             /* PEM_write_SSL_SESSION(debug_log, SSL_get_session(ssl)); */
@@ -2687,7 +2695,7 @@
     }
 
     // Connection established. Retrieve TLS connection parameters for logging.
-    conn->clientConnection->tlsNegotiations()->fillWith(ssl);
+    conn->clientConnection->tlsNegotiations()->retrieveNegotiatedInfo(ssl);
 
     client_cert = SSL_get_peer_certificate(ssl);
 
@@ -3089,10 +3097,14 @@
                                      this, ConnStateData::requestTimeout);
     commSetConnTimeout(clientConnection, Config.Timeout.request, timeoutCall);
 
-    // Disable the client read handler until CachePeer selection is complete
-    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0);
-    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, clientNegotiateSSL, this, 0);
     switchedToHttps_ = true;
+
+    auto ssl = fd_table[clientConnection->fd].ssl.get();
+    BIO *b = SSL_get_rbio(ssl);
+    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
+    bio->setReadBufData(inBuf);
+    inBuf.clear();
+    clientNegotiateSSL(clientConnection->fd, this);
 }
 
 void
@@ -3117,19 +3129,67 @@
     if (bumpServerMode == Ssl::bumpServerFirst && !sslServerBump) {
         request->flags.sslPeek = true;
         sslServerBump = new Ssl::ServerBump(request);
-
-        // will call httpsPeeked() with certificate and connection, eventually
-        FwdState::fwdStart(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw());
-        return;
     } else if (bumpServerMode == Ssl::bumpPeek || bumpServerMode == Ssl::bumpStare) {
         request->flags.sslPeek = true;
         sslServerBump = new Ssl::ServerBump(request, NULL, bumpServerMode);
-        startPeekAndSplice();
-        return;
     }
 
-    // otherwise, use sslConnectHostOrIp
-    getSslContextStart();
+    // commSetConnTimeout() was called for this request before we switched.
+    // Fix timeout to request_start_timeout
+    typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
+    AsyncCall::Pointer timeoutCall =  JobCallback(33, 5,
+                                      TimeoutDialer, this, ConnStateData::requestTimeout);
+    commSetConnTimeout(clientConnection, Config.Timeout.request_start_timeout, timeoutCall);
+    // Also reset receivedFirstByte_ flag to allow this timeout work in the case we have
+    // a bumbed "connect" request on non transparent port.
+    receivedFirstByte_ = false;
+    // Get more data to peek at Tls
+    parsingTlsHandshake = true;
+    readSomeData();
+}
+
+void
+ConnStateData::parseTlsHandshake()
+{
+    Must(parsingTlsHandshake);
+
+    assert(!inBuf.isEmpty());
+    receivedFirstByte();
+    fd_note(clientConnection->fd, "Parsing TLS handshake");
+
+    bool unsupportedProtocol = false;
+    try {
+        if (!tlsParser.parseHello(inBuf)) {
+            // need more data to finish parsing
+            readSomeData();
+            return;
+        }
+    }
+    catch (const std::exception &ex) {
+        debugs(83, 2, "error on FD " << clientConnection->fd << ": " << ex.what());
+        unsupportedProtocol = true;
+    }
+
+    parsingTlsHandshake = false;
+
+    // Even if the parser failed, each TLS detail should either be set
+    // correctly or still be "unknown"; copying unknown detail is a no-op.
+    clientConnection->tlsNegotiations()->retrieveParsedInfo(tlsParser.details);
+
+    // We should disable read/write handlers
+    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0);
+    Comm::SetSelect(clientConnection->fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+
+    if (!sslServerBump) { // BumpClientFirst mode does not use this member
+        getSslContextStart();
+        return;
+    } else if (sslServerBump->act.step1 == Ssl::bumpServerFirst) {
+        // will call httpsPeeked() with certificate and connection, eventually
+        FwdState::fwdStart(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw());
+    } else {
+        Must(sslServerBump->act.step1 == Ssl::bumpPeek || sslServerBump->act.step1 == Ssl::bumpStare);
+        startPeekAndSplice(unsupportedProtocol);
+    }
 }
 
 bool
@@ -3148,77 +3208,24 @@
     return false;
 }
 
-/** negotiate an SSL connection */
-static void
-clientPeekAndSpliceSSL(int fd, void *data)
+void
+ConnStateData::startPeekAndSplice(const bool unsupportedProtocol)
 {
-    ConnStateData *conn = (ConnStateData *)data;
-    auto ssl = fd_table[fd].ssl.get();
-
-    debugs(83, 5, "Start peek and splice on FD " << fd);
-
-    int ret = 0;
-    if ((ret = Squid_SSL_accept(conn, clientPeekAndSpliceSSL)) < 0)
-        debugs(83, 2, "SSL_accept failed.");
-
-    BIO *b = SSL_get_rbio(ssl);
-    assert(b);
-    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
-    if (ret < 0) {
-        const err_type err = bio->noSslClient() ? ERR_PROTOCOL_UNKNOWN : ERR_SECURE_ACCEPT_FAIL;
-        if (!conn->spliceOnError(err))
-            conn->clientConnection->close();
+    if (unsupportedProtocol) {
+        if (!spliceOnError(ERR_PROTOCOL_UNKNOWN))
+            clientConnection->close();
         return;
     }
 
-    if (bio->rBufData().contentSize() > 0)
-        conn->receivedFirstByte();
-
-    if (bio->gotHello()) {
-        if (conn->serverBump()) {
-            Ssl::Bio::sslFeatures const &features = bio->receivedHelloFeatures();
-            if (!features.serverName.isEmpty()) {
-                conn->serverBump()->clientSni = features.serverName;
-                conn->resetSslCommonName(features.serverName.c_str());
-            }
+    if (serverBump()) {
+        Security::TlsDetails::Pointer const &details = tlsParser.details;
+        if (details && !details->serverName.isEmpty()) {
+            serverBump()->clientSni = details->serverName;
+            resetSslCommonName(details->serverName.c_str());
         }
-
-        debugs(83, 5, "I got hello. Start forwarding the request!!! ");
-        Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
-        Comm::SetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
-        conn->startPeekAndSpliceDone();
-        return;
     }
-}
-
-void ConnStateData::startPeekAndSplice()
-{
-    // will call httpsPeeked() with certificate and connection, eventually
-    auto unConfiguredCTX = Ssl::createSSLContext(port->signingCert, port->signPkey, *port);
-    fd_table[clientConnection->fd].dynamicSslContext = unConfiguredCTX;
-
-    if (!httpsCreate(clientConnection, unConfiguredCTX))
-        return;
-
-    // commSetConnTimeout() was called for this request before we switched.
-    // Fix timeout to request_start_timeout
-    typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> TimeoutDialer;
-    AsyncCall::Pointer timeoutCall =  JobCallback(33, 5,
-                                      TimeoutDialer, this, ConnStateData::requestTimeout);
-    commSetConnTimeout(clientConnection, Config.Timeout.request_start_timeout, timeoutCall);
-    // Also reset receivedFirstByte_ flag to allow this timeout work in the case we have
-    // a bumbed "connect" request on non transparent port.
-    receivedFirstByte_ = false;
 
-    // Disable the client read handler until CachePeer selection is complete
-    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, NULL, NULL, 0);
-    Comm::SetSelect(clientConnection->fd, COMM_SELECT_READ, clientPeekAndSpliceSSL, this, 0);
-    switchedToHttps_ = true;
-
-    auto ssl = fd_table[clientConnection->fd].ssl.get();
-    BIO *b = SSL_get_rbio(ssl);
-    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
-    bio->hold(true);
+    startPeekAndSpliceDone();
 }
 
 void httpsSslBumpStep2AccessCheckDone(allow_t answer, void *data)
@@ -3252,34 +3259,23 @@
 ConnStateData::splice()
 {
     // normally we can splice here, because we just got client hello message
-    auto ssl = fd_table[clientConnection->fd].ssl.get();
-
-    //retrieve received TLS client information
-    clientConnection->tlsNegotiations()->fillWith(ssl);
 
-    BIO *b = SSL_get_rbio(ssl);
-    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
-    MemBuf const &rbuf = bio->rBufData();
-    debugs(83,5, "Bio for  " << clientConnection << " read " << rbuf.contentSize() << " helo bytes");
-    // Do splice:
-    fd_table[clientConnection->fd].read_method = &default_read_method;
-    fd_table[clientConnection->fd].write_method = &default_write_method;
+    if (fd_table[clientConnection->fd].ssl.get()) {
+        // Restore default read methods
+        fd_table[clientConnection->fd].read_method = &default_read_method;
+        fd_table[clientConnection->fd].write_method = &default_write_method;
+    }
 
     if (transparent()) {
         // set the current protocol to something sensible (was "HTTPS" for the bumping process)
         // we are sending a faked-up HTTP/1.1 message wrapper, so go with that.
         transferProtocol = Http::ProtocolVersion();
-        // XXX: copy from MemBuf reallocates, not a regression since old code did too
-        SBuf temp;
-        temp.append(rbuf.content(), rbuf.contentSize());
-        return fakeAConnectRequest("intercepted TLS spliced", temp);
+        return fakeAConnectRequest("intercepted TLS spliced", inBuf);
     } else {
         // XXX: assuming that there was an HTTP/1.1 CONNECT to begin with...
 
         // reset the current protocol to HTTP/1.1 (was "HTTPS" for the bumping process)
         transferProtocol = Http::ProtocolVersion();
-        // inBuf still has the "CONNECT ..." request data, reset it to SSL hello message
-        inBuf.append(rbuf.content(), rbuf.contentSize());
         Http::StreamPointer context = pipeline.front();
         ClientHttpRequest *http = context->http;
         tunnelStart(http);
@@ -3310,6 +3306,39 @@
         return;
     }
 
+    // will call httpsPeeked() with certificate and connection, eventually
+    auto unConfiguredCTX = Ssl::createSSLContext(port->signingCert, port->signPkey, *port);
+    fd_table[clientConnection->fd].dynamicSslContext = unConfiguredCTX;
+
+    if (!httpsCreate(clientConnection, unConfiguredCTX))
+        return;
+
+    switchedToHttps_ = true;
+
+    auto ssl = fd_table[clientConnection->fd].ssl.get();
+    BIO *b = SSL_get_rbio(ssl);
+    Ssl::ClientBio *bio = static_cast<Ssl::ClientBio *>(b->ptr);
+    bio->setReadBufData(inBuf);
+    bio->hold(true);
+
+    // Here squid should have all of the client hello message so the
+    // Squid_SSL_accept should return 0;
+    // This block exist only to force openSSL parse client hello and detect
+    // ERR_SECURE_ACCEPT_FAIL error, which should be checked and splice if required.
+    int ret = 0;
+    if ((ret = Squid_SSL_accept(this, NULL)) < 0) {
+        debugs(83, 2, "SSL_accept failed.");
+        const err_type err = ERR_SECURE_ACCEPT_FAIL;
+        if (!spliceOnError(err))
+            clientConnection->close();
+        return;
+    }
+
+    // We need to reset inBuf here, to be used by incoming requests in the case
+    // of SSL bump
+    inBuf.clear();
+
+    debugs(83, 5, "Peek and splice at step2 done. Start forwarding the request!!! ");
     FwdState::Start(clientConnection, sslServerBump->entry, sslServerBump->request.getRaw(), http ? http->al : NULL);
 }
 
diff -u -r -N squid-4.0.10/src/client_side.h squid-4.0.11/src/client_side.h
--- squid-4.0.10/src/client_side.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/client_side.h	2016-06-10 08:32:57.000000000 +1200
@@ -24,6 +24,7 @@
 #include "auth/UserRequest.h"
 #endif
 #if USE_OPENSSL
+#include "security/Handshake.h"
 #include "ssl/support.h"
 #endif
 
@@ -202,7 +203,7 @@
     void postHttpsAccept();
 
     /// Initializes and starts a peek-and-splice negotiation with the SSL client
-    void startPeekAndSplice();
+    void startPeekAndSplice(const bool unknownProtocol);
     /// Called when the initialization of peek-and-splice negotiation finidhed
     void startPeekAndSpliceDone();
     /// Called when a peek-and-splice step finished. For example after
@@ -234,6 +235,7 @@
     void sslCrtdHandleReply(const Helper::Reply &reply);
 
     void switchToHttps(HttpRequest *request, Ssl::BumpMode bumpServerMode);
+    void parseTlsHandshake();
     bool switchedToHttps() const { return switchedToHttps_; }
     Ssl::ServerBump *serverBump() {return sslServerBump;}
     inline void setServerBump(Ssl::ServerBump *srvBump) {
@@ -255,6 +257,9 @@
 
     Ssl::BumpMode sslBumpMode; ///< ssl_bump decision (Ssl::bumpEnd if n/a).
 
+    /// Tls parser to use for client HELLO messages parsing on bumped
+    /// connections.
+    Security::HandshakeParser tlsParser;
 #else
     bool switchedToHttps() const { return false; }
 #endif
@@ -350,6 +355,8 @@
 
 #if USE_OPENSSL
     bool switchedToHttps_;
+    bool parsingTlsHandshake; ///< whether we are getting/parsing TLS Hello bytes
+
     /// The SSL server host name appears in CONNECT request or the server ip address for the intercepted requests
     String sslConnectHostOrIp; ///< The SSL server host name as passed in the CONNECT request
     SBuf sslCommonName_; ///< CN name for SSL certificate generation
diff -u -r -N squid-4.0.10/src/client_side_reply.cc squid-4.0.11/src/client_side_reply.cc
--- squid-4.0.10/src/client_side_reply.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/client_side_reply.cc	2016-06-10 08:32:57.000000000 +1200
@@ -278,6 +278,7 @@
         return;
     }
 
+    http->logType = LOG_TCP_REFRESH;
     http->request->flags.refresh = true;
 #if STORE_CLIENT_LIST_DEBUG
     /* Prevent a race with the store client memory free routines
@@ -1532,9 +1533,7 @@
     }
 
     // Decide if we send chunked reply
-    if (maySendChunkedReply &&
-            request->flags.proxyKeepalive &&
-            reply->bodySize(request->method) < 0) {
+    if (maySendChunkedReply && reply->bodySize(request->method) < 0) {
         debugs(88, 3, "clientBuildReplyHeader: chunked reply");
         request->flags.chunkedReply = true;
         hdr->putStr(Http::HdrType::TRANSFER_ENCODING, "chunked");
diff -u -r -N squid-4.0.10/src/client_side_request.cc squid-4.0.11/src/client_side_request.cc
--- squid-4.0.10/src/client_side_request.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/client_side_request.cc	2016-06-10 08:32:57.000000000 +1200
@@ -1056,7 +1056,6 @@
     HttpRequest *request = http->request;
     HttpHeader *req_hdr = &request->header;
     bool no_cache = false;
-    const char *str;
 
     request->imslen = -1;
     request->ims = req_hdr->getTime(Http::HdrType::IF_MODIFIED_SINCE);
@@ -1072,28 +1071,6 @@
             // RFC 2616: treat Pragma:no-cache as if it was Cache-Control:no-cache when Cache-Control is missing
         } else if (req_hdr->has(Http::HdrType::PRAGMA))
             no_cache = req_hdr->hasListMember(Http::HdrType::PRAGMA,"no-cache",',');
-
-        /*
-        * Work around for supporting the Reload button in IE browsers when Squid
-        * is used as an accelerator or transparent proxy, by turning accelerated
-        * IMS request to no-cache requests. Now knows about IE 5.5 fix (is
-        * actually only fixed in SP1, but we can't tell whether we are talking to
-        * SP1 or not so all 5.5 versions are treated 'normally').
-        */
-        if (Config.onoff.ie_refresh) {
-            if (http->flags.accel && request->flags.ims) {
-                if ((str = req_hdr->getStr(Http::HdrType::USER_AGENT))) {
-                    if (strstr(str, "MSIE 5.01") != NULL)
-                        no_cache=true;
-                    else if (strstr(str, "MSIE 5.0") != NULL)
-                        no_cache=true;
-                    else if (strstr(str, "MSIE 4.") != NULL)
-                        no_cache=true;
-                    else if (strstr(str, "MSIE 3.") != NULL)
-                        no_cache=true;
-                }
-            }
-        }
     }
 
     if (request->method == Http::METHOD_OTHER) {
diff -u -r -N squid-4.0.10/src/debug.cc squid-4.0.11/src/debug.cc
--- squid-4.0.10/src/debug.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/debug.cc	2016-06-10 08:32:57.000000000 +1200
@@ -14,6 +14,8 @@
 #include "SquidTime.h"
 #include "util.h"
 
+#include <algorithm>
+
 /* for shutting_down flag in xassert() */
 #include "globals.h"
 
@@ -22,8 +24,6 @@
 int Debug::log_stderr = -1;
 bool Debug::log_syslog = false;
 int Debug::Levels[MAX_DEBUG_SECTIONS];
-int Debug::level;
-int Debug::sectionLevel;
 char *Debug::cache_log = NULL;
 int Debug::rotateNumber = -1;
 FILE *debug_log = NULL;
@@ -134,7 +134,7 @@
 static void
 _db_print_stderr(const char *format, va_list args)
 {
-    if (Debug::log_stderr < Debug::level)
+    if (Debug::log_stderr < Debug::Level())
         return;
 
     if (debug_log == stderr)
@@ -149,7 +149,7 @@
 {
     /* level 0,1 go to syslog */
 
-    if (Debug::level > 1)
+    if (Debug::Level() > 1)
         return;
 
     if (!Debug::log_syslog)
@@ -162,7 +162,7 @@
 
     tmpbuf[BUFSIZ - 1] = '\0';
 
-    syslog(Debug::level == 0 ? LOG_WARNING : LOG_NOTICE, "%s", tmpbuf);
+    syslog(Debug::Level() == 0 ? LOG_WARNING : LOG_NOTICE, "%s", tmpbuf);
 }
 #endif /* HAVE_SYSLOG */
 
@@ -524,7 +524,7 @@
     static char buf[128];
     static time_t last_t = 0;
 
-    if (Debug::level > 1) {
+    if (Debug::Level() > 1) {
         char buf2[128];
         tm = localtime(&t);
         strftime(buf2, 127, "%Y/%m/%d %H:%M:%S", tm);
@@ -726,55 +726,75 @@
     return Ctx_Descrs[ctx] ? Ctx_Descrs[ctx] : "<null>";
 }
 
-int Debug::TheDepth = 0;
+Debug::Context *Debug::Current = nullptr;
 
-Debug::OutStream *Debug::CurrentDebug(NULL);
+Debug::Context::Context(const int aSection, const int aLevel):
+    level(aLevel),
+    sectionLevel(Levels[aSection]),
+    upper(Current)
+{
+    formatStream();
+}
 
-std::ostream &
-Debug::getDebugOut()
+/// Optimization: avoids new Context creation for every debugs().
+void
+Debug::Context::rewind(const int aSection, const int aLevel)
 {
-    assert(TheDepth >= 0);
-    ++TheDepth;
-    if (TheDepth > 1) {
-        assert(CurrentDebug);
-        *CurrentDebug << std::endl << "reentrant debuging " << TheDepth << "-{";
-    } else {
-        assert(!CurrentDebug);
-        CurrentDebug = new Debug::OutStream;
-        // set default formatting flags
-        CurrentDebug->setf(std::ios::fixed);
-        CurrentDebug->precision(2);
-    }
-    return *CurrentDebug;
+    level = aLevel;
+    sectionLevel = Levels[aSection];
+    assert(upper == Current);
+
+    buf.str(std::string());
+    buf.clear();
+    // debugs() users are supposed to preserve format, but
+    // some do not, so we have to waste cycles resetting it for all.
+    formatStream();
 }
 
+/// configures default formatting for the debugging stream
 void
-Debug::finishDebug()
+Debug::Context::formatStream()
+{
+    const static std::ostringstream cleanStream;
+    buf.flags(cleanStream.flags() | std::ios::fixed);
+    buf.width(cleanStream.width());
+    buf.precision(2);
+    buf.fill(' ');
+    // If this is not enough, use copyfmt(cleanStream) which is ~10% slower.
+}
+
+std::ostringstream &
+Debug::Start(const int section, const int level)
 {
-    assert(TheDepth >= 0);
-    assert(CurrentDebug);
-    if (TheDepth > 1) {
-        *CurrentDebug << "}-" << TheDepth << std::endl;
+    Context *future = nullptr;
+
+    // prepare future context
+    if (Current) {
+        // all reentrant debugs() calls get here; create a dedicated context
+        future = new Context(section, level);
     } else {
-        assert(TheDepth == 1);
-        _db_print("%s\n", CurrentDebug->str().c_str());
-        delete CurrentDebug;
-        CurrentDebug = NULL;
+        // Optimization: Nearly all debugs() calls get here; avoid allocations
+        static Context *topContext = new Context(1, 1);
+        topContext->rewind(section, level);
+        future = topContext;
     }
-    --TheDepth;
+
+    Current = future;
+
+    return future->buf;
 }
 
-// Hack: replaces global ::xassert() to debug debugging assertions
-// Relies on assert macro calling xassert() without a specific scope.
 void
-Debug::xassert(const char *msg, const char *file, int line)
+Debug::Finish()
 {
+    // TODO: Optimize to remove at least one extra copy.
+    _db_print("%s\n", Current->buf.str().c_str());
 
-    if (CurrentDebug) {
-        *CurrentDebug << "assertion failed: " << file << ":" << line <<
-                      ": \"" << msg << "\"";
-    }
-    abort();
+    Context *past = Current;
+    Current = past->upper;
+    if (Current)
+        delete past;
+    // else it was a static topContext from Debug::Start()
 }
 
 size_t
@@ -800,6 +820,19 @@
     return path+BuildPrefixLength;
 }
 
+/// print data bytes using hex notation
+void
+Raw::printHex(std::ostream &os) const
+{
+    const auto savedFill = os.fill('0');
+    const auto savedFlags = os.flags(); // std::ios_base::fmtflags
+    os << std::hex;
+    std::for_each(data_, data_ + size_,
+    [&os](const char &c) { os << std::setw(2) << static_cast<uint8_t>(c); });
+    os.flags(savedFlags);
+    os.fill(savedFill);
+}
+
 std::ostream &
 Raw::print(std::ostream &os) const
 {
@@ -811,13 +844,17 @@
 
     // finalize debugging level if no level was set explicitly via minLevel()
     const int finalLevel = (level >= 0) ? level :
-                           (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
-    if (finalLevel <= Debug::sectionLevel) {
+                           (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
+    if (finalLevel <= Debug::SectionLevel()) {
         os << (label_ ? '=' : ' ');
-        if (data_)
-            os.write(data_, size_);
-        else
+        if (data_) {
+            if (useHex_)
+                printHex(os);
+            else
+                os.write(data_, size_);
+        } else {
             os << "[null]";
+        }
     }
 
     return os;
diff -u -r -N squid-4.0.10/src/Debug.h squid-4.0.11/src/Debug.h
--- squid-4.0.10/src/Debug.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/Debug.h	2016-06-10 08:32:57.000000000 +1200
@@ -52,36 +52,51 @@
 {
 
 public:
+    /// meta-information for debugs() or a similar debugging call
+    class Context
+    {
+    public:
+        Context(const int aSectionLevel, const int aLevel);
+
+        int level; ///< minimum debugging level required by the debugs() call
+        int sectionLevel; ///< maximum debugging level allowed during the call
+
+    private:
+        friend class Debug;
+        void rewind(const int aSection, const int aLevel);
+        void formatStream();
+        Context *upper; ///< previous or parent record in nested debugging calls
+        std::ostringstream buf; ///< debugs() output sink
+    };
+
+    /// whether debugging the given section and the given level produces output
+    static bool Enabled(const int section, const int level)
+    {
+        return level <= Debug::Levels[section];
+    }
+
     static char *debugOptions;
     static char *cache_log;
     static int rotateNumber;
     static int Levels[MAX_DEBUG_SECTIONS];
-    static int level; ///< minimum debugging level required by debugs() call
-    static int sectionLevel; ///< maximum debugging level allowed now
     static int override_X;
     static int log_stderr;
     static bool log_syslog;
 
-    static std::ostream &getDebugOut();
-    static void finishDebug();
     static void parseOptions(char const *);
 
-private:
-    // Hack: replaces global ::xassert() to debug debugging assertions
-    static void xassert(const char *msg, const char *file, int line);
+    /// minimum level required by the current debugs() call
+    static int Level() { return Current ? Current->level : 1; }
+    /// maximum level currently allowed
+    static int SectionLevel() { return Current ? Current->sectionLevel : 1; }
+
+    /// opens debugging context and returns output buffer
+    static std::ostringstream &Start(const int section, const int level);
+    /// logs output buffer created in Start() and closes debugging context
+    static void Finish();
 
-    /// Wrapper class to prevent SquidNew.h overrides getting confused
-    /// with the libc++6 std::ostringstream definitions
-    class OutStream : public std::ostringstream
-    {
-        MEMPROXY_CLASS(OutStream);
-    public:
-        void *operator new[] (size_t size) throw(std::bad_alloc) = delete; //{return xmalloc(size);}
-        void operator delete[] (void *address) throw() = delete; // {xfree(address);}
-    };
-
-    static OutStream *CurrentDebug;
-    static int TheDepth; // level of nested debugging calls
+private:
+    static Context *Current; ///< deepest active context; nil outside debugs()
 };
 
 extern FILE *debug_log;
@@ -97,15 +112,15 @@
  */
 #define debugs(SECTION, LEVEL, CONTENT) \
    do { \
-        if ((Debug::level = (LEVEL)) <= Debug::Levels[SECTION]) { \
-            Debug::sectionLevel = Debug::Levels[SECTION]; \
-            std::ostream &_dbo=Debug::getDebugOut(); \
-            if (Debug::level > DBG_IMPORTANT) { \
-                _dbo << (SECTION) << ',' << (LEVEL) << "| " \
+        const int _dbg_level = (LEVEL); \
+        if (Debug::Enabled((SECTION), _dbg_level)) { \
+            std::ostream &_dbo = Debug::Start((SECTION), _dbg_level); \
+            if (_dbg_level > DBG_IMPORTANT) { \
+                _dbo << (SECTION) << ',' << _dbg_level << "| " \
                      << SkipBuildPrefix(__FILE__)<<"("<<__LINE__<<") "<<__FUNCTION__<<": "; \
             } \
             _dbo << CONTENT; \
-            Debug::finishDebug(); \
+            Debug::Finish(); \
         } \
    } while (/*CONSTCOND*/ 0)
 
@@ -141,10 +156,6 @@
     return (os << (int)d);
 }
 
-/* Legacy debug style. Still used in some places. needs to die... */
-#define do_debug(SECTION, LEVEL)   ((Debug::level = (LEVEL)) <= Debug::Levels[SECTION])
-#define old_debug(SECTION, LEVEL)  if do_debug((SECTION), (LEVEL)) _db_print
-
 /* Legacy debug function definitions */
 void _db_init(const char *logfile, const char *options);
 void _db_print(const char *,...) PRINTF_FORMAT_ARG1;
@@ -159,11 +170,14 @@
 {
 public:
     Raw(const char *label, const char *data, const size_t size):
-        level(-1), label_(label), data_(data), size_(size) {}
+        level(-1), label_(label), data_(data), size_(size), useHex_(false) {}
 
     /// limit data printing to at least the given debugging level
     Raw &minLevel(const int aLevel) { level = aLevel; return *this; }
 
+    /// print data using two hex digits per byte (decoder: xxd -r -p)
+    Raw &hex() { useHex_ = true; return *this; }
+
     /// If debugging is prohibited by the current debugs() or section level,
     /// prints nothing. Otherwise, dumps data using one of these formats:
     ///   " label[size]=data" if label was set and data size is positive
@@ -178,9 +192,12 @@
     int level;
 
 private:
+    void printHex(std::ostream &os) const;
+
     const char *label_; ///< optional data name or ID; triggers size printing
     const char *data_; ///< raw data to be printed
     size_t size_; ///< data length
+    bool useHex_; ///< whether hex() has been called
 };
 
 inline
diff -u -r -N squid-4.0.10/src/esi/Expression.cc squid-4.0.11/src/esi/Expression.cc
--- squid-4.0.10/src/esi/Expression.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/esi/Expression.cc	2016-06-10 08:32:57.000000000 +1200
@@ -116,8 +116,6 @@
 static int membercompare(stackmember a, stackmember b);
 static char const *trim(char const *s);
 static stackmember getsymbol(const char *s, char const **endptr);
-static void printliteral(stackmember s);
-static void printmember(stackmember s);
 
 /* -2 = failed to compate
  * -1 = a less than b
@@ -846,105 +844,106 @@
     return rv;
 }
 
-void
-printliteral(stackmember s)
+static void
+printLiteral(std::ostream &os, const stackmember &s)
 {
     switch (s.valuestored) {
 
     case ESI_LITERAL_INVALID:
-        old_debug(86, 1)( " Invalid " );
+        os << " Invalid ";
         break;
 
     case ESI_LITERAL_FLOAT:
-        old_debug(86,1)("%f", s.value.floating);
+        os << s.value.floating;
         break;
 
     case ESI_LITERAL_STRING:
-        old_debug(86,1)("'%s'", s.value.string);
+        os << '\'' << s.value.string << '\'';
         break;
 
     case ESI_LITERAL_INT:
-        old_debug(86,1)("%d", s.value.integral);
+        os << s.value.integral;
         break;
 
     case ESI_LITERAL_BOOL:
-        old_debug(86,1)("%s",s.value.integral ? "true" : "false");
+        os << (s.value.integral ? "true" : "false");
     }
 }
 
-void
-printmember(stackmember s)
+static std::ostream &
+operator <<(std::ostream &os, const stackmember &s)
 {
     switch (s.valuetype) {
 
     case ESI_EXPR_INVALID:
-        old_debug(86,1)(" Invalid ");
+        os << " Invalid ";
         break;
 
     case ESI_EXPR_LITERAL:
-        printliteral(s);
+        printLiteral(os, s);
         break;
 
     case ESI_EXPR_EXPR:
-        old_debug(86,1)("%s", s.value.integral ? "true" : "false");
+        os << (s.value.integral ? "true" : "false");
         break;
 
     case ESI_EXPR_OR:
-        old_debug(86,1)("|");
+        os << "|";
         break;
 
     case ESI_EXPR_AND:
-        old_debug(86,1)("&");
+        os << "&";
         break;
 
     case ESI_EXPR_NOT:
-        old_debug(86,1)("!");
+        os << "!";
         break;
 
     case ESI_EXPR_START:
-        old_debug(86,1)("(");
+        os << "(";
         break;
 
     case ESI_EXPR_END:
-        old_debug(86,1)(")");
+        os << ")";
         break;
 
     case ESI_EXPR_EQ:
-        old_debug(86,1)("==");
+        os << "==";
         break;
 
     case ESI_EXPR_NOTEQ:
-        old_debug(86,1)("!=");
+        os << "!=";
         break;
 
     case ESI_EXPR_LESS:
-        old_debug(86,1)("<");
+        os << "<";
         break;
 
     case ESI_EXPR_LESSEQ:
-        old_debug(86,1)("<=");
+        os << "<=";
         break;
 
     case ESI_EXPR_MORE:
-        old_debug(86,1)(">");
+        os << ">";
         break;
 
     case ESI_EXPR_MOREEQ:
-        old_debug(86,1)(">=");
+        os << ">=";
         break;
     }
+
+    return os;
 }
 
 void
 dumpstack(stackmember * stack, int depth)
 {
-    int i;
-
-    for (i = 0; i < depth; ++i)
-        printmember(stack[i]);
-
-    if (depth)
-        old_debug(86,1)("\n");
+    if (depth) {
+        std::ostringstream buf;
+        for (int i = 0; i < depth; ++i)
+            buf << stack[i];
+        debugs(86,1, buf.str());
+    }
 }
 
 int
diff -u -r -N squid-4.0.10/src/esi/Makefile.am squid-4.0.11/src/esi/Makefile.am
--- squid-4.0.10/src/esi/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/esi/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -14,13 +14,13 @@
 	CustomParser.cc \
 	CustomParser.h
 
-if HAVE_LIBEXPAT
+if ENABLE_LIBEXPAT
 ESI_PARSER_SOURCES += \
 	ExpatParser.cc \
 	ExpatParser.h
 endif
 
-if HAVE_LIBXML2
+if ENABLE_LIBXML2
 ESI_PARSER_SOURCES += \
 	Libxml2Parser.cc \
 	Libxml2Parser.h
diff -u -r -N squid-4.0.10/src/esi/Makefile.in squid-4.0.11/src/esi/Makefile.in
--- squid-4.0.10/src/esi/Makefile.in	2016-05-06 23:36:54.000000000 +1200
+++ squid-4.0.11/src/esi/Makefile.in	2016-06-10 08:34:53.000000000 +1200
@@ -90,13 +90,13 @@
 host_triplet = @host@
 check_PROGRAMS =
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL)
-@HAVE_LIBEXPAT_TRUE@am__append_2 = \
-@HAVE_LIBEXPAT_TRUE@	ExpatParser.cc \
-@HAVE_LIBEXPAT_TRUE@	ExpatParser.h
+@ENABLE_LIBEXPAT_TRUE@am__append_2 = \
+@ENABLE_LIBEXPAT_TRUE@	ExpatParser.cc \
+@ENABLE_LIBEXPAT_TRUE@	ExpatParser.h
 
-@HAVE_LIBXML2_TRUE@am__append_3 = \
-@HAVE_LIBXML2_TRUE@	Libxml2Parser.cc \
-@HAVE_LIBXML2_TRUE@	Libxml2Parser.h
+@ENABLE_LIBXML2_TRUE@am__append_3 = \
+@ENABLE_LIBXML2_TRUE@	Libxml2Parser.cc \
+@ENABLE_LIBXML2_TRUE@	Libxml2Parser.h
 
 subdir = src/esi
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
@@ -178,8 +178,8 @@
 	Include.cc Include.h Literal.h Module.cc Module.h Parser.cc \
 	Parser.h Segment.cc Segment.h Sequence.cc Sequence.h Var.h \
 	VarState.cc VarState.h
-@HAVE_LIBEXPAT_TRUE@am__objects_1 = ExpatParser.lo
-@HAVE_LIBXML2_TRUE@am__objects_2 = Libxml2Parser.lo
+@ENABLE_LIBEXPAT_TRUE@am__objects_1 = ExpatParser.lo
+@ENABLE_LIBXML2_TRUE@am__objects_2 = Libxml2Parser.lo
 am__objects_3 = CustomParser.lo $(am__objects_1) $(am__objects_2)
 am_libesi_la_OBJECTS = Assign.lo Context.lo $(am__objects_3) Esi.lo \
 	Expression.lo Include.lo Module.lo Parser.lo Segment.lo \
diff -u -r -N squid-4.0.10/src/fs/rock/RockIoState.cc squid-4.0.11/src/fs/rock/RockIoState.cc
--- squid-4.0.10/src/fs/rock/RockIoState.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/fs/rock/RockIoState.cc	2016-06-10 08:32:57.000000000 +1200
@@ -185,7 +185,7 @@
     assert(!coreOff || coreOff == -1);
 
     // throw if an accepted unknown-size entry grew too big or max-size changed
-    Must(offset_ + size <= static_cast<uint64_t>(dir->maxObjectSize()));
+    Must(static_cast<uint64_t>(offset_ + size) <= static_cast<uint64_t>(dir->maxObjectSize()));
 
     // allocate the first slice during the first write
     if (!coreOff) {
diff -u -r -N squid-4.0.10/src/fs/ufs/UFSStoreState.cc squid-4.0.11/src/fs/ufs/UFSStoreState.cc
--- squid-4.0.10/src/fs/ufs/UFSStoreState.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/fs/ufs/UFSStoreState.cc	2016-06-10 08:32:57.000000000 +1200
@@ -169,7 +169,7 @@
     }
 
     const Store::Disk &dir = *INDEXSD(swap_dirn);
-    if (offset_ + size > static_cast<uint64_t>(dir.maxObjectSize())) {
+    if (static_cast<uint64_t>(offset_ + size) > static_cast<uint64_t>(dir.maxObjectSize())) {
         debugs(79, 2, "accepted unknown-size entry grew too big: " <<
                (offset_ + size) << " > " << dir.maxObjectSize());
         free_func((void*)buf);
diff -u -r -N squid-4.0.10/src/http/one/forward.h squid-4.0.11/src/http/one/forward.h
--- squid-4.0.10/src/http/one/forward.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/forward.h	2016-06-10 08:32:57.000000000 +1200
@@ -10,6 +10,7 @@
 #define SQUID_SRC_HTTP_ONE_FORWARD_H
 
 #include "base/RefCount.h"
+#include "sbuf/forward.h"
 
 namespace Http {
 namespace One {
@@ -27,6 +28,9 @@
 class ResponseParser;
 typedef RefCount<Http::One::ResponseParser> ResponseParserPointer;
 
+/// CRLF textual representation
+const SBuf &CrLf();
+
 } // namespace One
 } // namespace Http
 
diff -u -r -N squid-4.0.10/src/http/one/Parser.cc squid-4.0.11/src/http/one/Parser.cc
--- squid-4.0.10/src/http/one/Parser.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/Parser.cc	2016-06-10 08:32:57.000000000 +1200
@@ -16,6 +16,12 @@
 /// RFC 7230 section 2.6 - 7 magic octets
 const SBuf Http::One::Parser::Http1magic("HTTP/1.");
 
+const SBuf &Http::One::CrLf()
+{
+    static const SBuf crlf("\r\n");
+    return crlf;
+}
+
 void
 Http::One::Parser::clear()
 {
@@ -25,11 +31,34 @@
     mimeHeaderBlock_.clear();
 }
 
+/// characters HTTP permits tolerant parsers to accept as delimiters
+static const CharacterSet &
+RelaxedDelimiterCharacters()
+{
+    // RFC 7230 section 3.5
+    // tolerant parser MAY accept any of SP, HTAB, VT (%x0B), FF (%x0C),
+    // or bare CR as whitespace between request-line fields
+    static const CharacterSet RelaxedDels =
+        (CharacterSet::SP +
+         CharacterSet::HTAB +
+         CharacterSet("VT,FF","\x0B\x0C") +
+         CharacterSet::CR).rename("relaxed-WSP");
+
+    return RelaxedDels;
+}
+
+/// characters used to separate HTTP fields
+const CharacterSet &
+Http::One::Parser::DelimiterCharacters()
+{
+    return Config.onoff.relaxed_header_parser ?
+           RelaxedDelimiterCharacters() : CharacterSet::SP;
+}
+
 bool
 Http::One::Parser::skipLineTerminator(Http1::Tokenizer &tok) const
 {
-    static const SBuf crlf("\r\n");
-    if (tok.skip(crlf))
+    if (tok.skip(Http1::CrLf()))
         return true;
 
     if (Config.onoff.relaxed_header_parser && tok.skipOne(CharacterSet::LF))
@@ -38,6 +67,88 @@
     return false;
 }
 
+/// all characters except the LF line terminator
+static const CharacterSet &
+LineCharacters()
+{
+    static const CharacterSet line = CharacterSet::LF.complement("non-LF");
+    return line;
+}
+
+/**
+ * Remove invalid lines (if any) from the mime prefix
+ *
+ * RFC 7230 section 3:
+ * "A recipient that receives whitespace between the start-line and
+ * the first header field MUST ... consume each whitespace-preceded
+ * line without further processing of it."
+ *
+ * We need to always use the relaxed delimiters here to prevent
+ * line smuggling through strict parsers.
+ *
+ * Note that 'whitespace' in RFC 7230 includes CR. So that means
+ * sequences of CRLF will be pruned, but not sequences of bare-LF.
+ */
+void
+Http::One::Parser::cleanMimePrefix()
+{
+    Http1::Tokenizer tok(mimeHeaderBlock_);
+    while (tok.skipOne(RelaxedDelimiterCharacters())) {
+        (void)tok.skipAll(LineCharacters()); // optional line content
+        // LF terminator is required.
+        // trust headersEnd() to ensure that we have at least one LF
+        (void)tok.skipOne(CharacterSet::LF);
+    }
+
+    // If mimeHeaderBlock_ had just whitespace line(s) followed by CRLF,
+    // then we skipped everything, including that terminating LF.
+    // Restore the terminating CRLF if needed.
+    if (tok.atEnd())
+        mimeHeaderBlock_ = Http1::CrLf();
+    else
+        mimeHeaderBlock_ = tok.remaining();
+    // now mimeHeaderBlock_ has 0+ fields followed by the LF terminator
+}
+
+/**
+ * Replace obs-fold with a single SP,
+ *
+ * RFC 7230 section 3.2.4
+ * "A server that receives an obs-fold in a request message that is not
+ *  within a message/http container MUST ... replace
+ *  each received obs-fold with one or more SP octets prior to
+ *  interpreting the field value or forwarding the message downstream."
+ *
+ * "A proxy or gateway that receives an obs-fold in a response message
+ *  that is not within a message/http container MUST ... replace each
+ *  received obs-fold with one or more SP octets prior to interpreting
+ *  the field value or forwarding the message downstream."
+ */
+void
+Http::One::Parser::unfoldMime()
+{
+    Http1::Tokenizer tok(mimeHeaderBlock_);
+    const auto szLimit = mimeHeaderBlock_.length();
+    mimeHeaderBlock_.clear();
+    // prevent the mime sender being able to make append() realloc/grow multiple times.
+    mimeHeaderBlock_.reserveSpace(szLimit);
+
+    static const CharacterSet nonCRLF = (CharacterSet::CR + CharacterSet::LF).complement().rename("non-CRLF");
+
+    while (!tok.atEnd()) {
+        const SBuf all(tok.remaining());
+        const auto blobLen = tok.skipAll(nonCRLF); // may not be there
+        const auto crLen = tok.skipAll(CharacterSet::CR); // may not be there
+        const auto lfLen = tok.skipOne(CharacterSet::LF); // may not be there
+
+        if (lfLen && tok.skipAll(CharacterSet::WSP)) { // obs-fold!
+            mimeHeaderBlock_.append(all.substr(0, blobLen));
+            mimeHeaderBlock_.append(' '); // replace one obs-fold with one SP
+        } else
+            mimeHeaderBlock_.append(all.substr(0, blobLen + crLen + lfLen));
+    }
+}
+
 bool
 Http::One::Parser::grabMimeBlock(const char *which, const size_t limit)
 {
@@ -51,8 +162,8 @@
          *       So the rest of the code will need to deal with '0'-byte headers
          *       (ie, none, so don't try parsing em)
          */
-        // XXX: c_str() reallocates. performance regression.
-        if (SBuf::size_type mimeHeaderBytes = headersEnd(buf_.c_str(), buf_.length())) {
+        bool containsObsFold;
+        if (SBuf::size_type mimeHeaderBytes = headersEnd(buf_, containsObsFold)) {
 
             // Squid could handle these headers, but admin does not want to
             if (firstLineSize() + mimeHeaderBytes >= limit) {
@@ -64,6 +175,10 @@
             }
 
             mimeHeaderBlock_ = buf_.consume(mimeHeaderBytes);
+            cleanMimePrefix();
+            if (containsObsFold)
+                unfoldMime();
+
             debugs(74, 5, "mime header (0-" << mimeHeaderBytes << ") {" << mimeHeaderBlock_ << "}");
 
         } else { // headersEnd() == 0
@@ -102,12 +217,10 @@
     debugs(25, 5, "looking for " << name);
 
     // while we can find more LF in the SBuf
-    static CharacterSet iso8859Line = CharacterSet("non-LF",'\0','\n'-1) + CharacterSet(NULL, '\n'+1, (unsigned char)0xFF);
     Http1::Tokenizer tok(mimeHeaderBlock_);
     SBuf p;
-    static const SBuf crlf("\r\n");
 
-    while (tok.prefix(p, iso8859Line)) {
+    while (tok.prefix(p, LineCharacters())) {
         if (!tok.skipOne(CharacterSet::LF)) // move tokenizer past the LF
             break; // error. reached invalid octet or end of buffer insted of an LF ??
 
@@ -120,7 +233,7 @@
             continue;
 
         // drop any trailing *CR sequence
-        p.trim(crlf, false, true);
+        p.trim(Http1::CrLf(), false, true);
 
         debugs(25, 5, "checking " << p);
         p.consume(namelen + 1);
diff -u -r -N squid-4.0.10/src/http/one/Parser.h squid-4.0.11/src/http/one/Parser.h
--- squid-4.0.10/src/http/one/Parser.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/Parser.h	2016-06-10 08:32:57.000000000 +1200
@@ -111,6 +111,10 @@
     /// consume from the tokenizer and return true only if found
     bool skipLineTerminator(Http1::Tokenizer &tok) const;
 
+    /// the characters which are to be considered valid whitespace
+    /// (WSP / BSP / OWS)
+    static const CharacterSet &DelimiterCharacters();
+
     /**
      * Scan to find the mime headers block for current message.
      *
@@ -139,6 +143,10 @@
 
     /// Whether the invalid HTTP as HTTP/0.9 hack expects a mime header block
     bool hackExpectsMime_;
+
+private:
+    void cleanMimePrefix();
+    void unfoldMime();
 };
 
 } // namespace One
diff -u -r -N squid-4.0.10/src/http/one/RequestParser.cc squid-4.0.11/src/http/one/RequestParser.cc
--- squid-4.0.10/src/http/one/RequestParser.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/RequestParser.cc	2016-06-10 08:32:57.000000000 +1200
@@ -114,30 +114,6 @@
     return UriChars;
 }
 
-/// characters HTTP permits tolerant parsers to accept as delimiters
-static const CharacterSet &
-RelaxedDelimiterCharacters()
-{
-    // RFC 7230 section 3.5
-    // tolerant parser MAY accept any of SP, HTAB, VT (%x0B), FF (%x0C),
-    // or bare CR as whitespace between request-line fields
-    static const CharacterSet RelaxedDels =
-        CharacterSet::SP +
-        CharacterSet::HTAB +
-        CharacterSet("VT,FF","\x0B\x0C") +
-        CharacterSet::CR;
-
-    return RelaxedDels;
-}
-
-/// characters used to separate HTTP fields
-const CharacterSet &
-Http::One::RequestParser::DelimiterCharacters()
-{
-    return Config.onoff.relaxed_header_parser ?
-           RelaxedDelimiterCharacters() : CharacterSet::SP;
-}
-
 /// characters which Squid will accept in the HTTP request-target (URI)
 const CharacterSet &
 Http::One::RequestParser::RequestTargetCharacters()
diff -u -r -N squid-4.0.10/src/http/one/RequestParser.h squid-4.0.11/src/http/one/RequestParser.h
--- squid-4.0.10/src/http/one/RequestParser.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/RequestParser.h	2016-06-10 08:32:57.000000000 +1200
@@ -56,7 +56,6 @@
     bool skipTrailingCrs(Http1::Tokenizer &tok);
 
     bool http0() const {return !msgProtocol_.major;}
-    static const CharacterSet &DelimiterCharacters();
     static const CharacterSet &RequestTargetCharacters();
 
     /// what request method has been found on the first line
diff -u -r -N squid-4.0.10/src/http/one/TeChunkedParser.cc squid-4.0.11/src/http/one/TeChunkedParser.cc
--- squid-4.0.10/src/http/one/TeChunkedParser.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/http/one/TeChunkedParser.cc	2016-06-10 08:32:57.000000000 +1200
@@ -117,6 +117,11 @@
 bool
 Http::One::TeChunkedParser::parseChunkExtension(Http1::Tokenizer &tok, bool skipKnown)
 {
+    // Bug 4492: IBM_HTTP_Server sends SP padding
+    if (auto n = tok.skipAll(CharacterSet::SP)) {
+        debugs(94, 3, "skipping " << n << " spurious whitespace at start of chunk extension");
+    }
+
     SBuf ext;
     SBuf value;
     while (tok.skip(';') && tok.prefix(ext, CharacterSet::TCHAR)) {
diff -u -r -N squid-4.0.10/src/http/url_rewriters/LFS/url_lfs_rewrite.8 squid-4.0.11/src/http/url_rewriters/LFS/url_lfs_rewrite.8
--- squid-4.0.10/src/http/url_rewriters/LFS/url_lfs_rewrite.8	2016-05-07 00:32:14.000000000 +1200
+++ squid-4.0.11/src/http/url_rewriters/LFS/url_lfs_rewrite.8	2016-06-10 09:29:43.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "URL_LFS_REWRITE 8"
-.TH URL_LFS_REWRITE 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH URL_LFS_REWRITE 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/HttpHeader.cc squid-4.0.11/src/HttpHeader.cc
--- squid-4.0.10/src/HttpHeader.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/HttpHeader.cc	2016-06-10 08:32:57.000000000 +1200
@@ -595,21 +595,17 @@
 {
     debugs(55, 8, this << " del-by-id " << id);
     assert(any_registered_header(id));
-    int count=0;
 
     if (!CBIT_TEST(mask, id))
         return 0;
 
-    //replace matching items with nil and count them
-    std::replace_if(entries.begin(), entries.end(),
-    [&](const HttpHeaderEntry *e) {
-        if (e && e->id == id) {
-            ++count;
-            return true;
-        }
-        return false;
-    },
-    nullptr);
+    int count = 0;
+
+    HttpHeaderPos pos = HttpHeaderInitPos;
+    while (HttpHeaderEntry *e = getEntry(&pos)) {
+        if (e->id == id)
+            delAt(pos, count); // deletes e
+    }
 
     CBIT_CLR(mask, id);
     assert(count);
diff -u -r -N squid-4.0.10/src/log/DB/log_db_daemon.8 squid-4.0.11/src/log/DB/log_db_daemon.8
--- squid-4.0.10/src/log/DB/log_db_daemon.8	2016-05-07 00:32:23.000000000 +1200
+++ squid-4.0.11/src/log/DB/log_db_daemon.8	2016-06-10 09:29:50.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "LOG_DB_DAEMON 8"
-.TH LOG_DB_DAEMON 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH LOG_DB_DAEMON 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/LogTags.cc squid-4.0.11/src/LogTags.cc
--- squid-4.0.10/src/LogTags.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/LogTags.cc	2016-06-10 08:32:57.000000000 +1200
@@ -18,6 +18,7 @@
     "TCP_REFRESH_FAIL_OLD",
     "TCP_REFRESH_FAIL_ERR",
     "TCP_REFRESH_MODIFIED",
+    "TCP_REFRESH",
     "TCP_CLIENT_REFRESH_MISS",
     "TCP_IMS_HIT",
     "TCP_SWAPFAIL_MISS",
diff -u -r -N squid-4.0.10/src/LogTags.h squid-4.0.11/src/LogTags.h
--- squid-4.0.10/src/LogTags.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/LogTags.h	2016-06-10 08:32:57.000000000 +1200
@@ -25,6 +25,7 @@
     LOG_TCP_REFRESH_FAIL_OLD,   // refresh from origin failed, stale reply sent
     LOG_TCP_REFRESH_FAIL_ERR,   // refresh from origin failed, error forwarded
     LOG_TCP_REFRESH_MODIFIED,   // refresh from origin replaced existing entry
+    LOG_TCP_REFRESH,            // refresh from origin started, but still pending
     LOG_TCP_CLIENT_REFRESH_MISS,
     LOG_TCP_IMS_HIT,
     LOG_TCP_SWAPFAIL_MISS,
diff -u -r -N squid-4.0.10/src/Makefile.am squid-4.0.11/src/Makefile.am
--- squid-4.0.10/src/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -66,16 +66,16 @@
 SUBDIRS += snmp
 SNMP_LIBS = snmp/libsnmp.la $(SNMPLIB)
 else
-SNMP_SOURCE = 
+SNMP_SOURCE =
 endif
 DIST_SUBDIRS += snmp
 
-if USE_ADAPTATION
+if ENABLE_ADAPTATION
 SUBDIRS += adaptation
 endif
 DIST_SUBDIRS += adaptation
 
-if USE_ESI
+if ENABLE_ESI
 SUBDIRS += esi
 ESI_LIBS = \
 	esi/libesi.la \
@@ -113,27 +113,27 @@
 	NullDelayId.h \
 	ClientDelayConfig.cc \
 	ClientDelayConfig.h
-	
+
 if ENABLE_DELAY_POOLS
 DELAY_POOL_SOURCE = $(DELAY_POOL_ALL_SOURCE)
 else
-DELAY_POOL_SOURCE = 
+DELAY_POOL_SOURCE =
 endif
 
 if ENABLE_XPROF_STATS
 XPROF_STATS_SOURCE = ProfStats.cc
 else
-XPROF_STATS_SOURCE = 
+XPROF_STATS_SOURCE =
 endif
 
 if ENABLE_HTCP
 HTCPSOURCE = htcp.cc htcp.h
 endif
 
-if MAKE_LEAKFINDER
+if ENABLE_LEAKFINDER
 LEAKFINDERSOURCE =  LeakFinder.cc
 else
-LEAKFINDERSOURCE = 
+LEAKFINDERSOURCE =
 endif
 
 if ENABLE_UNLINKD
@@ -141,7 +141,7 @@
 UNLINKD = unlinkd
 else
 UNLINKDSOURCE = unlinkd.h
-UNLINKD = 
+UNLINKD =
 endif
 
 WIN32_ALL_SOURCE = \
@@ -181,8 +181,7 @@
 sbin_PROGRAMS = \
 	squid
 
-bin_PROGRAMS = 
-
+bin_PROGRAMS =
 
 libexec_PROGRAMS = \
 	$(UNLINKD)
@@ -539,7 +538,6 @@
 	ftp/libftp.la \
 	helper/libhelper.la \
 	http/libhttp.la \
-	parser/libparser.la \
 	dns/libdns.la \
 	base/libbase.la \
 	libsquid.la \
@@ -552,6 +550,7 @@
 	anyp/libanyp.la \
 	comm/libcomm.la \
 	security/libsecurity.la \
+	parser/libparser.la \
 	eui/libeui.la \
 	icmp/libicmp.la \
 	log/liblog.la \
@@ -888,10 +887,10 @@
 	tests/testLookupTable \
 	tests/testYesNoNone
 
-if HAVE_FS_ROCK
+if ENABLE_FS_ROCK
 check_PROGRAMS += tests/testRock
 endif
-if HAVE_FS_UFS
+if ENABLE_FS_UFS
 check_PROGRAMS += tests/testUfs
 endif
 
diff -u -r -N squid-4.0.10/src/Makefile.in squid-4.0.11/src/Makefile.in
--- squid-4.0.10/src/Makefile.in	2016-05-06 23:36:31.000000000 +1200
+++ squid-4.0.11/src/Makefile.in	2016-06-10 08:34:30.000000000 +1200
@@ -114,8 +114,8 @@
 @ENABLE_SSL_TRUE@	ssl/libsslutil.la
 
 @ENABLE_SNMP_TRUE@am__append_6 = snmp
-@USE_ADAPTATION_TRUE@am__append_7 = adaptation
-@USE_ESI_TRUE@am__append_8 = esi
+@ENABLE_ADAPTATION_TRUE@am__append_7 = adaptation
+@ENABLE_ESI_TRUE@am__append_8 = esi
 EXTRA_PROGRAMS = unlinkd$(EXEEXT) recv-announce$(EXEEXT) \
 	tests/testUfs$(EXEEXT) tests/testRock$(EXEEXT) \
 	ufsdump$(EXEEXT)
@@ -126,8 +126,8 @@
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_9 = $(LOADABLE_MODULES_SOURCES)
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_10 = -L$(top_builddir) $(LIBLTDL)
 @ENABLE_LOADABLE_MODULES_TRUE@am__append_11 = $(INCLTDL)
-@HAVE_FS_ROCK_TRUE@am__append_12 = tests/testRock
-@HAVE_FS_UFS_TRUE@am__append_13 = tests/testUfs
+@ENABLE_FS_ROCK_TRUE@am__append_12 = tests/testRock
+@ENABLE_FS_UFS_TRUE@am__append_13 = tests/testUfs
 subdir = src
 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
 am__aclocal_m4_deps = $(top_srcdir)/acinclude/ax_with_prog.m4 \
@@ -213,8 +213,8 @@
 	"$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" \
 	"$(DESTDIR)$(datadir)" "$(DESTDIR)$(sysconfdir)"
 @ENABLE_AUTH_TRUE@am__EXEEXT_1 = tests/testACLMaxUserIP$(EXEEXT)
-@HAVE_FS_ROCK_TRUE@am__EXEEXT_2 = tests/testRock$(EXEEXT)
-@HAVE_FS_UFS_TRUE@am__EXEEXT_3 = tests/testUfs$(EXEEXT)
+@ENABLE_FS_ROCK_TRUE@am__EXEEXT_2 = tests/testRock$(EXEEXT)
+@ENABLE_FS_UFS_TRUE@am__EXEEXT_3 = tests/testUfs$(EXEEXT)
 @ENABLE_UNLINKD_TRUE@am__EXEEXT_4 = unlinkd$(EXEEXT)
 PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS) $(noinst_PROGRAMS) \
 	$(sbin_PROGRAMS)
@@ -322,7 +322,7 @@
 @ENABLE_HTCP_TRUE@am__objects_5 = htcp.$(OBJEXT)
 @ENABLE_WIN32_IPC_FALSE@am__objects_6 = ipc.$(OBJEXT)
 @ENABLE_WIN32_IPC_TRUE@am__objects_6 = ipc_win32.$(OBJEXT)
-@MAKE_LEAKFINDER_TRUE@am__objects_7 = LeakFinder.$(OBJEXT)
+@ENABLE_LEAKFINDER_TRUE@am__objects_7 = LeakFinder.$(OBJEXT)
 @ENABLE_XPROF_STATS_TRUE@am__objects_8 = ProfStats.$(OBJEXT)
 am__objects_9 = snmp_core.$(OBJEXT) snmp_agent.$(OBJEXT)
 @ENABLE_SNMP_TRUE@am__objects_10 = $(am__objects_9)
@@ -404,9 +404,9 @@
 	swap_log_op.$(OBJEXT)
 nodist_squid_OBJECTS = $(am__objects_17)
 squid_OBJECTS = $(am_squid_OBJECTS) $(nodist_squid_OBJECTS)
-@USE_ESI_TRUE@am__DEPENDENCIES_4 = esi/libesi.la \
-@USE_ESI_TRUE@	$(top_builddir)/lib/libTrie/libTrie.a \
-@USE_ESI_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+@ENABLE_ESI_TRUE@am__DEPENDENCIES_4 = esi/libesi.la \
+@ENABLE_ESI_TRUE@	$(top_builddir)/lib/libTrie/libTrie.a \
+@ENABLE_ESI_TRUE@	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
 @ENABLE_SNMP_TRUE@am__DEPENDENCIES_5 = snmp/libsnmp.la \
 @ENABLE_SNMP_TRUE@	$(am__DEPENDENCIES_1)
 @ENABLE_LOADABLE_MODULES_TRUE@am__DEPENDENCIES_6 =  \
@@ -414,11 +414,11 @@
 squid_DEPENDENCIES = $(AUTH_ACL_LIBS) ident/libident.la acl/libacls.la \
 	acl/libstate.la $(AUTH_LIBS) acl/libapi.la \
 	clients/libclients.la servers/libservers.la ftp/libftp.la \
-	helper/libhelper.la http/libhttp.la parser/libparser.la \
-	dns/libdns.la base/libbase.la libsquid.la ip/libip.la \
-	fs/libfs.la DiskIO/libdiskio.la $(SSL_LIBS) ipc/libipc.la \
-	mgr/libmgr.la anyp/libanyp.la comm/libcomm.la \
-	security/libsecurity.la eui/libeui.la icmp/libicmp.la \
+	helper/libhelper.la http/libhttp.la dns/libdns.la \
+	base/libbase.la libsquid.la ip/libip.la fs/libfs.la \
+	DiskIO/libdiskio.la $(SSL_LIBS) ipc/libipc.la mgr/libmgr.la \
+	anyp/libanyp.la comm/libcomm.la security/libsecurity.la \
+	parser/libparser.la eui/libeui.la icmp/libicmp.la \
 	log/liblog.la format/libformat.la sbuf/libsbuf.la \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
 	$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
@@ -2766,12 +2766,12 @@
 @ENABLE_SNMP_FALSE@SNMP_SOURCE = 
 @ENABLE_SNMP_TRUE@SNMP_SOURCE = $(SNMP_ALL_SOURCE)
 @ENABLE_SNMP_TRUE@SNMP_LIBS = snmp/libsnmp.la $(SNMPLIB)
-@USE_ESI_FALSE@ESI_LIBS = 
-@USE_ESI_TRUE@ESI_LIBS = \
-@USE_ESI_TRUE@	esi/libesi.la \
-@USE_ESI_TRUE@	$(top_builddir)/lib/libTrie/libTrie.a \
-@USE_ESI_TRUE@	$(XMLLIB) \
-@USE_ESI_TRUE@	$(EXPATLIB)
+@ENABLE_ESI_FALSE@ESI_LIBS = 
+@ENABLE_ESI_TRUE@ESI_LIBS = \
+@ENABLE_ESI_TRUE@	esi/libesi.la \
+@ENABLE_ESI_TRUE@	$(top_builddir)/lib/libTrie/libTrie.a \
+@ENABLE_ESI_TRUE@	$(XMLLIB) \
+@ENABLE_ESI_TRUE@	$(EXPATLIB)
 
 DELAY_POOL_ALL_SOURCE = \
 	CommonPool.h \
@@ -2805,8 +2805,8 @@
 @ENABLE_XPROF_STATS_FALSE@XPROF_STATS_SOURCE = 
 @ENABLE_XPROF_STATS_TRUE@XPROF_STATS_SOURCE = ProfStats.cc
 @ENABLE_HTCP_TRUE@HTCPSOURCE = htcp.cc htcp.h
-@MAKE_LEAKFINDER_FALSE@LEAKFINDERSOURCE = 
-@MAKE_LEAKFINDER_TRUE@LEAKFINDERSOURCE = LeakFinder.cc
+@ENABLE_LEAKFINDER_FALSE@LEAKFINDERSOURCE = 
+@ENABLE_LEAKFINDER_TRUE@LEAKFINDERSOURCE = LeakFinder.cc
 @ENABLE_UNLINKD_FALSE@UNLINKDSOURCE = unlinkd.h
 @ENABLE_UNLINKD_TRUE@UNLINKDSOURCE = unlinkd.h unlinkd.cc
 @ENABLE_UNLINKD_FALSE@UNLINKD = 
@@ -2950,11 +2950,11 @@
 squid_LDADD = $(AUTH_ACL_LIBS) ident/libident.la acl/libacls.la \
 	acl/libstate.la $(AUTH_LIBS) acl/libapi.la \
 	clients/libclients.la servers/libservers.la ftp/libftp.la \
-	helper/libhelper.la http/libhttp.la parser/libparser.la \
-	dns/libdns.la base/libbase.la libsquid.la ip/libip.la \
-	fs/libfs.la DiskIO/libdiskio.la $(SSL_LIBS) ipc/libipc.la \
-	mgr/libmgr.la anyp/libanyp.la comm/libcomm.la \
-	security/libsecurity.la eui/libeui.la icmp/libicmp.la \
+	helper/libhelper.la http/libhttp.la dns/libdns.la \
+	base/libbase.la libsquid.la ip/libip.la fs/libfs.la \
+	DiskIO/libdiskio.la $(SSL_LIBS) ipc/libipc.la mgr/libmgr.la \
+	anyp/libanyp.la comm/libcomm.la security/libsecurity.la \
+	parser/libparser.la eui/libeui.la icmp/libicmp.la \
 	log/liblog.la format/libformat.la sbuf/libsbuf.la $(XTRA_OBJS) \
 	$(REPL_OBJS) $(NETTLELIB) $(CRYPTLIB) $(REGEXLIB) \
 	$(ADAPTATION_LIBS) $(ESI_LIBS) $(SNMP_LIBS) mem/libmem.la \
diff -u -r -N squid-4.0.10/src/mime.cc squid-4.0.11/src/mime.cc
--- squid-4.0.10/src/mime.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/mime.cc	2016-06-10 08:32:57.000000000 +1200
@@ -24,6 +24,8 @@
 #include "Store.h"
 #include "StoreClient.h"
 
+#include <array>
+
 #if HAVE_SYS_STAT_H
 #include <sys/stat.h>
 #endif
@@ -422,12 +424,11 @@
     if (status == Http::scOkay) {
         /* read the file into the buffer and append it to store */
         int n;
-        char *buf = (char *)memAllocate(MEM_4K_BUF);
-        while ((n = FD_READ_METHOD(fd, buf, sizeof(*buf))) > 0)
-            e->append(buf, n);
+        std::array<char, 4096> buf;
+        while ((n = FD_READ_METHOD(fd, buf.data(), buf.size())) > 0)
+            e->append(buf.data(), n);
 
         file_close(fd);
-        memFree(buf, MEM_4K_BUF);
     }
 
     e->flush();
diff -u -r -N squid-4.0.10/src/mime_header.cc squid-4.0.11/src/mime_header.cc
--- squid-4.0.10/src/mime_header.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/mime_header.cc	2016-06-10 08:32:57.000000000 +1200
@@ -13,10 +13,11 @@
 #include "profiler/Profiler.h"
 
 size_t
-headersEnd(const char *mime, size_t l)
+headersEnd(const char *mime, size_t l, bool &containsObsFold)
 {
     size_t e = 0;
     int state = 1;
+    containsObsFold = false;
 
     PROF_start(headersEnd);
 
@@ -35,7 +36,10 @@
                 state = 2;
             else if ('\n' == mime[e])
                 state = 3;
-            else
+            else if (' ' == mime[e] || '\t' == mime[e]) {
+                containsObsFold = true;
+                state = 0;
+            } else
                 state = 0;
 
             break;
diff -u -r -N squid-4.0.10/src/mime_header.h squid-4.0.11/src/mime_header.h
--- squid-4.0.10/src/mime_header.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/mime_header.h	2016-06-10 08:32:57.000000000 +1200
@@ -11,7 +11,35 @@
 #ifndef SQUID_MIME_HEADER_H_
 #define SQUID_MIME_HEADER_H_
 
-size_t headersEnd(const char *, size_t);
+/**
+ * Scan for the end of mime header block.
+ *
+ * Which is one of the following octet patterns:
+ * - CRLF CRLF, or
+ * - CRLF LF, or
+ * - LF CRLF, or
+ * - LF LF
+ *
+ * Also detects whether a obf-fold pattern exists within the mime block
+ * - CR*LF (SP / HTAB)
+ *
+ * \param containsObsFold will be set to true if obs-fold pattern is found.
+ */
+size_t headersEnd(const char *, size_t, bool &containsObsFold);
+
+inline size_t
+headersEnd(const SBuf &buf, bool &containsObsFold)
+{
+    return headersEnd(buf.rawContent(), buf.length(), containsObsFold);
+}
+
+/// \deprecated caller needs to be fixed to handle obs-fold
+inline size_t
+headersEnd(const char *buf, size_t sz)
+{
+    bool ignored;
+    return headersEnd(buf, sz, ignored);
+}
 
 #endif /* SQUID_MIME_HEADER_H_ */
 
diff -u -r -N squid-4.0.10/src/parser/BinaryTokenizer.cc squid-4.0.11/src/parser/BinaryTokenizer.cc
--- squid-4.0.10/src/parser/BinaryTokenizer.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.11/src/parser/BinaryTokenizer.cc	2016-06-10 08:32:57.000000000 +1200
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 24    SBuf */
+
+#include "squid.h"
+#include "parser/BinaryTokenizer.h"
+
+Parser::BinaryTokenizer::BinaryTokenizer(): BinaryTokenizer(SBuf())
+{
+}
+
+Parser::BinaryTokenizer::BinaryTokenizer(const SBuf &data, const bool expectMore):
+    context(nullptr),
+    data_(data),
+    parsed_(0),
+    syncPoint_(0),
+    expectMore_(expectMore)
+{
+}
+
+static inline
+std::ostream &
+operator <<(std::ostream &os, const Parser::BinaryTokenizerContext *context)
+{
+    if (context)
+        os << context->parent << context->name;
+    return os;
+}
+
+/// debugging helper that prints a "standard" debugs() trailer
+#define BinaryTokenizer_tail(size, start) \
+    " occupying " << (size) << " bytes @" << (start) << " in " << this << \
+    (expectMore_ ? ';' : '.');
+
+/// logs and throws if fewer than size octets remain; no other side effects
+void
+Parser::BinaryTokenizer::want(uint64_t size, const char *description) const
+{
+    if (parsed_ + size > data_.length()) {
+        debugs(24, 5, (parsed_ + size - data_.length()) << " more bytes for " <<
+               context << description << BinaryTokenizer_tail(size, parsed_));
+        Must(expectMore_); // throw an error on premature input termination
+        throw InsufficientInput();
+    }
+}
+
+void
+Parser::BinaryTokenizer::got(uint64_t size, const char *description) const
+{
+    debugs(24, 7, context << description <<
+           BinaryTokenizer_tail(size, parsed_ - size));
+}
+
+/// debugging helper for parsed number fields
+void
+Parser::BinaryTokenizer::got(uint32_t value, uint64_t size, const char *description) const
+{
+    debugs(24, 7, context << description << '=' << value <<
+           BinaryTokenizer_tail(size, parsed_ - size));
+}
+
+/// debugging helper for parsed areas/blobs
+void
+Parser::BinaryTokenizer::got(const SBuf &value, uint64_t size, const char *description) const
+{
+    debugs(24, 7, context << description << '=' <<
+           Raw(nullptr, value.rawContent(), value.length()).hex() <<
+           BinaryTokenizer_tail(size, parsed_ - size));
+
+}
+
+/// debugging helper for skipped fields
+void
+Parser::BinaryTokenizer::skipped(uint64_t size, const char *description) const
+{
+    debugs(24, 7, context << description << BinaryTokenizer_tail(size, parsed_ - size));
+
+}
+
+/// Returns the next ready-for-shift byte, adjusting the number of parsed bytes.
+/// The larger 32-bit return type helps callers shift/merge octets into numbers.
+/// This internal method does not perform out-of-bounds checks.
+uint32_t
+Parser::BinaryTokenizer::octet()
+{
+    // While char may be signed, we view data characters as unsigned,
+    // which helps to arrive at the right 32-bit return value.
+    return static_cast<uint8_t>(data_[parsed_++]);
+}
+
+void
+Parser::BinaryTokenizer::reset(const SBuf &data, const bool expectMore)
+{
+    *this = BinaryTokenizer(data, expectMore);
+}
+
+void
+Parser::BinaryTokenizer::rollback()
+{
+    parsed_ = syncPoint_;
+}
+
+void
+Parser::BinaryTokenizer::commit()
+{
+    syncPoint_ = parsed_;
+}
+
+bool
+Parser::BinaryTokenizer::atEnd() const
+{
+    return parsed_ >= data_.length();
+}
+
+uint8_t
+Parser::BinaryTokenizer::uint8(const char *description)
+{
+    want(1, description);
+    const uint8_t result = octet();
+    got(result, 1, description);
+    return result;
+}
+
+uint16_t
+Parser::BinaryTokenizer::uint16(const char *description)
+{
+    want(2, description);
+    const uint16_t result = (octet() << 8) | octet();
+    got(result, 2, description);
+    return result;
+}
+
+uint32_t
+Parser::BinaryTokenizer::uint24(const char *description)
+{
+    want(3, description);
+    const uint32_t result = (octet() << 16) | (octet() << 8) | octet();
+    got(result, 3, description);
+    return result;
+}
+
+uint32_t
+Parser::BinaryTokenizer::uint32(const char *description)
+{
+    want(4, description);
+    const uint32_t result = (octet() << 24) | (octet() << 16) | (octet() << 8) | octet();
+    got(result, 4, description);
+    return result;
+}
+
+SBuf
+Parser::BinaryTokenizer::area(uint64_t size, const char *description)
+{
+    want(size, description);
+    const SBuf result = data_.substr(parsed_, size);
+    parsed_ += size;
+    got(result, size, description);
+    return result;
+}
+
+void
+Parser::BinaryTokenizer::skip(uint64_t size, const char *description)
+{
+    want(size, description);
+    parsed_ += size;
+    skipped(size, description);
+}
+
+/*
+ * BinaryTokenizer::pstringN() implementations below reduce debugging noise by
+ * not parsing empty areas and not summarizing parsing context.success().
+ */
+
+SBuf
+Parser::BinaryTokenizer::pstring8(const char *description)
+{
+    BinaryTokenizerContext pstring(*this, description);
+    if (const uint8_t length = uint8(".length"))
+        return area(length, ".octets");
+    return SBuf();
+}
+
+SBuf
+Parser::BinaryTokenizer::pstring16(const char *description)
+{
+    BinaryTokenizerContext pstring(*this, description);
+    if (const uint16_t length = uint16(".length"))
+        return area(length, ".octets");
+    return SBuf();
+}
+
+SBuf
+Parser::BinaryTokenizer::pstring24(const char *description)
+{
+    BinaryTokenizerContext pstring(*this, description);
+    if (const uint32_t length = uint24(".length"))
+        return area(length, ".octets");
+    return SBuf();
+}
+
diff -u -r -N squid-4.0.10/src/parser/BinaryTokenizer.h squid-4.0.11/src/parser/BinaryTokenizer.h
--- squid-4.0.10/src/parser/BinaryTokenizer.h	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.11/src/parser/BinaryTokenizer.h	2016-06-10 08:32:57.000000000 +1200
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SRC_PARSER_BINARYTOKENIZER_H
+#define SQUID_SRC_PARSER_BINARYTOKENIZER_H
+
+#include "sbuf/SBuf.h"
+
+namespace Parser
+{
+
+class BinaryTokenizer;
+
+/// enables efficient debugging with concise field names: Hello.version.major
+class BinaryTokenizerContext
+{
+public:
+    /// starts parsing named object
+    explicit BinaryTokenizerContext(BinaryTokenizer &tk, const char *aName);
+    ~BinaryTokenizerContext() { close(); }
+
+    /// ends parsing named object; repeated calls OK
+    inline void close();
+
+    /// reports successful parsing of a named object and calls close()
+    inline void success();
+
+    BinaryTokenizer &tokenizer; ///< tokenizer being used for parsing
+    const BinaryTokenizerContext * const parent; ///< enclosing context or nullptr
+    const char *const name; ///< this context description or nullptr
+    uint64_t start; ///< context parsing begins at this tokenizer position
+};
+
+/// Safely extracts byte-oriented (i.e., non-textual) fields from raw input.
+/// Assume that the integers are stored in network byte order.
+/// Supports commit points for atomic incremental parsing of multi-part fields.
+/// Throws InsufficientInput when more input is needed to parse the next field.
+/// Throws on errors.
+class BinaryTokenizer
+{
+public:
+    class InsufficientInput {}; // thrown when a method runs out of data
+    typedef uint64_t size_type; // enough for the largest supported offset
+
+    BinaryTokenizer();
+    explicit BinaryTokenizer(const SBuf &data, const bool expectMore = false);
+
+    /// restart parsing from the very beginning
+    /// this method is for using one BinaryTokenizer to parse independent inputs
+    void reset(const SBuf &data, const bool expectMore);
+
+    /// change input state without changing parsing state
+    /// this method avoids append overheads during incremental parsing
+    void reinput(const SBuf &data, const bool expectMore) { data_ = data; expectMore_ = expectMore; }
+
+    /// make progress: future parsing failures will not rollback beyond this point
+    void commit();
+
+    /// resume [incremental] parsing from the last commit point
+    void rollback();
+
+    /// no more bytes to parse or skip
+    bool atEnd() const;
+
+    /// parse a single-byte unsigned integer
+    uint8_t uint8(const char *description);
+
+    /// parse a two-byte unsigned integer
+    uint16_t uint16(const char *description);
+
+    /// parse a three-byte unsigned integer (returned as uint32_t)
+    uint32_t uint24(const char *description);
+
+    /// parse a four-byte unsigned integer
+    uint32_t uint32(const char *description);
+
+    /// parse size consecutive bytes as an opaque blob
+    SBuf area(uint64_t size, const char *description);
+
+    /*
+     * Variable-length arrays (a.k.a. Pascal or prefix strings).
+     * pstringN() extracts and returns N-bit length followed by length bytes
+     */
+    SBuf pstring8(const char *description); ///< up to 255 byte-long p-string
+    SBuf pstring16(const char *description); ///< up to 64 KiB-long p-string
+    SBuf pstring24(const char *description); ///< up to 16 MiB-long p-string!
+
+    /// ignore the next size bytes
+    void skip(uint64_t size, const char *description);
+
+    /// the number of already parsed bytes
+    uint64_t parsed() const { return parsed_; }
+
+    /// yet unparsed bytes
+    SBuf leftovers() const { return data_.substr(parsed_); }
+
+    /// debugging helper for parsed multi-field structures
+    void got(uint64_t size, const char *description) const;
+
+    const BinaryTokenizerContext *context; ///< debugging: thing being parsed
+
+protected:
+    uint32_t octet();
+    void want(uint64_t size, const char *description) const;
+    void got(uint32_t value, uint64_t size, const char *description) const;
+    void got(const SBuf &value, uint64_t size, const char *description) const;
+    void skipped(uint64_t size, const char *description) const;
+
+private:
+    SBuf data_;
+    uint64_t parsed_; ///< number of data bytes parsed or skipped
+    uint64_t syncPoint_; ///< where to re-start the next parsing attempt
+    bool expectMore_; ///< whether more data bytes may arrive in the future
+};
+
+/* BinaryTokenizerContext */
+
+inline
+BinaryTokenizerContext::BinaryTokenizerContext(BinaryTokenizer &tk, const char *aName):
+    tokenizer(tk),
+    parent(tk.context),
+    name(aName),
+    start(tk.parsed())
+{
+    tk.context = this;
+}
+
+inline
+void
+BinaryTokenizerContext::close() {
+    tokenizer.context = parent;
+}
+
+inline
+void
+BinaryTokenizerContext::success() {
+    tokenizer.got(tokenizer.parsed() - start, "");
+    close();
+}
+
+} /* namespace Parser */
+
+#endif // SQUID_SRC_PARSER_BINARYTOKENIZER_H
+
diff -u -r -N squid-4.0.10/src/parser/Makefile.am squid-4.0.11/src/parser/Makefile.am
--- squid-4.0.10/src/parser/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/parser/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -11,6 +11,8 @@
 noinst_LTLIBRARIES = libparser.la
 
 libparser_la_SOURCES = \
+	BinaryTokenizer.h \
+	BinaryTokenizer.cc \
 	Tokenizer.h \
 	Tokenizer.cc
 
diff -u -r -N squid-4.0.10/src/parser/Makefile.in squid-4.0.11/src/parser/Makefile.in
--- squid-4.0.10/src/parser/Makefile.in	2016-05-06 23:37:05.000000000 +1200
+++ squid-4.0.11/src/parser/Makefile.in	2016-06-10 08:35:03.000000000 +1200
@@ -163,7 +163,7 @@
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libparser_la_LIBADD =
-am_libparser_la_OBJECTS = Tokenizer.lo
+am_libparser_la_OBJECTS = BinaryTokenizer.lo Tokenizer.lo
 libparser_la_OBJECTS = $(am_libparser_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -718,6 +718,8 @@
 subst_perlshell = sed -e 's,[@]PERL[@],$(PERL),g' <$(srcdir)/$@.pl.in >$@ || ($(RM) -f $@ ; exit 1)
 noinst_LTLIBRARIES = libparser.la
 libparser_la_SOURCES = \
+	BinaryTokenizer.h \
+	BinaryTokenizer.cc \
 	Tokenizer.h \
 	Tokenizer.cc
 
@@ -785,6 +787,7 @@
 distclean-compile:
 	-rm -f *.tab.c
 
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BinaryTokenizer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Tokenizer.Plo@am__quote@
 
 .cc.o:
diff -u -r -N squid-4.0.10/src/parser/Tokenizer.cc squid-4.0.11/src/parser/Tokenizer.cc
--- squid-4.0.10/src/parser/Tokenizer.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/parser/Tokenizer.cc	2016-06-10 08:32:57.000000000 +1200
@@ -227,7 +227,7 @@
         }
         if (s >= end) return false;
     }
-    if (( base == 0 || base == 16) && *s == '0' && (s+1 <= end ) &&
+    if (( base == 0 || base == 16) && *s == '0' && (s+1 < end ) &&
             tolower(*(s+1)) == 'x') {
         s += 2;
         base = 16;
@@ -250,7 +250,8 @@
 
     int any = 0, c;
     int64_t acc = 0;
-    for (c = *s++; s <= end; c = *s++) {
+    do {
+        c = *s;
         if (xisdigit(c)) {
             c -= '0';
         } else if (xisalpha(c)) {
@@ -267,7 +268,7 @@
             acc *= base;
             acc += c;
         }
-    }
+    } while (++s < end);
 
     if (any == 0) // nothing was parsed
         return false;
@@ -279,6 +280,6 @@
         acc = -acc;
 
     result = acc;
-    return success(s - range.rawContent() - 1);
+    return success(s - range.rawContent());
 }
 
diff -u -r -N squid-4.0.10/src/security/cert_validators/fake/security_fake_certverify.8 squid-4.0.11/src/security/cert_validators/fake/security_fake_certverify.8
--- squid-4.0.10/src/security/cert_validators/fake/security_fake_certverify.8	2016-05-07 00:32:44.000000000 +1200
+++ squid-4.0.11/src/security/cert_validators/fake/security_fake_certverify.8	2016-06-10 09:30:03.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "SECURITY_FAKE_CERTVERIFY 8"
-.TH SECURITY_FAKE_CERTVERIFY 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH SECURITY_FAKE_CERTVERIFY 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/security/Handshake.cc squid-4.0.11/src/security/Handshake.cc
--- squid-4.0.10/src/security/Handshake.cc	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.11/src/security/Handshake.cc	2016-06-10 08:32:57.000000000 +1200
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+/* DEBUG: section 83    SSL-Bump Server/Peer negotiation */
+
+#include "squid.h"
+#include "security/Handshake.h"
+#if USE_OPENSSL
+#include "ssl/support.h"
+#endif
+
+#include <unordered_set>
+
+namespace Security {
+/*
+ * The types below represent various SSL and TLS protocol elements. Most names
+ * are based on RFC 5264 and RFC 6066 terminology. Objects of these explicit
+ * types are stored or passed around. Other protocol elements are simply parsed
+ * in-place, without declaring a corresponding explicit class.
+ */
+
+/// TLS Record Layer's content types from RFC 5246 Section 6.2.1
+enum ContentType {
+    ctChangeCipherSpec = 20,
+    ctAlert = 21,
+    ctHandshake = 22,
+    ctApplicationData = 23
+};
+
+/// TLS Record Layer's frame from RFC 5246 Section 6.2.1.
+class TLSPlaintext
+{
+public:
+    explicit TLSPlaintext(Parser::BinaryTokenizer &tk);
+
+    uint8_t type; ///< see ContentType
+    AnyP::ProtocolVersion version; ///< Record Layer, not necessarily the negotiated TLS version;
+    SBuf fragment; ///< possibly partial content
+};
+
+/// draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
+class Sslv2Record
+{
+public:
+    explicit Sslv2Record(Parser::BinaryTokenizer &tk);
+
+    SBuf fragment;
+};
+
+/// TLS Handshake protocol's handshake types from RFC 5246 Section 7.4
+enum HandshakeType {
+    hskClientHello = 1,
+    hskServerHello = 2,
+    hskCertificate = 11,
+    hskServerHelloDone = 14
+};
+
+/// TLS Handshake Protocol frame from RFC 5246 Section 7.4.
+class Handshake
+{
+public:
+    explicit Handshake(Parser::BinaryTokenizer &tk);
+
+    uint8_t msg_type; ///< see HandshakeType
+    SBuf msg_body; ///< Handshake Protocol message
+};
+
+/// TLS Alert protocol frame from RFC 5246 Section 7.2.
+class Alert
+{
+public:
+    explicit Alert(Parser::BinaryTokenizer &tk);
+
+    bool fatal() const { return level == 2; }
+
+    uint8_t level; ///< warning or fatal
+    uint8_t description; ///< close_notify, unexpected_message, etc.
+};
+
+/// The size of the TLS Random structure from RFC 5246 Section 7.4.1.2.
+static const uint64_t HelloRandomSize = 32;
+
+/// TLS Hello Extension from RFC 5246 Section 7.4.1.4.
+class Extension
+{
+public:
+    typedef uint16_t Type;
+    explicit Extension(Parser::BinaryTokenizer &tk);
+
+    /// whether this extension is supported by Squid and, hence, may be bumped
+    /// after peeking or spliced after staring (subject to other restrictions)
+    bool supported() const;
+
+    Type type;
+    SBuf data;
+};
+
+/// Extension types optimized for fast lookups.
+typedef std::unordered_set<Extension::Type> Extensions;
+static Extensions SupportedExtensions();
+
+} // namespace Security
+
+/// Convenience helper: We parse ProtocolVersion but store "int".
+static AnyP::ProtocolVersion
+ParseProtocolVersion(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, ".version");
+    uint8_t vMajor = tk.uint8(".major");
+    uint8_t vMinor = tk.uint8(".minor");
+    if (vMajor == 0 && vMinor == 2)
+        return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
+
+    Must(vMajor == 3);
+    if (vMinor == 0)
+        return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
+
+    return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, (vMinor - 1));
+}
+
+Security::TLSPlaintext::TLSPlaintext(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, "TLSPlaintext");
+    type = tk.uint8(".type");
+    Must(type >= ctChangeCipherSpec && type <= ctApplicationData);
+    version = ParseProtocolVersion(tk);
+    // TODO: Must(version.major == 3);
+    fragment = tk.pstring16(".fragment");
+    context.success();
+}
+
+Security::Handshake::Handshake(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, "Handshake");
+    msg_type = tk.uint8(".msg_type");
+    msg_body = tk.pstring24(".msg_body");
+    context.success();
+}
+
+Security::Alert::Alert(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, "Alert");
+    level = tk.uint8(".level");
+    description = tk.uint8(".description");
+    context.success();
+}
+
+Security::Extension::Extension(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, "Extension");
+    type = tk.uint16(".type");
+    data = tk.pstring16(".data");
+    context.success();
+}
+
+bool
+Security::Extension::supported() const
+{
+    static const Extensions supportedExtensions = SupportedExtensions();
+    return supportedExtensions.find(type) != supportedExtensions.end();
+}
+
+Security::Sslv2Record::Sslv2Record(Parser::BinaryTokenizer &tk)
+{
+    Parser::BinaryTokenizerContext context(tk, "Sslv2Record");
+    const uint16_t head = tk.uint16(".head");
+    const uint16_t length = head & 0x7FFF;
+    Must((head & 0x8000) && length); // SSLv2 message [without padding]
+    fragment = tk.area(length, ".fragment");
+    context.success();
+}
+
+Security::TlsDetails::TlsDetails():
+    compressionSupported(false),
+    doHeartBeats(false),
+    tlsTicketsExtension(false),
+    hasTlsTicket(false),
+    tlsStatusRequest(false),
+    unsupportedExtensions(false)
+{
+}
+
+/* Security::HandshakeParser */
+
+Security::HandshakeParser::HandshakeParser():
+    details(new TlsDetails),
+    state(atHelloNone),
+    resumingSession(false),
+    currentContentType(0),
+    done(nullptr),
+    expectingModernRecords(false)
+{
+}
+
+void
+Security::HandshakeParser::parseVersion2Record()
+{
+    const Sslv2Record record(tkRecords);
+    tkRecords.commit();
+    details->tlsVersion = AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
+    parseVersion2HandshakeMessage(record.fragment);
+    state = atHelloReceived;
+    done = "SSLv2";
+}
+
+/// RFC 5246. Appendix E.2. Compatibility with SSL 2.0
+/// And draft-hickman-netscape-ssl-00. Section 4.1. SSL Record Header Format
+bool
+Security::HandshakeParser::isSslv2Record(const SBuf &raw) const
+{
+    Parser::BinaryTokenizer tk(raw, true);
+    const uint16_t head = tk.uint16("?v2Hello.msg_head");
+    const uint8_t type = tk.uint8("?v2Hello.msg_type");
+    const uint16_t length = head & 0x7FFF;
+    return (head & 0x8000) && length && type == 1;
+}
+
+void
+Security::HandshakeParser::parseRecord()
+{
+    if (expectingModernRecords)
+        parseModernRecord();
+    else
+        parseVersion2Record();
+}
+
+/// parses a single TLS Record Layer frame
+void
+Security::HandshakeParser::parseModernRecord()
+{
+    const TLSPlaintext record(tkRecords);
+    tkRecords.commit();
+
+    details->tlsVersion = record.version;
+
+    // RFC 5246: length MUST NOT exceed 2^14
+    Must(record.fragment.length() <= (1 << 14));
+    // RFC 5246: MUST NOT send zero-length [non-application] fragments
+    Must(record.fragment.length() || record.type == ContentType::ctApplicationData);
+
+    if (currentContentType != record.type) {
+        Must(tkMessages.atEnd()); // no currentContentType leftovers
+        fragments = record.fragment;
+        tkMessages.reset(fragments, true); // true because more fragments may come
+        currentContentType = record.type;
+    } else {
+        fragments.append(record.fragment);
+        tkMessages.reinput(fragments, true); // true because more fragments may come
+        tkMessages.rollback();
+    }
+    parseMessages();
+}
+
+/// parses one or more "higher-level protocol" frames of currentContentType
+void
+Security::HandshakeParser::parseMessages()
+{
+    for (; !tkMessages.atEnd(); tkMessages.commit()) {
+        switch (currentContentType) {
+        case ContentType::ctChangeCipherSpec:
+            parseChangeCipherCpecMessage();
+            continue;
+        case ContentType::ctAlert:
+            parseAlertMessage();
+            continue;
+        case ContentType::ctHandshake:
+            parseHandshakeMessage();
+            continue;
+        case ContentType::ctApplicationData:
+            parseApplicationDataMessage();
+            continue;
+        }
+        skipMessage("unknown ContentType msg [fragment]");
+    }
+}
+
+void
+Security::HandshakeParser::parseChangeCipherCpecMessage()
+{
+    Must(currentContentType == ContentType::ctChangeCipherSpec);
+    // We are currently ignoring Change Cipher Spec Protocol messages.
+    skipMessage("ChangeCipherCpec msg [fragment]");
+
+    // Everything after the ChangeCipherCpec message may be encrypted.
+    // Continuing parsing is pointless. Stop here.
+    resumingSession = true;
+    done = "ChangeCipherCpec";
+}
+
+void
+Security::HandshakeParser::parseAlertMessage()
+{
+    Must(currentContentType == ContentType::ctAlert);
+    const Alert alert(tkMessages);
+    debugs(83, (alert.fatal() ? 2:3),
+           "level " << static_cast<int>(alert.level) <<
+           " description " << static_cast<int>(alert.description));
+    if (alert.fatal())
+        done = "fatal Alert";
+    // else ignore the warning (at least for now)
+}
+
+void
+Security::HandshakeParser::parseHandshakeMessage()
+{
+    Must(currentContentType == ContentType::ctHandshake);
+
+    const Handshake message(tkMessages);
+
+    switch (message.msg_type) {
+    case HandshakeType::hskClientHello:
+        Must(state < atHelloReceived);
+        Security::HandshakeParser::parseClientHelloHandshakeMessage(message.msg_body);
+        state = atHelloReceived;
+        done = "ClientHello";
+        return;
+    case HandshakeType::hskServerHello:
+        Must(state < atHelloReceived);
+        parseServerHelloHandshakeMessage(message.msg_body);
+        state = atHelloReceived;
+        return;
+    case HandshakeType::hskCertificate:
+        Must(state < atCertificatesReceived);
+        state = atCertificatesReceived;
+        return;
+    case HandshakeType::hskServerHelloDone:
+        Must(state < atHelloDoneReceived);
+        // zero-length
+        state = atHelloDoneReceived;
+        done = "ServerHelloDone";
+        return;
+    }
+    debugs(83, 5, "ignoring " << message.msg_body.length() << "-byte type-" <<
+           message.msg_type << " handshake message");
+}
+
+void
+Security::HandshakeParser::parseApplicationDataMessage()
+{
+    Must(currentContentType == ContentType::ctApplicationData);
+    skipMessage("app data [fragment]");
+}
+
+void
+Security::HandshakeParser::parseVersion2HandshakeMessage(const SBuf &raw)
+{
+    Parser::BinaryTokenizer tk(raw);
+    Parser::BinaryTokenizerContext hello(tk, "V2ClientHello");
+    Must(tk.uint8(".type") == hskClientHello); // Only client hello supported.
+    details->tlsSupportedVersion = ParseProtocolVersion(tk);
+    const uint16_t ciphersLen = tk.uint16(".cipher_specs.length");
+    const uint16_t sessionIdLen = tk.uint16(".session_id.length");
+    const uint16_t challengeLen = tk.uint16(".challenge.length");
+    parseV23Ciphers(tk.area(ciphersLen, ".cipher_specs.body"));
+    details->sessionId = tk.area(sessionIdLen, ".session_id.body");
+    tk.skip(challengeLen, ".challenge.body");
+    hello.success();
+}
+
+void
+Security::HandshakeParser::parseClientHelloHandshakeMessage(const SBuf &raw)
+{
+    Parser::BinaryTokenizer tk(raw);
+    Parser::BinaryTokenizerContext hello(tk, "ClientHello");
+    details->tlsSupportedVersion = ParseProtocolVersion(tk);
+    details->clientRandom = tk.area(HelloRandomSize, ".random");
+    details->sessionId = tk.pstring8(".session_id");
+    parseCiphers(tk.pstring16(".cipher_suites"));
+    details->compressionSupported = parseCompressionMethods(tk.pstring8(".compression_methods"));
+    if (!tk.atEnd()) // extension-free message ends here
+        parseExtensions(tk.pstring16(".extensions"));
+    hello.success();
+}
+
+bool
+Security::HandshakeParser::parseCompressionMethods(const SBuf &raw)
+{
+    if (raw.length() == 0)
+        return false;
+    Parser::BinaryTokenizer tk(raw);
+    while (!tk.atEnd()) {
+        // Probably here we should check for DEFLATE(1) compression method
+        // which is the only supported by openSSL subsystem.
+        if (tk.uint8("compression_method") != 0)
+            return true;
+    }
+    return false;
+}
+
+void
+Security::HandshakeParser::parseExtensions(const SBuf &raw)
+{
+    Parser::BinaryTokenizer tk(raw);
+    while (!tk.atEnd()) {
+        Extension extension(tk);
+
+        if (!details->unsupportedExtensions && !extension.supported()) {
+            debugs(83, 5, "first unsupported extension: " << extension.type);
+            details->unsupportedExtensions = true;
+        }
+
+        switch(extension.type) {
+        case 0: // The SNI extension; RFC 6066, Section 3
+            details->serverName = parseSniExtension(extension.data);
+            break;
+        case 5: // Certificate Status Request; RFC 6066, Section 8
+            details->tlsStatusRequest = true;
+            break;
+        case 15: // The heartBeats, RFC 6520
+            details->doHeartBeats = true;
+            break;
+        case 16: { // Application-Layer Protocol Negotiation Extension, RFC 7301
+            Parser::BinaryTokenizer tkAPN(extension.data);
+            details->tlsAppLayerProtoNeg = tkAPN.pstring16("APN");
+            break;
+        }
+        case 35: // SessionTicket TLS Extension; RFC 5077
+            details->tlsTicketsExtension = true;
+            details->hasTlsTicket = !extension.data.isEmpty();
+        case 13172: // Next Protocol Negotiation Extension (expired draft?)
+        default:
+            break;
+        }
+    }
+}
+
+void
+Security::HandshakeParser::parseCiphers(const SBuf &raw)
+{
+    details->ciphers.reserve(raw.length() / sizeof(uint16_t));
+    Parser::BinaryTokenizer tk(raw);
+    while (!tk.atEnd()) {
+        const uint16_t cipher = tk.uint16("cipher");
+        details->ciphers.insert(cipher);
+    }
+}
+
+void
+Security::HandshakeParser::parseV23Ciphers(const SBuf &raw)
+{
+    Parser::BinaryTokenizer tk(raw);
+    while (!tk.atEnd()) {
+        // RFC 6101 Appendix E, RFC 5246 Appendix E2
+        // Unlike TLS, ciphers in SSLv23 Hellos are 3 bytes long and come in
+        // two versions: v2 and v3. The two versions may co-exist in a single
+        // SSLv23 Hello. Only v3 ciphers have a first byte value of zero.
+        // The ciphers are needed for our peeking/staring code that
+        // does not support SSLv2, so we ignore v2 ciphers.
+        const uint8_t prefix = tk.uint8("prefix");
+        const uint16_t cipher = tk.uint16("cipher");
+        if (prefix == 0)
+            details->ciphers.insert(cipher);
+    }
+}
+
+/// RFC 5246 Section 7.4.1.3. Server Hello
+void
+Security::HandshakeParser::parseServerHelloHandshakeMessage(const SBuf &raw)
+{
+    Parser::BinaryTokenizer tk(raw);
+    Parser::BinaryTokenizerContext hello(tk, "ServerHello");
+    details->tlsSupportedVersion = ParseProtocolVersion(tk);
+    tk.skip(HelloRandomSize, ".random");
+    details->sessionId = tk.pstring8(".session_id");
+    details->ciphers.insert(tk.uint16(".cipher_suite"));
+    details->compressionSupported = tk.uint8(".compression_method") != 0; // not null
+    if (!tk.atEnd()) // extensions present
+        parseExtensions(tk.pstring16(".extensions"));
+    hello.success();
+}
+
+// RFC 6066 Section 3: ServerNameList (may be sent by both clients and servers)
+SBuf
+Security::HandshakeParser::parseSniExtension(const SBuf &extensionData) const
+{
+    // Servers SHOULD send an empty SNI extension, not an empty ServerNameList!
+    if (extensionData.isEmpty())
+        return SBuf();
+
+    // SNI MUST NOT contain more than one name of the same name_type but
+    // we ignore violations and simply return the first host name found.
+    Parser::BinaryTokenizer tkList(extensionData);
+    Parser::BinaryTokenizer tkNames(tkList.pstring16("ServerNameList"));
+    while (!tkNames.atEnd()) {
+        Parser::BinaryTokenizerContext serverName(tkNames, "ServerName");
+        const uint8_t nameType = tkNames.uint8(".name_type");
+        const SBuf name = tkNames.pstring16(".name");
+        serverName.success();
+
+        if (nameType == 0) {
+            debugs(83, 3, "host_name=" << name);
+            return name; // it may be empty
+        }
+        // else we just parsed a new/unsupported NameType which,
+        // according to RFC 6066, MUST begin with a 16-bit length field
+    }
+    return SBuf(); // SNI extension lacks host_name
+}
+
+void
+Security::HandshakeParser::skipMessage(const char *description)
+{
+    // tkMessages/fragments can only contain messages of the same ContentType.
+    // To skip a message, we can and should skip everything we have [left]. If
+    // we have partial messages, debugging will mislead about their boundaries.
+    tkMessages.skip(tkMessages.leftovers().length(), description);
+}
+
+bool
+Security::HandshakeParser::parseHello(const SBuf &data)
+{
+    try {
+        if (!expectingModernRecords.configured())
+            expectingModernRecords.configure(!isSslv2Record(data));
+
+        // data contains everything read so far, but we may read more later
+        tkRecords.reinput(data, true);
+        tkRecords.rollback();
+        while (!done)
+            parseRecord();
+        debugs(83, 7, "success; got: " << done);
+        // we are done; tkRecords may have leftovers we are not interested in
+        return true;
+    }
+    catch (const Parser::BinaryTokenizer::InsufficientInput &) {
+        debugs(83, 5, "need more data");
+        return false;
+    }
+    return false; // unreached
+}
+
+#if USE_OPENSSL
+
+/// A helper function to create a set of all supported TLS extensions
+static
+Security::Extensions
+Security::SupportedExtensions()
+{
+    // optimize lookup speed by reserving the number of values x3, approximately
+    Security::Extensions extensions(64);
+
+    // Keep this list ordered and up to date by running something like
+    // egrep '# *define TLSEXT_TYPE_' /usr/include/openssl/tls1.h
+    // TODO: Teach OpenSSL to return the list of extensions it supports.
+#if defined(TLSEXT_TYPE_server_name) // 0
+    extensions.insert(TLSEXT_TYPE_server_name);
+#endif
+#if defined(TLSEXT_TYPE_max_fragment_length) // 1
+    extensions.insert(TLSEXT_TYPE_max_fragment_length);
+#endif
+#if defined(TLSEXT_TYPE_client_certificate_url) // 2
+    extensions.insert(TLSEXT_TYPE_client_certificate_url);
+#endif
+#if defined(TLSEXT_TYPE_trusted_ca_keys) // 3
+    extensions.insert(TLSEXT_TYPE_trusted_ca_keys);
+#endif
+#if defined(TLSEXT_TYPE_truncated_hmac) // 4
+    extensions.insert(TLSEXT_TYPE_truncated_hmac);
+#endif
+#if defined(TLSEXT_TYPE_status_request) // 5
+    extensions.insert(TLSEXT_TYPE_status_request);
+#endif
+#if defined(TLSEXT_TYPE_user_mapping) // 6
+    extensions.insert(TLSEXT_TYPE_user_mapping);
+#endif
+#if defined(TLSEXT_TYPE_client_authz) // 7
+    extensions.insert(TLSEXT_TYPE_client_authz);
+#endif
+#if defined(TLSEXT_TYPE_server_authz) // 8
+    extensions.insert(TLSEXT_TYPE_server_authz);
+#endif
+#if defined(TLSEXT_TYPE_cert_type) // 9
+    extensions.insert(TLSEXT_TYPE_cert_type);
+#endif
+#if defined(TLSEXT_TYPE_elliptic_curves) // 10
+    extensions.insert(TLSEXT_TYPE_elliptic_curves);
+#endif
+#if defined(TLSEXT_TYPE_ec_point_formats) // 11
+    extensions.insert(TLSEXT_TYPE_ec_point_formats);
+#endif
+#if defined(TLSEXT_TYPE_srp) // 12
+    extensions.insert(TLSEXT_TYPE_srp);
+#endif
+#if defined(TLSEXT_TYPE_signature_algorithms) // 13
+    extensions.insert(TLSEXT_TYPE_signature_algorithms);
+#endif
+#if defined(TLSEXT_TYPE_use_srtp) // 14
+    extensions.insert(TLSEXT_TYPE_use_srtp);
+#endif
+#if defined(TLSEXT_TYPE_heartbeat) // 15
+    extensions.insert(TLSEXT_TYPE_heartbeat);
+#endif
+#if defined(TLSEXT_TYPE_session_ticket) // 35
+    extensions.insert(TLSEXT_TYPE_session_ticket);
+#endif
+#if defined(TLSEXT_TYPE_renegotiate) // 0xff01
+    extensions.insert(TLSEXT_TYPE_renegotiate);
+#endif
+#if defined(TLSEXT_TYPE_next_proto_neg) // 13172
+    extensions.insert(TLSEXT_TYPE_next_proto_neg);
+#endif
+
+    /*
+     * OpenSSL does not support these last extensions by default, but those
+     * building the OpenSSL libraries and/or Squid might define them.
+     */
+
+    // OpenSSL may be built to support draft-rescorla-tls-opaque-prf-input-00,
+    // with the extension type value configured at build time. OpenSSL, Squid,
+    // and TLS agents must all be built with the same extension type value.
+#if defined(TLSEXT_TYPE_opaque_prf_input)
+    extensions.insert(TLSEXT_TYPE_opaque_prf_input);
+#endif
+
+    // Define this to add extensions supported by your OpenSSL but unknown to
+    // your Squid version. Use {list-initialization} to add multiple extensions.
+#if defined(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID)
+    extensions.insert(TLSEXT_TYPE_SUPPORTED_BY_MY_SQUID);
+#endif
+
+    return extensions; // might be empty
+}
+
+#else
+
+static
+Security::Extensions
+Security::SupportedExtensions()
+{
+    return Extensions(); // no extensions are supported without OpenSSL
+}
+#endif
+
diff -u -r -N squid-4.0.10/src/security/Handshake.h squid-4.0.11/src/security/Handshake.h
--- squid-4.0.10/src/security/Handshake.h	1970-01-01 12:00:00.000000000 +1200
+++ squid-4.0.11/src/security/Handshake.h	2016-06-10 08:32:57.000000000 +1200
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ *
+ * Squid software is distributed under GPLv2+ license and includes
+ * contributions from numerous individuals and organizations.
+ * Please see the COPYING and CONTRIBUTORS files for details.
+ */
+
+#ifndef SQUID_SECURITY_HANDSHAKE_H
+#define SQUID_SECURITY_HANDSHAKE_H
+
+#include "anyp/ProtocolVersion.h"
+#include "base/YesNoNone.h"
+#include "parser/BinaryTokenizer.h"
+
+#include <unordered_set>
+
+namespace Security
+{
+
+class TlsDetails: public RefCountable
+{
+public:
+    typedef RefCount<TlsDetails> Pointer;
+
+    TlsDetails();
+    /// Prints to os stream a human readable form of TlsDetails object
+    std::ostream & print(std::ostream &os) const;
+
+    AnyP::ProtocolVersion tlsVersion; ///< The TLS hello message version
+    AnyP::ProtocolVersion tlsSupportedVersion; ///< The requested/used TLS version
+    bool compressionSupported; ///< The requested/used compressed  method
+    SBuf serverName; ///< The SNI hostname, if any
+    bool doHeartBeats;
+    bool tlsTicketsExtension; ///< whether TLS tickets extension is enabled
+    bool hasTlsTicket; ///< whether a TLS ticket is included
+    bool tlsStatusRequest; ///< whether the TLS status request extension is set
+    bool unsupportedExtensions; ///< whether any unsupported by Squid extensions are used
+    SBuf tlsAppLayerProtoNeg; ///< The value of the TLS application layer protocol extension if it is enabled
+    /// The client random number
+    SBuf clientRandom;
+    SBuf sessionId;
+
+    typedef std::unordered_set<uint16_t> Ciphers;
+    Ciphers ciphers;
+};
+
+inline
+std::ostream &operator <<(std::ostream &os, Security::TlsDetails const &details)
+{
+    return details.print(os);
+}
+
+/// Incremental TLS/SSL Handshake parser.
+class HandshakeParser
+{
+public:
+    /// The parsing states
+    typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived, atCertificatesReceived, atHelloDoneReceived, atNstReceived, atCcsReceived, atFinishReceived} ParserState;
+
+    HandshakeParser();
+
+    /// Parses the initial sequence of raw bytes sent by the TLS/SSL agent.
+    /// Returns true upon successful completion (e.g., got HelloDone).
+    /// Returns false if more data is needed.
+    /// Throws on errors.
+    bool parseHello(const SBuf &data);
+
+    TlsDetails::Pointer details; ///< TLS handshake meta info or nil.
+
+    ParserState state; ///< current parsing state.
+
+    bool resumingSession; ///< True if this is a resuming session
+
+private:
+    bool isSslv2Record(const SBuf &raw) const;
+    void parseRecord();
+    void parseModernRecord();
+    void parseVersion2Record();
+    void parseMessages();
+
+    void parseChangeCipherCpecMessage();
+    void parseAlertMessage();
+    void parseHandshakeMessage();
+    void parseApplicationDataMessage();
+    void skipMessage(const char *msgType);
+
+    bool parseRecordVersion2Try();
+    void parseVersion2HandshakeMessage(const SBuf &raw);
+    void parseClientHelloHandshakeMessage(const SBuf &raw);
+    void parseServerHelloHandshakeMessage(const SBuf &raw);
+
+    bool parseCompressionMethods(const SBuf &raw);
+    void parseExtensions(const SBuf &raw);
+    SBuf parseSniExtension(const SBuf &extensionData) const;
+
+    void parseCiphers(const SBuf &raw);
+    void parseV23Ciphers(const SBuf &raw);
+
+    unsigned int currentContentType; ///< The current TLS/SSL record content type
+
+    const char *done; ///< not nil if we got what we were looking for
+
+    /// concatenated TLSPlaintext.fragments of TLSPlaintext.type
+    SBuf fragments;
+
+    /// TLS record layer (parsing uninterpreted data)
+    Parser::BinaryTokenizer tkRecords;
+
+    /// TLS message layer (parsing fragments)
+    Parser::BinaryTokenizer tkMessages;
+
+    /// Whether to use TLS parser or a V2 compatible parser
+    YesNoNone expectingModernRecords;
+};
+
+}
+
+#endif // SQUID_SECURITY_HANDSHAKE_H
+
diff -u -r -N squid-4.0.10/src/security/Makefile.am squid-4.0.11/src/security/Makefile.am
--- squid-4.0.10/src/security/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -16,6 +16,8 @@
 	Context.h \
 	EncryptorAnswer.cc \
 	EncryptorAnswer.h \
+	Handshake.cc \
+	Handshake.h \
 	forward.h \
 	KeyData.h \
 	LockingPointer.h \
diff -u -r -N squid-4.0.10/src/security/Makefile.in squid-4.0.11/src/security/Makefile.in
--- squid-4.0.10/src/security/Makefile.in	2016-05-06 23:37:07.000000000 +1200
+++ squid-4.0.11/src/security/Makefile.in	2016-06-10 08:35:05.000000000 +1200
@@ -163,8 +163,9 @@
 CONFIG_CLEAN_VPATH_FILES =
 LTLIBRARIES = $(noinst_LTLIBRARIES)
 libsecurity_la_LIBADD =
-am_libsecurity_la_OBJECTS = EncryptorAnswer.lo NegotiationHistory.lo \
-	PeerOptions.lo ServerOptions.lo Session.lo
+am_libsecurity_la_OBJECTS = EncryptorAnswer.lo Handshake.lo \
+	NegotiationHistory.lo PeerOptions.lo ServerOptions.lo \
+	Session.lo
 libsecurity_la_OBJECTS = $(am_libsecurity_la_OBJECTS)
 AM_V_lt = $(am__v_lt_@AM_V@)
 am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -764,6 +765,8 @@
 	Context.h \
 	EncryptorAnswer.cc \
 	EncryptorAnswer.h \
+	Handshake.cc \
+	Handshake.h \
 	forward.h \
 	KeyData.h \
 	LockingPointer.h \
@@ -841,6 +844,7 @@
 	-rm -f *.tab.c
 
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/EncryptorAnswer.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Handshake.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NegotiationHistory.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/PeerOptions.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerOptions.Plo@am__quote@
diff -u -r -N squid-4.0.10/src/security/NegotiationHistory.cc squid-4.0.11/src/security/NegotiationHistory.cc
--- squid-4.0.10/src/security/NegotiationHistory.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/NegotiationHistory.cc	2016-06-10 08:32:57.000000000 +1200
@@ -15,70 +15,85 @@
 #include "ssl/support.h"
 #endif
 
-Security::NegotiationHistory::NegotiationHistory():
-    helloVersion_(-1),
-    supportedVersion_(-1),
-    version_(-1)
+Security::NegotiationHistory::NegotiationHistory()
 #if USE_OPENSSL
-    , cipher(NULL)
+    : cipher(nullptr)
 #endif
 {
 }
 
 const char *
-Security::NegotiationHistory::printTlsVersion(int v) const
+Security::NegotiationHistory::printTlsVersion(AnyP::ProtocolVersion const &v) const
 {
+    if (v.protocol != AnyP::PROTO_SSL && v.protocol != AnyP::PROTO_TLS)
+        return nullptr;
+
+    static char buf[512];
+    snprintf(buf, sizeof(buf), "%s/%d.%d", AnyP::ProtocolType_str[v.protocol], v.major, v.minor);
+    return buf;
+}
+
 #if USE_OPENSSL
+static AnyP::ProtocolVersion
+toProtocolVersion(const int v)
+{
     switch(v) {
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+#if defined(TLS1_2_VERSION)
     case TLS1_2_VERSION:
-        return "TLS/1.2";
+        return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 2);
+#endif
+#if defined(TLS1_1_VERSION)
     case TLS1_1_VERSION:
-        return "TLS/1.1";
+        return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 1);
 #endif
+#if defined(TLS1_VERSION)
     case TLS1_VERSION:
-        return "TLS/1.0";
+        return AnyP::ProtocolVersion(AnyP::PROTO_TLS, 1, 0);
+#endif
+#if defined(SSL3_VERSION)
     case SSL3_VERSION:
-        return "SSL/3.0";
+        return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0);
+#endif
+#if defined(SSL2_VERSION)
     case SSL2_VERSION:
-        return "SSL/2.0";
+        return AnyP::ProtocolVersion(AnyP::PROTO_SSL, 2, 0);
+#endif
     default:
-        return nullptr;
+        return AnyP::ProtocolVersion();
     }
-#else
-    return nullptr;
-#endif
 }
+#endif
 
 void
-Security::NegotiationHistory::fillWith(Security::SessionPtr ssl)
+Security::NegotiationHistory::retrieveNegotiatedInfo(Security::SessionPtr ssl)
 {
 #if USE_OPENSSL
     if ((cipher = SSL_get_current_cipher(ssl)) != NULL) {
         // Set the negotiated version only if the cipher negotiated
         // else probably the negotiation is not completed and version
         // is not the final negotiated version
-        version_ = ssl->version;
+        version_ = toProtocolVersion(ssl->version);
     }
 
-    BIO *b = SSL_get_rbio(ssl);
-    Ssl::Bio *bio = static_cast<Ssl::Bio *>(b->ptr);
-
-    if (::Config.onoff.logTlsServerHelloDetails) {
-        if (Ssl::ServerBio *srvBio = dynamic_cast<Ssl::ServerBio *>(bio))
-            srvBio->extractHelloFeatures();
+    if (Debug::Enabled(83, 5)) {
+        BIO *b = SSL_get_rbio(ssl);
+        Ssl::Bio *bio = static_cast<Ssl::Bio *>(b->ptr);
+        debugs(83, 5, "SSL connection info on FD " << bio->fd() <<
+               " SSL version " << version_ <<
+               " negotiated cipher " << cipherName());
     }
-
-    const Ssl::Bio::sslFeatures &features = bio->receivedHelloFeatures();
-    helloVersion_ = features.sslHelloVersion;
-    supportedVersion_ = features.sslVersion;
-
-    debugs(83, 5, "SSL connection info on FD " << bio->fd() <<
-           " SSL version " << version_ <<
-           " negotiated cipher " << cipherName());
 #endif
 }
 
+void
+Security::NegotiationHistory::retrieveParsedInfo(Security::TlsDetails::Pointer const &details)
+{
+    if (details) {
+        helloVersion_ = details->tlsVersion;
+        supportedVersion_ = details->tlsSupportedVersion;
+    }
+}
+
 const char *
 Security::NegotiationHistory::cipherName() const
 {
diff -u -r -N squid-4.0.10/src/security/NegotiationHistory.h squid-4.0.11/src/security/NegotiationHistory.h
--- squid-4.0.10/src/security/NegotiationHistory.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/NegotiationHistory.h	2016-06-10 08:32:57.000000000 +1200
@@ -9,6 +9,8 @@
 #ifndef SQUID_SRC_SECURITY_NEGOTIATIONHISTORY_H
 #define SQUID_SRC_SECURITY_NEGOTIATIONHISTORY_H
 
+#include "anyp/ProtocolVersion.h"
+#include "security/Handshake.h"
 #include "security/Session.h"
 
 namespace Security {
@@ -17,7 +19,13 @@
 {
 public:
     NegotiationHistory();
-    void fillWith(Security::SessionPtr); ///< Extract negotiation information from TLS object
+
+    /// Extract negotiation information from TLS object
+    void retrieveNegotiatedInfo(Security::SessionPtr);
+
+    /// Extract information from parser stored in TlsDetails  object
+    void retrieveParsedInfo(Security::TlsDetails::Pointer const &details);
+
     const char *cipherName() const; ///< The name of negotiated cipher
     /// String representation of TLS negotiated version
     const char *negotiatedVersion() const {return printTlsVersion(version_);}
@@ -28,10 +36,10 @@
     const char *supportedVersion() const {return printTlsVersion(supportedVersion_);}
 private:
     /// String representation of the TLS version 'v'
-    const char *printTlsVersion(int v) const;
-    int helloVersion_; ///< The TLL version of the hello message
-    int supportedVersion_; ///< The maximum supported TLS version
-    int version_; ///< The negotiated TLL version
+    const char *printTlsVersion(AnyP::ProtocolVersion const &v) const;
+    AnyP::ProtocolVersion helloVersion_; ///< The TLS version of the hello message
+    AnyP::ProtocolVersion supportedVersion_; ///< The maximum supported TLS version
+    AnyP::ProtocolVersion version_; ///< The negotiated TLS version
 #if USE_OPENSSL
     const SSL_CIPHER *cipher; ///< The negotiated cipher
 #endif
diff -u -r -N squid-4.0.10/src/security/PeerOptions.cc squid-4.0.11/src/security/PeerOptions.cc
--- squid-4.0.10/src/security/PeerOptions.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/PeerOptions.cc	2016-06-10 08:32:57.000000000 +1200
@@ -240,7 +240,7 @@
     }
 
 #else
-    fatal("Failed to allocate TLS client context: No TLS library\n");
+    debugs(83, 1, "WARNING: Failed to allocate TLS client context: No TLS library");
 
 #endif
 
@@ -250,20 +250,14 @@
 Security::ContextPtr
 Security::PeerOptions::createClientContext(bool setOptions)
 {
-    Security::ContextPtr t = nullptr;
-
     updateTlsVersionLimits();
 
+    Security::ContextPtr t = createBlankContext();
+    if (t) {
 #if USE_OPENSSL
-    // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
-    t = sslCreateClientContext(*this, (setOptions ? parsedOptions : 0), parsedFlags);
-
-#elif USE_GNUTLS && WHEN_READY_FOR_GNUTLS
-    t = createBlankContext();
-
+        // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
+        Ssl::InitClientContext(t, *this, (setOptions ? parsedOptions : 0), parsedFlags);
 #endif
-
-    if (t) {
         updateContextNpn(t);
         updateContextCa(t);
         updateContextCrl(t);
@@ -573,6 +567,22 @@
     //       it does support ALPN per-session, not per-context.
 }
 
+static const char *
+loadSystemTrustedCa(Security::ContextPtr &ctx)
+{
+#if USE_OPENSSL
+    if (SSL_CTX_set_default_verify_paths(ctx) == 0)
+        return ERR_error_string(ERR_get_error(), nullptr);
+
+#elif USE_GNUTLS
+    auto x = gnutls_certificate_set_x509_system_trust(ctx);
+    if (x < 0)
+        return gnutls_strerror(x);
+
+#endif
+    return nullptr;
+}
+
 void
 Security::PeerOptions::updateContextCa(Security::ContextPtr &ctx)
 {
@@ -594,17 +604,9 @@
     if (!flags.tlsDefaultCa)
         return;
 
-#if USE_OPENSSL
-    if (!SSL_CTX_set_default_verify_paths(ctx)) {
-        const int ssl_error = ERR_get_error();
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA : "
-               << ERR_error_string(ssl_error, NULL));
-    }
-#elif USE_GNUTLS
-    if (gnutls_certificate_set_x509_system_trust(ctx) != GNUTLS_E_SUCCESS) {
-        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA.");
+    if (const char *err = loadSystemTrustedCa(ctx)) {
+        debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA : " << err);
     }
-#endif
 }
 
 void
diff -u -r -N squid-4.0.10/src/security/ServerOptions.cc squid-4.0.11/src/security/ServerOptions.cc
--- squid-4.0.10/src/security/ServerOptions.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/ServerOptions.cc	2016-06-10 08:32:57.000000000 +1200
@@ -117,6 +117,21 @@
     return t;
 }
 
+Security::ContextPtr
+Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &port)
+{
+    updateTlsVersionLimits();
+
+    Security::ContextPtr t = createBlankContext();
+    if (t) {
+#if USE_OPENSSL
+        Ssl::InitServerContext(t, port);
+#endif
+    }
+
+    return t;
+}
+
 void
 Security::ServerOptions::loadDhParams()
 {
diff -u -r -N squid-4.0.10/src/security/ServerOptions.h squid-4.0.11/src/security/ServerOptions.h
--- squid-4.0.10/src/security/ServerOptions.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/security/ServerOptions.h	2016-06-10 08:32:57.000000000 +1200
@@ -9,6 +9,7 @@
 #ifndef SQUID_SRC_SECURITY_SERVEROPTIONS_H
 #define SQUID_SRC_SECURITY_SERVEROPTIONS_H
 
+#include "anyp/forward.h"
 #include "security/PeerOptions.h"
 
 namespace Security
@@ -31,6 +32,9 @@
     virtual Security::ContextPtr createBlankContext() const;
     virtual void dumpCfg(Packable *, const char *pfx) const;
 
+    /// generate a security server-context from these configured options
+    Security::ContextPtr createStaticServerContext(AnyP::PortCfg &);
+
     /// update the context with DH, EDH, EECDH settings
     void updateContextEecdh(Security::ContextPtr &);
 
diff -u -r -N squid-4.0.10/src/servers/FtpServer.cc squid-4.0.11/src/servers/FtpServer.cc
--- squid-4.0.10/src/servers/FtpServer.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/servers/FtpServer.cc	2016-06-10 08:32:57.000000000 +1200
@@ -1305,7 +1305,7 @@
     Must(header.has(Http::HdrType::FTP_ARGUMENTS));
     String &params = header.findEntry(Http::HdrType::FTP_ARGUMENTS)->value;
 
-    if (do_debug(9, 2)) {
+    if (Debug::Enabled(9, 2)) {
         MemBuf mb;
         mb.init();
         request->pack(&mb);
diff -u -r -N squid-4.0.10/src/SquidConfig.h squid-4.0.11/src/SquidConfig.h
--- squid-4.0.10/src/SquidConfig.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/SquidConfig.h	2016-06-10 08:32:57.000000000 +1200
@@ -305,7 +305,6 @@
         int digest_generation;
 #endif
 
-        int ie_refresh;
         int vary_ignore_expire;
         int surrogate_is_remote;
         int request_entities;
diff -u -r -N squid-4.0.10/src/SquidNew.cc squid-4.0.11/src/SquidNew.cc
--- squid-4.0.10/src/SquidNew.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/SquidNew.cc	2016-06-10 08:32:57.000000000 +1200
@@ -8,29 +8,45 @@
 
 /* DEBUG: none          Memory Allocation */
 
-#define _SQUID_EXTERNNEW_
-
 #include "squid.h"
 
-#ifdef __SUNPRO_CC
+#if !defined(__clang__)
 
 #include <new>
-void *operator new(size_t size) throw (std::bad_alloc)
+
+void *operator new(size_t size)
+{
+    return xmalloc(size);
+}
+void operator delete(void *address)
+{
+    xfree(address);
+}
+void *operator new[](size_t size)
+{
+    return xmalloc(size);
+}
+void operator delete[](void *address)
+{
+    xfree(address);
+}
+
+void *operator new(size_t size, const std::nothrow_t &tag)
 {
     return xmalloc(size);
 }
-void operator delete (void *address) throw()
+void operator delete(void *address, const std::nothrow_t &tag)
 {
-    xfree (address);
+    xfree(address);
 }
-void *operator new[] (size_t size) throw (std::bad_alloc)
+void *operator new[](size_t size, const std::nothrow_t &tag)
 {
     return xmalloc(size);
 }
-void operator delete[] (void *address) throw()
+void operator delete[](void *address, const std::nothrow_t &tag)
 {
-    xfree (address);
+    xfree(address);
 }
 
-#endif /* __SUNPRO_CC */
+#endif /* !defined(__clang__) */
 
diff -u -r -N squid-4.0.10/src/ssl/bio.cc squid-4.0.11/src/ssl/bio.cc
--- squid-4.0.10/src/ssl/bio.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/bio.cc	2016-06-10 08:32:57.000000000 +1200
@@ -15,9 +15,11 @@
 #if USE_OPENSSL
 
 #include "comm.h"
+#include "fd.h"
 #include "fde.h"
 #include "globals.h"
 #include "ip/Address.h"
+#include "parser/BinaryTokenizer.h"
 #include "ssl/bio.h"
 
 #if HAVE_OPENSSL_SSL_H
@@ -127,28 +129,6 @@
     return result;
 }
 
-int
-Ssl::Bio::readAndBuffer(char *buf, int size, BIO *table, const char *description)
-{
-    prepReadBuf();
-
-    size = min((int)rbuf.potentialSpaceSize(), size);
-    if (size <= 0) {
-        debugs(83, DBG_IMPORTANT, "Not enough space to hold " <<
-               rbuf.contentSize() << "+ byte " << description);
-        return -1;
-    }
-
-    const int bytes = Ssl::Bio::read(buf, size, table);
-    debugs(83, 5, "read " << bytes << " out of " << size << " bytes"); // move to Ssl::Bio::read()
-
-    if (bytes > 0) {
-        rbuf.append(buf, bytes);
-        debugs(83, 5, "recorded " << bytes << " bytes of " << description);
-    }
-    return bytes;
-}
-
 /// Called whenever the SSL connection state changes, an alert appears, or an
 /// error occurs. See SSL_set_info_callback().
 void
@@ -167,13 +147,6 @@
            SSL_state_string(ssl) << " (" << SSL_state_string_long(ssl) << ")");
 }
 
-void
-Ssl::Bio::prepReadBuf()
-{
-    if (rbuf.isNull())
-        rbuf.init(4096, 65536);
-}
-
 bool
 Ssl::ClientBio::isClientHello(int state)
 {
@@ -203,73 +176,40 @@
     return Ssl::Bio::write(buf, size, table);
 }
 
-const char *objToString(unsigned char const *bytes, int len)
-{
-    static std::string buf;
-    buf.clear();
-    for (int i = 0; i < len; i++ ) {
-        char tmp[3];
-        snprintf(tmp, sizeof(tmp), "%.2x", bytes[i]);
-        buf.append(tmp);
-    }
-    return buf.c_str();
-}
-
 int
 Ssl::ClientBio::read(char *buf, int size, BIO *table)
 {
-    if (helloState < atHelloReceived) {
-        int bytes = readAndBuffer(buf, size, table, "TLS client Hello");
-        if (bytes <= 0)
-            return bytes;
-    }
-
-    if (helloState == atHelloNone) {
-        helloSize = receivedHelloFeatures_.parseMsgHead(rbuf);
-        if (helloSize == 0) {
-            // Not enough bytes to get hello message size
-            BIO_set_retry_read(table);
-            return -1;
-        } else if (helloSize < 0) {
-            wrongProtocol = true;
-            return -1;
-        }
-
-        helloState = atHelloStarted; //Next state
-    }
-
-    if (helloState == atHelloStarted) {
-        const unsigned char *head = (const unsigned char *)rbuf.content();
-        const char *s = objToString(head, rbuf.contentSize());
-        debugs(83, 7, "SSL Header: " << s);
-
-        if (helloSize > rbuf.contentSize()) {
-            BIO_set_retry_read(table);
-            return -1;
-        }
-        receivedHelloFeatures_.get(rbuf);
-        helloState = atHelloReceived;
-    }
-
     if (holdRead_) {
         debugs(83, 7, "Hold flag is set, retry latter. (Hold " << size << "bytes)");
         BIO_set_retry_read(table);
         return -1;
     }
 
-    if (helloState == atHelloReceived) {
-        if (rbuf.hasContent()) {
-            int bytes = (size <= rbuf.contentSize() ? size : rbuf.contentSize());
-            memcpy(buf, rbuf.content(), bytes);
-            rbuf.consume(bytes);
-            return bytes;
-        } else
-            return Ssl::Bio::read(buf, size, table);
-    }
+    if (!rbuf.isEmpty()) {
+        int bytes = (size <= (int)rbuf.length() ? size : rbuf.length());
+        memcpy(buf, rbuf.rawContent(), bytes);
+        rbuf.consume(bytes);
+        return bytes;
+    } else
+        return Ssl::Bio::read(buf, size, table);
 
     return -1;
 }
 
+Ssl::ServerBio::ServerBio(const int anFd):
+    Bio(anFd),
+    helloMsgSize(0),
+    helloBuild(false),
+    allowSplice(false),
+    allowBump(false),
+    holdWrite_(false),
+    record_(false),
+    parsedHandshake(false),
+    bumpMode_(bumpNone),
+    rbufConsumePos(0)
+{
+}
+
 void
 Ssl::ServerBio::stateChanged(const SSL *ssl, int where, int ret)
 {
@@ -277,16 +217,93 @@
 }
 
 void
-Ssl::ServerBio::setClientFeatures(const Ssl::Bio::sslFeatures &features)
+Ssl::ServerBio::setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &aHello)
 {
-    clientFeatures = features;
+    clientTlsDetails = details;
+    clientHelloMessage = aHello;
 };
 
 int
 Ssl::ServerBio::read(char *buf, int size, BIO *table)
 {
-    return record_ ?
-           readAndBuffer(buf, size, table, "TLS server Hello") : Ssl::Bio::read(buf, size, table);
+    if (parsedHandshake) // done parsing TLS Hello
+        return readAndGive(buf, size, table);
+    else
+        return readAndParse(buf, size, table);
+}
+
+/// Read and give everything to OpenSSL.
+int
+Ssl::ServerBio::readAndGive(char *buf, const int size, BIO *table)
+{
+    // If we have unused buffered bytes, give those bytes to OpenSSL now,
+    // before reading more. TODO: Read if we have buffered less than size?
+    if (rbufConsumePos < rbuf.length())
+        return giveBuffered(buf, size);
+
+    if (record_) {
+        const int result = readAndBuffer(table);
+        if (result <= 0)
+            return result;
+        return giveBuffered(buf, size);
+    }
+
+    return Ssl::Bio::read(buf, size, table);
+}
+
+/// Read and give everything to our parser.
+/// When/if parsing is finished (successfully or not), start giving to OpenSSL.
+int
+Ssl::ServerBio::readAndParse(char *buf, const int size, BIO *table)
+{
+    const int result = readAndBuffer(table);
+    if (result <= 0)
+        return result;
+
+    try {
+        if (!parser_.parseHello(rbuf)) {
+            // need more data to finish parsing
+            BIO_set_retry_read(table);
+            return -1;
+        }
+        parsedHandshake = true; // done parsing (successfully)
+    }
+    catch (const std::exception &ex) {
+        debugs(83, 2, "parsing error on FD " << fd_ << ": " << ex.what());
+        parsedHandshake = true; // done parsing (due to an error)
+    }
+
+    return giveBuffered(buf, size);
+}
+
+/// Reads more data into the read buffer. Returns either the number of bytes
+/// read or, on errors (including "try again" errors), a negative number.
+int
+Ssl::ServerBio::readAndBuffer(BIO *table)
+{
+    char *space = rbuf.rawSpace(SQUID_TCP_SO_RCVBUF);
+    const int result = Ssl::Bio::read(space, rbuf.spaceSize(), table);
+    if (result <= 0)
+        return result;
+
+    rbuf.forceSize(rbuf.length() + result);
+    return result;
+}
+
+/// give previously buffered bytes to OpenSSL
+/// returns the number of bytes given
+int
+Ssl::ServerBio::giveBuffered(char *buf, const int size)
+{
+    if (rbuf.length() <= rbufConsumePos)
+        return -1; // buffered nothing yet
+
+    const int unsent = rbuf.length() - rbufConsumePos;
+    const int bytes = (size <= unsent ? size : unsent);
+    memcpy(buf, rbuf.rawContent() + rbufConsumePos, bytes);
+    rbufConsumePos += bytes;
+    debugs(83, 7, bytes << "<=" << size << " bytes to OpenSSL");
+    return bytes;
 }
 
 // This function makes the required checks to examine if the client hello
@@ -297,7 +314,7 @@
 // This is mostly possible in the cases where the web client uses openSSL
 // library similar with this one used by squid.
 static bool
-adjustSSL(SSL *ssl, Ssl::Bio::sslFeatures &features)
+adjustSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, SBuf &helloMessage)
 {
 #if SQUID_USE_OPENSSL_HELLO_OVERWRITE_HACK
     if (!ssl->s3) {
@@ -308,107 +325,78 @@
     // If the client supports compression but our context does not support
     // we can not adjust.
 #if !defined(OPENSSL_NO_COMP)
-    const bool requireCompression = (features.compressMethod && ssl->ctx->comp_methods == NULL);
+    const bool requireCompression = (details->compressionSupported && ssl->ctx->comp_methods == nullptr);
 #else
-    const bool requireCompression = features.compressMethod;
+    const bool requireCompression = details->compressionSupported;
 #endif
     if (requireCompression) {
         debugs(83, 5, "Client Hello Data supports compression, but we do not!");
         return false;
     }
 
-    // Check ciphers list
-    size_t token = 0;
-    size_t end = 0;
-    while (token != std::string::npos) {
-        end = features.clientRequestedCiphers.find(':',token);
-        std::string cipher;
-        cipher.assign(features.clientRequestedCiphers, token, end - token);
-        token = (end != std::string::npos ? end + 1 : std::string::npos);
-        bool found = false;
-        STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
-        for (int i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
-            SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
-            const char *cname = SSL_CIPHER_get_name(c);
-            if (cipher.compare(cname)) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            debugs(83, 5, "Client Hello Data supports cipher '"<< cipher <<"' but we do not support it!");
-            return false;
-        }
-    }
-
 #if !defined(SSL_TLSEXT_HB_ENABLED)
-    if (features.doHeartBeats) {
+    if (details->doHeartBeats) {
         debugs(83, 5, "Client Hello Data supports HeartBeats but we do not support!");
         return false;
     }
 #endif
 
-    for (std::list<int>::iterator it = features.extensions.begin(); it != features.extensions.end(); ++it) {
-        static int supportedExtensions[] = {
-#if defined(TLSEXT_TYPE_server_name)
-            TLSEXT_TYPE_server_name,
-#endif
-#if defined(TLSEXT_TYPE_opaque_prf_input)
-            TLSEXT_TYPE_opaque_prf_input,
-#endif
-#if defined(TLSEXT_TYPE_heartbeat)
-            TLSEXT_TYPE_heartbeat,
-#endif
+    if (details->unsupportedExtensions) {
+        debugs(83, 5, "Client Hello contains extensions that we do not support!");
+        return false;
+    }
+
+    SSL3_BUFFER *wb=&(ssl->s3->wbuf);
+    if (wb->len < (size_t)helloMessage.length()) {
+        debugs(83, 5, "Client Hello exceeds OpenSSL buffer: " << helloMessage.length() << " >= " << wb->len);
+        return false;
+    }
+
+    /* Check whether all on-the-wire ciphers are supported by OpenSSL. */
+
+    const auto &wireCiphers = details->ciphers;
+    Security::TlsDetails::Ciphers::size_type ciphersToFind = wireCiphers.size();
+
+    // RFC 5746: "TLS_EMPTY_RENEGOTIATION_INFO_SCSV is not a true cipher suite".
+    // It is commonly seen on the wire, including in from-OpenSSL traffic, but
+    // SSL_get_ciphers() does not return this _pseudo_ cipher suite in my tests.
+    // If OpenSSL supports scsvCipher, we count it (at most once) further below.
 #if defined(TLSEXT_TYPE_renegotiate)
-            TLSEXT_TYPE_renegotiate,
-#endif
-#if defined(TLSEXT_TYPE_ec_point_formats)
-            TLSEXT_TYPE_ec_point_formats,
-#endif
-#if defined(TLSEXT_TYPE_elliptic_curves)
-            TLSEXT_TYPE_elliptic_curves,
-#endif
-#if defined(TLSEXT_TYPE_session_ticket)
-            TLSEXT_TYPE_session_ticket,
-#endif
-#if defined(TLSEXT_TYPE_status_request)
-            TLSEXT_TYPE_status_request,
-#endif
-#if defined(TLSEXT_TYPE_use_srtp)
-            TLSEXT_TYPE_use_srtp,
-#endif
-#if 0 //Allow 13172 Firefox supported extension for testing purposes
-            13172,
+    // the 0x00FFFF mask converts 3-byte OpenSSL cipher to our 2-byte cipher
+    const uint16_t scsvCipher = SSL3_CK_SCSV & 0x00FFFF;
+#else
+    const uint16_t scsvCipher = 0;
 #endif
-            -1
-        };
-        bool found = false;
-        for (int i = 0; supportedExtensions[i] != -1; i++) {
-            if (*it == supportedExtensions[i]) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            debugs(83, 5, "Extension " << *it <<  " does not supported!");
-            return false;
-        }
+
+    STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
+    const int supportedCipherCount = sk_SSL_CIPHER_num(cipher_stack);
+    for (int idx = 0; idx < supportedCipherCount && ciphersToFind > 0; ++idx) {
+        const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, idx);
+        const auto id = SSL_CIPHER_get_id(cipher) & 0x00FFFF;
+        if (wireCiphers.find(id) != wireCiphers.end() && (!scsvCipher || id != scsvCipher))
+            --ciphersToFind;
     }
 
-    SSL3_BUFFER *wb=&(ssl->s3->wbuf);
-    if (wb->len < (size_t)features.helloMessage.length())
+    if (ciphersToFind > 0 && scsvCipher && wireCiphers.find(scsvCipher) != wireCiphers.end())
+        --ciphersToFind;
+
+    if (ciphersToFind > 0) {
+        // TODO: Add slowlyReportUnsupportedCiphers() to slowly find and report each of them
+        debugs(83, 5, "Client Hello Data has " << ciphersToFind << " ciphers that we do not support!");
         return false;
+    }
 
     debugs(83, 5, "OpenSSL SSL struct will be adjusted to mimic client hello data!");
 
     //Adjust ssl structure data.
     // We need to fix the random in SSL struct:
-    memcpy(ssl->s3->client_random, features.client_random, SSL3_RANDOM_SIZE);
-    memcpy(wb->buf, features.helloMessage.rawContent(), features.helloMessage.length());
-    wb->left = features.helloMessage.length();
+    if (details->clientRandom.length() == SSL3_RANDOM_SIZE)
+        memcpy(ssl->s3->client_random, details->clientRandom.c_str(), SSL3_RANDOM_SIZE);
+    memcpy(wb->buf, helloMessage.rawContent(), helloMessage.length());
+    wb->left = helloMessage.length();
 
-    size_t mainHelloSize = features.helloMessage.length() - 5;
-    const char *mainHello = features.helloMessage.rawContent() + 5;
+    size_t mainHelloSize = helloMessage.length() - 5;
+    const char *mainHello = helloMessage.rawContent() + 5;
     assert((size_t)ssl->init_buf->max > mainHelloSize);
     memcpy(ssl->init_buf->data, mainHello, mainHelloSize);
     debugs(83, 5, "Hello Data init and adjustd sizes :" << ssl->init_num << " = "<< mainHelloSize);
@@ -426,7 +414,7 @@
 {
 
     if (holdWrite_) {
-        debugs(83, 7,  "Hold write, for SSL connection on " << fd_ << "will not write bytes of size " << size);
+        debugs(83, 7, "postpone writing " << size << " bytes to SSL FD " << fd_);
         BIO_set_retry_write(table);
         return -1;
     }
@@ -441,18 +429,18 @@
             assert(helloMsg.isEmpty());
 
             auto ssl = fd_table[fd_].ssl.get();
-            if (clientFeatures.initialized_ && ssl) {
+            if (ssl) {
                 if (bumpMode_ == Ssl::bumpPeek) {
-                    if (adjustSSL(ssl, clientFeatures))
+                    if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage))
                         allowBump = true;
                     allowSplice = true;
-                    helloMsg.append(clientFeatures.helloMessage);
+                    helloMsg.append(clientHelloMessage);
                     debugs(83, 7,  "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for peek mode");
                 } else { /*Ssl::bumpStare*/
                     allowBump = true;
-                    if (adjustSSL(ssl, clientFeatures)) {
+                    if (adjustSSL(ssl, clientTlsDetails, clientHelloMessage)) {
                         allowSplice = true;
-                        helloMsg.append(clientFeatures.helloMessage);
+                        helloMsg.append(clientHelloMessage);
                         debugs(83, 7,  "SSL HELLO message for FD " << fd_ << ": Random number is adjusted for stare mode");
                     }
                 }
@@ -502,26 +490,10 @@
     }
 }
 
-void
-Ssl::ServerBio::extractHelloFeatures()
-{
-    if (!receivedHelloFeatures_.initialized_)
-        receivedHelloFeatures_.get(rbuf, false);
-}
-
 bool
 Ssl::ServerBio::resumingSession()
 {
-    extractHelloFeatures();
-
-    if (!clientFeatures.sessionId.isEmpty() && !receivedHelloFeatures_.sessionId.isEmpty())
-        return clientFeatures.sessionId == receivedHelloFeatures_.sessionId;
-
-    // is this a session resuming attempt using TLS tickets?
-    if (clientFeatures.hasTlsTicket && receivedHelloFeatures_.hasCcsOrNst)
-        return true;
-
-    return false;
+    return parser_.resumingSession;
 }
 
 /// initializes BIO table after allocation
@@ -643,556 +615,60 @@
     }
 }
 
-Ssl::Bio::sslFeatures::sslFeatures():
-    sslHelloVersion(-1),
-    sslVersion(-1),
-    compressMethod(-1),
-    helloMsgSize(0),
-    unknownCiphers(false),
-    doHeartBeats(true),
-    tlsTicketsExtension(false),
-    hasTlsTicket(false),
-    tlsStatusRequest(false),
-    hasCcsOrNst(false),
-    initialized_(false)
-{
-    memset(client_random, 0, SSL3_RANDOM_SIZE);
-}
-
-int Ssl::Bio::sslFeatures::toSquidSSLVersion() const
-{
-    if (sslVersion == SSL2_VERSION)
-        return 2;
-    else if (sslVersion == SSL3_VERSION)
-        return 3;
-    else if (sslVersion == TLS1_VERSION)
-        return 4;
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-    else if (sslVersion == TLS1_1_VERSION)
-        return 5;
-    else if (sslVersion == TLS1_2_VERSION)
-        return 6;
-#endif
-    else
-        return 1;
-}
-
-bool
-Ssl::Bio::sslFeatures::get(const SSL *ssl)
+void
+applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode)
 {
-    sslVersion = SSL_version(ssl);
-    debugs(83, 7, "SSL version: " << SSL_get_version(ssl) << " (" << sslVersion << ")");
-
+    // To increase the possibility for bumping after peek mode selection or
+    // splicing after stare mode selection it is good to set the
+    // SSL protocol version.
+    // The SSL_set_ssl_method is wrong here because it will restrict the
+    // permitted transport version to be identical to the version used in the
+    // ClientHello message.
+    // For example will prevent comunnicating with a tls1.0 server if the
+    // client sent and tlsv1.2 Hello message.
 #if defined(TLSEXT_NAMETYPE_host_name)
-    if (const char *server = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))
-        serverName = server;
-    debugs(83, 7, "SNI server name: " << serverName);
-#endif
-
-#if !defined(OPENSSL_NO_COMP)
-    if (ssl->session->compress_meth)
-        compressMethod = ssl->session->compress_meth;
-    else if (sslVersion >= 3) //if it is 3 or newer version then compression is disabled
-#endif
-        compressMethod = 0;
-    debugs(83, 7, "SSL compression: " << compressMethod);
-
-    STACK_OF(SSL_CIPHER) * ciphers = NULL;
-    if (ssl->server)
-        ciphers = ssl->session->ciphers;
-    else
-        ciphers = ssl->cipher_list;
-    if (ciphers) {
-        for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) {
-            SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
-            if (c != NULL) {
-                if (!clientRequestedCiphers.empty())
-                    clientRequestedCiphers.append(":");
-                clientRequestedCiphers.append(c->name);
-            }
-        }
-    }
-    debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
-
-    if (sslVersion >=3 && ssl->s3 && ssl->s3->client_random[0]) {
-        memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE);
-    }
-
-#if 0 /* XXX: OpenSSL 0.9.8k lacks at least some of these tlsext_* fields */
-    //The following extracted for logging purpuses:
-    // TLSEXT_TYPE_ec_point_formats
-    unsigned char *p;
-    int len;
-    if (ssl->server) {
-        p = ssl->session->tlsext_ecpointformatlist;
-        len = ssl->session->tlsext_ecpointformatlist_length;
-    } else {
-        p = ssl->tlsext_ecpointformatlist;
-        len = ssl->tlsext_ecpointformatlist_length;
-    }
-    if (p) {
-        ecPointFormatList = objToString(p, len);
-        debugs(83, 7, "tlsExtension ecPointFormatList of length " << len << " :" << ecPointFormatList);
-    }
-
-    // TLSEXT_TYPE_elliptic_curves
-    if (ssl->server) {
-        p = ssl->session->tlsext_ellipticcurvelist;
-        len = ssl->session->tlsext_ellipticcurvelist_length;
-    } else {
-        p = ssl->tlsext_ellipticcurvelist;
-        len = ssl->tlsext_ellipticcurvelist_length;
-    }
-    if (p) {
-        ellipticCurves = objToString(p, len);
-        debugs(83, 7, "tlsExtension ellipticCurveList of length " <<  len <<" :" << ellipticCurves);
-    }
-    // TLSEXT_TYPE_opaque_prf_input
-    p = NULL;
-    if (ssl->server) {
-        if (ssl->s3 &&  ssl->s3->client_opaque_prf_input) {
-            p = (unsigned char *)ssl->s3->client_opaque_prf_input;
-            len = ssl->s3->client_opaque_prf_input_len;
-        }
-    } else {
-        p = (unsigned char *)ssl->tlsext_opaque_prf_input;
-        len = ssl->tlsext_opaque_prf_input_len;
-    }
-    if (p) {
-        debugs(83, 7, "tlsExtension client-opaque-prf-input of length " << len);
-        opaquePrf = objToString(p, len);
+    if (!details->serverName.isEmpty()) {
+        SSL_set_tlsext_host_name(ssl, details->serverName.c_str());
     }
 #endif
-    initialized_ = true;
-    return true;
-}
-
-int
-Ssl::Bio::sslFeatures::parseMsgHead(const MemBuf &buf)
-{
-    const unsigned char *head = (const unsigned char *)buf.content();
-    const char *s = objToString(head, buf.contentSize());
-    debugs(83, 7, "SSL Header: " << s);
-    if (buf.contentSize() < 5)
-        return 0;
-
-    if (helloMsgSize > 0)
-        return helloMsgSize;
-
-    // Check for SSLPlaintext/TLSPlaintext record
-    // RFC6101 section 5.2.1
-    // RFC5246 section 6.2.1
-    if (head[0] == 0x16) {
-        debugs(83, 7, "SSL version 3 handshake message");
-        // The SSL version exist in the 2nd and 3rd bytes
-        sslHelloVersion = (head[1] << 8) | head[2];
-        debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
-        // The hello message size exist in 4th and 5th bytes
-        helloMsgSize = (head[3] << 8) + head[4];
-        debugs(83, 7, "SSL Header Size: " << helloMsgSize);
-        helloMsgSize +=5;
-    } else if ((head[0] & 0x80) && head[2] == 0x01 && head[3] == 0x03) {
-        debugs(83, 7, "SSL version 2 handshake message with v3 support");
-        sslHelloVersion = 0x0002;
-        debugs(83, 7, "SSL Version :" << std::hex << std::setw(8) << std::setfill('0') << sslVersion);
-        // The hello message size exist in 2nd byte
-        helloMsgSize = head[1];
-        helloMsgSize +=2;
-    } else {
-        debugs(83, 7, "Not an SSL acceptable handshake message (SSLv2 message?)");
-        return (helloMsgSize = -1);
-    }
-
-    // Set object as initialized. Even if we did not full parsing yet
-    // The basic features, like the SSL version is set
-    initialized_ = true;
-    return helloMsgSize;
-}
-
-bool
-Ssl::Bio::sslFeatures::checkForCcsOrNst(const unsigned char *msg, size_t size)
-{
-    while (size > 5) {
-        const int msgType = msg[0];
-        const int msgSslVersion = (msg[1] << 8) | msg[2];
-        debugs(83, 7, "SSL Message Version :" << std::hex << std::setw(8) << std::setfill('0') << msgSslVersion);
-        // Check for Change Cipher Spec message
-        // RFC5246 section 6.2.1
-        if (msgType == 0x14) {// Change Cipher Spec message found
-            debugs(83, 7, "SSL  Change Cipher Spec message found");
-            return true;
-        }
-        // Check for New Session Ticket message
-        // RFC5077 section 3.3
-        if (msgType == 0x04) {// New Session Ticket message found
-            debugs(83, 7, "TLS  New Session Ticket message found");
-            return true;
-        }
-        // The hello message size exist in 4th and 5th bytes
-        size_t msgLength = (msg[3] << 8) + msg[4];
-        debugs(83, 7, "SSL Message Size: " << msgLength);
-        msgLength += 5;
-
-        if (msgLength <= size) {
-            msg += msgLength;
-            size -= msgLength;
-        } else
-            size = 0;
-    }
-    return false;
-}
-
-bool
-Ssl::Bio::sslFeatures::get(const MemBuf &buf, bool record)
-{
-    int msgSize;
-    if ((msgSize = parseMsgHead(buf)) <= 0) {
-        debugs(83, 7, "Not a known SSL handshake message");
-        return false;
-    }
-
-    if (msgSize > buf.contentSize()) {
-        debugs(83, 2, "Partial SSL handshake message, can not parse!");
-        return false;
-    }
-
-    if (record) {
-        helloMessage.clear();
-        helloMessage.append(buf.content(), buf.contentSize());
-    }
-
-    const unsigned char *msg = (const unsigned char *)buf.content();
-    if (msg[0] & 0x80)
-        return parseV23Hello(msg, (size_t)msgSize);
-    else {
-        // Hello messages require 5 bytes header + 1 byte Msg type + 3 bytes for Msg size
-        if (buf.contentSize() < 9)
-            return false;
-
-        // Check for the Handshake/Message type
-        // The type 2 is a ServerHello, the type 1 is a ClientHello
-        // RFC5246 section 7.4
-        if (msg[5] == 0x2) { // ServerHello message
-            if (parseV3ServerHello(msg, (size_t)msgSize)) {
-                hasCcsOrNst = checkForCcsOrNst(msg + msgSize,  buf.contentSize() - msgSize);
-                return true;
-            }
-        } else if (msg[5] == 0x1) // ClientHello message,
-            return parseV3Hello(msg, (size_t)msgSize);
-    }
-
-    return false;
-}
 
-bool
-Ssl::Bio::sslFeatures::parseV3ServerHello(const unsigned char *messageContainer, size_t messageContainerSize)
-{
-    // Parse a ServerHello Handshake message
-    // RFC5246 section 7.4, 7.4.1.3
-    // The ServerHello starts at messageContainer + 5
-    const unsigned char *serverHello = messageContainer + 5;
-
-    // The Length field (bytes 1-3) plus 4 bytes of the serverHello message header (1 handshake type + 3 hello length)
-    const size_t helloSize = ((serverHello[1] << 16) | (serverHello[2] << 8) | serverHello[3]) + 4;
-    debugs(83, 7, "ServerHello message size: " << helloSize);
-    if (helloSize > messageContainerSize) {
-        debugs(83, 2, "ServerHello parse error");
-        return false;
-    }
-
-    // helloSize should be at least 38 bytes long:
-    // (SSL Version + Random + SessionId Length + Cipher Suite + Compression Method)
-    if (helloSize < 38) {
-        debugs(83, 2, "Too short ServerHello message");
-        return false;
-    }
-
-    debugs(83, 7, "Get fake features from v3 ServerHello message.");
-    // Get the correct version of the sub-hello message
-    sslVersion = (serverHello[4] << 8) | serverHello[5];
-    // At the position 38 (HelloHeader (6bytes) + SSL3_RANDOM_SIZE (32bytes))
-    const size_t sessIdLen = static_cast<size_t>(serverHello[38]);
-    debugs(83, 7, "Session ID Length: " <<  sessIdLen);
-
-    // The size should be enough to hold at least the following
-    // 4 (hello header)
-    // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
-    // + sessIdLength + 2 (cipher suite) + 1 (compression method)
-    // = 42 + sessIdLength
-    if (42 + sessIdLen > helloSize) {
-        debugs(83, 2, "ciphers length parse error");
-        return false;
-    }
-
-    // The sessionID stored at 39 position, after sessionID length field
-    sessionId.assign(reinterpret_cast<const char *>(serverHello + 39), sessIdLen);
-
-    // Check if there are extensions in hello message
-    // RFC5246 section 7.4.1.4
-    if (helloSize > 42 + sessIdLen + 2) {
-        // 42 + sessIdLen
-        const unsigned char *pToExtensions = serverHello + 42 + sessIdLen;
-        const size_t extensionsLen = (pToExtensions[0] << 8) | pToExtensions[1];
-        // Check if the hello size can hold extensions
-        if (42 + 2 + sessIdLen + extensionsLen > helloSize ) {
-            debugs(83, 2, "Extensions length parse error");
-            return false;
-        }
-
-        pToExtensions += 2;
-        const unsigned char *ext = pToExtensions;
-        while (ext + 4 <= pToExtensions + extensionsLen) {
-            const size_t extType = (ext[0] << 8) | ext[1];
-            ext += 2;
-            const size_t extLen = (ext[0] << 8) | ext[1];
-            ext += 2;
-            debugs(83, 7, "TLS Extension: " << std::hex << extType << " of size:" << extLen);
-            // SessionTicket TLS Extension, RFC5077 section 3.2
-            if (extType == 0x23) {
-                tlsTicketsExtension = true;
-            }
-            ext += extLen;
-        }
-    }
-    return true;
-}
-
-bool
-Ssl::Bio::sslFeatures::parseV3Hello(const unsigned char *messageContainer, size_t messageContainerSize)
-{
-    // Parse a ClientHello Handshake message
-    // RFC5246 section 7.4, 7.4.1.2
-    // The ClientHello starts at messageContainer + 5
-    const unsigned char * clientHello = messageContainer + 5;
-
-    debugs(83, 7, "Get fake features from v3 ClientHello message.");
-    // The Length field (bytes 1-3) plus 4 bytes of the clientHello message header (1 handshake type + 3 hello length)
-    const size_t helloSize = ((clientHello[1] << 16) | (clientHello[2] << 8) | clientHello[3]) + 4;
-    debugs(83, 7, "ClientHello message size: " << helloSize);
-    if (helloSize > messageContainerSize) {
-        debugs(83, 2, "ClientHello parse error");
-        return false;
-    }
-
-    // helloSize should be at least 38 bytes long:
-    // (SSL Version(2) + Random(32) + SessionId Length(1) + Cipher Suite Length(2) + Compression Method Length(1))
-    if (helloSize < 38) {
-        debugs(83, 2, "Too short ClientHello message");
-        return false;
-    }
-
-    //For SSLv3 or TLSv1.* protocols we can get some more informations
-    if (messageContainer[1] != 0x3 || clientHello[0] != 0x1 /*HELLO A message*/) {
-        debugs(83, 2, "Not an SSLv3/TLSv1.x client hello message, stop parsing here");
-        return true;
-    }
-
-    // Get the correct version of the sub-hello message
-    sslVersion = (clientHello[4] << 8) | clientHello[5];
-    //Get Client Random number. It starts on the position 6 of clientHello message
-    memcpy(client_random, clientHello + 6, SSL3_RANDOM_SIZE);
-    debugs(83, 7, "Client random: " <<  objToString(client_random, SSL3_RANDOM_SIZE));
-
-    // At the position 38 (6+SSL3_RANDOM_SIZE)
-    const size_t sessIDLen = static_cast<size_t>(clientHello[38]);
-    debugs(83, 7, "Session ID Length: " <<  sessIDLen);
-
-    // The helloSize should be enough to hold at least the following
-    // 1 handshake type + 3 hello Length
-    // + 2 (SSL Version) + 32 (random) + 1 (sessionId length)
-    // + sessIdLength + 2 (cipher suite length) + 1 (compression method length)
-    // = 42 + sessIdLength
-    if (42 + sessIDLen > helloSize) {
-        debugs(83, 2, "Session ID length parse error");
-        return false;
-    }
-
-    // The sessionID stored art 39 position, after sessionID length field
-    sessionId.assign(reinterpret_cast<const char *>(clientHello + 39), sessIDLen);
-
-    //Ciphers list. It is stored after the Session ID.
-    // It is a variable-length vector(RFC5246 section 4.3)
-    const unsigned char *ciphers = clientHello + 39 + sessIDLen;
-    const size_t ciphersLen = (ciphers[0] << 8) | ciphers[1];
-    if (42 + sessIDLen + ciphersLen > helloSize) {
-        debugs(83, 2, "ciphers length parse error");
-        return false;
-    }
-
-    ciphers += 2;
-    if (ciphersLen) {
+    if (!details->ciphers.empty()) {
+        SBuf strCiphers;
+        for (auto cipherId: details->ciphers) {
+            unsigned char cbytes[3];
+            cbytes[0] = (cipherId >> 8) & 0xFF;
+            cbytes[1] = cipherId & 0xFF;
+            cbytes[2] = 0;
 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-        const SSL_METHOD *method = TLS_method();
+            const SSL_METHOD *method = TLS_method();
 #else
-        const SSL_METHOD *method = SSLv23_method();
+            const SSL_METHOD *method = SSLv23_method();
 #endif
-        for (size_t i = 0; i < ciphersLen; i += 2) {
-            // each cipher in v3/tls  HELLO message is of size 2
-            const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i));
+            const SSL_CIPHER *c = method->get_cipher_by_char(cbytes);
             if (c != NULL) {
-                if (!clientRequestedCiphers.empty())
-                    clientRequestedCiphers.append(":");
-                clientRequestedCiphers.append(c->name);
-            } else
-                unknownCiphers = true;
-        }
-    }
-    debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
-
-    // Compression field: 1 bytes the number of compression methods and
-    // 1 byte for each compression method
-    const unsigned char *compression = ciphers + ciphersLen;
-    if (compression[0] > 1)
-        compressMethod = 1;
-    else
-        compressMethod = 0;
-    debugs(83, 7, "SSL compression methods number: " << static_cast<int>(compression[0]));
-
-    // Parse Extensions, RFC5246 section 7.4.1.4
-    const unsigned char *pToExtensions = compression + 1 + static_cast<int>(compression[0]);
-    if ((size_t)((pToExtensions - clientHello) + 2) < helloSize) {
-        const size_t extensionsLen = (pToExtensions[0] << 8) | pToExtensions[1];
-        if ((pToExtensions - clientHello) + 2 + extensionsLen > helloSize) {
-            debugs(83, 2, "Extensions length parse error");
-            return false;
-        }
-
-        pToExtensions += 2;
-        const unsigned char *ext = pToExtensions;
-        while (ext + 4 <= pToExtensions + extensionsLen) {
-            const size_t extType = (ext[0] << 8) | ext[1];
-            ext += 2;
-            const size_t extLen = (ext[0] << 8) | ext[1];
-            ext += 2;
-            debugs(83, 7, "TLS Extension: " << std::hex << extType << " of size:" << extLen);
-
-            if (ext + extLen > pToExtensions + extensionsLen) {
-                debugs(83, 2, "Extension " << std::hex << extType << " length parser error");
-                return false;
+                if (!strCiphers.isEmpty())
+                    strCiphers.append(":");
+                strCiphers.append(c->name);
             }
-
-            //The SNI extension has the type 0 (extType == 0)
-            // RFC6066 sections 3, 10.2
-            // The two first bytes indicates the length of the SNI data (should be extLen-2)
-            // The next byte is the hostname type, it should be '0' for normal hostname (ext[2] == 0)
-            // The 3rd and 4th bytes are the length of the hostname
-            if (extType == 0 && ext[2] == 0) {
-                const size_t hostLen = (ext[3] << 8) | ext[4];
-                if (hostLen < extLen)
-                    serverName.assign(reinterpret_cast<const char *>(ext+5), hostLen);
-                debugs(83, 7, "Found server name: " << serverName);
-            } else if (extType == 15 && ext[0] != 0) {
-                // The heartBeats are the type 15, RFC6520
-                doHeartBeats = true;
-            } else if (extType == 0x23) {
-                //SessionTicket TLS Extension RFC5077
-                tlsTicketsExtension = true;
-                if (extLen != 0)
-                    hasTlsTicket = true;
-            } else if (extType == 0x05) {
-                // RFC6066 sections 8, 10.2
-                tlsStatusRequest = true;
-            } else if (extType == 0x3374) {
-                // detected TLS next protocol negotiate extension
-            } else if (extType == 0x10) {
-                // Application-Layer Protocol Negotiation Extension, RFC7301
-                const size_t listLen = (ext[0] << 8) | ext[1];
-                if (listLen < extLen)
-                    tlsAppLayerProtoNeg.assign(reinterpret_cast<const char *>(ext+5), listLen);
-            } else
-                extensions.push_back(extType);
-
-            ext += extLen;
         }
+        if (!strCiphers.isEmpty())
+            SSL_set_cipher_list(ssl, strCiphers.c_str());
     }
-    return true;
-}
 
-bool
-Ssl::Bio::sslFeatures::parseV23Hello(const unsigned char *hello, size_t size)
-{
-    debugs(83, 7, "Get fake features from v23 ClientHello message.");
-    if (size < 7)
-        return false;
-
-    // Get the SSL/TLS version supported by client
-    sslVersion = (hello[3] << 8) | hello[4];
-
-    //Ciphers list. It is stored after the Session ID.
-    const unsigned int ciphersLen = (hello[5] << 8) | hello[6];
-    const unsigned char *ciphers = hello + 11;
-
-    if (size < ciphersLen + 11)
-        return false;
-
-    if (ciphersLen) {
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
-        const SSL_METHOD *method = TLS_method();
-#else
-        const SSL_METHOD *method = SSLv23_method();
-#endif
-        for (unsigned int i = 0; i < ciphersLen; i += 3) {
-            // The v2 hello messages cipher has 3 bytes.
-            // The v2 cipher has the first byte not null
-            // Because we are going to sent only v3 message we
-            // are ignoring these ciphers
-            if (ciphers[i] != 0)
-                continue;
-            const SSL_CIPHER *c = method->get_cipher_by_char((ciphers + i + 1));
-            if (c != NULL) {
-                if (!clientRequestedCiphers.empty())
-                    clientRequestedCiphers.append(":");
-                clientRequestedCiphers.append(c->name);
-            }
-        }
-    }
-    debugs(83, 7, "Ciphers requested by client: " << clientRequestedCiphers);
-
-    const unsigned int sessionIdLength = (hello[7] << 8) | hello[8];
-    debugs(83, 7, "SessionID length: " << sessionIdLength);
-    // SessionID starts at: hello+11+ciphersLen
-    if (sessionIdLength)
-        sessionId.assign((const char *)(hello + 11 + ciphersLen), sessionIdLength);
-
-    const unsigned int challengeLength = (hello[5] << 9) | hello[10];
-    debugs(83, 7, "Challenge Length: " << challengeLength);
-    //challenge starts at: hello+11+ciphersLen+sessionIdLength
-
-    compressMethod = 0;
-    return true;
-}
-
-void
-Ssl::Bio::sslFeatures::applyToSSL(SSL *ssl, Ssl::BumpMode bumpMode) const
-{
-    // To increase the possibility for bumping after peek mode selection or
-    // splicing after stare mode selection it is good to set the
-    // SSL protocol version.
-    // The SSL_set_ssl_method is not the correct method because it will strict
-    // SSL version which can be used to the SSL version used for client hello message.
-    // For example will prevent comunnicating with a tls1.0 server if the
-    // client sent and tlsv1.2 Hello message.
-#if defined(TLSEXT_NAMETYPE_host_name)
-    if (!serverName.isEmpty()) {
-        SSL_set_tlsext_host_name(ssl, serverName.c_str());
-    }
-#endif
-    if (!clientRequestedCiphers.empty())
-        SSL_set_cipher_list(ssl, clientRequestedCiphers.c_str());
 #if defined(SSL_OP_NO_COMPRESSION) /* XXX: OpenSSL 0.9.8k lacks SSL_OP_NO_COMPRESSION */
-    if (compressMethod == 0)
+    if (!details->compressionSupported)
         SSL_set_options(ssl, SSL_OP_NO_COMPRESSION);
 #endif
 
 #if defined(TLSEXT_STATUSTYPE_ocsp)
-    if (tlsStatusRequest)
+    if (details->tlsStatusRequest)
         SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
 #endif
 
 #if defined(TLSEXT_TYPE_application_layer_protocol_negotiation)
-    if (!tlsAppLayerProtoNeg.isEmpty()) {
+    if (!details->tlsAppLayerProtoNeg.isEmpty()) {
         if (bumpMode == Ssl::bumpPeek)
-            SSL_set_alpn_protos(ssl, (const unsigned char*)tlsAppLayerProtoNeg.rawContent(), tlsAppLayerProtoNeg.length());
+            SSL_set_alpn_protos(ssl, (const unsigned char*)details->tlsAppLayerProtoNeg.rawContent(), details->tlsAppLayerProtoNeg.length());
         else {
             static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
             SSL_set_alpn_protos(ssl, supported_protos, sizeof(supported_protos));
@@ -1201,20 +677,5 @@
 #endif
 }
 
-std::ostream &
-Ssl::Bio::sslFeatures::print(std::ostream &os) const
-{
-    static std::string buf;
-    // TODO: Also print missing features like the HeartBeats and AppLayerProtoNeg
-    return os << "v" << sslVersion <<
-           " SNI:" << (serverName.isEmpty() ? SBuf("-") : serverName) <<
-           " comp:" << compressMethod <<
-           " Ciphers:" << clientRequestedCiphers <<
-           " Random:" << objToString(client_random, SSL3_RANDOM_SIZE) <<
-           " ecPointFormats:" << ecPointFormatList <<
-           " ec:" << ellipticCurves <<
-           " opaquePrf:" << opaquePrf;
-}
-
-#endif /* USE_SSL */
+#endif // USE_OPENSSL
 
diff -u -r -N squid-4.0.10/src/ssl/bio.h squid-4.0.11/src/ssl/bio.h
--- squid-4.0.10/src/ssl/bio.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/bio.h	2016-06-10 08:32:57.000000000 +1200
@@ -10,7 +10,7 @@
 #define SQUID_SSL_BIO_H
 
 #include "fd.h"
-#include "sbuf/SBuf.h"
+#include "security/Handshake.h"
 
 #include <iosfwd>
 #include <list>
@@ -18,6 +18,7 @@
 #include <openssl/bio.h>
 #endif
 #include <string>
+#include <type_traits>
 
 namespace Ssl
 {
@@ -31,61 +32,6 @@
         BIO_TO_SERVER
     };
 
-    /// Class to store SSL connection features
-    class sslFeatures
-    {
-    public:
-        sslFeatures();
-        bool get(const SSL *ssl); ///< Retrieves the features from SSL object
-        /// Retrieves features from raw SSL Hello message.
-        /// \param record  whether to store Message to the helloMessage member
-        bool get(const MemBuf &, bool record = true);
-        /// Parses a v3 ClientHello message
-        bool parseV3Hello(const unsigned char *hello, size_t helloSize);
-        /// Parses a v23 ClientHello message
-        bool parseV23Hello(const unsigned char *hello, size_t helloSize);
-        /// Parses a v3 ServerHello message.
-        bool parseV3ServerHello(const unsigned char *hello, size_t helloSize);
-        /// Prints to os stream a human readable form of sslFeatures object
-        std::ostream & print(std::ostream &os) const;
-        /// Converts to the internal squid SSL version form the sslVersion
-        int toSquidSSLVersion() const;
-        /// Configure the SSL object with the SSL features of the sslFeatures object
-        void applyToSSL(SSL *ssl, Ssl::BumpMode bumpMode) const;
-        /// Parses an SSL Message header. It returns the ssl Message size.
-        /// \retval >0 if the hello size is retrieved
-        /// \retval 0 if the contents of the buffer are not enough
-        /// \retval <0 if the contents of buf are not SSLv3 or TLS hello message
-        int parseMsgHead(const MemBuf &);
-        /// Parses msg buffer and return true if one of the Change Cipher Spec
-        /// or New Session Ticket messages found
-        bool checkForCcsOrNst(const unsigned char *msg, size_t size);
-    public:
-        int sslHelloVersion; ///< The SSL hello message version
-        int sslVersion; ///< The requested/used SSL version
-        int compressMethod; ///< The requested/used compressed  method
-        int helloMsgSize; ///< the hello message size
-        mutable SBuf serverName; ///< The SNI hostname, if any
-        std::string clientRequestedCiphers; ///< The client requested ciphers
-        bool unknownCiphers; ///< True if one or more ciphers are unknown
-        std::string ecPointFormatList;///< tlsExtension ecPointFormatList
-        std::string ellipticCurves; ///< tlsExtension ellipticCurveList
-        std::string opaquePrf; ///< tlsExtension opaquePrf
-        bool doHeartBeats;
-        bool tlsTicketsExtension; ///< whether TLS tickets extension is enabled
-        bool hasTlsTicket; ///< whether a TLS ticket is included
-        bool tlsStatusRequest; ///< whether the TLS status request extension is set
-        SBuf tlsAppLayerProtoNeg; ///< The value of the TLS application layer protocol extension if it is enabled
-        /// whether Change Cipher Spec message included in ServerHello
-        /// handshake message
-        bool hasCcsOrNst;
-        /// The client random number
-        unsigned char client_random[SSL3_RANDOM_SIZE];
-        SBuf sessionId;
-        std::list<int> extensions;
-        SBuf helloMessage;
-        bool initialized_;
-    };
     explicit Bio(const int anFd);
     virtual ~Bio();
 
@@ -111,21 +57,10 @@
     /// Tells ssl connection to use BIO and monitor state via stateChanged()
     static void Link(SSL *ssl, BIO *bio);
 
-    /// Prepare the rbuf buffer to accept hello data
-    void prepReadBuf();
-
-    /// Reads data from socket and record them to a buffer
-    int readAndBuffer(char *buf, int size, BIO *table, const char *description);
-
-    /// Return the TLS features requested by TLS client
-    const Bio::sslFeatures &receivedHelloFeatures() const {return receivedHelloFeatures_;}
-
-    const MemBuf &rBufData() {return rbuf;}
+    const SBuf &rBufData() {return rbuf;} ///< The buffered input data
 protected:
     const int fd_; ///< the SSL socket we are reading and writing
-    MemBuf rbuf;  ///< Used to buffer input data.
-    /// The features retrieved from client or Server TLS hello message
-    Bio::sslFeatures receivedHelloFeatures_;
+    SBuf rbuf;  ///< Used to buffer input data.
 };
 
 /// BIO node to handle socket IO for squid client side
@@ -134,9 +69,7 @@
 class ClientBio: public Bio
 {
 public:
-    /// The ssl hello message read states
-    typedef enum {atHelloNone = 0, atHelloStarted, atHelloReceived} HelloReadState;
-    explicit ClientBio(const int anFd): Bio(anFd), holdRead_(false), holdWrite_(false), helloState(atHelloNone), helloSize(0), wrongProtocol(false) {}
+    explicit ClientBio(const int anFd): Bio(anFd), holdRead_(false), holdWrite_(false), helloSize(0) {}
 
     /// The ClientBio version of the Ssl::Bio::stateChanged method
     /// When the client hello message retrieved, fill the
@@ -148,20 +81,19 @@
     /// If the holdRead flag is true then it does not write any data
     /// to socket and sets the "read retry" flag of the BIO to true
     virtual int read(char *buf, int size, BIO *table);
-    /// Return true if the client hello message received and analized
-    bool gotHello() { return (helloState == atHelloReceived); }
     /// Prevents or allow writting on socket.
     void hold(bool h) {holdRead_ = holdWrite_ = h;}
-    /// True if client does not looks like an SSL client
-    bool noSslClient() {return wrongProtocol;}
+
+    /// Sets the buffered input data (Bio::rbuf).
+    /// Used to pass payload data (normally client HELLO data) retrieved
+    /// by the caller.
+    void setReadBufData(SBuf &data) {rbuf = data;}
 private:
     /// True if the SSL state corresponds to a hello message
     bool isClientHello(int state);
     bool holdRead_; ///< The read hold state of the bio.
     bool holdWrite_;  ///< The write hold state of the bio.
-    HelloReadState helloState; ///< The SSL hello read state
     int helloSize; ///< The SSL hello message sent by client size
-    bool wrongProtocol; ///< true if client SSL hello parsing failed
 };
 
 /// BIO node to handle socket IO for squid server side
@@ -182,7 +114,8 @@
 class ServerBio: public Bio
 {
 public:
-    explicit ServerBio(const int anFd): Bio(anFd), helloMsgSize(0), helloBuild(false), allowSplice(false), allowBump(false), holdWrite_(false), record_(false), bumpMode_(bumpNone) {}
+    explicit ServerBio(const int anFd);
+
     /// The ServerBio version of the Ssl::Bio::stateChanged method
     virtual void stateChanged(const SSL *ssl, int where, int ret);
     /// The ServerBio version of the Ssl::Bio::write method
@@ -197,13 +130,10 @@
     /// Flushes any buffered data
     virtual void flush(BIO *table);
     /// Sets the random number to use in client SSL HELLO message
-    void setClientFeatures(const sslFeatures &features);
-
-    /// Parses server Hello message if it is recorded and extracts
-    /// server-supported features.
-    void extractHelloFeatures();
+    void setClientFeatures(Security::TlsDetails::Pointer const &details, SBuf const &hello);
 
     bool resumingSession();
+
     /// The write hold state
     bool holdWrite() const {return holdWrite_;}
     /// Enables or disables the write hold state
@@ -217,8 +147,20 @@
     /// The bumping mode
     void mode(Ssl::BumpMode m) {bumpMode_ = m;}
     Ssl::BumpMode bumpMode() {return bumpMode_;} ///< return the bumping mode
+
+    /// \return the TLS Details advertised by TLS server.
+    const Security::TlsDetails::Pointer &receivedHelloDetails() const {return parser_.details;}
+
 private:
-    sslFeatures clientFeatures; ///< SSL client features extracted from ClientHello message or SSL object
+    int readAndGive(char *buf, const int size, BIO *table);
+    int readAndParse(char *buf, const int size, BIO *table);
+    int readAndBuffer(BIO *table);
+    int giveBuffered(char *buf, const int size);
+
+    /// SSL client features extracted from ClientHello message or SSL object
+    Security::TlsDetails::Pointer clientTlsDetails;
+    /// TLS client hello message, used to adapt our tls Hello message to the server
+    SBuf clientHelloMessage;
     SBuf helloMsg; ///< Used to buffer output data.
     mb_size_t  helloMsgSize;
     bool helloBuild; ///< True if the client hello message sent to the server
@@ -226,16 +168,18 @@
     bool allowBump;  ///< True if the SSL stream can be bumped
     bool holdWrite_;  ///< The write hold state of the bio.
     bool record_; ///< If true the input data recorded to rbuf for internal use
+    bool parsedHandshake; ///< whether we are done parsing TLS Hello
     Ssl::BumpMode bumpMode_;
-};
 
-inline
-std::ostream &operator <<(std::ostream &os, Ssl::Bio::sslFeatures const &f)
-{
-    return f.print(os);
-}
+    /// The size of data stored in rbuf which passed to the openSSL
+    size_t rbufConsumePos;
+    Security::HandshakeParser parser_; ///< The TLS/SSL messages parser.
+};
 
 } // namespace Ssl
 
+void
+applyTlsDetailsToSSL(SSL *ssl, Security::TlsDetails::Pointer const &details, Ssl::BumpMode bumpMode);
+
 #endif /* SQUID_SSL_BIO_H */
 
diff -u -r -N squid-4.0.10/src/ssl/PeekingPeerConnector.cc squid-4.0.11/src/ssl/PeekingPeerConnector.cc
--- squid-4.0.10/src/ssl/PeekingPeerConnector.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/PeekingPeerConnector.cc	2016-06-10 08:32:57.000000000 +1200
@@ -146,19 +146,13 @@
         // or terminate client and server connections
         assert(clientConn != NULL);
         SBuf *hostName = NULL;
-        Ssl::ClientBio *cltBio = NULL;
 
         //Enable Status_request tls extension, required to bump some clients
         SSL_set_tlsext_status_type(ssl, TLSEXT_STATUSTYPE_ocsp);
 
-        // In server-first bumping mode, clientSsl is NULL.
-        if (auto clientSsl = fd_table[clientConn->fd].ssl.get()) {
-            BIO *b = SSL_get_rbio(clientSsl);
-            cltBio = static_cast<Ssl::ClientBio *>(b->ptr);
-            const Ssl::Bio::sslFeatures &features = cltBio->receivedHelloFeatures();
-            if (!features.serverName.isEmpty())
-                hostName = new SBuf(features.serverName);
-        }
+        const Security::TlsDetails::Pointer details = csd->tlsParser.details;
+        if (details && !details->serverName.isEmpty())
+            hostName = new SBuf(details->serverName);
 
         if (!hostName) {
             // While we are peeking at the certificate, we may not know the server
@@ -174,16 +168,19 @@
 
         Must(!csd->serverBump() || csd->serverBump()->step <= Ssl::bumpStep2);
         if (csd->sslBumpMode == Ssl::bumpPeek || csd->sslBumpMode == Ssl::bumpStare) {
-            assert(cltBio);
-            const Ssl::Bio::sslFeatures &features = cltBio->receivedHelloFeatures();
-            if (features.sslVersion != -1) {
-                features.applyToSSL(ssl, csd->sslBumpMode);
+            auto clientSsl = fd_table[clientConn->fd].ssl.get();
+            Must(clientSsl);
+            BIO *bc = SSL_get_rbio(clientSsl);
+            Ssl::ClientBio *cltBio = static_cast<Ssl::ClientBio *>(bc->ptr);
+            Must(cltBio);
+            if (details && details->tlsVersion.protocol != AnyP::PROTO_NONE) {
+                applyTlsDetailsToSSL(ssl, details, csd->sslBumpMode);
                 // Should we allow it for all protocols?
-                if (features.sslVersion >= 3) {
+                if (details->tlsVersion.protocol == AnyP::PROTO_TLS || details->tlsVersion == AnyP::ProtocolVersion(AnyP::PROTO_SSL, 3, 0)) {
                     BIO *b = SSL_get_rbio(ssl);
                     Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
                     // Inherite client features, like SSL version, SNI and other
-                    srvBio->setClientFeatures(features);
+                    srvBio->setClientFeatures(details, cltBio->rBufData());
                     srvBio->recordInput(true);
                     srvBio->mode(csd->sslBumpMode);
                 }
@@ -254,14 +251,9 @@
         }
     }
 
-    // retrieve TLS server information if any
-    serverConnection()->tlsNegotiations()->fillWith(ssl);
     if (!error) {
         serverCertificateVerified();
         if (splice) {
-            //retrieved received TLS client informations
-            auto clientSsl = fd_table[clientConn->fd].ssl.get();
-            clientConn->tlsNegotiations()->fillWith(clientSsl);
             switchToTunnel(request.getRaw(), clientConn, serverConn);
             tunnelInsteadOfNegotiating();
         }
@@ -277,7 +269,7 @@
     Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
 
     if ((srvBio->bumpMode() == Ssl::bumpPeek || srvBio->bumpMode() == Ssl::bumpStare) && srvBio->holdWrite()) {
-        debugs(81, DBG_IMPORTANT, "hold write on SSL connection on FD " << fd);
+        debugs(81, 3, "hold write on SSL connection on FD " << fd);
         checkForPeekAndSplice();
         return;
     }
diff -u -r -N squid-4.0.10/src/ssl/PeerConnector.cc squid-4.0.11/src/ssl/PeerConnector.cc
--- squid-4.0.10/src/ssl/PeerConnector.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/PeerConnector.cc	2016-06-10 08:32:57.000000000 +1200
@@ -14,7 +14,9 @@
 #include "errorpage.h"
 #include "fde.h"
 #include "HttpRequest.h"
+#include "security/NegotiationHistory.h"
 #include "SquidConfig.h"
+#include "ssl/bio.h"
 #include "ssl/cert_validate_message.h"
 #include "ssl/Config.h"
 #include "ssl/helper.h"
@@ -134,6 +136,21 @@
 }
 
 void
+Ssl::PeerConnector::recordNegotiationDetails()
+{
+    const int fd = serverConnection()->fd;
+    Security::SessionPtr ssl = fd_table[fd].ssl.get();
+
+    // retrieve TLS server negotiated information if any
+    serverConnection()->tlsNegotiations()->retrieveNegotiatedInfo(ssl);
+    // retrieve TLS parsed extra info
+    BIO *b = SSL_get_rbio(ssl);
+    Ssl::ServerBio *bio = static_cast<Ssl::ServerBio *>(b->ptr);
+    if (const Security::TlsDetails::Pointer &details = bio->receivedHelloDetails())
+        serverConnection()->tlsNegotiations()->retrieveParsedInfo(details);
+}
+
+void
 Ssl::PeerConnector::negotiateSsl()
 {
     if (!Comm::IsConnOpen(serverConnection()) || fd_table[serverConnection()->fd].closing())
@@ -147,6 +164,8 @@
         return; // we might be gone by now
     }
 
+    recordNegotiationDetails();
+
     if (!sslFinalized())
         return;
 
@@ -332,6 +351,9 @@
         // no special error handling for all other errors
         break;
     }
+
+    // Log connection details, if any
+    recordNegotiationDetails();
     noteSslNegotiationError(ret, ssl_error, ssl_lib_error);
 }
 
diff -u -r -N squid-4.0.10/src/ssl/PeerConnector.h squid-4.0.11/src/ssl/PeerConnector.h
--- squid-4.0.10/src/ssl/PeerConnector.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/PeerConnector.h	2016-06-10 08:32:57.000000000 +1200
@@ -155,6 +155,10 @@
     /// If called the certificates validator will not used
     void bypassCertValidator() {useCertValidator_ = false;}
 
+    /// Called after negotiation finishes to record connection details for
+    /// logging
+    void recordNegotiationDetails();
+
     HttpRequestPointer request; ///< peer connection trigger or cause
     Comm::ConnectionPointer serverConn; ///< TCP connection to the peer
     AccessLogEntryPointer al; ///< info for the future access.log entry
diff -u -r -N squid-4.0.10/src/ssl/support.cc squid-4.0.11/src/ssl/support.cc
--- squid-4.0.10/src/ssl/support.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/support.cc	2016-06-10 08:32:57.000000000 +1200
@@ -135,7 +135,7 @@
     }
 
     if (newkey) {
-        if (do_debug(83, 5))
+        if (Debug::Enabled(83, 5))
             PEM_write_RSAPrivateKey(debug_log, rsa, NULL, NULL, 0, NULL, NULL);
 
         debugs(83, DBG_IMPORTANT, "Generated ephemeral RSA key of length " << keylen);
@@ -556,19 +556,18 @@
     return true;
 }
 
-Security::ContextPtr
-sslCreateServerContext(AnyP::PortCfg &port)
+bool
+Ssl::InitServerContext(Security::ContextPtr &sslContext, AnyP::PortCfg &port)
 {
-    Security::ContextPtr sslContext(port.secure.createBlankContext());
     if (!sslContext)
-        return nullptr;
+        return false;
 
     if (!SSL_CTX_use_certificate(sslContext, port.signingCert.get())) {
         const int ssl_error = ERR_get_error();
         const auto &keys = port.secure.certs.front();
         debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS certificate '" << keys.certFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
-        return NULL;
+        return false;
     }
 
     if (!SSL_CTX_use_PrivateKey(sslContext, port.signPkey.get())) {
@@ -576,7 +575,7 @@
         const auto &keys = port.secure.certs.front();
         debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire TLS private key '" << keys.privateKeyFile << "': " << ERR_error_string(ssl_error, NULL));
         SSL_CTX_free(sslContext);
-        return NULL;
+        return false;
     }
 
     Ssl::addChainToSslContext(sslContext, port.certsToChain.get());
@@ -588,7 +587,7 @@
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL certificate '" << certfile << "': " << ERR_error_string(ssl_error, NULL));
             SSL_CTX_free(sslContext);
-            return NULL;
+            return false;
         }
 
         debugs(83, DBG_IMPORTANT, "Using private key in " << keyfile);
@@ -598,7 +597,7 @@
             ssl_error = ERR_get_error();
             debugs(83, DBG_CRITICAL, "ERROR: Failed to acquire SSL private key '" << keyfile << "': " << ERR_error_string(ssl_error, NULL));
             SSL_CTX_free(sslContext);
-            return NULL;
+            return false;
         }
 
         debugs(83, 5, "Comparing private and public SSL keys.");
@@ -608,25 +607,24 @@
             debugs(83, DBG_CRITICAL, "ERROR: SSL private key '" << certfile << "' does not match public key '" <<
                    keyfile << "': " << ERR_error_string(ssl_error, NULL));
             SSL_CTX_free(sslContext);
-            return NULL;
+            return false;
         }
     */
 
     if (!configureSslContext(sslContext, port)) {
         debugs(83, DBG_CRITICAL, "ERROR: Configuring static SSL context");
         SSL_CTX_free(sslContext);
-        return NULL;
+        return false;
     }
 
-    return sslContext;
+    return true;
 }
 
-Security::ContextPtr
-sslCreateClientContext(Security::PeerOptions &peer, long options, long fl)
+bool
+Ssl::InitClientContext(Security::ContextPtr &sslContext, Security::PeerOptions &peer, long options, long fl)
 {
-    Security::ContextPtr sslContext(peer.createBlankContext());
     if (!sslContext)
-        return nullptr;
+        return false;
 
     SSL_CTX_set_options(sslContext, options);
 
@@ -689,7 +687,7 @@
         SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, ssl_verify_cb);
     }
 
-    return sslContext;
+    return true;
 }
 
 /// \ingroup ServerProtocolSSLInternal
diff -u -r -N squid-4.0.10/src/ssl/support.h squid-4.0.11/src/ssl/support.h
--- squid-4.0.10/src/ssl/support.h	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/ssl/support.h	2016-06-10 08:32:57.000000000 +1200
@@ -111,13 +111,13 @@
 extern Ipc::MemMap *SessionCache;
 extern const char *SessionCacheName;
 
-} //namespace Ssl
+/// initialize a TLS server context with OpenSSL specific settings
+bool InitServerContext(Security::ContextPtr &, AnyP::PortCfg &);
 
-/// \ingroup ServerProtocolSSLAPI
-Security::ContextPtr sslCreateServerContext(AnyP::PortCfg &port);
+/// initialize a TLS client context with OpenSSL specific settings
+bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long options, long flags);
 
-/// \ingroup ServerProtocolSSLAPI
-Security::ContextPtr sslCreateClientContext(Security::PeerOptions &, long options, long flags);
+} //namespace Ssl
 
 /// \ingroup ServerProtocolSSLAPI
 int ssl_read_method(int, char *, int);
diff -u -r -N squid-4.0.10/src/store/id_rewriters/file/storeid_file_rewrite.8 squid-4.0.11/src/store/id_rewriters/file/storeid_file_rewrite.8
--- squid-4.0.10/src/store/id_rewriters/file/storeid_file_rewrite.8	2016-05-07 00:31:09.000000000 +1200
+++ squid-4.0.11/src/store/id_rewriters/file/storeid_file_rewrite.8	2016-06-10 09:29:00.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "STOREID_FILE_REWRITE 8"
-.TH STOREID_FILE_REWRITE 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH STOREID_FILE_REWRITE 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/src/tests/stub_debug.cc squid-4.0.11/src/tests/stub_debug.cc
--- squid-4.0.10/src/tests/stub_debug.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tests/stub_debug.cc	2016-06-10 08:32:57.000000000 +1200
@@ -17,14 +17,11 @@
 #include "Debug.h"
 
 FILE *debug_log = NULL;
-int Debug::TheDepth = 0;
 
 char *Debug::debugOptions;
 char *Debug::cache_log= NULL;
 int Debug::rotateNumber = 0;
 int Debug::Levels[MAX_DEBUG_SECTIONS];
-int Debug::level;
-int Debug::sectionLevel;
 int Debug::override_X = 0;
 int Debug::log_stderr = 1;
 bool Debug::log_syslog = false;
@@ -80,49 +77,48 @@
 static void
 _db_print_stderr(const char *format, va_list args)
 {
-    if (1 < Debug::level)
+    if (1 < Debug::Level())
         return;
 
     vfprintf(stderr, format, args);
 }
 
-Debug::OutStream *Debug::CurrentDebug(NULL);
+void
+Debug::parseOptions(char const *)
+{}
 
-std::ostream &
-Debug::getDebugOut()
+const char*
+SkipBuildPrefix(const char* path)
 {
-    if (!CurrentDebug) {
-        CurrentDebug = new Debug::OutStream;
-        CurrentDebug->setf(std::ios::fixed);
-        CurrentDebug->precision(2);
-    }
-    return *CurrentDebug;
+    return path;
 }
 
-void
-Debug::parseOptions(char const *)
-{}
+Debug::Context *Debug::Current = nullptr;
 
-void
-Debug::finishDebug()
+Debug::Context::Context(const int aSection, const int aLevel):
+    level(aLevel),
+    sectionLevel(Levels[aSection]),
+    upper(Current)
 {
-    std::cerr << "debugs: " << CurrentDebug->str() << std::endl;
-    delete CurrentDebug;
-    CurrentDebug = NULL;
+    buf.setf(std::ios::fixed);
+    buf.precision(2);
 }
 
-void
-Debug::xassert(const char *msg, const char *file, int line)
+std::ostringstream &
+Debug::Start(const int section, const int level)
 {
-    getDebugOut() << "assertion failed: " << file << ":" << line <<
-                  ": \"" << msg << "\"";
-    abort();
+    Current = new Context(section, level);
+    return Current->buf;
 }
 
-const char*
-SkipBuildPrefix(const char* path)
+void
+Debug::Finish()
 {
-    return path;
+    if (Current) {
+        _db_print("%s\n", Current->buf.str().c_str());
+        delete Current;
+        Current = nullptr;
+    }
 }
 
 std::ostream &
@@ -136,10 +132,13 @@
 
     // finalize debugging level if no level was set explicitly via minLevel()
     const int finalLevel = (level >= 0) ? level :
-                           (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
-    if (finalLevel <= Debug::sectionLevel) {
+                           (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
+    if (finalLevel <= Debug::SectionLevel()) {
         os << (label_ ? '=' : ' ');
-        os.write(data_, size_);
+        if (data_)
+            os.write(data_, size_);
+        else
+            os << "[null]";
     }
 
     return os;
diff -u -r -N squid-4.0.10/src/tests/stub_libsecurity.cc squid-4.0.11/src/tests/stub_libsecurity.cc
--- squid-4.0.10/src/tests/stub_libsecurity.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tests/stub_libsecurity.cc	2016-06-10 08:32:57.000000000 +1200
@@ -34,11 +34,17 @@
 void Security::ServerOptions::parse(const char *) STUB
 void Security::ServerOptions::dumpCfg(Packable *, const char *) const STUB
 Security::ContextPtr Security::ServerOptions::createBlankContext() const STUB
+Security::ContextPtr Security::ServerOptions::createStaticServerContext(AnyP::PortCfg &) STUB_RETVAL(nullptr)
 void Security::ServerOptions::updateContextEecdh(Security::ContextPtr &) STUB
 
 #include "security/NegotiationHistory.h"
 Security::NegotiationHistory::NegotiationHistory() STUB
-void Security::NegotiationHistory::fillWith(Security::SessionPtr) STUB
+void Security::NegotiationHistory::retrieveNegotiatedInfo(Security::SessionPtr) STUB
+void Security::NegotiationHistory::retrieveParsedInfo(Security::TlsDetails::Pointer const &) STUB
 const char *Security::NegotiationHistory::cipherName() const STUB
-const char *Security::NegotiationHistory::printTlsVersion(int) const STUB
+const char *Security::NegotiationHistory::printTlsVersion(AnyP::ProtocolVersion const &v) const STUB
+
+#include "security/Handshake.h"
+Security::HandshakeParser::HandshakeParser() STUB
+bool Security::HandshakeParser::parseHello(const SBuf &) STUB_RETVAL(false)
 
diff -u -r -N squid-4.0.10/src/tests/stub_libsslsquid.cc squid-4.0.11/src/tests/stub_libsslsquid.cc
--- squid-4.0.10/src/tests/stub_libsslsquid.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tests/stub_libsslsquid.cc	2016-06-10 08:32:57.000000000 +1200
@@ -55,9 +55,9 @@
 CertError & CertError::operator = (const CertError &old) STUB_RETVAL(*this)
 bool CertError::operator == (const CertError &ce) const STUB_RETVAL(false)
 bool CertError::operator != (const CertError &ce) const STUB_RETVAL(false)
+bool InitServerContext(Security::ContextPtr &, AnyP::PortCfg &) STUB_RETVAL(false)
+bool InitClientContext(Security::ContextPtr &, Security::PeerOptions &, long, const char *) STUB_RETVAL(false)
 } // namespace Ssl
-Security::ContextPtr sslCreateServerContext(AnyP::PortCfg &port) STUB_RETVAL(NULL)
-Security::ContextPtr sslCreateClientContext(Security::PeerOptions &, long, const char *) STUB_RETVAL(nullptr)
 int ssl_read_method(int, char *, int) STUB_RETVAL(0)
 int ssl_write_method(int, const char *, int) STUB_RETVAL(0)
 void ssl_shutdown_method(SSL *ssl) STUB
diff -u -r -N squid-4.0.10/src/tests/stub_mime.cc squid-4.0.11/src/tests/stub_mime.cc
--- squid-4.0.10/src/tests/stub_mime.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tests/stub_mime.cc	2016-06-10 08:32:57.000000000 +1200
@@ -11,5 +11,5 @@
 #define STUB_API "mime.cc"
 #include "tests/STUB.h"
 
-size_t headersEnd(const char *mime, size_t l) STUB_RETVAL(0)
+size_t headersEnd(const char *, size_t, bool &) STUB_RETVAL(0)
 
diff -u -r -N squid-4.0.10/src/tests/testTokenizer.cc squid-4.0.11/src/tests/testTokenizer.cc
--- squid-4.0.10/src/tests/testTokenizer.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tests/testTokenizer.cc	2016-06-10 08:32:57.000000000 +1200
@@ -204,6 +204,7 @@
         const int64_t benchmark = 1234;
         CPPUNIT_ASSERT(t.int64(rv, 10));
         CPPUNIT_ASSERT_EQUAL(benchmark,rv);
+        CPPUNIT_ASSERT(t.buf().isEmpty());
     }
 
     // successful parse, autodetect base
@@ -213,6 +214,7 @@
         const int64_t benchmark = 1234;
         CPPUNIT_ASSERT(t.int64(rv));
         CPPUNIT_ASSERT_EQUAL(benchmark,rv);
+        CPPUNIT_ASSERT(t.buf().isEmpty());
     }
 
     // successful parse, autodetect base
@@ -222,6 +224,7 @@
         const int64_t benchmark = 01234;
         CPPUNIT_ASSERT(t.int64(rv));
         CPPUNIT_ASSERT_EQUAL(benchmark,rv);
+        CPPUNIT_ASSERT(t.buf().isEmpty());
     }
 
     // successful parse, autodetect base
@@ -231,6 +234,7 @@
         const int64_t benchmark = 0x12f4;
         CPPUNIT_ASSERT(t.int64(rv));
         CPPUNIT_ASSERT_EQUAL(benchmark,rv);
+        CPPUNIT_ASSERT(t.buf().isEmpty());
     }
 
     // API mismatch: don't eat leading space
@@ -238,6 +242,7 @@
         int64_t rv;
         Parser::Tokenizer t(SBuf(" 1234"));
         CPPUNIT_ASSERT(!t.int64(rv));
+        CPPUNIT_ASSERT_EQUAL(SBuf(" 1234"), t.buf());
     }
 
     // API mismatch: don't eat multiple leading spaces
@@ -245,6 +250,7 @@
         int64_t rv;
         Parser::Tokenizer t(SBuf("  1234"));
         CPPUNIT_ASSERT(!t.int64(rv));
+        CPPUNIT_ASSERT_EQUAL(SBuf("  1234"), t.buf());
     }
 
     // trailing spaces
@@ -282,6 +288,7 @@
         int64_t rv;
         Parser::Tokenizer t(SBuf("1029397752385698678762234"));
         CPPUNIT_ASSERT(!t.int64(rv));
+        CPPUNIT_ASSERT_EQUAL(SBuf("1029397752385698678762234"), t.buf());
     }
 
     // buffered sub-string parsing
@@ -293,6 +300,7 @@
         CPPUNIT_ASSERT_EQUAL(SBuf("22"),t.buf());
         CPPUNIT_ASSERT(t.int64(rv));
         CPPUNIT_ASSERT_EQUAL(benchmark,rv);
+        CPPUNIT_ASSERT(t.buf().isEmpty());
     }
 
     // base-16, prefix
diff -u -r -N squid-4.0.10/src/tunnel.cc squid-4.0.11/src/tunnel.cc
--- squid-4.0.10/src/tunnel.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/src/tunnel.cc	2016-06-10 08:32:57.000000000 +1200
@@ -21,6 +21,7 @@
 #include "comm/Read.h"
 #include "comm/Write.h"
 #include "errorpage.h"
+#include "fd.h"
 #include "fde.h"
 #include "FwdState.h"
 #include "globals.h"
@@ -164,6 +165,7 @@
     MemBuf *connectRespBuf; ///< accumulates peer CONNECT response when we need it
     bool connectReqWriting; ///< whether we are writing a CONNECT request to a peer
     SBuf preReadClientData;
+    SBuf preReadServerData;
     time_t started;         ///< when this tunnel was initiated.
 
     void copyRead(Connection &from, IOCB *completion);
@@ -214,6 +216,7 @@
     static void ReadConnectResponseDone(const Comm::ConnectionPointer &, char *buf, size_t len, Comm::Flag errcode, int xerrno, void *data);
     void readConnectResponseDone(char *buf, size_t len, Comm::Flag errcode, int xerrno);
     void copyClientBytes();
+    void copyServerBytes();
 };
 
 static const char *const conn_established = "HTTP/1.1 200 Connection established\r\n\r\n";
@@ -734,7 +737,7 @@
     CbcPointer<TunnelStateData> safetyLock(this);   /* ??? should be locked by the caller... */
 
     if (cbdataReferenceValid(this))
-        copyRead(server, ReadServer);
+        copyServerBytes();
 }
 
 static void
@@ -826,6 +829,20 @@
         copyRead(client, ReadClient);
 }
 
+void
+TunnelStateData::copyServerBytes()
+{
+    if (preReadServerData.length()) {
+        size_t copyBytes = preReadServerData.length() > SQUID_TCP_SO_RCVBUF ? SQUID_TCP_SO_RCVBUF : preReadServerData.length();
+        memcpy(server.buf, preReadServerData.rawContent(), copyBytes);
+        preReadServerData.consume(copyBytes);
+        server.bytesIn(copyBytes);
+        if (keepGoingAfterRead(copyBytes, Comm::OK, 0, server, client))
+            copy(copyBytes, server, client, TunnelStateData::WriteClientDone);
+    } else
+        copyRead(server, ReadServer);
+}
+
 /**
  * Set the HTTP status for this request and sets the read handlers for client
  * and server side connections.
@@ -841,7 +858,7 @@
 
         // Shovel any payload already pushed into reply buffer by the server response
         if (!tunnelState->server.len)
-            tunnelState->copyRead(tunnelState->server, TunnelStateData::ReadServer);
+            tunnelState->copyServerBytes();
         else {
             debugs(26, DBG_DATA, "Tunnel server PUSH Payload: \n" << Raw("", tunnelState->server.buf, tunnelState->server.len) << "\n----------");
             tunnelState->copy(tunnelState->server.len, tunnelState->server, tunnelState->client, TunnelStateData::WriteClientDone);
@@ -1298,11 +1315,8 @@
     assert(ssl);
     BIO *b = SSL_get_rbio(ssl);
     Ssl::ServerBio *srvBio = static_cast<Ssl::ServerBio *>(b->ptr);
-    const MemBuf &buf = srvBio->rBufData();
-
-    AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",
-                                         CommIoCbPtrFun(tunnelConnectedWriteDone, tunnelState));
-    tunnelState->client.write(buf.content(), buf.contentSize(), call, NULL);
+    tunnelState->preReadServerData = srvBio->rBufData();
+    tunnelStartShoveling(tunnelState);
 }
 #endif //USE_OPENSSL
 
diff -u -r -N squid-4.0.10/test-suite/Makefile.am squid-4.0.11/test-suite/Makefile.am
--- squid-4.0.10/test-suite/Makefile.am	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/test-suite/Makefile.am	2016-06-10 08:32:57.000000000 +1200
@@ -27,10 +27,10 @@
 ESI_ALL_TESTS = \
 	ESIExpressions
 
-if USE_ESI
+if ENABLE_ESI
   ESI_TESTS = $(ESI_ALL_TESTS)
 else
-  ESI_TESTS = 
+  ESI_TESTS =
 endif
 
 ## Sort by dependencies - test lowest layers first
diff -u -r -N squid-4.0.10/test-suite/Makefile.in squid-4.0.11/test-suite/Makefile.in
--- squid-4.0.10/test-suite/Makefile.in	2016-05-06 23:37:11.000000000 +1200
+++ squid-4.0.11/test-suite/Makefile.in	2016-06-10 08:35:09.000000000 +1200
@@ -169,7 +169,7 @@
 CONFIG_CLEAN_FILES =
 CONFIG_CLEAN_VPATH_FILES =
 am__EXEEXT_1 = ESIExpressions$(EXEEXT)
-@USE_ESI_TRUE@am__EXEEXT_2 = $(am__EXEEXT_1)
+@ENABLE_ESI_TRUE@am__EXEEXT_2 = $(am__EXEEXT_1)
 am__objects_1 = stub_cbdata.$(OBJEXT) stub_debug.$(OBJEXT) \
 	stub_MemBuf.$(OBJEXT) stub_SBuf.$(OBJEXT) stub_tools.$(OBJEXT) \
 	stub_fatal.$(OBJEXT)
@@ -813,8 +813,8 @@
 ESI_ALL_TESTS = \
 	ESIExpressions
 
-@USE_ESI_FALSE@ESI_TESTS = 
-@USE_ESI_TRUE@ESI_TESTS = $(ESI_ALL_TESTS)
+@ENABLE_ESI_FALSE@ESI_TESTS = 
+@ENABLE_ESI_TRUE@ESI_TESTS = $(ESI_ALL_TESTS)
 tcp_banger2_LDADD = $(top_builddir)/lib/libmiscutil.la
 
 #do not include stub_libmem.cc here, as it would override libmem.la in
diff -u -r -N squid-4.0.10/test-suite/stub_debug.cc squid-4.0.11/test-suite/stub_debug.cc
--- squid-4.0.10/test-suite/stub_debug.cc	2016-05-07 00:32:58.000000000 +1200
+++ squid-4.0.11/test-suite/stub_debug.cc	2016-06-10 09:30:12.000000000 +1200
@@ -17,14 +17,11 @@
 #include "Debug.h"
 
 FILE *debug_log = NULL;
-int Debug::TheDepth = 0;
 
 char *Debug::debugOptions;
 char *Debug::cache_log= NULL;
 int Debug::rotateNumber = 0;
 int Debug::Levels[MAX_DEBUG_SECTIONS];
-int Debug::level;
-int Debug::sectionLevel;
 int Debug::override_X = 0;
 int Debug::log_stderr = 1;
 bool Debug::log_syslog = false;
@@ -80,49 +77,48 @@
 static void
 _db_print_stderr(const char *format, va_list args)
 {
-    if (1 < Debug::level)
+    if (1 < Debug::Level())
         return;
 
     vfprintf(stderr, format, args);
 }
 
-Debug::OutStream *Debug::CurrentDebug(NULL);
+void
+Debug::parseOptions(char const *)
+{}
 
-std::ostream &
-Debug::getDebugOut()
+const char*
+SkipBuildPrefix(const char* path)
 {
-    if (!CurrentDebug) {
-        CurrentDebug = new Debug::OutStream;
-        CurrentDebug->setf(std::ios::fixed);
-        CurrentDebug->precision(2);
-    }
-    return *CurrentDebug;
+    return path;
 }
 
-void
-Debug::parseOptions(char const *)
-{}
+Debug::Context *Debug::Current = nullptr;
 
-void
-Debug::finishDebug()
+Debug::Context::Context(const int aSection, const int aLevel):
+    level(aLevel),
+    sectionLevel(Levels[aSection]),
+    upper(Current)
 {
-    std::cerr << "debugs: " << CurrentDebug->str() << std::endl;
-    delete CurrentDebug;
-    CurrentDebug = NULL;
+    buf.setf(std::ios::fixed);
+    buf.precision(2);
 }
 
-void
-Debug::xassert(const char *msg, const char *file, int line)
+std::ostringstream &
+Debug::Start(const int section, const int level)
 {
-    getDebugOut() << "assertion failed: " << file << ":" << line <<
-                  ": \"" << msg << "\"";
-    abort();
+    Current = new Context(section, level);
+    return Current->buf;
 }
 
-const char*
-SkipBuildPrefix(const char* path)
+void
+Debug::Finish()
 {
-    return path;
+    if (Current) {
+        _db_print("%s\n", Current->buf.str().c_str());
+        delete Current;
+        Current = nullptr;
+    }
 }
 
 std::ostream &
@@ -136,10 +132,13 @@
 
     // finalize debugging level if no level was set explicitly via minLevel()
     const int finalLevel = (level >= 0) ? level :
-                           (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
-    if (finalLevel <= Debug::sectionLevel) {
+                           (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
+    if (finalLevel <= Debug::SectionLevel()) {
         os << (label_ ? '=' : ' ');
-        os.write(data_, size_);
+        if (data_)
+            os.write(data_, size_);
+        else
+            os << "[null]";
     }
 
     return os;
diff -u -r -N squid-4.0.10/tools/helper-mux/helper-mux.8 squid-4.0.11/tools/helper-mux/helper-mux.8
--- squid-4.0.10/tools/helper-mux/helper-mux.8	2016-05-07 00:33:04.000000000 +1200
+++ squid-4.0.11/tools/helper-mux/helper-mux.8	2016-06-10 09:30:16.000000000 +1200
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "HELPER-MUX 8"
-.TH HELPER-MUX 8 "2016-05-06" "perl v5.22.2" "User Contributed Perl Documentation"
+.TH HELPER-MUX 8 "2016-06-09" "perl v5.22.2" "User Contributed Perl Documentation"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
diff -u -r -N squid-4.0.10/tools/squidclient/squidclient.cc squid-4.0.11/tools/squidclient/squidclient.cc
--- squid-4.0.10/tools/squidclient/squidclient.cc	2016-05-06 23:35:13.000000000 +1200
+++ squid-4.0.11/tools/squidclient/squidclient.cc	2016-06-10 08:32:57.000000000 +1200
@@ -111,7 +111,7 @@
             << "HTTP Options:" << std::endl
             << "    -a           Do NOT include Accept: header." << std::endl
             << "    -A           User-Agent: header. Use \"\" to omit." << std::endl
-            << "    -H 'string'  Extra headers to send. Use '\\n' for new lines." << std::endl
+            << "    -H 'string'  Extra headers to send. Supports '\\\\', '\\n', '\\r' and '\\t'." << std::endl
             << "    -i IMS       If-Modified-Since time (in Epoch seconds)." << std::endl
             << "    -j hosthdr   Host header content" << std::endl
             << "    -k           Keep the connection active. Default is to do only one request then close." << std::endl
@@ -132,6 +132,56 @@
     exit(1);
 }
 
+static void
+shellUnescape(char *buf)
+{
+    if (!buf)
+        return;
+
+    unsigned char *p, *d;
+
+    d = p = reinterpret_cast<unsigned char *>(buf);
+
+    while (auto ch = *p) {
+
+        if (ch == '\\') {
+            ++p;
+
+            switch (*p) {
+            case 'n':
+                ch = '\n';
+                break;
+            case 'r':
+                ch = '\r';
+                break;
+            case 't':
+                ch = '\t';
+                break;
+            case '\\':
+                ch = '\\';
+                break;
+            default:
+                ch = *p;
+                debugVerbose(1, "Warning: unsupported shell code '\\" << ch << "'");
+                break;
+            }
+
+            *d = ch;
+
+            if (!ch)
+                continue;
+
+        } else {
+            *d = *p;
+        }
+
+        ++p;
+        ++d;
+    }
+
+    *d = '\0';
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -262,10 +312,8 @@
 
             case 'H':
                 if (strlen(optarg)) {
-                    char *t;
                     strncpy(extra_hdrs, optarg, sizeof(extra_hdrs));
-                    while ((t = strstr(extra_hdrs, "\\n")))
-                        *t = '\r', *(t + 1) = '\n';
+                    shellUnescape(extra_hdrs);
                 }
                 break;
 
diff -u -r -N squid-4.0.10/tools/squidclient/stub_debug.cc squid-4.0.11/tools/squidclient/stub_debug.cc
--- squid-4.0.10/tools/squidclient/stub_debug.cc	2016-05-07 00:33:08.000000000 +1200
+++ squid-4.0.11/tools/squidclient/stub_debug.cc	2016-06-10 09:30:19.000000000 +1200
@@ -17,14 +17,11 @@
 #include "Debug.h"
 
 FILE *debug_log = NULL;
-int Debug::TheDepth = 0;
 
 char *Debug::debugOptions;
 char *Debug::cache_log= NULL;
 int Debug::rotateNumber = 0;
 int Debug::Levels[MAX_DEBUG_SECTIONS];
-int Debug::level;
-int Debug::sectionLevel;
 int Debug::override_X = 0;
 int Debug::log_stderr = 1;
 bool Debug::log_syslog = false;
@@ -80,49 +77,48 @@
 static void
 _db_print_stderr(const char *format, va_list args)
 {
-    if (1 < Debug::level)
+    if (1 < Debug::Level())
         return;
 
     vfprintf(stderr, format, args);
 }
 
-Debug::OutStream *Debug::CurrentDebug(NULL);
+void
+Debug::parseOptions(char const *)
+{}
 
-std::ostream &
-Debug::getDebugOut()
+const char*
+SkipBuildPrefix(const char* path)
 {
-    if (!CurrentDebug) {
-        CurrentDebug = new Debug::OutStream;
-        CurrentDebug->setf(std::ios::fixed);
-        CurrentDebug->precision(2);
-    }
-    return *CurrentDebug;
+    return path;
 }
 
-void
-Debug::parseOptions(char const *)
-{}
+Debug::Context *Debug::Current = nullptr;
 
-void
-Debug::finishDebug()
+Debug::Context::Context(const int aSection, const int aLevel):
+    level(aLevel),
+    sectionLevel(Levels[aSection]),
+    upper(Current)
 {
-    std::cerr << "debugs: " << CurrentDebug->str() << std::endl;
-    delete CurrentDebug;
-    CurrentDebug = NULL;
+    buf.setf(std::ios::fixed);
+    buf.precision(2);
 }
 
-void
-Debug::xassert(const char *msg, const char *file, int line)
+std::ostringstream &
+Debug::Start(const int section, const int level)
 {
-    getDebugOut() << "assertion failed: " << file << ":" << line <<
-                  ": \"" << msg << "\"";
-    abort();
+    Current = new Context(section, level);
+    return Current->buf;
 }
 
-const char*
-SkipBuildPrefix(const char* path)
+void
+Debug::Finish()
 {
-    return path;
+    if (Current) {
+        _db_print("%s\n", Current->buf.str().c_str());
+        delete Current;
+        Current = nullptr;
+    }
 }
 
 std::ostream &
@@ -136,10 +132,13 @@
 
     // finalize debugging level if no level was set explicitly via minLevel()
     const int finalLevel = (level >= 0) ? level :
-                           (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
-    if (finalLevel <= Debug::sectionLevel) {
+                           (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
+    if (finalLevel <= Debug::SectionLevel()) {
         os << (label_ ? '=' : ' ');
-        os.write(data_, size_);
+        if (data_)
+            os.write(data_, size_);
+        else
+            os << "[null]";
     }
 
     return os;
diff -u -r -N squid-4.0.10/tools/stub_debug.cc squid-4.0.11/tools/stub_debug.cc
--- squid-4.0.10/tools/stub_debug.cc	2016-05-07 00:33:01.000000000 +1200
+++ squid-4.0.11/tools/stub_debug.cc	2016-06-10 09:30:14.000000000 +1200
@@ -17,14 +17,11 @@
 #include "Debug.h"
 
 FILE *debug_log = NULL;
-int Debug::TheDepth = 0;
 
 char *Debug::debugOptions;
 char *Debug::cache_log= NULL;
 int Debug::rotateNumber = 0;
 int Debug::Levels[MAX_DEBUG_SECTIONS];
-int Debug::level;
-int Debug::sectionLevel;
 int Debug::override_X = 0;
 int Debug::log_stderr = 1;
 bool Debug::log_syslog = false;
@@ -80,49 +77,48 @@
 static void
 _db_print_stderr(const char *format, va_list args)
 {
-    if (1 < Debug::level)
+    if (1 < Debug::Level())
         return;
 
     vfprintf(stderr, format, args);
 }
 
-Debug::OutStream *Debug::CurrentDebug(NULL);
+void
+Debug::parseOptions(char const *)
+{}
 
-std::ostream &
-Debug::getDebugOut()
+const char*
+SkipBuildPrefix(const char* path)
 {
-    if (!CurrentDebug) {
-        CurrentDebug = new Debug::OutStream;
-        CurrentDebug->setf(std::ios::fixed);
-        CurrentDebug->precision(2);
-    }
-    return *CurrentDebug;
+    return path;
 }
 
-void
-Debug::parseOptions(char const *)
-{}
+Debug::Context *Debug::Current = nullptr;
 
-void
-Debug::finishDebug()
+Debug::Context::Context(const int aSection, const int aLevel):
+    level(aLevel),
+    sectionLevel(Levels[aSection]),
+    upper(Current)
 {
-    std::cerr << "debugs: " << CurrentDebug->str() << std::endl;
-    delete CurrentDebug;
-    CurrentDebug = NULL;
+    buf.setf(std::ios::fixed);
+    buf.precision(2);
 }
 
-void
-Debug::xassert(const char *msg, const char *file, int line)
+std::ostringstream &
+Debug::Start(const int section, const int level)
 {
-    getDebugOut() << "assertion failed: " << file << ":" << line <<
-                  ": \"" << msg << "\"";
-    abort();
+    Current = new Context(section, level);
+    return Current->buf;
 }
 
-const char*
-SkipBuildPrefix(const char* path)
+void
+Debug::Finish()
 {
-    return path;
+    if (Current) {
+        _db_print("%s\n", Current->buf.str().c_str());
+        delete Current;
+        Current = nullptr;
+    }
 }
 
 std::ostream &
@@ -136,10 +132,13 @@
 
     // finalize debugging level if no level was set explicitly via minLevel()
     const int finalLevel = (level >= 0) ? level :
-                           (size_ > 40 ? DBG_DATA : Debug::sectionLevel);
-    if (finalLevel <= Debug::sectionLevel) {
+                           (size_ > 40 ? DBG_DATA : Debug::SectionLevel());
+    if (finalLevel <= Debug::SectionLevel()) {
         os << (label_ ? '=' : ' ');
-        os.write(data_, size_);
+        if (data_)
+            os.write(data_, size_);
+        else
+            os << "[null]";
     }
 
     return os;
