diff -u -r -N squid-3.1.8/ChangeLog squid-3.1.9/ChangeLog --- squid-3.1.8/ChangeLog 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/ChangeLog 2010-10-26 00:34:24.000000000 +1300 @@ -1,3 +1,36 @@ +Changes to squid-3.1.9 (25 Oct 2010): + + - Bug 3088: dnsserver is segfaulting + - Bug 3084: IPv6 without Host: header in request causes connection to hang + - Bug 3082: Typo in error message + - Bug 3073: tunnelStateFree memory leak of host member + - Bug 3058: errorSend and ICY leak MemBuf object + - Bug 3057: 64-bit Solaris 9 Squid unable to determine peer IP and port + - Bug 3056: comm.cc "!fd_table[fd].closing()" assertion crash when a helper dies + - Bug 3053: cache version 1 LFS support detection broken + - Bug 3051: integer display overflow + - Bug 3040: Lower-case domain entries from hosts and resolv.conf files + - Bug 3036: adaptation_access acls cannot see myportname + - Bug 3023: url_rewrite_program silently fails to rewrite on broken URLs + - Bug 2964: Prevent memory leaks when ICAP transactions fail + - Bug 2808: getRoundRobinParent not handling weights correctly + - Bug 2793: memory statistics sometimes display wrong + - Bug 2356: Port from 2.7: Solaris /dev/poll event ports support + - Bug 2311: crashes with ICAP RESPMOD for HTTP body size greater than 100kb + - Ensure /var/cache or jail equivalent exists on install + - HTTP/1.1: delete Warnings that have warning-date different from Date + - HTTP/1.1: do not remove ETag header from partial responses + - HTTP/1.1: make date parser stricter to better handle malformed Expires + - HTTP/1.1: improve age calculation + - HTTP/1.1: reply with a 504 error if required validation fails + - HTTP/1.1: add appropriate Warnings if serving a stale hit + - HTTP/1.1: support requests with Cache-Control: min-fresh + - HTTP/1.1: do not cache replies to requests with Cache-Control: no-store + - squidclient: Display IP(s) connected to in verbose (-v) display + - Fixes several issues with ICAP persistent connections + - Fixes small leaks in Netdb, DNS, ICAP, ICY, HTTPS + - ... and some cosmetic polishing + Changes to squid-3.1.8 (04 Sep 2010): - Bug 3033: incorrect information regarding TOS diff -u -r -N squid-3.1.8/compat/compat_shared.h squid-3.1.9/compat/compat_shared.h --- squid-3.1.8/compat/compat_shared.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/compat/compat_shared.h 2010-10-26 00:34:24.000000000 +1300 @@ -68,7 +68,7 @@ /* Limited due to delay pools */ # define SQUID_MAXFD_LIMIT ((signed int)FD_SETSIZE) -#elif defined(USE_KQUEUE) || defined(USE_EPOLL) +#elif defined(USE_KQUEUE) || defined(USE_EPOLL) || defined(USE_DEVPOLL) # define SQUID_FDSET_NOUSE 1 #else diff -u -r -N squid-3.1.8/compat/os/solaris.h squid-3.1.9/compat/os/solaris.h --- squid-3.1.8/compat/os/solaris.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/compat/os/solaris.h 2010-10-26 00:34:25.000000000 +1300 @@ -64,5 +64,13 @@ //#define s6_addr16 _S6_un._S6_u16 #define s6_addr32 _S6_un._S6_u32 +/* Bug 3057: Solaris 9 defines struct addrinfo with size_t instead of socklen_t + * this causes binary incompatibility on 64-bit systems. + * Fix this by bundling a copy of the OpenSolaris 10 netdb.h to use instead. + */ +#if defined(__sparcv9) +#include "compat/os/opensolaris_10_netdb.h" +#endif + #endif /* _SQUID_SOLARIS_ */ #endif /* SQUID_OS_SOALRIS_H */ diff -u -r -N squid-3.1.8/compat/testPreCompiler.cc squid-3.1.9/compat/testPreCompiler.cc --- squid-3.1.8/compat/testPreCompiler.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/compat/testPreCompiler.cc 2010-10-26 00:34:24.000000000 +1300 @@ -63,3 +63,85 @@ CPPUNIT_ASSERT(undefinedFalse); CPPUNIT_ASSERT(!undefinedTrue); } + +/** + * Test several ways of defining pre-compiler directives. + * Squid-3 uses #if FOO syntax for precompiler directives. + * These tests ensure that the inputs will work as expected + * when undefined macros are used in && conditions + */ +void +testPreCompiler::testIfDefAnd() +{ + /* Not Defined to exist at all == false - when used in a compound if */ +#undef UNDEFINED_FOO +#define ONE_FOO 1 + +#if UNDEFINED_FOO && ONE_FOO + bool undefinedAndTrueA = true; +#else + bool undefinedAndTrueA = false; +#endif +#if !UNDEFINED_FOO && ONE_FOO + bool undefinedAndFalseA = true; +#else + bool undefinedAndFalseA = false; +#endif + CPPUNIT_ASSERT(undefinedAndFalseA); + CPPUNIT_ASSERT(!undefinedAndTrueA); + +#if ONE_FOO && UNDEFINED_FOO + bool undefinedAndTrueB = true; +#else + bool undefinedAndTrueB = false; +#endif +#if ONE_FOO && !UNDEFINED_FOO + bool undefinedAndFalseB = true; +#else + bool undefinedAndFalseB = false; +#endif + CPPUNIT_ASSERT(undefinedAndFalseB); + CPPUNIT_ASSERT(!undefinedAndTrueB); +} + +/** + * Test several ways of defining pre-compiler directives. + * Squid-3 uses #if FOO syntax for precompiler directives. + * These tests ensure that the inputs will work as expected + * when undefined macros are used in || conditions + */ +void +testPreCompiler::testIfDefOr() +{ + /* Not Defined to exist at all == false - when used in a compound if */ +#undef UNDEFINED_FOO +#define ZERO_FOO 0 + +#if UNDEFINED_FOO || ZERO_FOO + bool undefinedOrTrueA = true; +#else + bool undefinedOrTrueA = false; +#endif +#if !UNDEFINED_FOO || ZERO_FOO + bool undefinedOrFalseA = true; +#else + bool undefinedOrFalseA = false; +#endif + CPPUNIT_ASSERT(undefinedOrFalseA); + CPPUNIT_ASSERT(!undefinedOrTrueA); + +#if ZERO_FOO || UNDEFINED_FOO + bool undefinedOrTrueB = true; +#else + bool undefinedOrTrueB = false; +#endif +#if ZERO_FOO || !UNDEFINED_FOO + bool undefinedOrFalseB = true; +#else + bool undefinedOrFalseB = false; +#endif + CPPUNIT_ASSERT(undefinedOrFalseB); + CPPUNIT_ASSERT(!undefinedOrTrueB); + +} + diff -u -r -N squid-3.1.8/compat/testPreCompiler.h squid-3.1.9/compat/testPreCompiler.h --- squid-3.1.8/compat/testPreCompiler.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/compat/testPreCompiler.h 2010-10-26 00:34:26.000000000 +1300 @@ -11,10 +11,14 @@ { CPPUNIT_TEST_SUITE( testPreCompiler ); CPPUNIT_TEST( testIfDef ); + CPPUNIT_TEST( testIfDefAnd ); + CPPUNIT_TEST( testIfDefOr ); CPPUNIT_TEST_SUITE_END(); protected: void testIfDef(); + void testIfDefAnd(); + void testIfDefOr(); }; #endif /* SQUID_COMPAT_TESTS_TESTPRECOMPILER_H */ diff -u -r -N squid-3.1.8/configure squid-3.1.9/configure --- squid-3.1.8/configure 2010-09-04 15:26:52.000000000 +1200 +++ squid-3.1.9/configure 2010-10-26 00:35:32.000000000 +1300 @@ -1,7 +1,7 @@ #! /bin/sh # From configure.in Revision. # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.62 for Squid Web Proxy 3.1.8. +# Generated by GNU Autoconf 2.62 for Squid Web Proxy 3.1.9. # # Report bugs to . # @@ -750,8 +750,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='3.1.8' -PACKAGE_STRING='Squid Web Proxy 3.1.8' +PACKAGE_VERSION='3.1.9' +PACKAGE_STRING='Squid Web Proxy 3.1.9' PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/' ac_unique_file="src/main.cc" @@ -1107,6 +1107,7 @@ enable_select enable_kqueue enable_epoll +enable_devpoll enable_http_violations enable_ipfw_transparent enable_ipf_transparent @@ -1712,7 +1713,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 3.1.8 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 3.1.9 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1782,7 +1783,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 3.1.8:";; + short | recursive ) echo "Configuration of Squid Web Proxy 3.1.9:";; esac cat <<\_ACEOF @@ -1874,6 +1875,7 @@ --disable-select Disable select(2) support. --enable-kqueue Enable kqueue(2) support (experimental). --disable-epoll Disable Linux epoll(2) support. + --disable-devpoll Disable Solaris /dev/poll support. --disable-http-violations This allows you to remove code which is known to violate the HTTP protocol specification. @@ -2109,7 +2111,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 3.1.8 +Squid Web Proxy configure 3.1.9 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -2123,7 +2125,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 3.1.8, which was +It was created by Squid Web Proxy $as_me 3.1.9, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ @@ -2841,7 +2843,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='3.1.8' + VERSION='3.1.9' cat >>confdefs.h <<_ACEOF @@ -5647,13 +5649,13 @@ else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5650: $ac_compile\"" >&5) + (eval echo "\"\$as_me:5652: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5653: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:5655: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5656: output\"" >&5) + (eval echo "\"\$as_me:5658: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6875,7 +6877,7 @@ ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 6878 "configure"' > conftest.$ac_ext + echo '#line 6880 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -9434,11 +9436,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9437: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9439: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9441: \$? = $ac_status" >&5 + echo "$as_me:9443: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9773,11 +9775,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9776: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9778: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9780: \$? = $ac_status" >&5 + echo "$as_me:9782: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -9878,11 +9880,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9881: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9883: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9885: \$? = $ac_status" >&5 + echo "$as_me:9887: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -9933,11 +9935,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9936: $lt_compile\"" >&5) + (eval echo "\"\$as_me:9938: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9940: \$? = $ac_status" >&5 + echo "$as_me:9942: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -12733,7 +12735,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12736 "configure" +#line 12738 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12829,7 +12831,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12832 "configure" +#line 12834 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -14849,11 +14851,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14852: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14854: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14856: \$? = $ac_status" >&5 + echo "$as_me:14858: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -14948,11 +14950,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14951: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14953: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:14955: \$? = $ac_status" >&5 + echo "$as_me:14957: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -15000,11 +15002,11 @@ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15003: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15005: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15007: \$? = $ac_status" >&5 + echo "$as_me:15009: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -16915,7 +16917,7 @@ lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 16918 "configure" +#line 16920 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -22827,6 +22829,468 @@ fi fi +enable_devpoll=auto +# Check whether --enable-devpoll was given. +if test "${enable_devpoll+set}" = set; then + enableval=$enable_devpoll; + case "$enableval" in + yes) + { $as_echo "$as_me:$LINENO: WARNING: Forcing devpoll() to be enabled" >&5 +$as_echo "$as_me: WARNING: Forcing devpoll() to be enabled" >&2;} + SELECT_TYPE="devpoll" + enable_devpoll="yes" + ;; + no) + { $as_echo "$as_me:$LINENO: WARNING: Forcing devpoll() to be disabled" >&5 +$as_echo "$as_me: WARNING: Forcing devpoll() to be disabled" >&2;} + enable_devpoll=no + ;; +esac + +fi + +if test "x$enable_devpoll" != "xno"; then + + # Check for /dev/poll + +for ac_func in ioctl +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if test `eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +for ac_func in write +do +as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 +$as_echo_n "checking for $ac_func... " >&6; } +if { as_var=$as_ac_var; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define $ac_func to an innocuous variant, in case declares $ac_func. + For example, HP-UX 11i declares gettimeofday. */ +#define $ac_func innocuous_$ac_func + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $ac_func (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $ac_func + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $ac_func (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$ac_func || defined __stub___$ac_func +choke me +#endif + +int +main () +{ +return $ac_func (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then + eval "$as_ac_var=yes" +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + eval "$as_ac_var=no" +fi + +rm -rf conftest.dSYM +rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \ + conftest$ac_exeext conftest.$ac_ext +fi +ac_res=`eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if test `eval 'as_val=${'$as_ac_var'} + $as_echo "$as_val"'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + +for ac_header in sys/devpoll.h +do +as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:$LINENO: checking $ac_header usability" >&5 +$as_echo_n "checking $ac_header usability... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then + ac_header_compiler=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:$LINENO: checking $ac_header presence" >&5 +$as_echo_n "checking $ac_header presence... " >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then + ac_header_preproc=yes +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ $as_echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in + yes:no: ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +$as_echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +$as_echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ----------------------------------------------- ## +## Report this to http://www.squid-cache.org/bugs/ ## +## ----------------------------------------------- ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ $as_echo "$as_me:$LINENO: checking for $ac_header" >&5 +$as_echo_n "checking for $ac_header... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + $as_echo_n "(cached) " >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` + { $as_echo "$as_me:$LINENO: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + +fi +if test `eval 'as_val=${'$as_ac_Header'} + $as_echo "$as_val"'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +else + + if test "x$enable_devpoll" = "xyes"; then + { { $as_echo "$as_me:$LINENO: error: --enable-devpoll specified but /dev/poll headers not found" >&5 +$as_echo "$as_me: error: --enable-devpoll specified but /dev/poll headers not found" >&2;} + { (exit 1); exit 1; }; } + fi + enable_devpoll=no +fi + +done + + + if test "$ac_cv_func_ioctl" = "yes" && test "$ac_cv_func_write" = "yes"; then + { $as_echo "$as_me:$LINENO: checking if /dev/poll works" >&5 +$as_echo_n "checking if /dev/poll works... " >&6; } +if test "${ac_cv_devpoll_works+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include +#include +#include +#include +int main(int argc, char **argv) +{ + int fd = open("/dev/poll", O_RDWR); + if (fd < 0) { + perror("devpoll_create:"); + return 1; + } + return 0; +} + +_ACEOF +rm -f conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\"" +$as_echo "$ac_try_echo") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_devpoll_works=yes +else + $as_echo "$as_me: program exited with status $ac_status" >&5 +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_devpoll_works=no +fi +rm -rf conftest.dSYM +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_devpoll_works" >&5 +$as_echo "$ac_cv_devpoll_works" >&6; } + fi + + if test "x$enable_devpoll" = "xyes" && test "x$ac_cv_devpoll_works" = "xno" ; then + { { $as_echo "$as_me:$LINENO: error: /dev/poll does not work. Force-enabling it is not going to help." >&5 +$as_echo "$as_me: error: /dev/poll does not work. Force-enabling it is not going to help." >&2;} + { (exit 1); exit 1; }; } + fi +fi + http_violations=1 # Check whether --enable-http-violations was given. if test "${enable_http_violations+set}" = set; then @@ -46450,6 +46914,8 @@ SELECT_TYPE="kqueue" elif test -z "$disable_poll" && test "$ac_cv_func_poll" = "yes" ; then SELECT_TYPE="poll" +elif test "x$enable_devpoll" != "xno" && test "x$ac_cv_devpoll_works" = "xyes"; then + SELECT_TYPE="devpoll" elif test -z "$disable_select" && test "$ac_cv_func_select" = "yes" ; then case "$host_os" in mingw|mingw32) @@ -46460,8 +46926,8 @@ ;; esac else - { $as_echo "$as_me:$LINENO: WARNING: Eep! Can't find poll, kqueue, epoll, or select!" >&5 -$as_echo "$as_me: WARNING: Eep! Can't find poll, kqueue, epoll, or select!" >&2;} + { $as_echo "$as_me:$LINENO: WARNING: Eep! Cannot find epoll, kqueue, /dev/poll, poll or select!" >&5 +$as_echo "$as_me: WARNING: Eep! Cannot find epoll, kqueue, /dev/poll, poll or select!" >&2;} { $as_echo "$as_me:$LINENO: WARNING: I'll try select and hope for the best." >&5 $as_echo "$as_me: WARNING: I'll try select and hope for the best." >&2;} SELECT_TYPE="select" @@ -46539,6 +47005,13 @@ _ACEOF ;; +devpoll) + +cat >>confdefs.h <<\_ACEOF +#define USE_DEVPOLL 1 +_ACEOF + + ;; poll) cat >>confdefs.h <<\_ACEOF @@ -49210,7 +49683,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 3.1.8, which was +This file was extended by Squid Web Proxy $as_me 3.1.9, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -49263,7 +49736,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -Squid Web Proxy config.status 3.1.8 +Squid Web Proxy config.status 3.1.9 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" diff -u -r -N squid-3.1.8/configure.in squid-3.1.9/configure.in --- squid-3.1.8/configure.in 2010-09-04 15:26:52.000000000 +1200 +++ squid-3.1.9/configure.in 2010-10-26 00:35:32.000000000 +1300 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_INIT([Squid Web Proxy],[3.1.8],[http://www.squid-cache.org/bugs/],[squid]) +AC_INIT([Squid Web Proxy],[3.1.9],[http://www.squid-cache.org/bugs/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -1339,6 +1339,62 @@ fi fi +dnl Enable solaris /dev/poll +enable_devpoll=auto +AC_ARG_ENABLE(devpoll, + AS_HELP_STRING([--disable-devpoll],[Disable Solaris /dev/poll support.]), +[ + case "$enableval" in + yes) + AC_MSG_WARN([Forcing devpoll() to be enabled]) + SELECT_TYPE="devpoll" + enable_devpoll="yes" + ;; + no) + AC_MSG_WARN([Forcing devpoll() to be disabled]) + enable_devpoll=no + ;; +esac +]) +dnl auto-detect and verify devpoll header and library present and working +if test "x$enable_devpoll" != "xno"; then + + # Check for /dev/poll + AC_CHECK_FUNCS(ioctl) + AC_CHECK_FUNCS(write) + + dnl devpoll requires sys/devpoll.h + AC_CHECK_HEADERS([sys/devpoll.h],,[ + if test "x$enable_devpoll" = "xyes"; then + AC_MSG_ERROR([--enable-devpoll specified but /dev/poll headers not found]) + fi + enable_devpoll=no]) + + dnl Verify that /dev/poll really works + if test "$ac_cv_func_ioctl" = "yes" && test "$ac_cv_func_write" = "yes"; then + AC_CACHE_CHECK(if /dev/poll works, ac_cv_devpoll_works, + AC_RUN_IFELSE([AC_LANG_SOURCE([[ +#include +#include +#include +#include +int main(int argc, char **argv) +{ + int fd = open("/dev/poll", O_RDWR); + if (fd < 0) { + perror("devpoll_create:"); + return 1; + } + return 0; +} + ]])],[ac_cv_devpoll_works=yes],[ac_cv_devpoll_works=no],[:])) + fi + + if test "x$enable_devpoll" = "xyes" && test "x$ac_cv_devpoll_works" = "xno" ; then + AC_MSG_ERROR([/dev/poll does not work. Force-enabling it is not going to help.]) + fi +fi + dnl Disable HTTP violations http_violations=1 AC_ARG_ENABLE(http-violations, @@ -3017,6 +3073,8 @@ SELECT_TYPE="kqueue" elif test -z "$disable_poll" && test "$ac_cv_func_poll" = "yes" ; then SELECT_TYPE="poll" +elif test "x$enable_devpoll" != "xno" && test "x$ac_cv_devpoll_works" = "xyes"; then + SELECT_TYPE="devpoll" elif test -z "$disable_select" && test "$ac_cv_func_select" = "yes" ; then case "$host_os" in mingw|mingw32) @@ -3027,7 +3085,7 @@ ;; esac else - AC_MSG_WARN([Eep! Can't find poll, kqueue, epoll, or select!]) + AC_MSG_WARN([Eep! Cannot find epoll, kqueue, /dev/poll, poll or select!]) AC_MSG_WARN([I'll try select and hope for the best.]) SELECT_TYPE="select" AC_DEFINE(USE_SELECT,1) @@ -3047,6 +3105,9 @@ epoll) AC_DEFINE(USE_EPOLL,1,[Use epoll() for the IO loop]) ;; +devpoll) + AC_DEFINE(USE_DEVPOLL,1,[Use /dev/poll for the IO loop]) + ;; poll) AC_DEFINE(USE_POLL,1,[Use poll() for the IO loop]) ;; diff -u -r -N squid-3.1.8/include/autoconf.h.in squid-3.1.9/include/autoconf.h.in --- squid-3.1.8/include/autoconf.h.in 2010-09-04 15:26:15.000000000 +1200 +++ squid-3.1.9/include/autoconf.h.in 2010-10-26 00:34:47.000000000 +1300 @@ -297,6 +297,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H +/* Define to 1 if you have the `ioctl' function. */ +#undef HAVE_IOCTL + /* Define to 1 if you have the header file. */ #undef HAVE_IOMANIP @@ -759,6 +762,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_CAPABILITY_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_DEVPOLL_H + /* Define to 1 if you have the header file, and it defines `DIR'. */ #undef HAVE_SYS_DIR_H @@ -905,6 +911,9 @@ /* This value is set to 1 to indicate that the system argz facility works */ #undef HAVE_WORKING_ARGZ +/* Define to 1 if you have the `write' function. */ +#undef HAVE_WRITE + /* __int64 is defined in system headers */ #undef HAVE___INT64 @@ -1118,6 +1127,9 @@ /* Define to Enable chunked Memory Pools support (experimental) */ #undef USE_CHUNKEDMEMPOOLS +/* Use /dev/poll for the IO loop */ +#undef USE_DEVPOLL + /* DiskIO modules are expected to be available. */ #undef USE_DISKIO diff -u -r -N squid-3.1.8/include/getaddrinfo.h squid-3.1.9/include/getaddrinfo.h --- squid-3.1.8/include/getaddrinfo.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/include/getaddrinfo.h 2010-10-26 00:34:23.000000000 +1300 @@ -62,7 +62,7 @@ int ai_family; /* PF_xxx */ int ai_socktype; /* SOCK_xxx */ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ - size_t ai_addrlen; /* length of ai_addr */ + socklen_t ai_addrlen; /* length of ai_addr */ char *ai_canonname; /* canonical name for nodename */ struct sockaddr *ai_addr; /* binary address */ struct addrinfo *ai_next; /* next structure in linked list */ diff -u -r -N squid-3.1.8/include/version.h squid-3.1.9/include/version.h --- squid-3.1.8/include/version.h 2010-09-04 15:26:52.000000000 +1200 +++ squid-3.1.9/include/version.h 2010-10-26 00:35:32.000000000 +1300 @@ -9,7 +9,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1283570743 +#define SQUID_RELEASE_TIME 1288006445 #endif #ifndef APP_SHORTNAME diff -u -r -N squid-3.1.8/lib/heap.c squid-3.1.9/lib/heap.c --- squid-3.1.8/lib/heap.c 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/lib/heap.c 2010-10-26 00:34:24.000000000 +1300 @@ -356,8 +356,8 @@ { heap_node *kid; int left = 0, right = 0; - int true = 1; - while (true) { + int isTrue = 1; + while (isTrue) { left = Left(elm->id); right = Right(elm->id); if (!_heap_node_exist(hp, left)) { diff -u -r -N squid-3.1.8/lib/rfc1123.c squid-3.1.9/lib/rfc1123.c --- squid-3.1.8/lib/rfc1123.c 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/lib/rfc1123.c 2010-10-26 00:34:24.000000000 +1300 @@ -124,7 +124,7 @@ char *t; memset(&tm, 0, sizeof(tm)); - if (!day || !month || !year || !aTime) + if (!day || !month || !year || !aTime || (zone && strcmp(zone, "GMT"))) return NULL; tm.tm_mday = atoi(day); tm.tm_mon = make_month(month); @@ -181,12 +181,16 @@ timestr = t; else if (!year) year = t; + else + return NULL; } else if (!wday) wday = t; else if (!month) month = t; else if (!zone) zone = t; + else + return NULL; } tm = parse_date_elements(day, month, year, timestr, zone); diff -u -r -N squid-3.1.8/RELEASENOTES.html squid-3.1.9/RELEASENOTES.html --- squid-3.1.8/RELEASENOTES.html 2010-09-04 15:47:57.000000000 +1200 +++ squid-3.1.9/RELEASENOTES.html 2010-10-26 01:06:40.000000000 +1300 @@ -1,11 +1,11 @@ - - Squid 3.1.8 release notes + + Squid 3.1.9 release notes -

Squid 3.1.8 release notes

+

Squid 3.1.9 release notes

Squid Developers


@@ -70,7 +70,7 @@

1. Notice

-

The Squid Team are pleased to announce the release of Squid-3.1.8

+

The Squid Team are pleased to announce the release of Squid-3.1.9

This new release is available for download from http://www.squid-cache.org/Versions/v3/3.1/ or the mirrors.

@@ -262,7 +262,7 @@

Real transparent Interception (TPROXY) may be able to perform IPv6 interception. -However this currently still needs kernel patching with experimental patches to enable IPv6. +However this currently still needs patching of kernels older than 2.6.37. Squid will attempt to discover support on startup and may permit or deny IPv6 wildcard for tproxy flagged ports depending on your system.

diff -u -r -N squid-3.1.8/SPONSORS squid-3.1.9/SPONSORS --- squid-3.1.8/SPONSORS 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/SPONSORS 2010-10-26 00:34:25.000000000 +1300 @@ -77,3 +77,8 @@ Treehouse Networks has contributed significant development resources toward Squid-3 development and maintenance for their customer gateways and CDN. + +BBC (UK) and Siemens IT Solutions and Services (UK) + + Provided developement and testing resources for Solaris /dev/poll + support. diff -u -r -N squid-3.1.8/src/access_log.cc squid-3.1.9/src/access_log.cc --- squid-3.1.8/src/access_log.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/access_log.cc 2010-10-26 00:34:23.000000000 +1300 @@ -67,7 +67,8 @@ "TCP_HIT", "TCP_MISS", "TCP_REFRESH_UNMODIFIED", - "TCP_REFRESH_FAIL", + "TCP_REFRESH_FAIL", // same tag logged for LOG_TCP_REFRESH_FAIL_OLD and + "TCP_REFRESH_FAIL", // LOG_TCP_REFRESH_FAIL_ERR for backward-compatibility "TCP_REFRESH_MODIFIED", "TCP_CLIENT_REFRESH_MISS", "TCP_IMS_HIT", @@ -2423,7 +2424,7 @@ if (code == LOG_TCP_IMS_HIT) return 1; - if (code == LOG_TCP_REFRESH_FAIL) + if (code == LOG_TCP_REFRESH_FAIL_OLD) return 1; if (code == LOG_TCP_REFRESH_UNMODIFIED) diff -u -r -N squid-3.1.8/src/acl/MyPortName.cc squid-3.1.9/src/acl/MyPortName.cc --- squid-3.1.8/src/acl/MyPortName.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/acl/MyPortName.cc 2010-10-26 00:34:25.000000000 +1300 @@ -38,18 +38,18 @@ #include "acl/MyPortName.h" #include "acl/StringData.h" #include "acl/Checklist.h" +#include "HttpRequest.h" /* for ConnStateData */ #include "client_side.h" - - - int -ACLMyPortNameStrategy::match (ACLData * &data, ACLFilledChecklist *checklist) +ACLMyPortNameStrategy::match(ACLData * &data, ACLFilledChecklist *checklist) { if (checklist->conn() != NULL) - return data->match (checklist->conn()->port->name); + return data->match(checklist->conn()->port->name); + if (checklist->request != NULL) + return data->match(checklist->request->myportname.termedBuf()); return 0; } diff -u -r -N squid-3.1.8/src/adaptation/History.cc squid-3.1.9/src/adaptation/History.cc --- squid-3.1.8/src/adaptation/History.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/History.cc 2010-10-26 00:34:25.000000000 +1300 @@ -39,10 +39,10 @@ int Adaptation::History::recordXactStart(const String &serviceId, const timeval &when, bool retrying) { - if (retrying) { - Must(!theEntries.empty()); // or there would be nothing to retry + // the history will be empty on retries if it was enabled after the failure + if (retrying && !theEntries.empty()) theEntries.back().retried = true; - } + theEntries.push_back(Adaptation::History::Entry(serviceId, when)); return theEntries.size() - 1; // record position becomes history ID } diff -u -r -N squid-3.1.8/src/adaptation/icap/Elements.cc squid-3.1.9/src/adaptation/icap/Elements.cc --- squid-3.1.8/src/adaptation/icap/Elements.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/Elements.cc 2010-10-26 00:34:25.000000000 +1300 @@ -8,6 +8,7 @@ { const XactOutcome xoUnknown = "ICAP_ERR_UNKNOWN"; +const XactOutcome xoRace = "ICAP_ERR_RACE"; const XactOutcome xoError = "ICAP_ERR_OTHER"; const XactOutcome xoOpt = "ICAP_OPT"; const XactOutcome xoEcho = "ICAP_ECHO"; diff -u -r -N squid-3.1.8/src/adaptation/icap/Elements.h squid-3.1.9/src/adaptation/icap/Elements.h --- squid-3.1.8/src/adaptation/icap/Elements.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/Elements.h 2010-10-26 00:34:25.000000000 +1300 @@ -64,6 +64,7 @@ typedef const char *XactOutcome; ///< transaction result for logging extern const XactOutcome xoUnknown; ///< initial value: outcome was not set +extern const XactOutcome xoRace; ///< ICAP server closed pconn when we started extern const XactOutcome xoError; ///< all kinds of transaction errors extern const XactOutcome xoOpt; ///< OPTION transaction extern const XactOutcome xoEcho; ///< preserved virgin message (ICAP 204) diff -u -r -N squid-3.1.8/src/adaptation/icap/ModXact.cc squid-3.1.9/src/adaptation/icap/ModXact.cc --- squid-3.1.8/src/adaptation/icap/ModXact.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/ModXact.cc 2010-10-26 00:34:25.000000000 +1300 @@ -61,7 +61,7 @@ // nothing to do because we are using temporary buffers // parsing; TODO: do not set until we parse, see ICAPOptXact - icapReply = HTTPMSGLOCK(new HttpReply); + icapReply = new HttpReply; icapReply->protoPrefix = "ICAP/"; // TODO: make an IcapReply class? debugs(93,7, HERE << "initialized." << status()); @@ -93,11 +93,11 @@ { Must(!state.serviceWaiting); debugs(93, 7, HERE << "will wait for the ICAP service" << status()); - state.serviceWaiting = true; typedef NullaryMemFunT Dialer; AsyncCall::Pointer call = JobCallback(93,5, Dialer, this, Adaptation::Icap::ModXact::noteServiceReady); service().callWhenReady(call); + state.serviceWaiting = true; // after callWhenReady() which may throw } void Adaptation::Icap::ModXact::noteServiceReady() @@ -159,11 +159,14 @@ Must(state.writing == State::writingHeaders); // determine next step - if (preview.enabled()) - state.writing = preview.done() ? State::writingPaused : State::writingPreview; - else if (virginBody.expected()) + if (preview.enabled()) { + if (preview.done()) + decideWritingAfterPreview("zero-size"); + else + state.writing = State::writingPreview; + } else if (virginBody.expected()) { state.writing = State::writingPrime; - else { + } else { stopWriting(true); return; } @@ -222,14 +225,22 @@ // change state once preview is written - if (preview.done()) { - debugs(93, 7, HERE << "wrote entire Preview body" << status()); + if (preview.done()) + decideWritingAfterPreview("body"); +} - if (preview.ieof()) - stopWriting(true); - else - state.writing = State::writingPaused; - } +/// determine state.writing after we wrote the entire preview +void Adaptation::Icap::ModXact::decideWritingAfterPreview(const char *kind) +{ + if (preview.ieof()) // nothing more to write + stopWriting(true); + else if (state.parsing == State::psIcapHeader) // did not get a reply yet + state.writing = State::writingPaused; // wait for the ICAP server reply + else + stopWriting(true); // ICAP server reply implies no post-preview writing + + debugs(93, 6, HERE << "decided on writing after " << kind << " preview" << + status()); } void Adaptation::Icap::ModXact::writePrimeBody() @@ -850,32 +861,34 @@ // allocate the adapted message and copy metainfo Must(!adapted.header); - HttpMsg *newHead = NULL; - if (const HttpRequest *oldR = dynamic_cast(oldHead)) { - HttpRequest *newR = new HttpRequest; - newR->canonical = oldR->canonical ? - xstrdup(oldR->canonical) : NULL; // parse() does not set it - newHead = newR; - } else if (dynamic_cast(oldHead)) { - HttpReply *newRep = new HttpReply; - newHead = newRep; - } - Must(newHead); - newHead->inheritProperties(oldHead); + { + HttpMsg::Pointer newHead; + if (const HttpRequest *oldR = dynamic_cast(oldHead)) { + HttpRequest::Pointer newR(new HttpRequest); + newR->canonical = oldR->canonical ? + xstrdup(oldR->canonical) : NULL; // parse() does not set it + newHead = newR; + } else if (dynamic_cast(oldHead)) { + newHead = new HttpReply; + } + Must(newHead != NULL); - adapted.setHeader(newHead); + newHead->inheritProperties(oldHead); + + adapted.setHeader(newHead); + } // parse the buffer back http_status error = HTTP_STATUS_NONE; - Must(newHead->parse(&httpBuf, true, &error)); + Must(adapted.header->parse(&httpBuf, true, &error)); - Must(newHead->hdr_sz == httpBuf.contentSize()); // no leftovers + Must(adapted.header->hdr_sz == httpBuf.contentSize()); // no leftovers httpBuf.clean(); debugs(93, 7, HERE << "cloned virgin message " << oldHead << " to " << - newHead); + adapted.header); // setup adapted body pipe if needed if (oldHead->body_pipe != NULL) { @@ -1085,6 +1098,11 @@ mustStop("adapted body consumer aborted"); } +Adaptation::Icap::ModXact::~ModXact() +{ + delete bodyParser; +} + // internal cleanup void Adaptation::Icap::ModXact::swanSong() { @@ -1296,21 +1314,20 @@ icapBuf.Printf("%s=%d, ", section, (int) httpBuf.contentSize()); // begin cloning - HttpMsg *headClone = NULL; + HttpMsg::Pointer headClone; if (const HttpRequest* old_request = dynamic_cast(head)) { - HttpRequest* new_request = new HttpRequest; - assert(old_request->canonical); + HttpRequest::Pointer new_request(new HttpRequest); + Must(old_request->canonical); urlParse(old_request->method, old_request->canonical, new_request); new_request->http_ver = old_request->http_ver; headClone = new_request; } else if (const HttpReply *old_reply = dynamic_cast(head)) { - HttpReply* new_reply = new HttpReply; + HttpReply::Pointer new_reply(new HttpReply); new_reply->sline = old_reply->sline; headClone = new_reply; } - - Must(headClone); + Must(headClone != NULL); headClone->inheritProperties(head); HttpHeaderPos pos = HttpHeaderInitPos; @@ -1327,7 +1344,7 @@ // pack polished HTTP header packHead(httpBuf, headClone); - delete headClone; + // headClone unlocks and, hence, deletes the message we packed } void Adaptation::Icap::ModXact::packHead(MemBuf &httpBuf, const HttpMsg *head) diff -u -r -N squid-3.1.8/src/adaptation/icap/ModXact.h squid-3.1.9/src/adaptation/icap/ModXact.h --- squid-3.1.8/src/adaptation/icap/ModXact.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/ModXact.h 2010-10-26 00:34:24.000000000 +1300 @@ -137,6 +137,7 @@ public: ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s); + virtual ~ModXact(); // BodyProducer methods virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); @@ -183,6 +184,7 @@ void writePreviewBody(); void writePrimeBody(); void writeSomeBody(const char *label, size_t size); + void decideWritingAfterPreview(const char *previewKind); void startReading(); void readMore(); diff -u -r -N squid-3.1.8/src/adaptation/icap/Options.cc squid-3.1.9/src/adaptation/icap/Options.cc --- squid-3.1.8/src/adaptation/icap/Options.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/Options.cc 2010-10-26 00:34:25.000000000 +1300 @@ -89,8 +89,12 @@ istag = h->getByName("ISTag"); - if (h->getByName("Opt-body-type").size()) - error = "ICAP service returns unsupported OPTIONS body"; + if (h->getByName("Opt-body-type").size()) { + // TODO: add a class to rate-limit such warnings using FadingCounter + debugs(93,DBG_IMPORTANT, "WARNING: Ignoring unsupported ICAP " << + "OPTIONS body; type: " << h->getByName("Opt-body-type")); + // Do not set error, assuming the response headers are valid. + } cfgIntHeader(h, "Max-Connections", max_connections); diff -u -r -N squid-3.1.8/src/adaptation/icap/OptXact.cc squid-3.1.9/src/adaptation/icap/OptXact.cc --- squid-3.1.8/src/adaptation/icap/OptXact.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/OptXact.cc 2010-10-26 00:34:24.000000000 +1300 @@ -18,7 +18,8 @@ Adaptation::Icap::OptXact::OptXact(Adaptation::Icap::ServiceRep::Pointer &aService): AsyncJob("Adaptation::Icap::OptXact"), - Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService) + Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService), + readAll(false) { } @@ -65,11 +66,17 @@ // comm module read a portion of the ICAP response for us void Adaptation::Icap::OptXact::handleCommRead(size_t) { - if (HttpMsg *r = parseResponse()) { + if (parseResponse()) { + Must(icapReply != NULL); + // We read everything if there is no response body. If there is a body, + // we cannot parse it because we do not support any opt-body-types, so + // we leave readAll false which forces connection closure. + readAll = !icapReply->header.getByNameListMember("Encapsulated", + "opt-body", ',').size(); + debugs(93, 7, HERE << "readAll=" << readAll); icap_tio_finish = current_time; setOutcome(xoOpt); - sendAnswer(r); - icapReply = HTTPMSGLOCK(dynamic_cast(r)); + sendAnswer(icapReply); Must(done()); // there should be nothing else to do return; } @@ -77,24 +84,23 @@ scheduleRead(); } -HttpMsg *Adaptation::Icap::OptXact::parseResponse() +bool Adaptation::Icap::OptXact::parseResponse() { debugs(93, 5, HERE << "have " << readBuf.contentSize() << " bytes to parse" << status()); debugs(93, 5, HERE << "\n" << readBuf.content()); - HttpReply *r = HTTPMSGLOCK(new HttpReply); + HttpReply::Pointer r(new HttpReply); r->protoPrefix = "ICAP/"; // TODO: make an IcapReply class? - if (!parseHttpMsg(r)) { // throws on errors - HTTPMSGUNLOCK(r); - return 0; - } + if (!parseHttpMsg(r)) // throws on errors + return false; if (httpHeaderHasConnDir(&r->header, "close")) reuseConnection = false; - return r; + icapReply = r; + return true; } void Adaptation::Icap::OptXact::swanSong() diff -u -r -N squid-3.1.8/src/adaptation/icap/OptXact.h squid-3.1.9/src/adaptation/icap/OptXact.h --- squid-3.1.8/src/adaptation/icap/OptXact.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/OptXact.h 2010-10-26 00:34:24.000000000 +1300 @@ -60,14 +60,18 @@ virtual void handleCommRead(size_t size); void makeRequest(MemBuf &buf); - HttpMsg *parseResponse(); + bool parseResponse(); void startReading(); + virtual bool doneReading() const { return commEof || readAll; } virtual void swanSong(); private: virtual void finalizeLogInfo(); + + bool readAll; ///< read the entire OPTIONS response + CBDATA_CLASS2(OptXact); }; diff -u -r -N squid-3.1.8/src/adaptation/icap/Xaction.cc squid-3.1.9/src/adaptation/icap/Xaction.cc --- squid-3.1.8/src/adaptation/icap/Xaction.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/Xaction.cc 2010-10-26 00:34:23.000000000 +1300 @@ -52,7 +52,6 @@ debugs(93,3, typeName << " destructed, this=" << this << " [icapx" << id << ']'); // we should not call virtual status() here HTTPMSGUNLOCK(icapRequest); - HTTPMSGUNLOCK(icapReply); } Adaptation::Icap::ServiceRep & @@ -270,9 +269,10 @@ theService->cfg().methodStr() << " " << theService->cfg().uri << status()); reuseConnection = false; - service().noteFailure(); - throw TexcHere(connector != NULL ? + const bool whileConnecting = connector != NULL; + closeConnection(); // so that late Comm callbacks do not disturb bypass + throw TexcHere(whileConnecting ? "timed out while connecting to the ICAP service" : "timed out while talking to the ICAP service"); } @@ -357,23 +357,31 @@ Must(io.flag == COMM_OK); Must(io.size >= 0); - al.icap.bytesRead+=io.size; + if (!io.size) { + commEof = true; + reuseConnection = false; - updateTimeout(); + // detect a pconn race condition: eof on the first pconn read + if (!al.icap.bytesRead && retriable()) { + setOutcome(xoRace); + mustStop("pconn race"); + return; + } + } else { - debugs(93, 3, HERE << "read " << io.size << " bytes"); + al.icap.bytesRead+=io.size; - /* - * See comments in Adaptation::Icap::Xaction.h about why we use commBuf - * here instead of reading directly into readBuf.buf. - */ + updateTimeout(); + + debugs(93, 3, HERE << "read " << io.size << " bytes"); + + /* + * See comments in Adaptation::Icap::Xaction.h about why we use commBuf + * here instead of reading directly into readBuf.buf. + */ - if (io.size > 0) { readBuf.append(commBuf, io.size); disableRetries(); // because pconn did not fail - } else { - reuseConnection = false; - commEof = true; } handleCommRead(io.size); diff -u -r -N squid-3.1.8/src/adaptation/icap/Xaction.h squid-3.1.9/src/adaptation/icap/Xaction.h --- squid-3.1.8/src/adaptation/icap/Xaction.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/adaptation/icap/Xaction.h 2010-10-26 00:34:24.000000000 +1300 @@ -40,8 +40,8 @@ #include "adaptation/icap/ServiceRep.h" #include "adaptation/Initiate.h" #include "AccessLogEntry.h" +#include "HttpReply.h" -class HttpMsg; class CommConnectCbParams; namespace Adaptation @@ -80,7 +80,7 @@ // TODO: create these only when actually sending/receiving HttpRequest *icapRequest; ///< sent (or at least created) ICAP request - HttpReply *icapReply; ///< received ICAP reply, if any + HttpReply::Pointer icapReply; ///< received ICAP reply, if any /// the number of times we tried to get to the service, including this time int attempts; diff -u -r -N squid-3.1.8/src/base/AsyncJob.cc squid-3.1.9/src/base/AsyncJob.cc --- squid-3.1.8/src/base/AsyncJob.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/base/AsyncJob.cc 2010-10-26 00:34:24.000000000 +1300 @@ -22,12 +22,14 @@ AsyncJob::AsyncJob(const char *aTypeName): typeName(aTypeName), inCall(NULL), id(++TheLastId) { - debugs(93,3, "AsyncJob of type " << typeName << " constructed, this=" << this << - " [async" << id << ']'); + debugs(93,5, "AsyncJob constructed, this=" << this << + " type=" << typeName << " [job" << id << ']'); } AsyncJob::~AsyncJob() { + debugs(93,5, "AsyncJob destructed, this=" << this << + " type=" << typeName << " [job" << id << ']'); } void AsyncJob::start() diff -u -r -N squid-3.1.8/src/BodyPipe.cc squid-3.1.9/src/BodyPipe.cc --- squid-3.1.8/src/BodyPipe.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/BodyPipe.cc 2010-10-26 00:34:24.000000000 +1300 @@ -129,7 +129,7 @@ BodyPipe::BodyPipe(Producer *aProducer): theBodySize(-1), theProducer(aProducer), theConsumer(0), thePutSize(0), theGetSize(0), - mustAutoConsume(false), isCheckedOut(false) + mustAutoConsume(false), abortedConsumption(false), isCheckedOut(false) { // TODO: teach MemBuf to start with zero minSize // TODO: limit maxSize by theBodySize, when known? @@ -231,6 +231,8 @@ return false; } + Must(!abortedConsumption); // did not promise to never consume + theConsumer = aConsumer; debugs(91,7, HERE << "set consumer" << status()); if (theBuf.hasContent()) @@ -241,25 +243,30 @@ return true; } -// When BodyPipe consumer is gone, all events for that consumer must not -// reach the new consumer (if any). Otherwise, the calls may go out of order -// (if _some_ calls are dropped due to the ultimate destination being -// temporary NULL). The code keeps track of the number of outstanding -// events and skips that number if consumer leaves. TODO: when AscyncCall -// support is improved, should we just schedule calls directly to consumer? void BodyPipe::clearConsumer() { if (theConsumer.set()) { debugs(91,7, HERE << "clearing consumer" << status()); theConsumer.clear(); - if (consumedSize() && !exhausted()) { - AsyncCall::Pointer call= asyncCall(91, 7, - "BodyProducer::noteBodyConsumerAborted", - BodyProducerDialer(theProducer, - &BodyProducer::noteBodyConsumerAborted, this)); - ScheduleCallHere(call); - } + // do not abort if we have not consumed so that HTTP or ICAP can retry + // benign xaction failures due to persistent connection race conditions + if (consumedSize()) + expectNoConsumption(); + } +} + +void +BodyPipe::expectNoConsumption() +{ + Must(!theConsumer); + if (!abortedConsumption && !exhausted()) { + AsyncCall::Pointer call= asyncCall(91, 7, + "BodyProducer::noteBodyConsumerAborted", + BodyProducerDialer(theProducer, + &BodyProducer::noteBodyConsumerAborted, this)); + ScheduleCallHere(call); + abortedConsumption = true; } } @@ -337,7 +344,7 @@ // raw buffers should always check them in (possibly unchanged) // instead of relying on the automated undo mechanism of Checkout. // The code can always use a temporary buffer to accomplish that. - assert(checkout.checkedOutSize == currentSize); + Must(checkout.checkedOutSize == currentSize); } // TODO: Optimize: inform consumer/producer about more data/space only if @@ -433,6 +440,8 @@ if (mustAutoConsume) outputBuffer.append(" A", 2); + if (abortedConsumption) + outputBuffer.append(" !C", 3); if (isCheckedOut) outputBuffer.append(" L", 2); // Locked @@ -454,8 +463,13 @@ BodyPipeCheckout::~BodyPipeCheckout() { - if (!checkedIn) - pipe.undoCheckOut(*this); + if (!checkedIn) { + // Do not pipe.undoCheckOut(*this) because it asserts or throws + // TODO: consider implementing the long-term solution discussed at + // http://www.mail-archive.com/squid-dev@squid-cache.org/msg07910.html + debugs(91,2, HERE << "Warning: cannot undo BodyPipeCheckout"); + pipe.checkIn(*this); + } } void diff -u -r -N squid-3.1.8/src/BodyPipe.h squid-3.1.9/src/BodyPipe.h --- squid-3.1.8/src/BodyPipe.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/BodyPipe.h 2010-10-26 00:34:23.000000000 +1300 @@ -109,6 +109,7 @@ // called by consumers bool setConsumerIfNotLate(const Consumer::Pointer &aConsumer); void clearConsumer(); // aborts if still piping + void expectNoConsumption(); ///< there will be no more setConsumer() calls size_t getMoreData(MemBuf &buf); void consume(size_t size); bool expectMoreAfter(uint64_t offset) const; @@ -148,6 +149,7 @@ MemBuf theBuf; // produced but not yet consumed content, if any bool mustAutoConsume; // consume when there is no consumer + bool abortedConsumption; ///< called BodyProducer::noteBodyConsumerAborted bool isCheckedOut; // to keep track of checkout violations CBDATA_CLASS2(BodyPipe); diff -u -r -N squid-3.1.8/src/cf.data.pre squid-3.1.9/src/cf.data.pre --- squid-3.1.8/src/cf.data.pre 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/cf.data.pre 2010-10-26 00:34:25.000000000 +1300 @@ -724,7 +724,6 @@ TYPE: acl_access IFDEF: FOLLOW_X_FORWARDED_FOR LOC: Config.accessList.followXFF -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying the X-Forwarded-For header to be followed to @@ -811,7 +810,6 @@ NAME: http_access TYPE: acl_access LOC: Config.accessList.http -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying access based on defined access lists @@ -906,7 +904,6 @@ NAME: icp_access TYPE: acl_access LOC: Config.accessList.icp -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying access to the ICP port based on defined @@ -928,7 +925,6 @@ IFDEF: USE_HTCP TYPE: acl_access LOC: Config.accessList.htcp -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying access to the HTCP port based on defined @@ -954,7 +950,6 @@ IFDEF: USE_HTCP TYPE: acl_access LOC: Config.accessList.htcp_clr -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START Allowing or Denying access to purge content using HTCP based @@ -997,7 +992,6 @@ NAME: ident_lookup_access TYPE: acl_access IFDEF: USE_IDENT -DEFAULT: none DEFAULT_IF_NONE: deny all LOC: Ident::TheConfig.identLookup DOC_START @@ -2536,7 +2530,6 @@ NAME: access_log cache_access_log TYPE: access_log LOC: Config.Log.accesslogs -DEFAULT: none DEFAULT_IF_NONE: @DEFAULT_ACCESS_LOG@ squid DOC_START These files log client request activities. Has a line every HTTP or @@ -2896,7 +2889,6 @@ NAME: cache_log TYPE: string -DEFAULT: none DEFAULT_IF_NONE: @DEFAULT_CACHE_LOG@ LOC: Debug::cache_log DOC_START @@ -2927,7 +2919,6 @@ NAME: coredump_dir TYPE: string LOC: Config.coredump_dir -DEFAULT: none DEFAULT_IF_NONE: none DOC_START By default Squid leaves core files in the directory from where @@ -4565,7 +4556,6 @@ NAME: wccp2_service TYPE: wccp2_service LOC: Config.Wccp2.info -DEFAULT: none DEFAULT_IF_NONE: standard 0 IFDEF: USE_WCCPv2 DOC_START @@ -4794,7 +4784,6 @@ NAME: snmp_access TYPE: acl_access LOC: Config.accessList.snmp -DEFAULT: none DEFAULT_IF_NONE: deny all IFDEF: SQUID_SNMP DOC_START @@ -6067,7 +6056,6 @@ TYPE: acl_access IFDEF: ICAP_CLIENT LOC: Adaptation::Icap::TheConfig.repeat -DEFAULT: none DEFAULT_IF_NONE: deny all DOC_START This ACL determines which retriable ICAP transactions are @@ -6517,7 +6505,6 @@ TYPE: string LOC: Config.as_whois_server DEFAULT: whois.ra.net -DEFAULT_IF_NONE: whois.ra.net DOC_START WHOIS server to query for AS numbers. NOTE: AS numbers are queried only when Squid starts up, not for every request. diff -u -r -N squid-3.1.8/src/cf_gen.cc squid-3.1.9/src/cf_gen.cc --- squid-3.1.8/src/cf_gen.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/cf_gen.cc 2010-10-26 00:34:23.000000000 +1300 @@ -557,27 +557,25 @@ continue; } - if (entry->default_value == NULL) { + if (entry->default_value == NULL && entry->default_if_none == NULL) { fprintf(stderr, "NO DEFAULT FOR %s\n", entry->name); rc |= 1; continue; } - assert(entry->default_value); - - if (entry->ifdef) - fprintf(fp, "#if %s\n", entry->ifdef); - - if (strcmp(entry->default_value, "none") == 0) { + if (entry->default_value == NULL || strcmp(entry->default_value, "none") == 0) { fprintf(fp, "\t/* No default for %s */\n", entry->name); } else { + if (entry->ifdef) + fprintf(fp, "#if %s\n", entry->ifdef); + fprintf(fp, "\tdefault_line(\"%s %s\");\n", entry->name, entry->default_value); - } - if (entry->ifdef) - fprintf(fp, "#endif\n"); + if (entry->ifdef) + fprintf(fp, "#endif\n"); + } } fprintf(fp, "\tcfg_filename = NULL;\n"); diff -u -r -N squid-3.1.8/src/ChunkedCodingParser.cc squid-3.1.9/src/ChunkedCodingParser.cc --- squid-3.1.8/src/ChunkedCodingParser.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/ChunkedCodingParser.cc 2010-10-26 00:34:24.000000000 +1300 @@ -116,7 +116,7 @@ if (findCrlf(crlfBeg, crlfEnd)) { if (crlfBeg != 0) { - throw TexcHere("found data bewteen chunk end and CRLF"); + throw TexcHere("found data between chunk end and CRLF"); return; } diff -u -r -N squid-3.1.8/src/client_side.cc squid-3.1.9/src/client_side.cc --- squid-3.1.8/src/client_side.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/client_side.cc 2010-10-26 00:34:24.000000000 +1300 @@ -575,9 +575,9 @@ } delete checklist; - - accessLogFreeMemory(&al); } + + accessLogFreeMemory(&al); } void @@ -1075,7 +1075,7 @@ return 0; /* must use strong validator for sub-range requests */ } - return etagIsEqual(&rep_tag, &spec.tag); + return etagIsStrongEqual(rep_tag, spec.tag); } /* got modification time? */ @@ -1161,8 +1161,6 @@ debugs(33, 3, "clientBuildRangeHeader: range spec count: " << spec_count << " virgin clen: " << rep->content_length); assert(spec_count > 0); - /* ETags should not be returned with Partial Content replies? */ - hdr->delById(HDR_ETAG); /* append appropriate header(s) */ if (spec_count == 1) { @@ -1798,7 +1796,7 @@ int vhost = conn->port->vhost; int vport = conn->port->vport; char *host; - char ntoabuf[MAX_IPSTRLEN]; + char ipbuf[MAX_IPSTRLEN]; http->flags.accel = 1; @@ -1855,19 +1853,19 @@ /* Put the local socket IP address as the hostname. */ int url_sz = strlen(url) + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); + http->getConn()->me.ToHostname(ipbuf,MAX_IPSTRLEN); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), - http->getConn()->me.GetPort(), url); + ipbuf, http->getConn()->me.GetPort(), url); debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'"); } else if (vport > 0) { /* Put the local socket IP address as the hostname, but static port */ int url_sz = strlen(url) + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); + http->getConn()->me.ToHostname(ipbuf,MAX_IPSTRLEN); snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), - vport, url); + ipbuf, vport, url); debugs(33, 5, "ACCEL VPORT REWRITE: '" << http->uri << "'"); } } @@ -1876,7 +1874,7 @@ prepareTransparentURL(ConnStateData * conn, ClientHttpRequest *http, char *url, const char *req_hdr) { char *host; - char ntoabuf[MAX_IPSTRLEN]; + char ipbuf[MAX_IPSTRLEN]; if (*url != '/') return; /* already in good shape */ @@ -1894,10 +1892,10 @@ /* Put the local socket IP address as the hostname. */ int url_sz = strlen(url) + 32 + Config.appendDomainLen; http->uri = (char *)xcalloc(url_sz, 1); + http->getConn()->me.ToHostname(ipbuf,MAX_IPSTRLEN), snprintf(http->uri, url_sz, "%s://%s:%d%s", http->getConn()->port->protocol, - http->getConn()->me.NtoA(ntoabuf,MAX_IPSTRLEN), - http->getConn()->me.GetPort(), url); + ipbuf, http->getConn()->me.GetPort(), url); debugs(33, 5, "TRANSPARENT REWRITE: '" << http->uri << "'"); } } @@ -2413,6 +2411,7 @@ request->indirect_client_addr = conn->peer; #endif /* FOLLOW_X_FORWARDED_FOR */ request->my_addr = conn->me; + request->myportname = conn->port->name; request->http_ver = http_ver; tePresent = request->header.has(HDR_TRANSFER_ENCODING); diff -u -r -N squid-3.1.8/src/client_side_reply.cc squid-3.1.9/src/client_side_reply.cc --- squid-3.1.8/src/client_side_reply.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/client_side_reply.cc 2010-10-26 00:34:24.000000000 +1300 @@ -350,21 +350,18 @@ // request to origin was aborted if (EBIT_TEST(http->storeEntry()->flags, ENTRY_ABORTED)) { debugs(88, 3, "handleIMSReply: request to origin aborted '" << http->storeEntry()->url() << "', sending old entry to client" ); - http->logType = LOG_TCP_REFRESH_FAIL; + http->logType = LOG_TCP_REFRESH_FAIL_OLD; sendClientOldEntry(); } HttpReply *old_rep = (HttpReply *) old_entry->getReply(); // origin replied 304 - // TODO FIXME: old_rep2 was forcibly unshadowed, used to be old_rep. Are we sure - // that the right semantics were preserved? if (status == HTTP_NOT_MODIFIED) { http->logType = LOG_TCP_REFRESH_UNMODIFIED; // update headers on existing entry - HttpReply *old_rep2 = (HttpReply *) old_entry->getReply(); - old_rep2->updateOnNotModified(http->storeEntry()->getReply()); + old_rep->updateOnNotModified(http->storeEntry()->getReply()); old_entry->timestampsSet(); // if client sent IMS @@ -376,7 +373,7 @@ } else { // send existing entry, it's still valid debugs(88, 3, "handleIMSReply: origin replied 304, revalidating existing entry and sending " << - old_rep2->sline.status << " to client"); + old_rep->sline.status << " to client"); sendClientOldEntry(); } } @@ -390,9 +387,14 @@ } // origin replied with an error - else { + else if (http->request->flags.fail_on_validation_err) { + http->logType = LOG_TCP_REFRESH_FAIL_ERR; + debugs(88, 3, "handleIMSReply: origin replied with error " << status << + ", forwarding to client due to fail_on_validation_err"); + sendClientUpstreamResponse(); + } else { // ignore and let client have old entry - http->logType = LOG_TCP_REFRESH_FAIL; + http->logType = LOG_TCP_REFRESH_FAIL_OLD; debugs(88, 3, "handleIMSReply: origin replied with error " << status << ", sending old entry (" << old_rep->sline.status << ") to client"); sendClientOldEntry(); @@ -514,7 +516,7 @@ ) { http->logType = LOG_TCP_NEGATIVE_HIT; sendMoreData(result); - } else if (!Config.onoff.offline && refreshCheckHTTP(e, r) && !http->flags.internal) { + } else if (!http->flags.internal && refreshCheckHTTP(e, r)) { debugs(88, 5, "clientCacheHit: in refreshCheck() block"); /* * We hold a stale copy; it needs to be validated @@ -1298,6 +1300,13 @@ } } + // add Warnings required by RFC 2616 if serving a stale hit + if (http->request->flags.stale_if_hit && logTypeIsATcpHit(http->logType)) { + hdr->putWarning(110, "Response is stale"); + if (http->request->flags.need_validation) + hdr->putWarning(111, "Revalidation failed"); + } + /* Filter unproxyable authentication types */ if (http->logType != LOG_TCP_DENIED && diff -u -r -N squid-3.1.8/src/client_side_request.cc squid-3.1.9/src/client_side_request.cc --- squid-3.1.8/src/client_side_request.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/client_side_request.cc 2010-10-26 00:34:23.000000000 +1300 @@ -1009,11 +1009,18 @@ if ((t = strchr(result, ':')) != NULL) { http->redirect.status = status; http->redirect.location = xstrdup(t + 1); + // TODO: validate the URL produced here is RFC 2616 compliant absolute URI } else { - debugs(85, 1, "clientRedirectDone: bad input: " << result); + if (old_request->http_ver < HttpVersion(1,1)) + debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 302 redirect Location: " << result); + else + debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid 303 redirect Location: " << result); } - } else if (strcmp(result, http->uri)) - new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method); + } else if (strcmp(result, http->uri)) { + if (!(new_request = HttpRequest::CreateFromUrlAndMethod(result, old_request->method))) + debugs(85, DBG_CRITICAL, "ERROR: URL-rewrite produces invalid request: " << + old_request->method << " " << result << " HTTP/1.1"); + } } if (new_request) { diff -u -r -N squid-3.1.8/src/comm_devpoll.cc squid-3.1.9/src/comm_devpoll.cc --- squid-3.1.8/src/comm_devpoll.cc 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.9/src/comm_devpoll.cc 2010-10-26 00:34:23.000000000 +1300 @@ -0,0 +1,476 @@ +/* + * $Id$ + * + * DEBUG: section 05 Socket Functions + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +/* + * This is a very simple driver for Solaris /dev/poll. + * + * The updates are batched, one trip through the comm loop. + * (like libevent.) We keep a pointer into the structs so we + * can zero out an entry in the poll list if its active. + * + * Ported by Peter Payne from Squid 2.7.STABLE9 comm_devpoll.c + * on August 11, 2010 at 3pm (GMT+0100 Europe/London). + * + * Last modified 2010-10-08 + */ + + +#include "squid.h" + +/* + * There are several poll types in Squid, ALL of which are compiled and linked + * in. Thus conditional compile-time flags are used to prevent the different + * modules from creating several versions of the same function simultaneously. + */ + +#if USE_DEVPOLL + +#include "CacheManager.h" +#include "Store.h" +#include "fde.h" +#include "SquidTime.h" + +#if HAVE_SYS_DEVPOLL_H +/* Solaris /dev/poll support, see "man -s 7D poll" */ +#include +#endif + +#define DEBUG_DEVPOLL 0 + +/* OPEN_MAX is defined in , presumably included by sys/devpoll.h */ +#define DEVPOLL_UPDATESIZE OPEN_MAX +#define DEVPOLL_QUERYSIZE OPEN_MAX + +/* TYPEDEFS */ +typedef short pollfd_events_t; /* type of pollfd.events from sys/poll.h */ + +/* STRUCTURES */ +/** \brief Current state */ +struct _devpoll_state { + pollfd_events_t state; /**< current known state of file handle */ +}; + +/** \brief Update list + * + * This structure contains an array of settings to send to the /dev/poll + * interface. Rather than send changes to /dev/poll one at a time they + * are pushed onto this array (updating cur to indicate how many of the + * pfds structure elements have been set) until it is full before it + * is written out the API. + */ +struct { + struct pollfd *pfds; /**< ptr to array of struct pollfd config elements */ + int cur; /**< index of last written element of array, or -1 if none */ + int size; /**< maximum number of elements in array */ +} devpoll_update; + + +/* STATIC VARIABLES */ +static int devpoll_fd; /**< handle to /dev/poll device */ +static int max_poll_time = 1000; /**< maximum milliseconds to spend in poll */ + +static struct _devpoll_state *devpoll_state; /**< array of socket states */ +static struct dvpoll do_poll; /**< data struct for storing poll results */ +static int dpoll_nfds; /**< maximum number of poll results */ + +/* PROTOTYPES */ +static void commDevPollRegisterWithCacheManager(void); + + +/* PRIVATE FUNCTIONS */ +/** \brief Write batched file descriptor event changes to poll device + * + * Writes out the static array of file descriptor event changes to the + * poll device. This is done only when necessary (i.e. just before + * the poll device is queried during the select call, and whenever + * the number of changes to store in the array exceeds the size of the + * array). + */ +static void +comm_flush_updates(void) +{ + int i; + if (devpoll_update.cur == -1) + return; /* array of changes to make is empty */ + + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << (devpoll_update.cur + 1) << " fds queued" + ); + + i = write( + devpoll_fd, /* open handle to /dev/poll */ + devpoll_update.pfds, /* pointer to array of struct pollfd */ + (devpoll_update.cur + 1) * sizeof(struct pollfd) /* bytes to process */ + ); + assert(i > 0); + assert(static_cast(i) == (sizeof(struct pollfd) * (devpoll_update.cur + 1))); + devpoll_update.cur = -1; /* reset size of array, no elements remain */ +} + +/** \brief Register change in desired polling state for file descriptor + * + * Prevents unnecessary calls to the /dev/poll API by queueing changes + * in the devpoll_update array. If the array fills up the comm_flush_updates + * function is called. + * + * @param fd file descriptor to register change with + * @param events events to register (usually POLLIN, POLLOUT, or POLLREMOVE) + */ +static void +comm_update_fd(int fd, int events) +{ + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "FD " << fd << ", events=" << events + ); + + /* Is the array already full and in need of flushing? */ + if (devpoll_update.cur != -1 && (devpoll_update.cur == devpoll_update.size)) + comm_flush_updates(); + + /* Push new event onto array */ + devpoll_update.cur++; + devpoll_update.pfds[devpoll_update.cur].fd = fd; + devpoll_update.pfds[devpoll_update.cur].events = events; + devpoll_update.pfds[devpoll_update.cur].revents = 0; +} + + +static void commIncomingStats(StoreEntry *sentry) +{ + StatCounters *f = &statCounter; + storeAppendPrintf(sentry, "Total number of devpoll loops: %ld\n", statCounter.select_loops); + storeAppendPrintf(sentry, "Histogram of returned filedescriptors\n"); + statHistDump(&f->select_fds_hist, sentry, statHistIntDumper); +} + + +static void +commDevPollRegisterWithCacheManager(void) +{ + CacheManager::GetInstance()-> + registerAction( + "comm_devpoll_incoming", + "comm_incoming() stats", + commIncomingStats, + 0, + 1 + ); +} + + +/* PUBLIC FUNCTIONS */ + +/** \brief Initialise /dev/poll support + * + * Allocates memory, opens /dev/poll device handle. + */ +void +comm_select_init(void) +{ + /* allocate memory first before attempting to open poll device */ + /* This tracks the FD devpoll offset+state */ + devpoll_state = (struct _devpoll_state *)xcalloc( + SQUID_MAXFD, sizeof(struct _devpoll_state) + ); + + /* And this is the stuff we use to read events */ + do_poll.dp_fds = (struct pollfd *)xcalloc( + DEVPOLL_QUERYSIZE, sizeof(struct pollfd) + ); + dpoll_nfds = DEVPOLL_QUERYSIZE; + + devpoll_update.pfds = (struct pollfd *)xcalloc( + DEVPOLL_UPDATESIZE, sizeof(struct pollfd) + ); + devpoll_update.cur = -1; + devpoll_update.size = DEVPOLL_UPDATESIZE; + + /* attempt to open /dev/poll device */ + devpoll_fd = open("/dev/poll", O_RDWR); + if (devpoll_fd < 0) + fatalf("comm_select_init: can't open /dev/poll: %s\n", xstrerror()); + + fd_open(devpoll_fd, FD_UNKNOWN, "devpoll ctl"); + + commDevPollRegisterWithCacheManager(); +} + +/** \brief Set polling state of file descriptor and callback functions + * + * Sets requested polling state for given file handle along with + * desired callback function in the event the request event triggers. + * + * Note that setting a polling state with a NULL callback function will + * clear the polling for that event on that file descriptor. + * + * @param fd file descriptor to change + * @param type may be COMM_SELECT_READ (input) or COMM_SELECT_WRITE (output) + * @param handler callback function, or NULL to stop type of polling + * @param client_data pointer to be provided to call back function + * @param timeout if non-zero then timeout relative to now + */ +void +commSetSelect(int fd, unsigned int type, PF * handler, + void *client_data, time_t timeout) +{ + assert(fd >= 0); + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "FD " << fd << ",type=" << type + << ",handler=" << handler << ",client_data=" << client_data + << ",timeout=" << timeout << ")" + ); + + /* POLLIN/POLLOUT are defined in */ + fde *F = &fd_table[fd]; + if (!F->flags.open) { + /* remove from poll set */ + comm_update_fd( fd, POLLREMOVE ); + devpoll_state[fd].state = 0; + return; + } + + pollfd_events_t state_old = devpoll_state[fd].state; + pollfd_events_t state_new = 0; /* new state (derive from old state) */ + + if ( type & COMM_SELECT_READ ) { + if ( handler != NULL ) { + /* we want to POLLIN */ + state_new |= POLLIN; + } else { + ; /* we want to clear POLLIN because handler is NULL */ + } + + F->read_handler = handler; + F->read_data = client_data; + } else if ( state_old & POLLIN ) { + /* we're not changing reading state so take from existing */ + state_new |= POLLIN; + } + + if ( type & COMM_SELECT_WRITE ) { + if ( handler != NULL ) { + /* we want to POLLOUT */ + state_new |= POLLOUT; + } else { + ; /* we want to clear POLLOUT because handler is NULL */ + } + + F->write_handler = handler; + F->write_data = client_data; + } else if ( state_old & POLLOUT ) { + /* we're not changing writing state so take from existing */ + state_new |= POLLOUT; + } + + if ( pollfd_events_t bits_changed = (state_old ^ state_new) ) { + /* something has changed, update /dev/poll of what to listen for */ + + /* did any bits clear? (in which case a poll remove is necessary) */ + if ( bits_changed & state_old ) { + comm_update_fd( fd, POLLREMOVE ); + /* existing state cleared, so update with all required events */ + if ( state_new ) + comm_update_fd( fd, state_new ); + } else { + /* only update with new required event */ + if ( pollfd_events_t newly_set_only = (bits_changed & state_new) ) + comm_update_fd( fd, newly_set_only ); + } + + devpoll_state[fd].state = state_new; + } + + if (timeout) + F->timeout = squid_curtime + timeout; +} + + +/** \brief Clear polling of file handle (both read and write) + * + * @param fd file descriptor to clear polling on + */ +void +commResetSelect(int fd) +{ + commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); +} + + +/** \brief Do poll and trigger callback functions as appropriate + * + * Check all connections for new connections and input data that is to be + * processed. Also check for connections with data queued and whether we can + * write it out. + * + * Called to do the new-style IO, courtesy of of squid (like most of this + * new IO code). This routine handles the stuff we've hidden in + * comm_setselect and fd_table[] and calls callbacks for IO ready + * events. + * + * @param msec milliseconds to poll for (limited by max_poll_time) + */ +comm_err_t +comm_select(int msec) +{ + int num, i; + fde *F; + PF *hdl; + + PROF_start(comm_check_incoming); + + if (msec > max_poll_time) + msec = max_poll_time; + + for (;;) { + do_poll.dp_timeout = msec; + do_poll.dp_nfds = dpoll_nfds; + + comm_flush_updates(); /* ensure latest changes are sent to /dev/poll */ + + num = ioctl(devpoll_fd, DP_POLL, &do_poll); + ++statCounter.select_loops; + + if (num >= 0) + break; /* no error, skip out of loop */ + + if (ignoreErrno(errno)) + break; /* error is one we may ignore, skip out of loop */ + + /* error during poll */ + getCurrentTime(); + PROF_stop(comm_check_incoming); + return COMM_ERROR; + } + + PROF_stop(comm_check_incoming); + getCurrentTime(); + + statHistCount(&statCounter.select_fds_hist, num); + + if (num == 0) + return COMM_TIMEOUT; /* no error */ + + PROF_start(comm_handle_ready_fd); + + for (i = 0; i < num; i++) { + int fd = (int)do_poll.dp_fds[i].fd; + F = &fd_table[fd]; + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "got FD " << fd + << ",events=" << std::hex << do_poll.dp_fds[i].revents + << ",monitoring=" << devpoll_state[fd].state + << ",F->read_handler=" << F->read_handler + << ",F->write_handler=" << F->write_handler + ); + + /* handle errors */ + if (do_poll.dp_fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "devpoll event error: fd " << fd + ); + continue; + } + + /* check if file descriptor has data to read */ + if (do_poll.dp_fds[i].revents & POLLIN || F->flags.read_pending) { + if ( (hdl = F->read_handler) != NULL ) { + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "Calling read handler on FD " << fd + ); + PROF_start(comm_read_handler); + F->flags.read_pending = 0; + F->read_handler = NULL; + hdl(fd, F->read_data); + PROF_stop(comm_read_handler); + statCounter.select_fds++; + } else { + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "no read handler for FD " << fd + ); + // remove interest since no handler exist for this event. + commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0); + } + } + + /* check if file descriptor is ready to write */ + if (do_poll.dp_fds[i].revents & POLLOUT) { + if ((hdl = F->write_handler) != NULL) { + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "Calling write handler on FD " << fd + ); + PROF_start(comm_write_handler); + F->write_handler = NULL; + hdl(fd, F->write_data); + PROF_stop(comm_write_handler); + statCounter.select_fds++; + } else { + debugs( + 5, + DEBUG_DEVPOLL ? 0 : 8, + HERE << "no write handler for FD " << fd + ); + // remove interest since no handler exist for this event. + commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0); + } + } + } + + PROF_stop(comm_handle_ready_fd); + return COMM_OK; +} + + +void +comm_quick_poll_required(void) +{ + max_poll_time = 10; +} + +#endif /* USE_DEVPOLL */ diff -u -r -N squid-3.1.8/src/dns_internal.cc squid-3.1.9/src/dns_internal.cc --- squid-3.1.8/src/dns_internal.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/dns_internal.cc 2010-10-26 00:34:25.000000000 +1300 @@ -43,7 +43,7 @@ #include "fde.h" #include "ip/tools.h" #include "MemBuf.h" - +#include "util.h" #include "wordlist.h" #if HAVE_ARPA_NAMESER_H @@ -258,6 +258,7 @@ assert(npc < npc_alloc); strcpy(searchpath[npc].domain, buf); + Tolower(searchpath[npc].domain); debugs(78, 3, "idnsAddPathComponent: Added domain #" << npc << ": " << searchpath[npc].domain); npc++; } @@ -1110,6 +1111,7 @@ safe_free(message->answer); message->answer = result; + message->ancount += q->initial_AAAA.count; n += q->initial_AAAA.count; q->initial_AAAA.count=0; } else if (q->initial_AAAA.count > 0 && n <= 0) { diff -u -r -N squid-3.1.8/src/dnsserver.cc squid-3.1.9/src/dnsserver.cc --- squid-3.1.8/src/dnsserver.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/dnsserver.cc 2010-10-26 00:34:23.000000000 +1300 @@ -214,8 +214,10 @@ hints.ai_flags = AI_CANONNAME; for (;;) { - xfreeaddrinfo(AI); - AI = NULL; + if (AI != NULL) { + xfreeaddrinfo(AI); + AI = NULL; + } if ( 0 == (res = xgetaddrinfo(buf,NULL,&hints,&AI)) ) break; diff -u -r -N squid-3.1.8/src/enums.h squid-3.1.9/src/enums.h --- squid-3.1.8/src/enums.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/enums.h 2010-10-26 00:34:24.000000000 +1300 @@ -41,7 +41,8 @@ LOG_TCP_HIT, LOG_TCP_MISS, LOG_TCP_REFRESH_UNMODIFIED, // refresh from origin revalidated existing entry - LOG_TCP_REFRESH_FAIL, // refresh from origin failed + 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_CLIENT_REFRESH_MISS, LOG_TCP_IMS_HIT, @@ -143,6 +144,7 @@ CC_MAX_AGE, CC_S_MAXAGE, CC_MAX_STALE, + CC_MIN_FRESH, CC_ONLY_IF_CACHED, CC_OTHER, CC_ENUM_END diff -u -r -N squid-3.1.8/src/errorpage.cc squid-3.1.9/src/errorpage.cc --- squid-3.1.8/src/errorpage.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/errorpage.cc 2010-10-26 00:34:23.000000000 +1300 @@ -457,7 +457,9 @@ rep = err->BuildHttpReply(); - comm_write_mbuf(fd, rep->pack(), errorSendComplete, err); + MemBuf *mb = rep->pack(); + comm_write_mbuf(fd, mb, errorSendComplete, err); + delete mb; delete rep; } diff -u -r -N squid-3.1.8/src/esi/Expression.cc squid-3.1.9/src/esi/Expression.cc --- squid-3.1.8/src/esi/Expression.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/esi/Expression.cc 2010-10-26 00:34:24.000000000 +1300 @@ -707,6 +707,7 @@ rv.eval = NULL; /* A literal */ rv.valuetype = ESI_EXPR_INVALID; rv.valuestored = ESI_LITERAL_INVALID; + rv.precedence = 1; /* A literal */ if (('0' <= *s && *s <= '9') || *s == '-') { size_t length = strspn (s, "0123456789."); diff -u -r -N squid-3.1.8/src/ETag.cc squid-3.1.9/src/ETag.cc --- squid-3.1.8/src/ETag.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/ETag.cc 2010-10-26 00:34:25.000000000 +1300 @@ -40,6 +40,13 @@ * field-value that maybe used in many http fields. */ +/// whether etag strings match +static bool +etagStringsMatch(const ETag &tag1, const ETag &tag2) +{ + return !strcmp(tag1.str, tag2.str); +} + /* parses a string as weak or strong entity-tag; returns true on success */ /* note: we do not duplicate "str"! */ int @@ -62,11 +69,14 @@ return etag->str != NULL; } -/* returns true if etags are equal */ -int -etagIsEqual(const ETag * tag1, const ETag * tag2) +bool +etagIsStrongEqual(const ETag &tag1, const ETag &tag2) +{ + return !tag1.weak && !tag2.weak && etagStringsMatch(tag1, tag2); +} + +bool +etagIsWeakEqual(const ETag &tag1, const ETag &tag2) { - assert(tag1 && tag2); - assert(!tag1->weak && !tag2->weak); /* weak comparison not implemented yet */ - return !strcmp(tag1->str, tag2->str); + return etagStringsMatch(tag1, tag2); } diff -u -r -N squid-3.1.8/src/forward.cc squid-3.1.9/src/forward.cc --- squid-3.1.8/src/forward.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/forward.cc 2010-10-26 00:34:23.000000000 +1300 @@ -164,6 +164,8 @@ serversFree(&servers); + doneWithRetries(); + HTTPMSGUNLOCK(request); if (err) @@ -414,6 +416,12 @@ if (shutting_down) return false; + if (!self) { // we have aborted before the server called us back + debugs(17, 5, HERE << "not retrying because of earlier abort"); + // we will be destroyed when the server clears its Pointer to us + return false; + } + if (entry->store_status != STORE_PENDING) return false; @@ -497,12 +505,6 @@ void FwdState::retryOrBail() { - if (!self) { // we have aborted before the server called us back - debugs(17, 5, HERE << "not retrying because of earlier abort"); - // we will be destroyed when the server clears its Pointer to us - return; - } - if (checkRetry()) { int originserver = (servers->_peer == NULL); debugs(17, 3, "fwdServerClosed: re-forwarding (" << n_tries << " tries, " << (squid_curtime - start_t) << " secs)"); @@ -539,13 +541,26 @@ return; } - if (!err && shutting_down) { + // TODO: should we call completed() here and move doneWithRetries there? + doneWithRetries(); + + if (self != NULL && !err && shutting_down) { errorCon(ERR_SHUTTING_DOWN, HTTP_SERVICE_UNAVAILABLE, request); } self = NULL; // refcounted } +// If the Server quits before nibbling at the request body, the body sender +// will not know (so that we can retry). Call this if we will not retry. We +// will notify the sender so that it does not get stuck waiting for space. +void +FwdState::doneWithRetries() +{ + if (request && request->body_pipe != NULL) + request->body_pipe->expectNoConsumption(); +} + // called by the server that failed after calling unregister() void FwdState::handleUnregisteredServerEnd() @@ -581,7 +596,7 @@ debugs(81, 1, "fwdNegotiateSSL: Error negotiating SSL connection on FD " << fd << ": " << ERR_error_string(ERR_get_error(), NULL) << " (" << ssl_error << "/" << ret << "/" << errno << ")"); - ErrorState *anErr = errorCon(ERR_SECURE_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); + ErrorState *const anErr = makeConnectingError(ERR_SECURE_CONNECT_FAIL); #ifdef EPROTO anErr->xerrno = EPROTO; @@ -701,7 +716,7 @@ debugs(17, 4, "fwdConnectDone: Unknown host: " << request->GetHost()); - ErrorState *anErr = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE, request); + ErrorState *const anErr = makeConnectingError(ERR_DNS_FAIL); anErr->dnsError = dns.error; @@ -710,7 +725,7 @@ comm_close(server_fd); } else if (status != COMM_OK) { assert(fs); - ErrorState *anErr = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE, request); + ErrorState *const anErr = makeConnectingError(ERR_CONNECT_FAIL); anErr->xerrno = xerrno; fail(anErr); @@ -1153,6 +1168,19 @@ return reforwardableStatus(s); } +/** + * Create "503 Service Unavailable" or "504 Gateway Timeout" error depending + * on whether this is a validation request. RFC 2616 says that we MUST reply + * with "504 Gateway Timeout" if validation fails and cached reply has + * proxy-revalidate, must-revalidate or s-maxage Cache-Control directive. + */ +ErrorState * +FwdState::makeConnectingError(const err_type type) const +{ + return errorCon(type, request->flags.need_validation ? + HTTP_GATEWAY_TIMEOUT : HTTP_SERVICE_UNAVAILABLE, request); +} + static void fwdStats(StoreEntry * s) { diff -u -r -N squid-3.1.8/src/forward.h squid-3.1.9/src/forward.h --- squid-3.1.8/src/forward.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/forward.h 2010-10-26 00:34:25.000000000 +1300 @@ -63,8 +63,10 @@ static void logReplyStatus(int tries, http_status status); void updateHierarchyInfo(); + void doneWithRetries(); void completed(); void retryOrBail(); + ErrorState *makeConnectingError(const err_type type) const; static void RegisterWithCacheManager(void); #if WIP_FWD_LOG diff -u -r -N squid-3.1.8/src/fqdncache.cc squid-3.1.9/src/fqdncache.cc --- squid-3.1.8/src/fqdncache.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/fqdncache.cc 2010-10-26 00:34:23.000000000 +1300 @@ -858,6 +858,7 @@ while (hostnames) { fce->names[j] = xstrdup(hostnames->key); + Tolower(fce->names[j]); j++; hostnames = hostnames->next; diff -u -r -N squid-3.1.8/src/fs/ufs/ufscommon.cc squid-3.1.9/src/fs/ufs/ufscommon.cc --- squid-3.1.8/src/fs/ufs/ufscommon.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/fs/ufs/ufscommon.cc 2010-10-26 00:34:25.000000000 +1300 @@ -45,10 +45,14 @@ CBDATA_CLASS_INIT(RebuildState); - -class UFSSwapLogParser_old:public UFSSwapLogParser +/// Parse a swap header entry created on a system with 32-bit size_t and sfileno +/// this is typical of 32-bit systems without large file support +/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still. +class UFSSwapLogParser_v1_32bs:public UFSSwapLogParser { public: + /// version 1 cache swap.state entry with 32-bit size_t (swap_file_sz) + /// time_t an sfileno have no variation from the v1 baseline format struct StoreSwapLogDataOld { char op; sfileno swap_filen; @@ -56,41 +60,134 @@ time_t lastref; time_t expires; time_t lastmod; - size_t swap_file_sz; + uint32_t swap_file_sz; u_short refcount; u_short flags; unsigned char key[SQUID_MD5_DIGEST_LENGTH]; }; - UFSSwapLogParser_old(FILE *fp):UFSSwapLogParser(fp) { - record_size = sizeof(UFSSwapLogParser_old::StoreSwapLogDataOld); + UFSSwapLogParser_v1_32bs(FILE *fp):UFSSwapLogParser(fp) { + record_size = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld); } - bool ReadRecord(StoreSwapLogData &swapData); -}; + /// Convert the on-disk 32-bit format to our current format while reading + bool ReadRecord(StoreSwapLogData &swapData) { + UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld readData; + int bytes = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld); + + assert(log); + if (fread(&readData, bytes, 1, log) != 1) { + return false; + } + swapData.op = readData.op; + swapData.swap_filen = readData.swap_filen; + swapData.timestamp = readData.timestamp; + swapData.lastref = readData.lastref; + swapData.expires = readData.expires; + swapData.lastmod = readData.lastmod; + swapData.swap_file_sz = readData.swap_file_sz; + swapData.refcount = readData.refcount; + swapData.flags = readData.flags; + xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH); + return true; + } +}; -bool UFSSwapLogParser_old::ReadRecord(StoreSwapLogData &swapData) +/// Parse a swap header entry created on a system with 32-bit size_t, time_t and sfileno +/// this is typical of 32-bit systems without large file support and with old kernels +/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still. +class UFSSwapLogParser_v1_32bst:public UFSSwapLogParser { - UFSSwapLogParser_old::StoreSwapLogDataOld readData; - int bytes = sizeof(UFSSwapLogParser_old::StoreSwapLogDataOld); +public: + /// version 1 cache swap.state entry with 32-bit size_t (swap_file_sz) + /// time_t also differs + /// sfileno has no variation from the v1 baseline format + struct StoreSwapLogDataOld { + char op; + sfileno swap_filen; + int32_t timestamp; + int32_t lastref; + int32_t expires; + int32_t lastmod; + uint32_t swap_file_sz; + u_short refcount; + u_short flags; + unsigned char key[SQUID_MD5_DIGEST_LENGTH]; + }; + UFSSwapLogParser_v1_32bst(FILE *fp):UFSSwapLogParser(fp) { + record_size = sizeof(UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld); + } + /// Convert the on-disk 32-bit format to our current format while reading + bool ReadRecord(StoreSwapLogData &swapData) { + UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld readData; + int bytes = sizeof(UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld); - assert(log); + assert(log); - if (fread(&readData, bytes, 1, log) != 1) { - return false; + if (fread(&readData, bytes, 1, log) != 1) { + return false; + } + swapData.op = readData.op; + swapData.swap_filen = readData.swap_filen; + swapData.timestamp = readData.timestamp; + swapData.lastref = readData.lastref; + swapData.expires = readData.expires; + swapData.lastmod = readData.lastmod; + swapData.swap_file_sz = readData.swap_file_sz; + swapData.refcount = readData.refcount; + swapData.flags = readData.flags; + xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH); + return true; } - swapData.op = readData.op; - swapData.swap_filen = readData.swap_filen; - swapData.timestamp = readData.timestamp; - swapData.lastref = readData.lastref; - swapData.expires = readData.expires; - swapData.lastmod = readData.lastmod; - swapData.swap_file_sz = readData.swap_file_sz; - swapData.refcount = readData.refcount; - swapData.flags = readData.flags; - xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH); - return true; -} +}; +/// Parse a swap header entry created on a system with 64-bit size_t and sfileno +/// this is typical of 64-bit systems prior to this patch fixing sfileno to 32-bits +/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still. +class UFSSwapLogParser_v1_64bfn:public UFSSwapLogParser +{ +public: + /// version 1 cache swap.state entry with 64-bit sfileno + struct StoreSwapLogDataOld { + char op; + int64_t swap_filen; + time_t timestamp; + time_t lastref; + time_t expires; + time_t lastmod; + uint64_t swap_file_sz; + u_short refcount; + u_short flags; + unsigned char key[SQUID_MD5_DIGEST_LENGTH]; + }; + UFSSwapLogParser_v1_64bfn(FILE *fp):UFSSwapLogParser(fp) { + record_size = sizeof(UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld); + } + /// Convert the on-disk 64-bit format to our current format while reading + bool ReadRecord(StoreSwapLogData &swapData) { + UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld readData; + int bytes = sizeof(UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld); + + assert(log); + + if (fread(&readData, bytes, 1, log) != 1) { + return false; + } + swapData.op = readData.op; + if ((readData.swap_filen>>32) != 0) { + fatalf("File ID on record is greater than maximum cache file ID."); + } + swapData.swap_filen = (int32_t)readData.swap_filen; + swapData.timestamp = readData.timestamp; + swapData.lastref = readData.lastref; + swapData.expires = readData.expires; + swapData.lastmod = readData.lastmod; + swapData.swap_file_sz = readData.swap_file_sz; + swapData.refcount = readData.refcount; + swapData.flags = readData.flags; + xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH); + return true; + } +}; class UFSSwapLogParser_v1:public UFSSwapLogParser { @@ -125,29 +222,58 @@ return NULL; if (header.op != SWAP_LOG_VERSION) { - debugs(47, 1, "Old swap file detected... "); + debugs(47, 1, "Old swap file detected..."); fseek(fp, 0, SEEK_SET); - return new UFSSwapLogParser_old(fp); + return new UFSSwapLogParser_v1_32bs(fp); // Um. 32-bits except time_t, and can't determine that. } if (header.version == 1) { if (fseek(fp, header.record_size, SEEK_SET) != 0) return NULL; - if (header.record_size == sizeof(struct UFSSwapLogParser_old::StoreSwapLogDataOld)) { - debugs(47, 1, "Version 1 of swap file without LFS support detected... "); - return new UFSSwapLogParser_old(fp); - } - + // baseline + // 32-bit sfileno + // native time_t (hopefully 64-bit) + // 64-bit file size if (header.record_size == sizeof(StoreSwapLogData)) { debugs(47, 1, "Version 1 of swap file with LFS support detected... "); return new UFSSwapLogParser_v1(fp); } - debugs(47, 1, "The swap file has wrong format!... "); + // which means we have a 3-way grid of permutations to import (yuck!) + // 1) sfileno 32-bit / 64-bit (64-bit was broken) + // 2) time_t 32-bit / 64-bit + // 3) size_t 32-bit / 64-bit (32-bit was pre-LFS) + + // 32-bit systems... + // only LFS (size_t) differs from baseline + if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld)) { + debugs(47, 1, "Version 1 (32-bit) swap file without LFS support detected... "); + return new UFSSwapLogParser_v1_32bs(fp); + } + // LFS (size_t) and timestamps (time_t) differs from baseline + if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld)) { + debugs(47, 1, "Version 1 (32-bit) swap file with short timestamps and without LFS support detected... "); + return new UFSSwapLogParser_v1_32bst(fp); + } + // No downgrade for 64-bit timestamps to 32-bit. + + // 64-bit systems + // sfileno was 64-bit for a some builds + if (header.record_size == sizeof(struct UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld)) { + debugs(47, 1, "Version 1 (64-bit) swap file with broken sfileno detected... "); + return new UFSSwapLogParser_v1_64bfn(fp); + } + // NP: 64-bit system with 32-bit size_t/time_t are not handled. + + debugs(47, 1, "WARNING: The swap file has wrong format!... "); + debugs(47, 1, "NOTE: Cannot safely downgrade caches to short (32-bit) timestamps."); return NULL; } + // XXX: version 2 of swapfile. This time use fixed-bit sizes for everything!! + // and preferrably write to disk in network-order bytes for the larger fields. + return NULL; } diff -u -r -N squid-3.1.8/src/helper.cc squid-3.1.9/src/helper.cc --- squid-3.1.8/src/helper.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/helper.cc 2010-10-26 00:34:24.000000000 +1300 @@ -728,21 +728,6 @@ srv->writebuf = NULL; } - for (i = 0; i < concurrency; i++) { - if ((r = srv->requests[i])) { - void *cbdata; - - if (cbdataReferenceValidDone(r->data, &cbdata)) - r->callback(cbdata, NULL); - - helperRequestFree(r); - - srv->requests[i] = NULL; - } - } - - safe_free(srv->requests); - if (srv->wfd != srv->rfd && srv->wfd != -1) comm_close(srv->wfd); @@ -770,6 +755,20 @@ } } + for (i = 0; i < concurrency; i++) { + if ((r = srv->requests[i])) { + void *cbdata; + + if (cbdataReferenceValidDone(r->data, &cbdata)) + r->callback(cbdata, NULL); + + helperRequestFree(r); + + srv->requests[i] = NULL; + } + } + safe_free(srv->requests); + cbdataReferenceDone(srv->parent); cbdataFree(srv); } @@ -793,17 +792,6 @@ #endif - if ((r = srv->request)) { - void *cbdata; - - if (cbdataReferenceValidDone(r->data, &cbdata)) - r->callback(cbdata, srv, NULL); - - helperStatefulRequestFree(r); - - srv->request = NULL; - } - /* TODO: walk the local queue of requests and carry them all out */ if (srv->wfd != srv->rfd && srv->wfd != -1) comm_close(srv->wfd); @@ -831,6 +819,17 @@ } } + if ((r = srv->request)) { + void *cbdata; + + if (cbdataReferenceValidDone(r->data, &cbdata)) + r->callback(cbdata, srv, NULL); + + helperStatefulRequestFree(r); + + srv->request = NULL; + } + if (srv->data != NULL) hlp->datapool->free(srv->data); diff -u -r -N squid-3.1.8/src/http.cc squid-3.1.9/src/http.cc --- squid-3.1.8/src/http.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/http.cc 2010-10-26 00:34:24.000000000 +1300 @@ -372,6 +372,12 @@ if (surrogateNoStore) return 0; + // RFC 2616: do not cache replies to responses with no-store CC directive + if (request && request->cache_control && + EBIT_TEST(request->cache_control->mask, CC_NO_STORE) && + !REFRESH_OVERRIDE(ignore_no_store)) + return 0; + if (!ignoreCacheControl) { if (EBIT_TEST(cc_mask, CC_PRIVATE)) { if (!REFRESH_OVERRIDE(ignore_private)) @@ -681,6 +687,7 @@ tmprep->header.putExt("X-Transformed-From", "HTTP/0.9"); mb = tmprep->pack(); newrep->parse(mb, eof, &error); + delete mb; delete tmprep; } else { if (!parsed && error > 0) { // unrecoverable parsing error @@ -708,6 +715,8 @@ readBuf->consume(header_bytes_read); } + newrep->removeStaleWarnings(); + /* Skip 1xx messages for now. Advertised in Via as an internal 1.0 hop */ if (newrep->sline.protocol == PROTO_HTTP && newrep->sline.status >= 100 && newrep->sline.status < 200) { @@ -896,9 +905,9 @@ no_cache: if (!ignoreCacheControl && rep->cache_control) { - if (EBIT_TEST(rep->cache_control->mask, CC_PROXY_REVALIDATE)) - EBIT_SET(entry->flags, ENTRY_REVALIDATE); - else if (EBIT_TEST(rep->cache_control->mask, CC_MUST_REVALIDATE)) + if (EBIT_TEST(rep->cache_control->mask, CC_PROXY_REVALIDATE) || + EBIT_TEST(rep->cache_control->mask, CC_MUST_REVALIDATE) || + EBIT_TEST(rep->cache_control->mask, CC_S_MAXAGE)) EBIT_SET(entry->flags, ENTRY_REVALIDATE); } @@ -1490,7 +1499,7 @@ HttpRequest * orig_request, StoreEntry * entry, HttpHeader * hdr_out, - http_state_flags flags) + const http_state_flags flags) { /* building buffer for complex strings */ #define BBUF_SZ (MAX_URL+32) @@ -1930,8 +1939,7 @@ HttpStateData::buildRequestPrefix(HttpRequest * aRequest, HttpRequest * original_request, StoreEntry * sentry, - MemBuf * mb, - http_state_flags stateFlags) + MemBuf * mb) { const int offset = mb->size; HttpVersion httpver(1,1); @@ -1943,7 +1951,7 @@ { HttpHeader hdr(hoRequest); Packer p; - httpBuildRequestHeader(aRequest, original_request, sentry, &hdr, stateFlags); + httpBuildRequestHeader(aRequest, original_request, sentry, &hdr, flags); if (aRequest->flags.pinned && aRequest->flags.connection_auth) aRequest->flags.auth_sent = 1; @@ -2031,7 +2039,7 @@ } mb.init(); - buildRequestPrefix(request, orig_request, entry, &mb, flags); + buildRequestPrefix(request, orig_request, entry, &mb); debugs(11, 6, "httpSendRequest: FD " << fd << ":\n" << mb.buf); comm_write_mbuf(fd, &mb, requestSender); diff -u -r -N squid-3.1.8/src/http.h squid-3.1.9/src/http.h --- squid-3.1.8/src/http.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/http.h 2010-10-26 00:34:26.000000000 +1300 @@ -51,7 +51,7 @@ HttpRequest * orig_request, StoreEntry * entry, HttpHeader * hdr_out, - http_state_flags flags); + const http_state_flags flags); virtual int dataDescriptor() const; /* should be private */ @@ -117,8 +117,7 @@ mb_size_t buildRequestPrefix(HttpRequest * request, HttpRequest * orig_request, StoreEntry * entry, - MemBuf * mb, - http_state_flags flags); + MemBuf * mb); static bool decideIfWeDoRanges (HttpRequest * orig_request); bool peerSupportsConnectionPinning() const; diff -u -r -N squid-3.1.8/src/HttpHdrCc.cc squid-3.1.9/src/HttpHdrCc.cc --- squid-3.1.8/src/HttpHdrCc.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpHdrCc.cc 2010-10-26 00:34:25.000000000 +1300 @@ -51,6 +51,7 @@ {"max-age", (http_hdr_type)CC_MAX_AGE}, {"s-maxage", (http_hdr_type)CC_S_MAXAGE}, {"max-stale", (http_hdr_type)CC_MAX_STALE}, + {"min-fresh", (http_hdr_type)CC_MIN_FRESH}, {"Other,", (http_hdr_type)CC_OTHER} /* ',' will protect from matches */ }; @@ -89,7 +90,7 @@ httpHdrCcCreate(void) { HttpHdrCc *cc = (HttpHdrCc *)memAllocate(MEM_HTTP_HDR_CC); - cc->max_age = cc->s_maxage = cc->max_stale = -1; + cc->max_age = cc->s_maxage = cc->max_stale = cc->min_fresh = -1; return cc; } @@ -181,6 +182,16 @@ break; + case CC_MIN_FRESH: + + if (!p || !httpHeaderParseInt(p, &cc->min_fresh)) { + debugs(65, 2, "cc: invalid min-fresh specs near '" << item << "'"); + cc->min_fresh = -1; + EBIT_CLR(cc->mask, type); + } + + break; + case CC_OTHER: if (cc->other.size()) @@ -220,6 +231,7 @@ dup->max_age = cc->max_age; dup->s_maxage = cc->s_maxage; dup->max_stale = cc->max_stale; + dup->min_fresh = cc->min_fresh; return dup; } @@ -248,6 +260,9 @@ if (flag == CC_MAX_STALE && cc->max_stale >= 0) packerPrintf(p, "=%d", (int) cc->max_stale); + if (flag == CC_MIN_FRESH) + packerPrintf(p, "=%d", (int) cc->min_fresh); + pcount++; } } diff -u -r -N squid-3.1.8/src/HttpHeader.cc squid-3.1.9/src/HttpHeader.cc --- squid-3.1.8/src/HttpHeader.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpHeader.cc 2010-10-26 00:34:24.000000000 +1300 @@ -184,7 +184,7 @@ HDR_UPGRADE, HDR_VARY, HDR_VIA, - /* HDR_WARNING, */ + HDR_WARNING, HDR_WWW_AUTHENTICATE, HDR_AUTHENTICATION_INFO, HDR_PROXY_AUTHENTICATION_INFO, @@ -1188,6 +1188,14 @@ mb.clean(); } +void +HttpHeader::putWarning(const int code, const char *const text) +{ + char buf[512]; + snprintf(buf, sizeof(buf), "%i %s \"%s\"", code, visible_appname_string, text); + putStr(HDR_WARNING, buf); +} + /* add extension header (these fields are not parsed/analyzed/joined, etc.) */ void HttpHeader::putExt(const char *name, const char *value) diff -u -r -N squid-3.1.8/src/HttpHeader.h squid-3.1.9/src/HttpHeader.h --- squid-3.1.8/src/HttpHeader.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpHeader.h 2010-10-26 00:34:24.000000000 +1300 @@ -239,6 +239,7 @@ void putContRange(const HttpHdrContRange * cr); void putRange(const HttpHdrRange * range); void putSc(HttpHdrSc *sc); + void putWarning(const int code, const char *const text); ///< add a Warning header void putExt(const char *name, const char *value); int getInt(http_hdr_type id) const; int64_t getInt64(http_hdr_type id) const; diff -u -r -N squid-3.1.8/src/HttpMsg.h squid-3.1.9/src/HttpMsg.h --- squid-3.1.8/src/HttpMsg.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpMsg.h 2010-10-26 00:34:23.000000000 +1300 @@ -42,10 +42,16 @@ // common parts of HttpRequest and HttpReply +template +class HttpMsgPointerT; + + class HttpMsg { public: + typedef HttpMsgPointerT Pointer; + HttpMsg(http_hdr_owner_type owner); virtual ~HttpMsg(); @@ -186,6 +192,17 @@ HttpMsgPointerT(const HttpMsgPointerT &p): msg(p.msg) { lock(); } HttpMsgPointerT &operator =(const HttpMsgPointerT &p) { if (msg != p.msg) { unlock(); msg = p.msg; lock(); } return *this; } + HttpMsgPointerT &operator =(Msg *newM) + { if (msg != newM) { unlock(); msg = newM; lock(); } return *this; } + + /// support converting a child msg pointer into a parent msg pointer + template + HttpMsgPointerT(const HttpMsgPointerT &o): msg(o.raw()) { lock(); } + + /// support assigning a child msg pointer to a parent msg pointer + template + HttpMsgPointerT &operator =(const HttpMsgPointerT &o) + { if (msg != o.raw()) { unlock(); msg = o.raw(); lock(); } return *this; } Msg &operator *() { return *msg; } const Msg &operator *() const { return *msg; } @@ -195,6 +212,9 @@ operator const Msg *() const { return msg; } // add more as needed + /// public access for HttpMsgPointerT copying and assignment; avoid + Msg *raw() const { return msg; } + protected: void lock() { if (msg) HTTPMSGLOCK(msg); } ///< prevent msg destruction void unlock() { HTTPMSGUNLOCK(msg); } ///< allows/causes msg destruction diff -u -r -N squid-3.1.8/src/HttpReply.cc squid-3.1.9/src/HttpReply.cc --- squid-3.1.8/src/HttpReply.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpReply.cc 2010-10-26 00:34:24.000000000 +1300 @@ -629,3 +629,67 @@ keep_alive = aRep->keep_alive; return true; } + +void HttpReply::removeStaleWarnings() +{ + String warning; + if (header.getList(HDR_WARNING, &warning)) { + const String newWarning = removeStaleWarningValues(warning); + if (warning.size() && warning.size() == newWarning.size()) + return; // some warnings are there and none changed + header.delById(HDR_WARNING); + if (newWarning.size()) { // some warnings left + HttpHeaderEntry *const e = + new HttpHeaderEntry(HDR_WARNING, NULL, newWarning.termedBuf()); + header.addEntry(e); + } + } +} + +/** + * Remove warning-values with warn-date different from Date value from + * a single header entry. Returns a string with all valid warning-values. + */ +String HttpReply::removeStaleWarningValues(const String &value) +{ + String newValue; + const char *item = 0; + int len = 0; + const char *pos = 0; + while (strListGetItem(&value, ',', &item, &len, &pos)) { + bool keep = true; + // Does warning-value have warn-date (which contains quoted date)? + // We scan backwards, looking for two quoted strings. + // warning-value = warn-code SP warn-agent SP warn-text [SP warn-date] + const char *p = item + len - 1; + + while (p >= item && xisspace(*p)) --p; // skip whitespace + + // warning-value MUST end with quote + if (p >= item && *p == '"') { + const char *const warnDateEnd = p; + --p; + while (p >= item && *p != '"') --p; // find the next quote + + const char *warnDateBeg = p + 1; + --p; + while (p >= item && xisspace(*p)) --p; // skip whitespace + + if (p >= item && *p == '"' && warnDateBeg - p > 2) { + // found warn-text + String warnDate; + warnDate.append(warnDateBeg, warnDateEnd - warnDateBeg); + const time_t time = parse_rfc1123(warnDate.termedBuf()); + keep = (time > 0 && time == date); // keep valid and matching date + } + } + + if (keep) { + if (newValue.size()) + newValue.append(", "); + newValue.append(item, len); + } + } + + return newValue; +} diff -u -r -N squid-3.1.8/src/HttpReply.h squid-3.1.9/src/HttpReply.h --- squid-3.1.8/src/HttpReply.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpReply.h 2010-10-26 00:34:24.000000000 +1300 @@ -52,6 +52,8 @@ { public: + typedef HttpMsgPointerT Pointer; + MEMPROXY_CLASS(HttpReply); HttpReply(); ~HttpReply(); @@ -138,6 +140,9 @@ */ HttpReply *clone() const; + /// Remove Warnings with warn-date different from Date value + void removeStaleWarnings(); + private: /** initialize */ void init(); @@ -160,6 +165,8 @@ */ void calcMaxBodySize(HttpRequest& request); + String removeStaleWarningValues(const String &value); + mutable int64_t bodySizeMax; /**< cached result of calcMaxBodySize */ protected: diff -u -r -N squid-3.1.8/src/HttpRequest.cc squid-3.1.9/src/HttpRequest.cc --- squid-3.1.8/src/HttpRequest.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpRequest.cc 2010-10-26 00:34:25.000000000 +1300 @@ -51,6 +51,8 @@ HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, protocol_t aProtocol, const char *aUrlpath) : HttpMsg(hoRequest) { + static unsigned int id = 1; + debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id); init(); initHTTP(aMethod, aProtocol, aUrlpath); } @@ -58,6 +60,7 @@ HttpRequest::~HttpRequest() { clean(); + debugs(93,7, HERE << "destructed, this=" << this); } void @@ -96,6 +99,7 @@ peer_login = NULL; // not allocated/deallocated by this class peer_domain = NULL; // not allocated/deallocated by this class vary_headers = NULL; + myportname = null_string; tag = null_string; extacl_user = null_string; extacl_passwd = null_string; @@ -143,6 +147,8 @@ if (pinned_connection) cbdataReferenceDone(pinned_connection); + myportname.clean(); + tag.clean(); extacl_user.clean(); @@ -202,6 +208,7 @@ copy->vary_headers = vary_headers ? xstrdup(vary_headers) : NULL; // XXX: what to do with copy->peer_domain? + copy->myportname = myportname; copy->tag = tag; copy->extacl_user = extacl_user; copy->extacl_passwd = extacl_passwd; diff -u -r -N squid-3.1.8/src/HttpRequest.h squid-3.1.9/src/HttpRequest.h --- squid-3.1.8/src/HttpRequest.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/HttpRequest.h 2010-10-26 00:34:23.000000000 +1300 @@ -65,6 +65,8 @@ { public: + typedef HttpMsgPointerT Pointer; + MEMPROXY_CLASS(HttpRequest); HttpRequest(); HttpRequest(const HttpRequestMethod& aMethod, protocol_t aProtocol, const char *aUrlpath); @@ -185,6 +187,8 @@ char *peer_domain; /* Configured peer forceddomain */ + String myportname; // Internal tag name= value from port this requests arrived in. + String tag; /* Internal tag for this request */ String extacl_user; /* User name returned by extacl lookup */ diff -u -r -N squid-3.1.8/src/icmp/net_db.cc squid-3.1.9/src/icmp/net_db.cc --- squid-3.1.8/src/icmp/net_db.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/icmp/net_db.cc 2010-10-26 00:34:25.000000000 +1300 @@ -251,6 +251,7 @@ char *key = new char[MAX_IPSTRLEN]; networkFromInaddr(addr).NtoA(key,MAX_IPSTRLEN); n = (netdbEntry *) hash_lookup(addr_table, key); + delete[] key; return n; } diff -u -r -N squid-3.1.8/src/ip/IpAddress.h squid-3.1.9/src/ip/IpAddress.h --- squid-3.1.8/src/ip/IpAddress.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/ip/IpAddress.h 2010-10-26 00:34:24.000000000 +1300 @@ -256,7 +256,7 @@ * eg. 127.0.0.1 (IPv4) or [::1] (IPv6) \param buf Allocated buffer to write address to \param len byte length of buffer available for writing. - \return pointer to buffer received. + \return amount of buffer filled. */ unsigned int ToHostname(char *buf, const unsigned int len) const; diff -u -r -N squid-3.1.8/src/ipcache.cc squid-3.1.9/src/ipcache.cc --- squid-3.1.8/src/ipcache.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/ipcache.cc 2010-10-26 00:34:24.000000000 +1300 @@ -295,6 +295,7 @@ static ipcache_entry *i; i = (ipcache_entry *)memAllocate(MEM_IPCACHE_ENTRY); i->hash.key = xstrdup(name); + Tolower(static_cast(i->hash.key)); i->expires = squid_curtime + Config.negativeDnsTtl; return i; } diff -u -r -N squid-3.1.8/src/Makefile.am squid-3.1.9/src/Makefile.am --- squid-3.1.8/src/Makefile.am 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/Makefile.am 2010-10-26 00:34:23.000000000 +1300 @@ -258,6 +258,7 @@ comm_select_win32.cc \ comm_poll.cc \ comm_poll.h \ + comm_devpoll.cc \ comm_epoll.cc \ comm_epoll.h \ comm_kqueue.cc \ @@ -805,6 +806,7 @@ echo "$(INSTALL_DATA) squid.conf.documented $(DESTDIR)$(DEFAULT_CONFIG_FILE).documented"; \ $(INSTALL_DATA) squid.conf.documented $(DESTDIR)$(DEFAULT_CONFIG_FILE).documented; \ $(mkinstalldirs) $(DESTDIR)$(DEFAULT_LOG_PREFIX); \ + $(mkinstalldirs) $(DESTDIR)$(DEFAULT_SWAP_DIR); \ $(mkinstalldirs) $(DESTDIR)`dirname $(DEFAULT_PIDFILE)` uninstall-local: squid.conf.default diff -u -r -N squid-3.1.8/src/Makefile.in squid-3.1.9/src/Makefile.in --- squid-3.1.8/src/Makefile.in 2010-09-04 15:26:26.000000000 +1200 +++ squid-3.1.9/src/Makefile.in 2010-10-26 00:35:02.000000000 +1300 @@ -174,17 +174,18 @@ ClientRequestContext.h clientStream.cc clientStream.h CommIO.h \ CompletionDispatcher.cc CompletionDispatcher.h comm_select.cc \ comm_select.h comm_select_win32.cc comm_poll.cc comm_poll.h \ - comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ - CommRead.h ConfigOption.cc ConfigParser.cc ConfigParser.h \ - ConnectionDetail.h debug.cc Debug.h defines.h CommonPool.h \ - CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ - DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ - DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ - DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ - DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ - NullDelayId.cc NullDelayId.h disk.cc DiskIO/DiskIOModule.cc \ - DiskIO/ReadRequest.cc DiskIO/ReadRequest.h \ - DiskIO/WriteRequest.cc DiskIO/WriteRequest.h DiskIO/DiskFile.h \ + comm_devpoll.cc comm_epoll.cc comm_epoll.h comm_kqueue.cc \ + comm_kqueue.h CommRead.h ConfigOption.cc ConfigParser.cc \ + ConfigParser.h ConnectionDetail.h debug.cc Debug.h defines.h \ + CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \ + DelayId.h DelayIdComposite.h DelayBucket.cc DelayBucket.h \ + DelayConfig.cc DelayConfig.h DelayPool.cc DelayPool.h \ + DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \ + DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \ + DelayVector.h NullDelayId.cc NullDelayId.h disk.cc \ + DiskIO/DiskIOModule.cc DiskIO/ReadRequest.cc \ + DiskIO/ReadRequest.h DiskIO/WriteRequest.cc \ + DiskIO/WriteRequest.h DiskIO/DiskFile.h \ DiskIO/DiskIOStrategy.h DiskIO/IORequestor.h \ DiskIO/DiskIOModule.h dlink.h dlink.cc dns_internal.cc \ DnsLookupDetails.h DnsLookupDetails.cc dns.cc enums.h \ @@ -230,7 +231,8 @@ LoadableModule.cc LoadableModules.h LoadableModules.cc am__objects_4 = AclRegs.$(OBJEXT) AuthReg.$(OBJEXT) am__objects_5 = comm_select.$(OBJEXT) comm_select_win32.$(OBJEXT) \ - comm_poll.$(OBJEXT) comm_epoll.$(OBJEXT) comm_kqueue.$(OBJEXT) + comm_poll.$(OBJEXT) comm_devpoll.$(OBJEXT) \ + comm_epoll.$(OBJEXT) comm_kqueue.$(OBJEXT) am__objects_6 = delay_pools.$(OBJEXT) DelayId.$(OBJEXT) \ DelayBucket.$(OBJEXT) DelayConfig.$(OBJEXT) \ DelayPool.$(OBJEXT) DelaySpec.$(OBJEXT) DelayTagged.$(OBJEXT) \ @@ -397,33 +399,33 @@ client_db.cc client_side.cc client_side_reply.cc \ client_side_request.cc ClientInfo.h clientStream.cc \ comm_select.cc comm_select.h comm_select_win32.cc comm_poll.cc \ - comm_poll.h comm_epoll.cc comm_epoll.h comm_kqueue.cc \ - comm_kqueue.h ConfigOption.cc ConfigParser.cc CommonPool.h \ - CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ - DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ - DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ - DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ - DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ - NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ - dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ - errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ - fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ - htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ - HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ - HttpReply.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc \ - ipc_win32.cc ipcache.cc int.cc internal.cc list.cc logfile.cc \ - multicast.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ - mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ - peer_digest.cc peer_select.cc peer_sourcehash.cc \ - peer_userhash.cc redirect.cc referer.cc refresh.cc \ - RemovalPolicy.cc Server.cc snmp_core.cc snmp_agent.cc \ - ssl_support.cc ssl_support.h SquidMath.h SquidMath.cc stat.cc \ - StatHist.cc stmem.cc store.cc store_client.cc store_digest.cc \ - store_dir.cc store_io.cc store_key_md5.cc store_log.cc \ - store_rebuild.cc store_swapin.cc store_swapmeta.cc \ - store_swapout.cc StoreFileSystem.cc StoreIOState.cc \ - StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + comm_poll.h comm_devpoll.cc comm_epoll.cc comm_epoll.h \ + comm_kqueue.cc comm_kqueue.h ConfigOption.cc ConfigParser.cc \ + CommonPool.h CompositePoolNode.h delay_pools.cc DelayId.cc \ + DelayId.h DelayIdComposite.h DelayBucket.cc DelayBucket.h \ + DelayConfig.cc DelayConfig.h DelayPool.cc DelayPool.h \ + DelayPools.h DelaySpec.cc DelaySpec.h DelayTagged.cc \ + DelayTagged.h DelayUser.cc DelayUser.h DelayVector.cc \ + DelayVector.h NullDelayId.cc NullDelayId.h disk.cc dlink.h \ + dlink.cc dns_internal.cc DnsLookupDetails.h \ + DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ + external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ + fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ + HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ + icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ + internal.cc list.cc logfile.cc multicast.cc mem_node.cc \ + MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ + Packer.cc Parsing.cc pconn.cc peer_digest.cc peer_select.cc \ + peer_sourcehash.cc peer_userhash.cc redirect.cc referer.cc \ + refresh.cc RemovalPolicy.cc Server.cc snmp_core.cc \ + snmp_agent.cc ssl_support.cc ssl_support.h SquidMath.h \ + SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ + store_client.cc store_digest.cc store_dir.cc store_io.cc \ + store_key_md5.cc store_log.cc store_rebuild.cc store_swapin.cc \ + store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ tunnel.cc SwapDir.cc url.cc URLScheme.cc urn.cc useragent.cc \ @@ -621,37 +623,37 @@ ChunkedCodingParser.cc client_db.cc client_side.cc \ client_side_reply.cc client_side_request.cc ClientInfo.h \ clientStream.cc comm_select.cc comm_select.h \ - comm_select_win32.cc comm_poll.cc comm_poll.h comm_epoll.cc \ - comm_epoll.h comm_kqueue.cc comm_kqueue.h ConfigOption.cc \ - ConfigParser.cc CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - disk.cc dlink.h dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ - HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ - icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ - internal.cc list.cc logfile.cc multicast.cc mem_node.cc \ - MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ - Packer.cc Parsing.cc pconn.cc peer_digest.cc peer_select.cc \ - peer_sourcehash.cc peer_userhash.cc redirect.cc referer.cc \ - refresh.cc Server.cc snmp_core.cc snmp_agent.cc ssl_support.cc \ - ssl_support.h SquidMath.h SquidMath.cc stat.cc StatHist.cc \ - stmem.cc store.cc store_client.cc store_digest.cc store_dir.cc \ - store_io.cc store_key_md5.cc store_log.cc store_rebuild.cc \ - store_swapin.cc store_swapmeta.cc store_swapout.cc \ - StoreFileSystem.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreSwapLogData.cc event.cc tools.cc tunnel.cc SwapDir.cc \ - url.cc URLScheme.cc urn.cc useragent.cc wccp2.cc whois.cc \ - win32.cc wordlist.cc + comm_select_win32.cc comm_poll.cc comm_poll.h comm_devpoll.cc \ + comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ + ConfigOption.cc ConfigParser.cc CommonPool.h \ + CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ + DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ + DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ + DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ + DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ + NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ + dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ + errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ + HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ + HttpReply.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc \ + ipc_win32.cc ipcache.cc int.cc internal.cc list.cc logfile.cc \ + multicast.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ + mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ + peer_digest.cc peer_select.cc peer_sourcehash.cc \ + peer_userhash.cc redirect.cc referer.cc refresh.cc Server.cc \ + snmp_core.cc snmp_agent.cc ssl_support.cc ssl_support.h \ + SquidMath.h SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ + store_client.cc store_digest.cc store_dir.cc store_io.cc \ + store_key_md5.cc store_log.cc store_rebuild.cc store_swapin.cc \ + store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ + tunnel.cc SwapDir.cc url.cc URLScheme.cc urn.cc useragent.cc \ + wccp2.cc whois.cc win32.cc wordlist.cc am_tests_testEvent_OBJECTS = debug.$(OBJEXT) EventLoop.$(OBJEXT) \ HttpRequest.$(OBJEXT) HttpRequestMethod.$(OBJEXT) \ mem.$(OBJEXT) RemovalPolicy.$(OBJEXT) String.$(OBJEXT) \ @@ -715,37 +717,37 @@ ChunkedCodingParser.cc client_db.cc client_side.cc \ client_side_reply.cc client_side_request.cc ClientInfo.h \ clientStream.cc comm_select.cc comm_select.h \ - comm_select_win32.cc comm_poll.cc comm_poll.h comm_epoll.cc \ - comm_epoll.h comm_kqueue.cc comm_kqueue.h ConfigOption.cc \ - ConfigParser.cc CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - disk.cc dlink.h dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ - HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ - icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ - internal.cc list.cc logfile.cc multicast.cc mem_node.cc \ - MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ - Packer.cc Parsing.cc pconn.cc peer_digest.cc peer_select.cc \ - peer_sourcehash.cc peer_userhash.cc redirect.cc referer.cc \ - refresh.cc Server.cc snmp_core.cc snmp_agent.cc ssl_support.cc \ - ssl_support.h SquidMath.h SquidMath.cc stat.cc StatHist.cc \ - stmem.cc store.cc store_client.cc store_digest.cc store_dir.cc \ - store_io.cc store_key_md5.cc store_log.cc store_rebuild.cc \ - store_swapin.cc store_swapmeta.cc store_swapout.cc \ - StoreFileSystem.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreSwapLogData.cc event.cc tools.cc tunnel.cc SwapDir.cc \ - url.cc URLScheme.cc urn.cc useragent.cc wccp2.cc whois.cc \ - win32.cc wordlist.cc + comm_select_win32.cc comm_poll.cc comm_poll.h comm_devpoll.cc \ + comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ + ConfigOption.cc ConfigParser.cc CommonPool.h \ + CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ + DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ + DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ + DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ + DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ + NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ + dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ + errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ + HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ + HttpReply.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc \ + ipc_win32.cc ipcache.cc int.cc internal.cc list.cc logfile.cc \ + multicast.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ + mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ + peer_digest.cc peer_select.cc peer_sourcehash.cc \ + peer_userhash.cc redirect.cc referer.cc refresh.cc Server.cc \ + snmp_core.cc snmp_agent.cc ssl_support.cc ssl_support.h \ + SquidMath.h SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ + store_client.cc store_digest.cc store_dir.cc store_io.cc \ + store_key_md5.cc store_log.cc store_rebuild.cc store_swapin.cc \ + store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ + tunnel.cc SwapDir.cc url.cc URLScheme.cc urn.cc useragent.cc \ + wccp2.cc whois.cc win32.cc wordlist.cc am_tests_testEventLoop_OBJECTS = debug.$(OBJEXT) EventLoop.$(OBJEXT) \ HttpRequest.$(OBJEXT) HttpRequestMethod.$(OBJEXT) \ mem.$(OBJEXT) RemovalPolicy.$(OBJEXT) String.$(OBJEXT) \ @@ -826,33 +828,34 @@ ChunkedCodingParser.cc client_db.cc client_side.cc \ client_side_reply.cc client_side_request.cc ClientInfo.h \ clientStream.cc comm_select.cc comm_select.h \ - comm_select_win32.cc comm_poll.cc comm_poll.h comm_epoll.cc \ - comm_epoll.h comm_kqueue.cc comm_kqueue.h ConfigOption.cc \ - ConfigParser.cc CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - disk.cc dlink.h dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ - HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ - icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ - internal.cc list.cc logfile.cc multicast.cc mem_node.cc \ - MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ - Packer.cc Parsing.cc pconn.cc peer_digest.cc peer_select.cc \ - peer_sourcehash.cc peer_userhash.cc redirect.cc referer.cc \ - refresh.cc RemovalPolicy.cc Server.cc snmp_core.cc \ - snmp_agent.cc ssl_support.cc ssl_support.h SquidMath.h \ - SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ - store_client.cc store_digest.cc store_dir.cc store_io.cc \ - store_key_md5.cc store_log.cc store_rebuild.cc store_swapin.cc \ - store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ - StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + comm_select_win32.cc comm_poll.cc comm_poll.h comm_devpoll.cc \ + comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ + ConfigOption.cc ConfigParser.cc CommonPool.h \ + CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ + DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ + DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ + DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ + DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ + NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ + dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ + errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ + HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ + HttpReply.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc \ + ipc_win32.cc ipcache.cc int.cc internal.cc list.cc logfile.cc \ + multicast.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ + mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ + peer_digest.cc peer_select.cc peer_sourcehash.cc \ + peer_userhash.cc redirect.cc referer.cc refresh.cc \ + RemovalPolicy.cc Server.cc snmp_core.cc snmp_agent.cc \ + ssl_support.cc ssl_support.h SquidMath.h SquidMath.cc stat.cc \ + StatHist.cc stmem.cc store.cc store_client.cc store_digest.cc \ + store_dir.cc store_io.cc store_key_md5.cc store_log.cc \ + store_rebuild.cc store_swapin.cc store_swapmeta.cc \ + store_swapout.cc StoreFileSystem.cc StoreIOState.cc \ + StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ tunnel.cc SwapDir.cc url.cc URLScheme.cc urn.cc useragent.cc \ @@ -1010,36 +1013,37 @@ ChunkedCodingParser.cc client_db.cc client_side.cc \ client_side_reply.cc client_side_request.cc ClientInfo.h \ clientStream.cc comm_select.cc comm_select.h \ - comm_select_win32.cc comm_poll.cc comm_poll.h comm_epoll.cc \ - comm_epoll.h comm_kqueue.cc comm_kqueue.h ConfigOption.cc \ - ConfigParser.cc CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - disk.cc dlink.h dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHeader.cc HttpHeaderTools.cc HttpHdrCc.cc \ - HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ - HttpHdrScTarget.cc HttpMsg.cc HttpReply.cc HttpStatusLine.cc \ - icp_v2.cc icp_v3.cc ipc.cc ipc_win32.cc ipcache.cc int.cc \ - internal.cc list.cc logfile.cc multicast.cc mem_node.cc \ - MemBuf.cc MemObject.cc mime.cc mime_header.cc neighbors.cc \ - Packer.cc Parsing.cc pconn.cc peer_digest.cc peer_select.cc \ - peer_sourcehash.cc peer_userhash.cc redirect.cc referer.cc \ - refresh.cc Server.cc snmp_core.cc snmp_agent.cc ssl_support.cc \ - ssl_support.h SquidMath.h SquidMath.cc stat.cc StatHist.cc \ - stmem.cc store.cc store_client.cc store_digest.cc store_dir.cc \ - store_io.cc store_key_md5.cc store_log.cc store_rebuild.cc \ - store_swapin.cc store_swapmeta.cc store_swapout.cc \ - StoreFileSystem.cc StoreIOState.cc StoreMeta.cc \ - StoreMetaMD5.cc StoreMetaSTD.cc StoreMetaSTDLFS.cc \ - StoreMetaUnpacker.cc StoreMetaURL.cc StoreMetaVary.cc \ - StoreSwapLogData.cc event.cc tools.cc tunnel.cc SwapDir.cc \ - urn.cc useragent.cc wccp2.cc whois.cc win32.cc wordlist.cc + comm_select_win32.cc comm_poll.cc comm_poll.h comm_devpoll.cc \ + comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ + ConfigOption.cc ConfigParser.cc CommonPool.h \ + CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ + DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ + DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ + DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ + DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ + NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ + dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ + errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHeader.cc \ + HttpHeaderTools.cc HttpHdrCc.cc HttpHdrContRange.cc \ + HttpHdrRange.cc HttpHdrSc.cc HttpHdrScTarget.cc HttpMsg.cc \ + HttpReply.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc ipc.cc \ + ipc_win32.cc ipcache.cc int.cc internal.cc list.cc logfile.cc \ + multicast.cc mem_node.cc MemBuf.cc MemObject.cc mime.cc \ + mime_header.cc neighbors.cc Packer.cc Parsing.cc pconn.cc \ + peer_digest.cc peer_select.cc peer_sourcehash.cc \ + peer_userhash.cc redirect.cc referer.cc refresh.cc Server.cc \ + snmp_core.cc snmp_agent.cc ssl_support.cc ssl_support.h \ + SquidMath.h SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ + store_client.cc store_digest.cc store_dir.cc store_io.cc \ + store_key_md5.cc store_log.cc store_rebuild.cc store_swapin.cc \ + store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ + StoreMetaVary.cc StoreSwapLogData.cc event.cc tools.cc \ + tunnel.cc SwapDir.cc urn.cc useragent.cc wccp2.cc whois.cc \ + win32.cc wordlist.cc am_tests_testURL_OBJECTS = debug.$(OBJEXT) url.$(OBJEXT) \ URLScheme.$(OBJEXT) HttpRequest.$(OBJEXT) \ HttpRequestMethod.$(OBJEXT) mem.$(OBJEXT) \ @@ -1144,34 +1148,34 @@ ChunkedCodingParser.cc client_db.cc client_side.cc \ client_side_reply.cc client_side_request.cc ClientInfo.h \ clientStream.cc comm_select.cc comm_select.h \ - comm_select_win32.cc comm_poll.cc comm_poll.h comm_epoll.cc \ - comm_epoll.h comm_kqueue.cc comm_kqueue.h ConfigOption.cc \ - ConfigParser.cc debug.cc CommonPool.h CompositePoolNode.h \ - delay_pools.cc DelayId.cc DelayId.h DelayIdComposite.h \ - DelayBucket.cc DelayBucket.h DelayConfig.cc DelayConfig.h \ - DelayPool.cc DelayPool.h DelayPools.h DelaySpec.cc DelaySpec.h \ - DelayTagged.cc DelayTagged.h DelayUser.cc DelayUser.h \ - DelayVector.cc DelayVector.h NullDelayId.cc NullDelayId.h \ - disk.cc dlink.h dlink.cc dns_internal.cc DnsLookupDetails.h \ - DnsLookupDetails.cc dns.cc errorpage.cc ETag.cc \ - external_acl.cc ExternalACLEntry.cc fd.cc fde.cc forward.cc \ - fqdncache.cc ftp.cc gopher.cc helper.cc htcp.cc htcp.h http.cc \ - HttpBody.cc HttpHdrCc.cc HttpHdrContRange.cc HttpHdrRange.cc \ - HttpHdrSc.cc HttpHdrScTarget.cc HttpHeader.cc \ - HttpHeaderTools.cc HttpMsg.cc HttpReply.cc HttpRequest.cc \ - HttpRequestMethod.cc HttpStatusLine.cc icp_v2.cc icp_v3.cc \ - int.cc internal.cc ipc.cc ipc_win32.cc ipcache.cc list.cc \ - logfile.cc mem.cc mem_node.cc MemObject.cc mime.cc \ - mime_header.cc multicast.cc neighbors.cc Parsing.cc \ - peer_digest.cc peer_select.cc peer_sourcehash.cc \ - peer_userhash.cc pconn.cc redirect.cc referer.cc refresh.cc \ - RemovalPolicy.cc Server.cc snmp_core.cc snmp_agent.cc \ - ssl_support.cc ssl_support.h SquidMath.h SquidMath.cc stat.cc \ - StatHist.cc stmem.cc store.cc store_client.cc store_digest.cc \ - store_dir.cc store_key_md5.cc store_io.cc store_log.cc \ - store_rebuild.cc store_swapin.cc store_swapmeta.cc \ - store_swapout.cc StoreFileSystem.cc StoreIOState.cc \ - StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ + comm_select_win32.cc comm_poll.cc comm_poll.h comm_devpoll.cc \ + comm_epoll.cc comm_epoll.h comm_kqueue.cc comm_kqueue.h \ + ConfigOption.cc ConfigParser.cc debug.cc CommonPool.h \ + CompositePoolNode.h delay_pools.cc DelayId.cc DelayId.h \ + DelayIdComposite.h DelayBucket.cc DelayBucket.h DelayConfig.cc \ + DelayConfig.h DelayPool.cc DelayPool.h DelayPools.h \ + DelaySpec.cc DelaySpec.h DelayTagged.cc DelayTagged.h \ + DelayUser.cc DelayUser.h DelayVector.cc DelayVector.h \ + NullDelayId.cc NullDelayId.h disk.cc dlink.h dlink.cc \ + dns_internal.cc DnsLookupDetails.h DnsLookupDetails.cc dns.cc \ + errorpage.cc ETag.cc external_acl.cc ExternalACLEntry.cc fd.cc \ + fde.cc forward.cc fqdncache.cc ftp.cc gopher.cc helper.cc \ + htcp.cc htcp.h http.cc HttpBody.cc HttpHdrCc.cc \ + HttpHdrContRange.cc HttpHdrRange.cc HttpHdrSc.cc \ + HttpHdrScTarget.cc HttpHeader.cc HttpHeaderTools.cc HttpMsg.cc \ + HttpReply.cc HttpRequest.cc HttpRequestMethod.cc \ + HttpStatusLine.cc icp_v2.cc icp_v3.cc int.cc internal.cc \ + ipc.cc ipc_win32.cc ipcache.cc list.cc logfile.cc mem.cc \ + mem_node.cc MemObject.cc mime.cc mime_header.cc multicast.cc \ + neighbors.cc Parsing.cc peer_digest.cc peer_select.cc \ + peer_sourcehash.cc peer_userhash.cc pconn.cc redirect.cc \ + referer.cc refresh.cc RemovalPolicy.cc Server.cc snmp_core.cc \ + snmp_agent.cc ssl_support.cc ssl_support.h SquidMath.h \ + SquidMath.cc stat.cc StatHist.cc stmem.cc store.cc \ + store_client.cc store_digest.cc store_dir.cc store_key_md5.cc \ + store_io.cc store_log.cc store_rebuild.cc store_swapin.cc \ + store_swapmeta.cc store_swapout.cc StoreFileSystem.cc \ + StoreIOState.cc StoreMeta.cc StoreMetaMD5.cc StoreMetaSTD.cc \ StoreMetaSTDLFS.cc StoreMetaUnpacker.cc StoreMetaURL.cc \ StoreMetaVary.cc StoreSwapLogData.cc String.cc SwapDir.cc \ event.cc time.cc tools.cc tunnel.cc url.cc URLScheme.cc urn.cc \ @@ -1721,6 +1725,7 @@ comm_select_win32.cc \ comm_poll.cc \ comm_poll.h \ + comm_devpoll.cc \ comm_epoll.cc \ comm_epoll.h \ comm_kqueue.cc \ @@ -3903,6 +3908,7 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_side_reply.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/client_side_request.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm_devpoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm_epoll.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm_kqueue.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/comm_poll.Po@am__quote@ @@ -4611,6 +4617,7 @@ echo "$(INSTALL_DATA) squid.conf.documented $(DESTDIR)$(DEFAULT_CONFIG_FILE).documented"; \ $(INSTALL_DATA) squid.conf.documented $(DESTDIR)$(DEFAULT_CONFIG_FILE).documented; \ $(mkinstalldirs) $(DESTDIR)$(DEFAULT_LOG_PREFIX); \ + $(mkinstalldirs) $(DESTDIR)$(DEFAULT_SWAP_DIR); \ $(mkinstalldirs) $(DESTDIR)`dirname $(DEFAULT_PIDFILE)` uninstall-local: squid.conf.default diff -u -r -N squid-3.1.8/src/mem_node.cc squid-3.1.9/src/mem_node.cc --- squid-3.1.8/src/mem_node.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/mem_node.cc 2010-10-26 00:34:24.000000000 +1300 @@ -36,19 +36,19 @@ #include "squid.h" #include "mem_node.h" -static int makeMemNodeDataOffset(); +static ptrdiff_t makeMemNodeDataOffset(); -static int _mem_node_data_offset = makeMemNodeDataOffset(); +static ptrdiff_t _mem_node_data_offset = makeMemNodeDataOffset(); /* * Calculate the offset between the start of a mem_node and * its 'data' member */ -static int +static ptrdiff_t makeMemNodeDataOffset() { mem_node *p = 0L; - return int(ptrdiff_t(&p->data)); + return ptrdiff_t(&p->data); } /* diff -u -r -N squid-3.1.8/src/neighbors.cc squid-3.1.9/src/neighbors.cc --- squid-3.1.8/src/neighbors.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/neighbors.cc 2010-10-26 00:34:24.000000000 +1300 @@ -320,7 +320,7 @@ if (p->weight == q->weight) { if (q->rr_count < p->rr_count) continue; - } else if ( (double) q->rr_count / q->weight < (double) p->rr_count / p->weight) { + } else if ( ((double) q->rr_count / q->weight) < ((double) p->rr_count / p->weight)) { continue; } } diff -u -r -N squid-3.1.8/src/protos.h squid-3.1.9/src/protos.h --- squid-3.1.8/src/protos.h 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/protos.h 2010-10-26 00:34:24.000000000 +1300 @@ -221,7 +221,10 @@ /* ETag */ SQUIDCEXTERN int etagParseInit(ETag * etag, const char *str); -SQUIDCEXTERN int etagIsEqual(const ETag * tag1, const ETag * tag2); +/// whether etags are strong-equal +SQUIDCEXTERN bool etagIsStrongEqual(const ETag &tag1, const ETag &tag2); +/// whether etags are weak-equal +SQUIDCEXTERN bool etagIsWeakEqual(const ETag &tag1, const ETag &tag2); #include "HttpStatusCode.h" SQUIDCEXTERN const char *httpStatusString(http_status status); diff -u -r -N squid-3.1.8/src/refresh.cc squid-3.1.9/src/refresh.cc --- squid-3.1.8/src/refresh.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/refresh.cc 2010-10-26 00:34:24.000000000 +1300 @@ -254,29 +254,43 @@ if (NULL == R) R = &DefaultRefresh; - memset(&sf, '\0', sizeof(sf)); - - staleness = refreshStaleness(entry, check_time, age, R, &sf); - - debugs(22, 3, "Staleness = " << staleness); - debugs(22, 3, "refreshCheck: Matched '" << R->pattern << " " << (int) R->min << " " << (int) (100.0 * R->pct) << "%% " << (int) R->max << "'"); - - debugs(22, 3, "refreshCheck: age = " << age); + debugs(22, 3, "\tage:\t" << age); debugs(22, 3, "\tcheck_time:\t" << mkrfc1123(check_time)); debugs(22, 3, "\tentry->timestamp:\t" << mkrfc1123(entry->timestamp)); + if (request && !request->flags.ignore_cc) { + const HttpHdrCc *const cc = request->cache_control; + if (cc && cc->min_fresh > 0) { + debugs(22, 3, "\tage + min-fresh:\t" << age << " + " << + cc->min_fresh << " = " << age + cc->min_fresh); + debugs(22, 3, "\tcheck_time + min-fresh:\t" << check_time << " + " + << cc->min_fresh << " = " << + mkrfc1123(check_time + cc->min_fresh)); + age += cc->min_fresh; + check_time += cc->min_fresh; + } + } + + memset(&sf, '\0', sizeof(sf)); + + staleness = refreshStaleness(entry, check_time, age, R, &sf); + + debugs(22, 3, "Staleness = " << staleness); + if (EBIT_TEST(entry->flags, ENTRY_REVALIDATE) && staleness > -1 #if HTTP_VIOLATIONS && !R->flags.ignore_must_revalidate #endif ) { debugs(22, 3, "refreshCheck: YES: Must revalidate stale response"); + if (request) + request->flags.fail_on_validation_err = 1; return STALE_MUST_REVALIDATE; } @@ -436,6 +450,20 @@ return 1; } +/// whether reply is stale if it is a hit +static bool +refreshIsStaleIfHit(const int reason) +{ + switch (reason) { + case FRESH_MIN_RULE: + case FRESH_LMFACTOR_RULE: + case FRESH_EXPIRES: + return false; + default: + return true; + } +} + /* refreshCheck... functions below are protocol-specific wrappers around * refreshCheck() function above */ @@ -445,7 +473,8 @@ int reason = refreshCheck(entry, request, 0); refreshCounts[rcHTTP].total++; refreshCounts[rcHTTP].status[reason]++; - return (reason < 200) ? 0 : 1; + request->flags.stale_if_hit = refreshIsStaleIfHit(reason); + return (Config.onoff.offline || reason < 200) ? 0 : 1; } int diff -u -r -N squid-3.1.8/src/SquidString.h squid-3.1.9/src/SquidString.h --- squid-3.1.8/src/SquidString.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/SquidString.h 2010-10-26 00:34:24.000000000 +1300 @@ -44,7 +44,7 @@ /* squid string placeholder (for printf) */ #ifndef SQUIDSTRINGPH #define SQUIDSTRINGPH "%.*s" -#define SQUIDSTRINGPRINT(s) s.psize(),s.rawBuf() +#define SQUIDSTRINGPRINT(s) (s).psize(),(s).rawBuf() #endif /* SQUIDSTRINGPH */ diff -u -r -N squid-3.1.8/src/stat.cc squid-3.1.9/src/stat.cc --- squid-3.1.8/src/stat.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/stat.cc 2010-10-26 00:34:23.000000000 +1300 @@ -451,7 +451,7 @@ #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO struct mallinfo mp; - int t; + long t; #endif runtime = tvSubDsec(squid_start, current_time); @@ -545,17 +545,20 @@ storeAppendPrintf(sentry, "\tStorage Mem size:\t%lu KB\n", - (unsigned long)mem_node::StoreMemSize() >> 10); + (unsigned long)(mem_node::StoreMemSize() >> 10)); + double mFree = 0.0; + if (mem_node::InUseCount() <= store_pages_max) + mFree = Math::doublePercent((store_pages_max - mem_node::InUseCount()), store_pages_max); storeAppendPrintf(sentry, "\tStorage Mem capacity:\t%4.1f%% used, %4.1f%% free\n", Math::doublePercent(mem_node::InUseCount(), store_pages_max), - Math::doublePercent((store_pages_max - mem_node::InUseCount()), store_pages_max)); + mFree); storeAppendPrintf(sentry, "\tMean Object Size:\t%0.2f KB\n", n_disk_objects ? (double) store_swap_size / n_disk_objects : 0.0); - storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%d\n", - statCounter.unlink.requests); + storeAppendPrintf(sentry, "\tRequests given to unlinkd:\t%ld\n", + (long)statCounter.unlink.requests); storeAppendPrintf(sentry, "Median Service Times (seconds) 5 min 60 min:\n"); @@ -613,11 +616,11 @@ #endif - storeAppendPrintf(sentry, "\tMaximum Resident Size: %d KB\n", - rusage_maxrss(&rusage)); + storeAppendPrintf(sentry, "\tMaximum Resident Size: %ld KB\n", + (long)rusage_maxrss(&rusage)); - storeAppendPrintf(sentry, "\tPage faults with physical i/o: %d\n", - rusage_pagefaults(&rusage)); + storeAppendPrintf(sentry, "\tPage faults with physical i/o: %ld\n", + (long)rusage_pagefaults(&rusage)); #if HAVE_MSTATS && HAVE_GNUMALLOC_H @@ -625,11 +628,11 @@ storeAppendPrintf(sentry, "Memory usage for %s via mstats():\n",APP_SHORTNAME); - storeAppendPrintf(sentry, "\tTotal space in arena: %6d KB\n", - ms.bytes_total >> 10); + storeAppendPrintf(sentry, "\tTotal space in arena: %6ld KB\n", + (long)(ms.bytes_total >> 10)); - storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n", - ms.bytes_free >> 10, Math::intPercent(ms.bytes_free, ms.bytes_total)); + storeAppendPrintf(sentry, "\tTotal free: %6ld KB %d%%\n", + (long)(ms.bytes_free >> 10), Math::intPercent(ms.bytes_free, ms.bytes_total)); #elif HAVE_MALLINFO && HAVE_STRUCT_MALLINFO @@ -638,55 +641,55 @@ storeAppendPrintf(sentry, "Memory usage for %s via mallinfo():\n",APP_SHORTNAME); storeAppendPrintf(sentry, "\tTotal space in arena: %6ld KB\n", - (long)mp.arena >> 10); + (long)(mp.arena >> 10)); storeAppendPrintf(sentry, "\tOrdinary blocks: %6ld KB %6ld blks\n", - (long)mp.uordblks >> 10, (long)mp.ordblks); + (long)(mp.uordblks >> 10), (long)mp.ordblks); storeAppendPrintf(sentry, "\tSmall blocks: %6ld KB %6ld blks\n", - (long)mp.usmblks >> 10, (long)mp.smblks); + (long)(mp.usmblks >> 10), (long)mp.smblks); storeAppendPrintf(sentry, "\tHolding blocks: %6ld KB %6ld blks\n", - (long)mp.hblkhd >> 10, (long)mp.hblks); + (long)(mp.hblkhd >> 10), (long)mp.hblks); storeAppendPrintf(sentry, "\tFree Small blocks: %6ld KB\n", - (long)mp.fsmblks >> 10); + (long)(mp.fsmblks >> 10)); storeAppendPrintf(sentry, "\tFree Ordinary blocks: %6ld KB\n", - (long)mp.fordblks >> 10); + (long)(mp.fordblks >> 10)); t = mp.uordblks + mp.usmblks + mp.hblkhd; - storeAppendPrintf(sentry, "\tTotal in use: %6d KB %d%%\n", - t >> 10, Math::intPercent(t, mp.arena + mp.hblkhd)); + storeAppendPrintf(sentry, "\tTotal in use: %6ld KB %d%%\n", + (long)(t >> 10), Math::intPercent(t, mp.arena + mp.hblkhd)); t = mp.fsmblks + mp.fordblks; - storeAppendPrintf(sentry, "\tTotal free: %6d KB %d%%\n", - t >> 10, Math::intPercent(t, mp.arena + mp.hblkhd)); + storeAppendPrintf(sentry, "\tTotal free: %6ld KB %d%%\n", + (long)(t >> 10), Math::intPercent(t, mp.arena + mp.hblkhd)); t = mp.arena + mp.hblkhd; - storeAppendPrintf(sentry, "\tTotal size: %6d KB\n", - t >> 10); + storeAppendPrintf(sentry, "\tTotal size: %6ld KB\n", + (long)(t >> 10)); #if HAVE_STRUCT_MALLINFO_MXFAST storeAppendPrintf(sentry, "\tmax size of small blocks:\t%d\n", mp.mxfast); - storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%d\n", - mp.nlblks); + storeAppendPrintf(sentry, "\tnumber of small blocks in a holding block:\t%ld\n", + (long)mp.nlblks); - storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%d\n", mp.grain); + storeAppendPrintf(sentry, "\tsmall block rounding factor:\t%ld\n", (long)mp.grain); - storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%d\n" - ,mp.uordbytes); + storeAppendPrintf(sentry, "\tspace (including overhead) allocated in ord. blks:\t%ld\n", + (long)mp.uordbytes); - storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%d\n", - mp.allocated); + storeAppendPrintf(sentry, "\tnumber of ordinary blocks allocated:\t%ld\n", + (long)mp.allocated); - storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%d\n", - mp.treeoverhead); + storeAppendPrintf(sentry, "\tbytes used in maintaining the free tree:\t%ld\n", + (long)mp.treeoverhead); #endif /* HAVE_STRUCT_MALLINFO_MXFAST */ #endif /* HAVE_MALLINFO */ @@ -695,13 +698,13 @@ #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO - storeAppendPrintf(sentry, "\tTotal accounted: %6d KB %3d%%\n", - statMemoryAccounted() >> 10, Math::intPercent(statMemoryAccounted(), t)); + storeAppendPrintf(sentry, "\tTotal accounted: %6ld KB %3d%%\n", + (long)(statMemoryAccounted() >> 10), Math::intPercent(statMemoryAccounted(), t)); #else - storeAppendPrintf(sentry, "\tTotal accounted: %6d KB\n", - statMemoryAccounted() >> 10); + storeAppendPrintf(sentry, "\tTotal accounted: %6ld KB\n", + (long)(statMemoryAccounted() >> 10)); #endif { @@ -709,12 +712,15 @@ memPoolGetGlobalStats(&mp_stats); #if !(HAVE_MSTATS && HAVE_GNUMALLOC_H) && HAVE_MALLINFO && HAVE_STRUCT_MALLINFO - storeAppendPrintf(sentry, "\tmemPool accounted: %6d KB %3d%%\n", - (int) mp_stats.TheMeter->alloc.level >> 10, + storeAppendPrintf(sentry, "\tmemPool accounted: %6ld KB %3d%%\n", + (long)(mp_stats.TheMeter->alloc.level >> 10), Math::intPercent(mp_stats.TheMeter->alloc.level, t)); - storeAppendPrintf(sentry, "\tmemPool unaccounted: %6d KB %3d%%\n", - (t - (int) mp_stats.TheMeter->alloc.level) >> 10, - Math::intPercent((t - mp_stats.TheMeter->alloc.level), t)); + + int iFree = 0; + if (t >= mp_stats.TheMeter->alloc.level) + iFree = Math::intPercent((t - mp_stats.TheMeter->alloc.level), t); + storeAppendPrintf(sentry, "\tmemPool unaccounted: %6ld KB %3d%%\n", + (long)((t - mp_stats.TheMeter->alloc.level) >> 10), iFree); #endif storeAppendPrintf(sentry, "\tmemPoolAlloc calls: %9.0f\n", @@ -744,10 +750,10 @@ (unsigned long)StoreEntry::inUseCount()); storeAppendPrintf(sentry, "\t%6lu StoreEntries with MemObjects\n", (unsigned long)MemObject::inUseCount()); - storeAppendPrintf(sentry, "\t%6d Hot Object Cache Items\n", - hot_obj_count); - storeAppendPrintf(sentry, "\t%6d on-disk objects\n", - n_disk_objects); + storeAppendPrintf(sentry, "\t%6ld Hot Object Cache Items\n", + (long)hot_obj_count); + storeAppendPrintf(sentry, "\t%6ld on-disk objects\n", + (long)n_disk_objects); #if XMALLOC_STATISTICS @@ -1266,122 +1272,122 @@ (int) f->timestamp.tv_sec, (int) f->timestamp.tv_usec, mkrfc1123(f->timestamp.tv_sec)); - storeAppendPrintf(sentry, "client_http.requests = %d\n", - f->client_http.requests); - storeAppendPrintf(sentry, "client_http.hits = %d\n", - f->client_http.hits); - storeAppendPrintf(sentry, "client_http.errors = %d\n", - f->client_http.errors); - storeAppendPrintf(sentry, "client_http.kbytes_in = %d\n", - (int) f->client_http.kbytes_in.kb); - storeAppendPrintf(sentry, "client_http.kbytes_out = %d\n", - (int) f->client_http.kbytes_out.kb); - storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %d\n", - (int) f->client_http.hit_kbytes_out.kb); - - storeAppendPrintf(sentry, "server.all.requests = %d\n", - (int) f->server.all.requests); - storeAppendPrintf(sentry, "server.all.errors = %d\n", - (int) f->server.all.errors); - storeAppendPrintf(sentry, "server.all.kbytes_in = %d\n", - (int) f->server.all.kbytes_in.kb); - storeAppendPrintf(sentry, "server.all.kbytes_out = %d\n", - (int) f->server.all.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.http.requests = %d\n", - (int) f->server.http.requests); - storeAppendPrintf(sentry, "server.http.errors = %d\n", - (int) f->server.http.errors); - storeAppendPrintf(sentry, "server.http.kbytes_in = %d\n", - (int) f->server.http.kbytes_in.kb); - storeAppendPrintf(sentry, "server.http.kbytes_out = %d\n", - (int) f->server.http.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.ftp.requests = %d\n", - (int) f->server.ftp.requests); - storeAppendPrintf(sentry, "server.ftp.errors = %d\n", - (int) f->server.ftp.errors); - storeAppendPrintf(sentry, "server.ftp.kbytes_in = %d\n", - (int) f->server.ftp.kbytes_in.kb); - storeAppendPrintf(sentry, "server.ftp.kbytes_out = %d\n", - (int) f->server.ftp.kbytes_out.kb); - - storeAppendPrintf(sentry, "server.other.requests = %d\n", - (int) f->server.other.requests); - storeAppendPrintf(sentry, "server.other.errors = %d\n", - (int) f->server.other.errors); - storeAppendPrintf(sentry, "server.other.kbytes_in = %d\n", - (int) f->server.other.kbytes_in.kb); - storeAppendPrintf(sentry, "server.other.kbytes_out = %d\n", - (int) f->server.other.kbytes_out.kb); - - storeAppendPrintf(sentry, "icp.pkts_sent = %d\n", - f->icp.pkts_sent); - storeAppendPrintf(sentry, "icp.pkts_recv = %d\n", - f->icp.pkts_recv); - storeAppendPrintf(sentry, "icp.queries_sent = %d\n", - f->icp.queries_sent); - storeAppendPrintf(sentry, "icp.replies_sent = %d\n", - f->icp.replies_sent); - storeAppendPrintf(sentry, "icp.queries_recv = %d\n", - f->icp.queries_recv); - storeAppendPrintf(sentry, "icp.replies_recv = %d\n", - f->icp.replies_recv); - storeAppendPrintf(sentry, "icp.query_timeouts = %d\n", - f->icp.query_timeouts); - storeAppendPrintf(sentry, "icp.replies_queued = %d\n", - f->icp.replies_queued); - storeAppendPrintf(sentry, "icp.kbytes_sent = %d\n", - (int) f->icp.kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.kbytes_recv = %d\n", - (int) f->icp.kbytes_recv.kb); - storeAppendPrintf(sentry, "icp.q_kbytes_sent = %d\n", - (int) f->icp.q_kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.r_kbytes_sent = %d\n", - (int) f->icp.r_kbytes_sent.kb); - storeAppendPrintf(sentry, "icp.q_kbytes_recv = %d\n", - (int) f->icp.q_kbytes_recv.kb); - storeAppendPrintf(sentry, "icp.r_kbytes_recv = %d\n", - (int) f->icp.r_kbytes_recv.kb); + storeAppendPrintf(sentry, "client_http.requests = %ld\n", + (long)f->client_http.requests); + storeAppendPrintf(sentry, "client_http.hits = %ld\n", + (long)f->client_http.hits); + storeAppendPrintf(sentry, "client_http.errors = %ld\n", + (long)f->client_http.errors); + storeAppendPrintf(sentry, "client_http.kbytes_in = %ld\n", + (long)f->client_http.kbytes_in.kb); + storeAppendPrintf(sentry, "client_http.kbytes_out = %ld\n", + (long)f->client_http.kbytes_out.kb); + storeAppendPrintf(sentry, "client_http.hit_kbytes_out = %ld\n", + (long)f->client_http.hit_kbytes_out.kb); + + storeAppendPrintf(sentry, "server.all.requests = %ld\n", + (long)f->server.all.requests); + storeAppendPrintf(sentry, "server.all.errors = %ld\n", + (long) f->server.all.errors); + storeAppendPrintf(sentry, "server.all.kbytes_in = %ld\n", + (long) f->server.all.kbytes_in.kb); + storeAppendPrintf(sentry, "server.all.kbytes_out = %ld\n", + (long) f->server.all.kbytes_out.kb); + + storeAppendPrintf(sentry, "server.http.requests = %ld\n", + (long) f->server.http.requests); + storeAppendPrintf(sentry, "server.http.errors = %ld\n", + (long) f->server.http.errors); + storeAppendPrintf(sentry, "server.http.kbytes_in = %ld\n", + (long) f->server.http.kbytes_in.kb); + storeAppendPrintf(sentry, "server.http.kbytes_out = %ld\n", + (long) f->server.http.kbytes_out.kb); + + storeAppendPrintf(sentry, "server.ftp.requests = %ld\n", + (long) f->server.ftp.requests); + storeAppendPrintf(sentry, "server.ftp.errors = %ld\n", + (long) f->server.ftp.errors); + storeAppendPrintf(sentry, "server.ftp.kbytes_in = %ld\n", + (long) f->server.ftp.kbytes_in.kb); + storeAppendPrintf(sentry, "server.ftp.kbytes_out = %ld\n", + (long) f->server.ftp.kbytes_out.kb); + + storeAppendPrintf(sentry, "server.other.requests = %ld\n", + (long) f->server.other.requests); + storeAppendPrintf(sentry, "server.other.errors = %ld\n", + (long) f->server.other.errors); + storeAppendPrintf(sentry, "server.other.kbytes_in = %ld\n", + (long) f->server.other.kbytes_in.kb); + storeAppendPrintf(sentry, "server.other.kbytes_out = %ld\n", + (long) f->server.other.kbytes_out.kb); + + storeAppendPrintf(sentry, "icp.pkts_sent = %ld\n", + (long)f->icp.pkts_sent); + storeAppendPrintf(sentry, "icp.pkts_recv = %ld\n", + (long)f->icp.pkts_recv); + storeAppendPrintf(sentry, "icp.queries_sent = %ld\n", + (long)f->icp.queries_sent); + storeAppendPrintf(sentry, "icp.replies_sent = %ld\n", + (long)f->icp.replies_sent); + storeAppendPrintf(sentry, "icp.queries_recv = %ld\n", + (long)f->icp.queries_recv); + storeAppendPrintf(sentry, "icp.replies_recv = %ld\n", + (long)f->icp.replies_recv); + storeAppendPrintf(sentry, "icp.query_timeouts = %ld\n", + (long)f->icp.query_timeouts); + storeAppendPrintf(sentry, "icp.replies_queued = %ld\n", + (long)f->icp.replies_queued); + storeAppendPrintf(sentry, "icp.kbytes_sent = %ld\n", + (long) f->icp.kbytes_sent.kb); + storeAppendPrintf(sentry, "icp.kbytes_recv = %ld\n", + (long) f->icp.kbytes_recv.kb); + storeAppendPrintf(sentry, "icp.q_kbytes_sent = %ld\n", + (long) f->icp.q_kbytes_sent.kb); + storeAppendPrintf(sentry, "icp.r_kbytes_sent = %ld\n", + (long) f->icp.r_kbytes_sent.kb); + storeAppendPrintf(sentry, "icp.q_kbytes_recv = %ld\n", + (long) f->icp.q_kbytes_recv.kb); + storeAppendPrintf(sentry, "icp.r_kbytes_recv = %ld\n", + (long) f->icp.r_kbytes_recv.kb); #if USE_CACHE_DIGESTS - storeAppendPrintf(sentry, "icp.times_used = %d\n", - f->icp.times_used); - storeAppendPrintf(sentry, "cd.times_used = %d\n", - f->cd.times_used); - storeAppendPrintf(sentry, "cd.msgs_sent = %d\n", - f->cd.msgs_sent); - storeAppendPrintf(sentry, "cd.msgs_recv = %d\n", - f->cd.msgs_recv); - storeAppendPrintf(sentry, "cd.memory = %d\n", - (int) f->cd.memory.kb); - storeAppendPrintf(sentry, "cd.local_memory = %d\n", - (int) (store_digest ? store_digest->mask_size / 1024 : 0)); - storeAppendPrintf(sentry, "cd.kbytes_sent = %d\n", - (int) f->cd.kbytes_sent.kb); - storeAppendPrintf(sentry, "cd.kbytes_recv = %d\n", - (int) f->cd.kbytes_recv.kb); -#endif - - storeAppendPrintf(sentry, "unlink.requests = %d\n", - f->unlink.requests); - storeAppendPrintf(sentry, "page_faults = %d\n", - f->page_faults); + storeAppendPrintf(sentry, "icp.times_used = %ld\n", + (long)f->icp.times_used); + storeAppendPrintf(sentry, "cd.times_used = %ld\n", + (long)f->cd.times_used); + storeAppendPrintf(sentry, "cd.msgs_sent = %ld\n", + (long)f->cd.msgs_sent); + storeAppendPrintf(sentry, "cd.msgs_recv = %ld\n", + (long)f->cd.msgs_recv); + storeAppendPrintf(sentry, "cd.memory = %ld\n", + (long) f->cd.memory.kb); + storeAppendPrintf(sentry, "cd.local_memory = %ld\n", + (long) (store_digest ? store_digest->mask_size / 1024 : 0)); + storeAppendPrintf(sentry, "cd.kbytes_sent = %ld\n", + (long) f->cd.kbytes_sent.kb); + storeAppendPrintf(sentry, "cd.kbytes_recv = %ld\n", + (long) f->cd.kbytes_recv.kb); +#endif + + storeAppendPrintf(sentry, "unlink.requests = %ld\n", + (long)f->unlink.requests); + storeAppendPrintf(sentry, "page_faults = %ld\n", + (long)f->page_faults); storeAppendPrintf(sentry, "select_loops = %ld\n", - f->select_loops); + (long)f->select_loops); storeAppendPrintf(sentry, "cpu_time = %f\n", f->cputime); storeAppendPrintf(sentry, "wall_time = %f\n", tvSubDsec(f->timestamp, current_time)); - storeAppendPrintf(sentry, "swap.outs = %d\n", - f->swap.outs); - storeAppendPrintf(sentry, "swap.ins = %d\n", - f->swap.ins); - storeAppendPrintf(sentry, "swap.files_cleaned = %d\n", - f->swap.files_cleaned); - storeAppendPrintf(sentry, "aborted_requests = %d\n", - f->aborted_requests); + storeAppendPrintf(sentry, "swap.outs = %ld\n", + (long)f->swap.outs); + storeAppendPrintf(sentry, "swap.ins = %ld\n", + (long)f->swap.ins); + storeAppendPrintf(sentry, "swap.files_cleaned = %ld\n", + (long)f->swap.files_cleaned); + storeAppendPrintf(sentry, "aborted_requests = %ld\n", + (long)f->aborted_requests); } void diff -u -r -N squid-3.1.8/src/store.cc squid-3.1.9/src/store.cc --- squid-3.1.8/src/store.cc 2010-09-04 15:25:58.000000000 +1200 +++ squid-3.1.9/src/store.cc 2010-10-26 00:34:24.000000000 +1300 @@ -1486,14 +1486,7 @@ const HttpReply *reply = getReply(); time_t served_date = reply->date; int age = reply->header.getInt(HDR_AGE); - /* - * The timestamp calculations below tries to mimic the properties - * of the age calculation in RFC2616 section 13.2.3. The implementaion - * isn't complete, and the most notable exception from the RFC is that - * this does not account for response_delay, but it probably does - * not matter much as this is calculated immediately when the headers - * are received, not when the whole response has been received. - */ + /* Compute the timestamp, mimicking RFC2616 section 13.2.3. */ /* make sure that 0 <= served_date <= squid_curtime */ if (served_date < 0 || served_date > squid_curtime) @@ -1509,6 +1502,14 @@ if (squid_curtime > age) served_date = squid_curtime - age; + // compensate for Squid-to-server and server-to-Squid delays + if (mem_obj && mem_obj->request) { + const time_t request_sent = + mem_obj->request->hier.peer_http_request_sent.tv_sec; + if (0 < request_sent && request_sent < squid_curtime) + served_date -= (squid_curtime - request_sent); + } + if (reply->expires > 0 && reply->date > -1) expires = served_date + (reply->expires - reply->date); else diff -u -r -N squid-3.1.8/src/structs.h squid-3.1.9/src/structs.h --- squid-3.1.8/src/structs.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/structs.h 2010-10-26 00:34:23.000000000 +1300 @@ -723,6 +723,7 @@ int max_age; int s_maxage; int max_stale; + int min_fresh; String other; }; @@ -1010,7 +1011,7 @@ struct request_flags { - request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),destinationIPLookedUp_(0) { + request_flags(): range(0),nocache(0),ims(0),auth(0),cachable(0),hierarchical(0),loopdetect(0),proxy_keepalive(0),proxying(0),refresh(0),redirected(0),need_validation(0),fail_on_validation_err(0),stale_if_hit(0),accelerated(0),ignore_cc(0),intercepted(0),spoof_client_ip(0),internal(0),internalclient(0),must_keepalive(0),destinationIPLookedUp_(0) { #if HTTP_VIOLATIONS nocache_hack = 0; #endif @@ -1032,6 +1033,8 @@ unsigned int refresh:1; unsigned int redirected:1; unsigned int need_validation:1; + unsigned int fail_on_validation_err:1; ///< whether we should fail if validation fails + unsigned int stale_if_hit:1; ///< reply is stale if it is a hit #if HTTP_VIOLATIONS unsigned int nocache_hack:1; /* for changing/ignoring no-cache requests */ #endif diff -u -r -N squid-3.1.8/src/tests/testHttpRequest.cc squid-3.1.9/src/tests/testHttpRequest.cc --- squid-3.1.8/src/tests/testHttpRequest.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/tests/testHttpRequest.cc 2010-10-26 00:34:24.000000000 +1300 @@ -932,6 +932,27 @@ CPPUNIT_ASSERT_EQUAL(0, output.v_min); input.reset(); + // negative major version (bug 3062) + input.append("GET / HTTP/-999999.1\n", 21); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / HTTP/-999999.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(2, output.m_end); + CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(4, output.u_start); + CPPUNIT_ASSERT_EQUAL(4, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(6, output.v_start); + CPPUNIT_ASSERT_EQUAL(19, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/-999999.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + // no minor version input.append("GET / HTTP/1.\n", 14); //printf("TEST: '%s'\n",input.content()); @@ -952,6 +973,27 @@ CPPUNIT_ASSERT_EQUAL(1, output.v_maj); CPPUNIT_ASSERT_EQUAL(0, output.v_min); input.reset(); + + // negative major version (bug 3062 corollary) + input.append("GET / HTTP/1.-999999\n", 21); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / HTTP/1.-999999\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(2, output.m_end); + CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(4, output.u_start); + CPPUNIT_ASSERT_EQUAL(4, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(6, output.v_start); + CPPUNIT_ASSERT_EQUAL(19, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.-999999", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); // binary line input.append("\xB\xC\xE\xF\n", 5); diff -u -r -N squid-3.1.8/src/tunnel.cc squid-3.1.9/src/tunnel.cc --- squid-3.1.8/src/tunnel.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/tunnel.cc 2010-10-26 00:34:24.000000000 +1300 @@ -175,7 +175,7 @@ assert(tunnelState->noConnections()); safe_free(tunnelState->url); FwdState::serversFree(&tunnelState->servers); - tunnelState->host = NULL; + safe_free(tunnelState->host); HTTPMSGUNLOCK(tunnelState->request); delete tunnelState; } @@ -758,7 +758,7 @@ } tunnelState->servers = fs; - tunnelState->host = fs->_peer ? fs->_peer->host : xstrdup(request->GetHost()); + tunnelState->host = fs->_peer ? xstrdup(fs->_peer->host) : xstrdup(request->GetHost()); if (fs->_peer == NULL) { tunnelState->port = request->port; diff -u -r -N squid-3.1.8/src/typedefs.h squid-3.1.9/src/typedefs.h --- squid-3.1.8/src/typedefs.h 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/typedefs.h 2010-10-26 00:34:23.000000000 +1300 @@ -36,7 +36,7 @@ #ifndef SQUID_TYPEDEFS_H #define SQUID_TYPEDEFS_H -typedef signed int sfileno; +typedef int32_t sfileno; typedef signed int sdirno; typedef struct { diff -u -r -N squid-3.1.8/src/unlinkd.cc squid-3.1.9/src/unlinkd.cc --- squid-3.1.8/src/unlinkd.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/src/unlinkd.cc 2010-10-26 00:34:23.000000000 +1300 @@ -69,7 +69,7 @@ * time. */ if (queuelen >= UNLINKD_QUEUE_LIMIT) { -#if defined(USE_EPOLL) || defined(USE_KQUEUE) +#if defined(USE_EPOLL) || defined(USE_KQUEUE) || defined(USE_DEVPOLL) /* * DPW 2007-04-23 * We can't use fd_set when using epoll() or kqueue(). In diff -u -r -N squid-3.1.8/tools/squidclient.cc squid-3.1.9/tools/squidclient.cc --- squid-3.1.8/tools/squidclient.cc 2010-09-04 15:25:57.000000000 +1200 +++ squid-3.1.9/tools/squidclient.cc 2010-10-26 00:34:25.000000000 +1300 @@ -447,7 +447,7 @@ } if (opt_verbose) - fprintf(stderr, "Request: '%s'\n", msg); + fprintf(stderr, "Request:'%s'\n", msg); if (ping) { #if HAVE_SIGACTION @@ -475,6 +475,9 @@ int fsize = 0; struct addrinfo *AI = NULL; + if (opt_verbose) + fprintf(stderr, "Resolving... %s\n", hostname); + /* Connect to the server */ if (localhost) { @@ -512,6 +515,11 @@ iaddr.SetPort(port); + if (opt_verbose) { + char ipbuf[MAX_IPSTRLEN]; + fprintf(stderr, "Connecting... %s(%s)\n", hostname, iaddr.NtoA(ipbuf, MAX_IPSTRLEN)); + } + if (client_comm_connect(conn, iaddr, ping ? &tv1 : NULL) < 0) { char hostnameBuf[MAX_IPSTRLEN]; iaddr.ToURL(hostnameBuf, MAX_IPSTRLEN); @@ -524,6 +532,10 @@ } exit(1); } + if (opt_verbose) { + char ipbuf[MAX_IPSTRLEN]; + fprintf(stderr, "Connected to: %s (%s)\n", hostname, iaddr.NtoA(ipbuf, MAX_IPSTRLEN)); + } /* Send the HTTP request */ bytesWritten = mywrite(conn, msg, strlen(msg));