diff -u -r -N squid-3.1.7/bootstrap.sh squid-3.1.8/bootstrap.sh --- squid-3.1.7/bootstrap.sh 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/bootstrap.sh 2010-09-04 15:25:58.000000000 +1200 @@ -7,9 +7,9 @@ # Autotool versions preferred. To override either edit the script # to match the versions you want to use, or set the variables on # the command line like "env acver=.. amver=... ./bootstrap.sh" -acversions="${acver:-2.63 2.62 2.61}" +acversions="${acver:-2.64 2.63 2.62 2.61}" amversions="${amver:-1.11 1.10 1.9}" -ltversions="${ltver:-2.2 1.5 1.4}" +ltversions="${ltver:-2.2}" check_version() { @@ -113,19 +113,6 @@ chmod u+w $makefile mv $makefile.new $makefile chmod u-w $makefile - - # Libtool 2.2.6b we bundle is slightly broken with non-portable dependencies - # HACK: Make it backward-compatible by linking the bundled headers. - for f in ltdl.h libltdl/lt_error.h libltdl/lt_system.h libltdl/lt_dlloader.h libltdl/slist.h; do - echo "Fixing $f ..." - sed 's//\"libltdl\/lt_system.h\"/g' $src/$f | - sed 's//\"libltdl\/lt__glibc.h\"/g' | - sed 's//\"libltdl\/lt_error.h\"/g' | - sed 's//\"libltdl\/lt_dlloader.h\"/g' > $src/$f.new; - chmod u+w $src/$f - mv $src/$f.new $src/$f - chmod u-w $src/$f - done fi } diff -u -r -N squid-3.1.7/ChangeLog squid-3.1.8/ChangeLog --- squid-3.1.7/ChangeLog 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/ChangeLog 2010-09-04 15:25:57.000000000 +1200 @@ -1,3 +1,16 @@ +Changes to squid-3.1.8 (04 Sep 2010): + + - Bug 3033: incorrect information regarding TOS + - Bug 3020: Segmentation fault: nameservers[vc->ns].vc = NULL + - Bug 3005,2972: Locate LTDL headers correctly (again) + - Bug 2872: leaking file descriptors + - Bug 2583: pure virtual method called + - Hardened DNS client against packet queue attacks + - Hardened HTTP request-line parser + - Several HTTP/1.1 support improvements + - Improved cross-compile support + - .. and several internal pointer safety fixes + Changes to squid-3.1.7 (23 Aug 2010): - Regression Bug 3021: Large DNS reply causes crash diff -u -r -N squid-3.1.7/compat/Makefile.in squid-3.1.8/compat/Makefile.in --- squid-3.1.7/compat/Makefile.in 2010-08-24 17:42:19.000000000 +1200 +++ squid-3.1.8/compat/Makefile.in 2010-09-04 15:26:19.000000000 +1200 @@ -40,6 +40,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = testPreCompiler$(EXEEXT) TESTS = testPreCompiler$(EXEEXT) testHeaders +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = compat ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -287,13 +288,8 @@ AM_CFLAGS = $(SQUID_CFLAGS) AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) # Ideally this would be 100% inline functions and macro wrappers. diff -u -r -N squid-3.1.7/configure squid-3.1.8/configure --- squid-3.1.7/configure 2010-08-24 17:43:37.000000000 +1200 +++ squid-3.1.8/configure 2010-09-04 15:26:52.000000000 +1200 @@ -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.7. +# Generated by GNU Autoconf 2.62 for Squid Web Proxy 3.1.8. # # Report bugs to . # @@ -750,8 +750,8 @@ # Identity of this package. PACKAGE_NAME='Squid Web Proxy' PACKAGE_TARNAME='squid' -PACKAGE_VERSION='3.1.7' -PACKAGE_STRING='Squid Web Proxy 3.1.7' +PACKAGE_VERSION='3.1.8' +PACKAGE_STRING='Squid Web Proxy 3.1.8' PACKAGE_BUGREPORT='http://www.squid-cache.org/bugs/' ac_unique_file="src/main.cc" @@ -1712,7 +1712,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.7 to adapt to many kinds of systems. +\`configure' configures Squid Web Proxy 3.1.8 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1782,7 +1782,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of Squid Web Proxy 3.1.7:";; + short | recursive ) echo "Configuration of Squid Web Proxy 3.1.8:";; esac cat <<\_ACEOF @@ -2109,7 +2109,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -Squid Web Proxy configure 3.1.7 +Squid Web Proxy configure 3.1.8 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, @@ -2123,7 +2123,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.7, which was +It was created by Squid Web Proxy $as_me 3.1.8, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ @@ -2841,7 +2841,7 @@ # Define the identity of the package. PACKAGE='squid' - VERSION='3.1.7' + VERSION='3.1.8' cat >>confdefs.h <<_ACEOF @@ -19451,11 +19451,7 @@ if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -22760,11 +22756,7 @@ $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -39923,6 +39915,362 @@ fi +#need the define for overflow checks +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:$LINENO: checking size of off_t" >&5 +$as_echo_n "checking size of off_t... " >&6; } +if test "${ac_cv_sizeof_off_t+set}" = set; then + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +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 +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (off_t))) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_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_lo=0 ac_mid=0 + while :; do + 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 +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (off_t))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_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_hi=$ac_mid; break +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr $ac_mid + 1` + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + 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 +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (off_t))) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_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_hi=-1 ac_mid=-1 + while :; do + 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 +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (off_t))) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_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_lo=$ac_mid; break +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_hi=`expr '(' $ac_mid ')' - 1` + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + ac_mid=`expr 2 '*' $ac_mid` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo= ac_hi= +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + ac_mid=`expr '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo` + 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 +int +main () +{ +static int test_array [1 - 2 * !(((long int) (sizeof (off_t))) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_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_hi=$ac_mid +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_lo=`expr '(' $ac_mid ')' + 1` +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in +?*) ac_cv_sizeof_off_t=$ac_lo;; +'') if test "$ac_cv_type_off_t" = yes; then + { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (off_t) +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute sizeof (off_t) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } + else + ac_cv_sizeof_off_t=0 + fi ;; +esac +else + 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 +static long int longval () { return (long int) (sizeof (off_t)); } +static unsigned long int ulongval () { return (long int) (sizeof (off_t)); } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (((long int) (sizeof (off_t))) < 0) + { + long int i = longval (); + if (i != ((long int) (sizeof (off_t)))) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ((long int) (sizeof (off_t)))) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + 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_sizeof_off_t=`cat conftest.val` +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 ) +if test "$ac_cv_type_off_t" = yes; then + { { $as_echo "$as_me:$LINENO: error: cannot compute sizeof (off_t) +See \`config.log' for more details." >&5 +$as_echo "$as_me: error: cannot compute sizeof (off_t) +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } + else + ac_cv_sizeof_off_t=0 + fi +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 +rm -f conftest.val +fi +{ $as_echo "$as_me:$LINENO: result: $ac_cv_sizeof_off_t" >&5 +$as_echo "$ac_cv_sizeof_off_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_OFF_T $ac_cv_sizeof_off_t +_ACEOF + + { $as_echo "$as_me:$LINENO: checking for pad128_t" >&5 $as_echo_n "checking for pad128_t... " >&6; } @@ -46229,11 +46577,7 @@ $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -46306,11 +46650,7 @@ $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -46394,11 +46734,7 @@ $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -46475,11 +46811,7 @@ $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then - { { $as_echo "$as_me:$LINENO: error: cannot run test program while cross compiling -See \`config.log' for more details." >&5 -$as_echo "$as_me: error: cannot run test program while cross compiling -See \`config.log' for more details." >&2;} - { (exit 1); exit 1; }; } + : else cat >conftest.$ac_ext <<_ACEOF /* confdefs.h. */ @@ -48878,7 +49210,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.7, which was +This file was extended by Squid Web Proxy $as_me 3.1.8, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -48931,7 +49263,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ -Squid Web Proxy config.status 3.1.7 +Squid Web Proxy config.status 3.1.8 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.7/configure.in squid-3.1.8/configure.in --- squid-3.1.7/configure.in 2010-08-24 17:43:36.000000000 +1200 +++ squid-3.1.8/configure.in 2010-09-04 15:26:52.000000000 +1200 @@ -2,7 +2,7 @@ dnl dnl $Id$ dnl -AC_INIT([Squid Web Proxy],[3.1.7],[http://www.squid-cache.org/bugs/],[squid]) +AC_INIT([Squid Web Proxy],[3.1.8],[http://www.squid-cache.org/bugs/],[squid]) AC_PREREQ(2.61) AC_CONFIG_HEADERS([include/autoconf.h]) AC_CONFIG_AUX_DIR(cfgaux) @@ -366,7 +366,7 @@ dnl Nasty hack to get autoconf 2.64 on Linux to run. dnl all other uses of RUN_IFELSE are wrapped inside CACHE_CHECK which breaks on 2.64 -AC_RUN_IFELSE([AC_LANG_SOURCE([[ int main(int argc, char **argv) { return 0; } ]])],[],[],[]) +AC_RUN_IFELSE([AC_LANG_SOURCE([[ int main(int argc, char **argv) { return 0; } ]])],[],[],[:]) dnl This is a developer only option.. developers know how to set defines dnl @@ -1331,7 +1331,7 @@ } return 0; } - ]])],[ac_cv_epoll_works=yes],[ac_cv_epoll_works=no],[])) + ]])],[ac_cv_epoll_works=yes],[ac_cv_epoll_works=no],[:])) fi if test "$force_epoll" = "yes" && test "$ac_cv_epoll_works" = "no" ; then @@ -2481,6 +2481,8 @@ AC_CHECK_SIZEOF(uint64_t,,SQUID_DEFAULT_SIZEOF_INCLUDES) AC_DEFINE(HAVE_UINT64_T,1,[uint64_t is defined in system headers]) ],,SQUID_DEFAULT_INCLUDES) +#need the define for overflow checks +AC_CHECK_SIZEOF(off_t) dnl On Solaris 9 x86, gcc may includes a "fixed" set of old system include files dnl that is incompatible with the updated Solaris header files. @@ -3075,7 +3077,7 @@ } return 0; } - ]])],[ac_cv_func_setresuid="yes"],[ac_cv_func_setresuid="no"],[]) + ]])],[ac_cv_func_setresuid="yes"],[ac_cv_func_setresuid="no"],[:]) ) if test "$ac_cv_func_setresuid" = "yes" ; then AC_DEFINE(HAVE_SETRESUID,1,[Yay! Another Linux brokenness. Its not good enough to know that setresuid() exists, because RedHat 5.0 declare setresuid() but doesn't implement it.]) @@ -3100,7 +3102,7 @@ strnstr(str, "fubar", size); return 0; } - ]])],[ac_cv_func_strnstr="yes"],[ac_cv_func_strnstr="no"],[]) + ]])],[ac_cv_func_strnstr="yes"],[ac_cv_func_strnstr="no"],[:]) ) if test "$ac_cv_func_strnstr" = "yes" ; then AC_DEFINE(HAVE_STRNSTR,1,[Yay! We have a working strnstr!]) @@ -3125,7 +3127,7 @@ return 0; } int main(int argc, char **argv) { return f (0, 42); } - ]])],[ac_cv_func_va_copy="yes"],[ac_cv_func_va_copy="no"],[]) + ]])],[ac_cv_func_va_copy="yes"],[ac_cv_func_va_copy="no"],[:]) ) if test "$ac_cv_func_va_copy" = "yes" ; then AC_DEFINE(HAVE_VA_COPY, 1, [If your system have va_copy]) @@ -3148,7 +3150,7 @@ return 0; } int main(int argc, char **argv) { return f (0, 42); } - ]])],[ac_cv_func___va_copy="yes"],[ac_cv_func___va_copy="no"],[]) + ]])],[ac_cv_func___va_copy="yes"],[ac_cv_func___va_copy="no"],[:]) ) if test "$ac_cv_func___va_copy" = "yes" ; then AC_DEFINE(HAVE___VA_COPY, 1, [Some systems have __va_copy instead of va_copy]) diff -u -r -N squid-3.1.7/helpers/basic_auth/getpwnam/Makefile.in squid-3.1.8/helpers/basic_auth/getpwnam/Makefile.in --- squid-3.1.7/helpers/basic_auth/getpwnam/Makefile.in 2010-08-24 17:42:23.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/getpwnam/Makefile.in 2010-09-04 15:26:21.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = getpwname_auth$(EXEEXT) subdir = helpers/basic_auth/getpwnam ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -280,7 +281,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) getpwname_auth_SOURCES = getpwnam_auth.c LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/helpers/basic_auth/LDAP/Makefile.in squid-3.1.8/helpers/basic_auth/LDAP/Makefile.in --- squid-3.1.7/helpers/basic_auth/LDAP/Makefile.in 2010-08-24 17:42:21.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/LDAP/Makefile.in 2010-09-04 15:26:20.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = squid_ldap_auth$(EXEEXT) subdir = helpers/basic_auth/LDAP ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -284,7 +285,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = squid_ldap_auth.8 squid_ldap_auth_SOURCES = squid_ldap_auth.c EXTRA_DIST = squid_ldap_auth.8 config.test diff -u -r -N squid-3.1.7/helpers/basic_auth/MSNT/Makefile.in squid-3.1.8/helpers/basic_auth/MSNT/Makefile.in --- squid-3.1.7/helpers/basic_auth/MSNT/Makefile.in 2010-08-24 17:42:21.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/MSNT/Makefile.in 2010-09-04 15:26:20.000000000 +1200 @@ -37,6 +37,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = msnt_auth$(EXEEXT) subdir = helpers/basic_auth/MSNT ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -285,7 +286,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) MSNTAUTH_CONF = $(sysconfdir)/msntauth.conf msnt_auth_SOURCES = md4.c rfcnb-io.c rfcnb-util.c session.c msntauth.c \ msntauth.h smbdes.c smbencrypt.c smblib-util.c smblib.c \ diff -u -r -N squid-3.1.7/helpers/basic_auth/mswin_sspi/Makefile.in squid-3.1.8/helpers/basic_auth/mswin_sspi/Makefile.in --- squid-3.1.7/helpers/basic_auth/mswin_sspi/Makefile.in 2010-08-24 17:42:24.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/mswin_sspi/Makefile.in 2010-09-04 15:26:21.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = mswin_auth$(EXEEXT) subdir = helpers/basic_auth/mswin_sspi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -280,7 +281,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) mswin_auth_SOURCES = mswin_auth.c valid.c valid.h LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/helpers/basic_auth/NCSA/Makefile.in squid-3.1.8/helpers/basic_auth/NCSA/Makefile.in --- squid-3.1.7/helpers/basic_auth/NCSA/Makefile.in 2010-08-24 17:42:21.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/NCSA/Makefile.in 2010-09-04 15:26:20.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = ncsa_auth$(EXEEXT) subdir = helpers/basic_auth/NCSA ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -284,7 +285,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) ncsa_auth_SOURCES = ncsa_auth.c crypt_md5.c crypt_md5.h man_MANS = ncsa_auth.8 EXTRA_DIST = ncsa_auth.8 config.test diff -u -r -N squid-3.1.7/helpers/basic_auth/PAM/Makefile.in squid-3.1.8/helpers/basic_auth/PAM/Makefile.in --- squid-3.1.7/helpers/basic_auth/PAM/Makefile.in 2010-08-24 17:42:22.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/PAM/Makefile.in 2010-09-04 15:26:20.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = pam_auth$(EXEEXT) subdir = helpers/basic_auth/PAM ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -283,7 +284,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = pam_auth.8 EXTRA_DIST = pam_auth.8 config.test LDADD = \ diff -u -r -N squid-3.1.7/helpers/basic_auth/SASL/Makefile.in squid-3.1.8/helpers/basic_auth/SASL/Makefile.in --- squid-3.1.7/helpers/basic_auth/SASL/Makefile.in 2010-08-24 17:42:22.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/SASL/Makefile.in 2010-09-04 15:26:21.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = sasl_auth$(EXEEXT) subdir = helpers/basic_auth/SASL ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -280,7 +281,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) LDADD = \ $(top_builddir)/compat/libcompat.la \ -L$(top_builddir)/lib -lmiscutil \ diff -u -r -N squid-3.1.7/helpers/basic_auth/SMB/Makefile.in squid-3.1.8/helpers/basic_auth/SMB/Makefile.in --- squid-3.1.7/helpers/basic_auth/SMB/Makefile.in 2010-08-24 17:42:23.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/SMB/Makefile.in 2010-09-04 15:26:21.000000000 +1200 @@ -45,6 +45,7 @@ $(top_srcdir)/src/Common.am ChangeLog check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = smb_auth$(EXEEXT) subdir = helpers/basic_auth/SMB ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -286,7 +287,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) # SAMBAPREFIX must point to the directory where Samba has been installed. # By default, Samba is installed in /usr/local/samba. If you changed this diff -u -r -N squid-3.1.7/helpers/basic_auth/squid_radius_auth/Makefile.in squid-3.1.8/helpers/basic_auth/squid_radius_auth/Makefile.in --- squid-3.1.7/helpers/basic_auth/squid_radius_auth/Makefile.in 2010-08-24 17:42:24.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/squid_radius_auth/Makefile.in 2010-09-04 15:26:22.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = squid_radius_auth$(EXEEXT) subdir = helpers/basic_auth/squid_radius_auth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -284,7 +285,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = squid_radius_auth.8 EXTRA_DIST = squid_radius_auth.8 config.test squid_radius_auth_SOURCES = \ diff -u -r -N squid-3.1.7/helpers/basic_auth/YP/Makefile.in squid-3.1.8/helpers/basic_auth/YP/Makefile.in --- squid-3.1.7/helpers/basic_auth/YP/Makefile.in 2010-08-24 17:42:23.000000000 +1200 +++ squid-3.1.8/helpers/basic_auth/YP/Makefile.in 2010-09-04 15:26:21.000000000 +1200 @@ -43,6 +43,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = yp_auth$(EXEEXT) subdir = helpers/basic_auth/YP ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -279,7 +280,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) yp_auth_SOURCES = yp_auth.c nis_support.h nis_support.c LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/helpers/digest_auth/eDirectory/Makefile.in squid-3.1.8/helpers/digest_auth/eDirectory/Makefile.in --- squid-3.1.7/helpers/digest_auth/eDirectory/Makefile.in 2010-08-24 17:42:24.000000000 +1200 +++ squid-3.1.8/helpers/digest_auth/eDirectory/Makefile.in 2010-09-04 15:26:22.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = digest_edir_auth$(EXEEXT) subdir = helpers/digest_auth/eDirectory ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -283,7 +284,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) digest_edir_auth_SOURCES = digest_pw_auth.c \ digest_common.h \ ldap_backend.c \ diff -u -r -N squid-3.1.7/helpers/digest_auth/ldap/Makefile.in squid-3.1.8/helpers/digest_auth/ldap/Makefile.in --- squid-3.1.7/helpers/digest_auth/ldap/Makefile.in 2010-08-24 17:42:24.000000000 +1200 +++ squid-3.1.8/helpers/digest_auth/ldap/Makefile.in 2010-09-04 15:26:22.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = digest_ldap_auth$(EXEEXT) subdir = helpers/digest_auth/ldap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -283,7 +284,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) digest_ldap_auth_SOURCES = digest_pw_auth.c \ digest_common.h \ ldap_backend.c \ diff -u -r -N squid-3.1.7/helpers/digest_auth/password/Makefile.in squid-3.1.8/helpers/digest_auth/password/Makefile.in --- squid-3.1.7/helpers/digest_auth/password/Makefile.in 2010-08-24 17:42:25.000000000 +1200 +++ squid-3.1.8/helpers/digest_auth/password/Makefile.in 2010-09-04 15:26:22.000000000 +1200 @@ -44,6 +44,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = digest_pw_auth$(EXEEXT) subdir = helpers/digest_auth/password ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -282,7 +283,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) digest_pw_auth_SOURCES = digest_pw_auth.c \ digest_common.h \ text_backend.c \ diff -u -r -N squid-3.1.7/helpers/external_acl/ip_user/Makefile.in squid-3.1.8/helpers/external_acl/ip_user/Makefile.in --- squid-3.1.7/helpers/external_acl/ip_user/Makefile.in 2010-08-24 17:42:25.000000000 +1200 +++ squid-3.1.8/helpers/external_acl/ip_user/Makefile.in 2010-09-04 15:26:22.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = ip_user_check$(EXEEXT) subdir = helpers/external_acl/ip_user ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -273,7 +274,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) ip_user_check_SOURCES = \ dict.c \ ip_user.h \ diff -u -r -N squid-3.1.7/helpers/external_acl/ldap_group/Makefile.in squid-3.1.8/helpers/external_acl/ldap_group/Makefile.in --- squid-3.1.7/helpers/external_acl/ldap_group/Makefile.in 2010-08-24 17:42:26.000000000 +1200 +++ squid-3.1.8/helpers/external_acl/ldap_group/Makefile.in 2010-09-04 15:26:23.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am ChangeLog check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = squid_ldap_group$(EXEEXT) subdir = helpers/external_acl/ldap_group ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -276,7 +277,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = squid_ldap_group.8 EXTRA_DIST = squid_ldap_group.8 config.test squid_ldap_group_SOURCES = squid_ldap_group.c diff -u -r -N squid-3.1.7/helpers/external_acl/session/Makefile.in squid-3.1.8/helpers/external_acl/session/Makefile.in --- squid-3.1.7/helpers/external_acl/session/Makefile.in 2010-08-24 17:42:26.000000000 +1200 +++ squid-3.1.8/helpers/external_acl/session/Makefile.in 2010-09-04 15:26:23.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = squid_session$(EXEEXT) subdir = helpers/external_acl/session ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -275,7 +276,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = squid_session.8 EXTRA_DIST = squid_session.8 config.test squid_session_SOURCES = squid_session.c diff -u -r -N squid-3.1.7/helpers/external_acl/unix_group/Makefile.in squid-3.1.8/helpers/external_acl/unix_group/Makefile.in --- squid-3.1.7/helpers/external_acl/unix_group/Makefile.in 2010-08-24 17:42:27.000000000 +1200 +++ squid-3.1.8/helpers/external_acl/unix_group/Makefile.in 2010-09-04 15:26:23.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = squid_unix_group$(EXEEXT) subdir = helpers/external_acl/unix_group ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -275,7 +276,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) man_MANS = squid_unix_group.8 EXTRA_DIST = squid_unix_group.8 config.test squid_unix_group_SOURCES = check_group.c diff -u -r -N squid-3.1.7/helpers/negotiate_auth/mswin_sspi/Makefile.in squid-3.1.8/helpers/negotiate_auth/mswin_sspi/Makefile.in --- squid-3.1.7/helpers/negotiate_auth/mswin_sspi/Makefile.in 2010-08-24 17:42:27.000000000 +1200 +++ squid-3.1.8/helpers/negotiate_auth/mswin_sspi/Makefile.in 2010-09-04 15:26:24.000000000 +1200 @@ -42,6 +42,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = mswin_negotiate_auth$(EXEEXT) subdir = helpers/negotiate_auth/mswin_sspi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -278,7 +279,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) mswin_negotiate_auth_SOURCES = libnegotiatessp.c negotiate_auth.c negotiate.h LDADD = -L$(top_builddir)/lib -lsspwin32 -ladvapi32 -lmiscutil $(XTRA_LIBS) EXTRA_DIST = readme.txt config.test diff -u -r -N squid-3.1.7/helpers/ntlm_auth/fakeauth/Makefile.in squid-3.1.8/helpers/ntlm_auth/fakeauth/Makefile.in --- squid-3.1.7/helpers/ntlm_auth/fakeauth/Makefile.in 2010-08-24 17:42:28.000000000 +1200 +++ squid-3.1.8/helpers/ntlm_auth/fakeauth/Makefile.in 2010-09-04 15:26:24.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = fakeauth_auth$(EXEEXT) subdir = helpers/ntlm_auth/fakeauth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -272,7 +273,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) fakeauth_auth_SOURCES = fakeauth_auth.c ntlm.h LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/helpers/ntlm_auth/mswin_sspi/Makefile.in squid-3.1.8/helpers/ntlm_auth/mswin_sspi/Makefile.in --- squid-3.1.7/helpers/ntlm_auth/mswin_sspi/Makefile.in 2010-08-24 17:42:28.000000000 +1200 +++ squid-3.1.8/helpers/ntlm_auth/mswin_sspi/Makefile.in 2010-09-04 15:26:24.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = mswin_ntlm_auth$(EXEEXT) subdir = helpers/ntlm_auth/mswin_sspi ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -272,7 +273,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) mswin_ntlm_auth_SOURCES = libntlmssp.c ntlm_auth.c ntlm.h LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/helpers/ntlm_auth/smb_lm/Makefile.in squid-3.1.8/helpers/ntlm_auth/smb_lm/Makefile.in --- squid-3.1.7/helpers/ntlm_auth/smb_lm/Makefile.in 2010-08-24 17:42:29.000000000 +1200 +++ squid-3.1.8/helpers/ntlm_auth/smb_lm/Makefile.in 2010-09-04 15:26:24.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) libexec_PROGRAMS = ntlm_smb_lm_auth$(EXEEXT) subdir = helpers/ntlm_auth/smb_lm ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -284,8 +285,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) \ - -I$(srcdir)/smbval + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) -I$(srcdir)/smbval SUBDIRS = smbval ntlm_smb_lm_auth_SOURCES = libntlmssp.c ntlm_smb_lm_auth.c ntlm_smb_lm_auth.h LDADD = \ diff -u -r -N squid-3.1.7/helpers/ntlm_auth/smb_lm/smbval/Makefile.in squid-3.1.8/helpers/ntlm_auth/smb_lm/smbval/Makefile.in --- squid-3.1.7/helpers/ntlm_auth/smb_lm/smbval/Makefile.in 2010-08-24 17:42:30.000000000 +1200 +++ squid-3.1.8/helpers/ntlm_auth/smb_lm/smbval/Makefile.in 2010-09-04 15:26:25.000000000 +1200 @@ -38,6 +38,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = helpers/ntlm_auth/smb_lm/smbval ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -273,7 +274,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) noinst_LIBRARIES = libsmbvalid.a libsmbvalid_a_SOURCES = valid.c session.c rfcnb-util.c rfcnb-io.c \ smblib-util.c smblib.c smbencrypt.c smbdes.c md4.c byteorder.h \ diff -u -r -N squid-3.1.7/include/squid_types.h squid-3.1.8/include/squid_types.h --- squid-3.1.7/include/squid_types.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/include/squid_types.h 2010-09-04 15:25:57.000000000 +1200 @@ -106,4 +106,14 @@ #endif #endif +#ifndef PRIX64 +#ifdef _SQUID_MSWIN_ /* Windows native port using MSVCRT */ +#define PRIX64 "I64X" +#elif SIZEOF_INT64_T > SIZEOF_LONG +#define PRIX64 "llX" +#else +#define PRIX64 "lX" +#endif +#endif + #endif /* SQUID_TYPES_H */ diff -u -r -N squid-3.1.7/include/version.h squid-3.1.8/include/version.h --- squid-3.1.7/include/version.h 2010-08-24 17:43:37.000000000 +1200 +++ squid-3.1.8/include/version.h 2010-09-04 15:26:52.000000000 +1200 @@ -9,7 +9,7 @@ */ #ifndef SQUID_RELEASE_TIME -#define SQUID_RELEASE_TIME 1282628458 +#define SQUID_RELEASE_TIME 1283570743 #endif #ifndef APP_SHORTNAME diff -u -r -N squid-3.1.7/lib/Makefile.in squid-3.1.8/lib/Makefile.in --- squid-3.1.7/lib/Makefile.in 2010-08-24 17:42:32.000000000 +1200 +++ squid-3.1.8/lib/Makefile.in 2010-09-04 15:26:25.000000000 +1200 @@ -42,7 +42,8 @@ strsep.c strtoll.c tempnam.c check_PROGRAMS = tests/testAll$(EXEEXT) TESTS = tests/testAll$(EXEEXT) testHeaders -@USE_ESI_TRUE@am__append_1 = libTrie +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +@USE_ESI_TRUE@am__append_2 = libTrie subdir = lib ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -336,14 +337,9 @@ AM_CFLAGS = $(SQUID_CFLAGS) AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - -SUBDIRS = $(am__append_1) +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) +SUBDIRS = $(am__append_2) @ENABLE_XPROF_STATS_FALSE@XPROF_STATS_SOURCE = @ENABLE_XPROF_STATS_TRUE@XPROF_STATS_SOURCE = Profiler.c @ENABLE_WIN32SPECIFIC_FALSE@LIBSSPWIN32 = diff -u -r -N squid-3.1.7/libltdl/libltdl/lt_dlloader.h squid-3.1.8/libltdl/libltdl/lt_dlloader.h --- squid-3.1.7/libltdl/libltdl/lt_dlloader.h 2010-08-24 17:42:13.000000000 +1200 +++ squid-3.1.8/libltdl/libltdl/lt_dlloader.h 2010-09-04 15:26:17.000000000 +1200 @@ -31,7 +31,7 @@ #if !defined(LT_DLLOADER_H) #define LT_DLLOADER_H 1 -#include "libltdl/lt_system.h" +#include LT_BEGIN_C_DECLS diff -u -r -N squid-3.1.7/libltdl/libltdl/lt_error.h squid-3.1.8/libltdl/libltdl/lt_error.h --- squid-3.1.7/libltdl/libltdl/lt_error.h 2010-08-24 17:42:13.000000000 +1200 +++ squid-3.1.8/libltdl/libltdl/lt_error.h 2010-09-04 15:26:17.000000000 +1200 @@ -32,7 +32,7 @@ #if !defined(LT_ERROR_H) #define LT_ERROR_H 1 -#include "libltdl/lt_system.h" +#include LT_BEGIN_C_DECLS diff -u -r -N squid-3.1.7/libltdl/libltdl/slist.h squid-3.1.8/libltdl/libltdl/slist.h --- squid-3.1.7/libltdl/libltdl/slist.h 2010-08-24 17:42:13.000000000 +1200 +++ squid-3.1.8/libltdl/libltdl/slist.h 2010-09-04 15:26:17.000000000 +1200 @@ -42,8 +42,8 @@ #define SLIST_H 1 #if defined(LTDL) -# include "libltdl/lt__glibc.h" -# include "libltdl/lt_system.h" +# include +# include #else # define LT_SCOPE #endif diff -u -r -N squid-3.1.7/libltdl/ltdl.h squid-3.1.8/libltdl/ltdl.h --- squid-3.1.7/libltdl/ltdl.h 2010-08-24 17:42:13.000000000 +1200 +++ squid-3.1.8/libltdl/ltdl.h 2010-09-04 15:26:17.000000000 +1200 @@ -33,9 +33,9 @@ #if !defined(LTDL_H) #define LTDL_H 1 -#include "libltdl/lt_system.h" -#include "libltdl/lt_error.h" -#include "libltdl/lt_dlloader.h" +#include +#include +#include LT_BEGIN_C_DECLS diff -u -r -N squid-3.1.7/RELEASENOTES.html squid-3.1.8/RELEASENOTES.html --- squid-3.1.7/RELEASENOTES.html 2010-08-24 18:21:00.000000000 +1200 +++ squid-3.1.8/RELEASENOTES.html 2010-09-04 15:47:57.000000000 +1200 @@ -1,11 +1,11 @@ - - Squid 3.1.7 release notes + + Squid 3.1.8 release notes -

Squid 3.1.7 release notes

+

Squid 3.1.8 release notes

Squid Developers


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

1. Notice

-

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

+

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

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

@@ -89,7 +89,6 @@

  • The lack of some features available in Squid-2.x series. See the regression sections below for full details.
  • -
  • IPv6 split-stack support for Windows XP, MacOS X, OpenBSD and maybe others is not complete.
  • CVE-2009-0801 : NAT interception vulnerability to malicious clients.

@@ -97,7 +96,6 @@

Currently known issues which only depends on available developer time and may still be resolved in a future 3.1 release are:

    -
  • An ongoing slow FD leak introduced somewhere during the Squid-3.0 cycle.
  • Windows support is still largely missing.
  • AIX support for building with the IBM compiler is broken.
@@ -1337,8 +1335,8 @@
https_port intercept ssl-bump connection-auth[=on|off]

New port options. see http_port.

-
icap_service bypass=on|off|1|0 routing=on|off|1|0
-

New options 'bypass=' and 'routing='. +

icap_service bypass=on|off|1|0 routing=on|off|1|0 ipv6=on|off
+

New options 'bypass=', 'routing=' and 'ipv6='.

         bypass=on|off|1|0
                 If set to 'on' or '1', the ICAP service is treated as
@@ -1365,6 +1363,11 @@
 
                 Routing is not allowed by default: the ICAP X-Next-Services
                 response header is ignored.
+
+        ipv6=on|off
+                Only has effect on split-stack systems. The default on those systems
+                is to use IPv4-only connections. When set to 'on' this option will
+                make Squid use IPv6-only connections to contact this ICAP service.
         
 

diff -u -r -N squid-3.1.7/src/acl/Makefile.in squid-3.1.8/src/acl/Makefile.in --- squid-3.1.7/src/acl/Makefile.in 2010-08-24 17:42:37.000000000 +1200 +++ squid-3.1.8/src/acl/Makefile.in 2010-09-04 15:26:27.000000000 +1200 @@ -35,8 +35,9 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = -@ENABLE_SSL_TRUE@am__append_1 = $(SSL_ACLS) -@ENABLE_ARP_ACL_TRUE@am__append_2 = $(ARP_ACLS) +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +@ENABLE_SSL_TRUE@am__append_2 = $(SSL_ACLS) +@ENABLE_ARP_ACL_TRUE@am__append_3 = $(ARP_ACLS) subdir = src/acl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -318,13 +319,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders TESTS = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libapi.la libstate.la libacls.la libapi_la_SOURCES = \ Acl.cc \ @@ -357,8 +353,8 @@ RequestMimeType.cc RequestMimeType.h SourceAsn.h \ SourceDomain.cc SourceDomain.h SourceIp.cc SourceIp.h Tag.cc \ Tag.h Url.cc Url.h UrlPath.cc UrlPath.h UrlPort.cc UrlPort.h \ - UserData.cc UserData.h Gadgets.cc Gadgets.h $(am__append_1) \ - $(am__append_2) + UserData.cc UserData.h Gadgets.cc Gadgets.h $(am__append_2) \ + $(am__append_3) EXTRA_libacls_la_SOURCES = $(SSL_ACLS) $(ARP_ACLS) SSL_ACLS = \ CertificateData.cc \ diff -u -r -N squid-3.1.7/src/adaptation/AccessCheck.cc squid-3.1.8/src/adaptation/AccessCheck.cc --- squid-3.1.7/src/adaptation/AccessCheck.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/AccessCheck.cc 2010-09-04 15:25:57.000000000 +1200 @@ -23,8 +23,9 @@ if (Config::Enabled) { // the new check will call the callback and delete self, eventually - return AsyncStart(new AccessCheck( - ServiceFilter(method, vp, req, rep), cb, cbdata)); + AsyncJob::Start(new AccessCheck( // we do not store so not a CbcPointer + ServiceFilter(method, vp, req, rep), cb, cbdata)); + return true; } debugs(83, 3, HERE << "adaptation off, skipping"); diff -u -r -N squid-3.1.7/src/adaptation/ecap/Makefile.in squid-3.1.8/src/adaptation/ecap/Makefile.in --- squid-3.1.7/src/adaptation/ecap/Makefile.in 2010-08-24 17:42:38.000000000 +1200 +++ squid-3.1.8/src/adaptation/ecap/Makefile.in 2010-09-04 15:26:27.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/adaptation/ecap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -275,13 +276,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders TESTS = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libecap.la libecap_la_SOURCES = \ Config.h \ diff -u -r -N squid-3.1.7/src/adaptation/ecap/ServiceRep.cc squid-3.1.8/src/adaptation/ecap/ServiceRep.cc --- squid-3.1.7/src/adaptation/ecap/ServiceRep.cc 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/adaptation/ecap/ServiceRep.cc 2010-09-04 15:25:57.000000000 +1200 @@ -57,11 +57,11 @@ } Adaptation::Initiate * -Adaptation::Ecap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator, - HttpMsg *virgin, HttpRequest *cause) +Adaptation::Ecap::ServiceRep::makeXactLauncher(HttpMsg *virgin, + HttpRequest *cause) { Must(up()); - XactionRep *rep = new XactionRep(initiator, virgin, cause, Pointer(this)); + XactionRep *rep = new XactionRep(virgin, cause, Pointer(this)); XactionRep::AdapterXaction x(theService->makeXaction(rep)); rep->master(x); return rep; diff -u -r -N squid-3.1.7/src/adaptation/ecap/ServiceRep.h squid-3.1.8/src/adaptation/ecap/ServiceRep.h --- squid-3.1.7/src/adaptation/ecap/ServiceRep.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/ecap/ServiceRep.h 2010-09-04 15:25:57.000000000 +1200 @@ -33,7 +33,7 @@ virtual bool probed() const; virtual bool up() const; - Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause); + Adaptation::Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause); // the methods below can only be called on an up() service virtual bool wantsUrl(const String &urlPath) const; diff -u -r -N squid-3.1.7/src/adaptation/ecap/XactionRep.cc squid-3.1.8/src/adaptation/ecap/XactionRep.cc --- squid-3.1.7/src/adaptation/ecap/XactionRep.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/ecap/XactionRep.cc 2010-09-04 15:25:58.000000000 +1200 @@ -14,11 +14,11 @@ CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Ecap::XactionRep, XactionRep); -Adaptation::Ecap::XactionRep::XactionRep(Adaptation::Initiator *anInitiator, - HttpMsg *virginHeader, HttpRequest *virginCause, - const Adaptation::ServicePointer &aService): +Adaptation::Ecap::XactionRep::XactionRep( + HttpMsg *virginHeader, HttpRequest *virginCause, + const Adaptation::ServicePointer &aService): AsyncJob("Adaptation::Ecap::XactionRep"), - Adaptation::Initiate("Adaptation::Ecap::XactionRep", anInitiator), + Adaptation::Initiate("Adaptation::Ecap::XactionRep"), theService(aService), theVirginRep(virginHeader), theCauseRep(NULL), proxyingVb(opUndecided), proxyingAb(opUndecided), @@ -430,9 +430,8 @@ const BodyPipePointer &vp = theVirginRep.raw().body_pipe; if (!canAccessVb) buf.append("x", 1); - if (vp != NULL && vp->stillConsuming(this)) { + if (vp != NULL) { // XXX: but may not be stillConsuming() buf.append("Vb", 2); - buf.append(vp->status(), strlen(vp->status())); // XXX } else buf.append("V.", 2); } @@ -441,9 +440,8 @@ MessageRep *rep = dynamic_cast(theAnswerRep.get()); Must(rep); const BodyPipePointer &ap = rep->raw().body_pipe; - if (ap != NULL && ap->stillProducing(this)) { + if (ap != NULL) { // XXX: but may not be stillProducing() buf.append(" Ab", 3); - buf.append(ap->status(), strlen(ap->status())); // XXX } else buf.append(" A.", 3); } diff -u -r -N squid-3.1.7/src/adaptation/ecap/XactionRep.h squid-3.1.8/src/adaptation/ecap/XactionRep.h --- squid-3.1.7/src/adaptation/ecap/XactionRep.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/ecap/XactionRep.h 2010-09-04 15:25:57.000000000 +1200 @@ -28,7 +28,7 @@ public BodyConsumer, public BodyProducer { public: - XactionRep(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service); + XactionRep(HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServicePointer &service); virtual ~XactionRep(); typedef libecap::shared_ptr AdapterXaction; diff -u -r -N squid-3.1.7/src/adaptation/icap/Launcher.cc squid-3.1.8/src/adaptation/icap/Launcher.cc --- squid-3.1.7/src/adaptation/icap/Launcher.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/Launcher.cc 2010-09-04 15:25:57.000000000 +1200 @@ -15,9 +15,9 @@ Adaptation::Icap::Launcher::Launcher(const char *aTypeName, - Adaptation::Initiator *anInitiator, Adaptation::ServicePointer &aService): + Adaptation::ServicePointer &aService): AsyncJob(aTypeName), - Adaptation::Initiate(aTypeName, anInitiator), + Adaptation::Initiate(aTypeName), theService(aService), theXaction(0), theLaunches(0) { } @@ -31,7 +31,7 @@ { Adaptation::Initiate::start(); - Must(theInitiator); + Must(theInitiator.set()); launchXaction("first"); } @@ -47,7 +47,7 @@ if (theLaunches >= TheConfig.repeat_limit) x->disableRepeats("over icap_retry_limit"); theXaction = initiateAdaptation(x); - Must(theXaction); + Must(initiated(theXaction)); } void Adaptation::Icap::Launcher::noteAdaptationAnswer(HttpMsg *message) @@ -76,7 +76,7 @@ Must(done()); // swanSong will notify the initiator } -void Adaptation::Icap::Launcher::noteXactAbort(XactAbortInfo &info) +void Adaptation::Icap::Launcher::noteXactAbort(XactAbortInfo info) { debugs(93,5, HERE << "theXaction:" << theXaction << " launches: " << theLaunches); @@ -102,10 +102,10 @@ void Adaptation::Icap::Launcher::swanSong() { - if (theInitiator) + if (theInitiator.set()) tellQueryAborted(true); // always final here because abnormal - if (theXaction) + if (theXaction.set()) clearAdaptation(theXaction); Adaptation::Initiate::swanSong(); diff -u -r -N squid-3.1.7/src/adaptation/icap/Launcher.h squid-3.1.8/src/adaptation/icap/Launcher.h --- squid-3.1.7/src/adaptation/icap/Launcher.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/Launcher.h 2010-09-04 15:25:57.000000000 +1200 @@ -73,7 +73,7 @@ class Launcher: public Adaptation::Initiate, public Adaptation::Initiator { public: - Launcher(const char *aTypeName, Adaptation::Initiator *anInitiator, Adaptation::ServicePointer &aService); + Launcher(const char *aTypeName, Adaptation::ServicePointer &aService); virtual ~Launcher(); // Adaptation::Initiate: asynchronous communication with the initiator @@ -81,7 +81,7 @@ // Adaptation::Initiator: asynchronous communication with the current transaction virtual void noteAdaptationAnswer(HttpMsg *message); - virtual void noteXactAbort(XactAbortInfo &info); + virtual void noteXactAbort(XactAbortInfo info); private: bool canRetry(XactAbortInfo &info) const; //< true if can retry in the case of persistent connection failures @@ -100,7 +100,7 @@ void launchXaction(const char *xkind); Adaptation::ServicePointer theService; ///< ICAP service for all launches - Adaptation::Initiate *theXaction; ///< current ICAP transaction + CbcPointer theXaction; ///< current ICAP transaction int theLaunches; // the number of transaction launches }; @@ -114,6 +114,10 @@ XactAbortInfo(const XactAbortInfo &); ~XactAbortInfo(); + std::ostream &print(std::ostream &os) const { + return os << isRetriable << ',' << isRepeatable; + } + HttpRequest *icapRequest; HttpReply *icapReply; bool isRetriable; @@ -123,31 +127,13 @@ XactAbortInfo &operator =(const XactAbortInfo &); // undefined }; -/* required by UnaryMemFunT */ -inline std::ostream &operator << (std::ostream &os, Adaptation::Icap::XactAbortInfo info) +inline +std::ostream & +operator <<(std::ostream &os, const XactAbortInfo &xai) { - // Nothing, it is unused - return os; + return xai.print(os); } -/// A Dialer class used to schedule the Adaptation::Icap::Launcher::noteXactAbort call -class XactAbortCall: public UnaryMemFunT -{ -public: - typedef void (Adaptation::Icap::Launcher::*DialMethod)(Adaptation::Icap::XactAbortInfo &); - XactAbortCall(Adaptation::Icap::Launcher *launcer, DialMethod aMethod, - const Adaptation::Icap::XactAbortInfo &info): - UnaryMemFunT(launcer, NULL, info), - dialMethod(aMethod) {} - virtual void print(std::ostream &os) const { os << '(' << "retriable:" << arg1.isRetriable << ", repeatable:" << arg1.isRepeatable << ')'; } - -public: - DialMethod dialMethod; - -protected: - virtual void doDial() { (object->*dialMethod)(arg1); } -}; - } // namespace Icap } // namespace Adaptation diff -u -r -N squid-3.1.7/src/adaptation/icap/Makefile.in squid-3.1.8/src/adaptation/icap/Makefile.in --- squid-3.1.7/src/adaptation/icap/Makefile.in 2010-08-24 17:42:39.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/Makefile.in 2010-09-04 15:26:27.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/adaptation/icap ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -276,13 +277,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders TESTS = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libicap.la libicap_la_SOURCES = \ Client.cc \ diff -u -r -N squid-3.1.7/src/adaptation/icap/ModXact.cc squid-3.1.8/src/adaptation/icap/ModXact.cc --- squid-3.1.7/src/adaptation/icap/ModXact.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/ModXact.cc 2010-09-04 15:25:57.000000000 +1200 @@ -37,10 +37,10 @@ memset(this, 0, sizeof(*this)); } -Adaptation::Icap::ModXact::ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, +Adaptation::Icap::ModXact::ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::Icap::ServiceRep::Pointer &aService): AsyncJob("Adaptation::Icap::ModXact"), - Adaptation::Icap::Xaction("Adaptation::Icap::ModXact", anInitiator, aService), + Adaptation::Icap::Xaction("Adaptation::Icap::ModXact", aService), virginConsumed(0), bodyParser(NULL), canStartBypass(false), // too early @@ -94,8 +94,9 @@ Must(!state.serviceWaiting); debugs(93, 7, HERE << "will wait for the ICAP service" << status()); state.serviceWaiting = true; - AsyncCall::Pointer call = asyncCall(93,5, "Adaptation::Icap::ModXact::noteServiceReady", - MemFun(this, &Adaptation::Icap::ModXact::noteServiceReady)); + typedef NullaryMemFunT Dialer; + AsyncCall::Pointer call = JobCallback(93,5, + Dialer, this, Adaptation::Icap::ModXact::noteServiceReady); service().callWhenReady(call); } @@ -1681,9 +1682,9 @@ /* Adaptation::Icap::ModXactLauncher */ -Adaptation::Icap::ModXactLauncher::ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer aService): +Adaptation::Icap::ModXactLauncher::ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer aService): AsyncJob("Adaptation::Icap::ModXactLauncher"), - Adaptation::Icap::Launcher("Adaptation::Icap::ModXactLauncher", anInitiator, aService) + Adaptation::Icap::Launcher("Adaptation::Icap::ModXactLauncher", aService) { virgin.setHeader(virginHeader); virgin.setCause(virginCause); @@ -1695,7 +1696,7 @@ Adaptation::Icap::ServiceRep::Pointer s = dynamic_cast(theService.getRaw()); Must(s != NULL); - return new Adaptation::Icap::ModXact(this, virgin.header, virgin.cause, s); + return new Adaptation::Icap::ModXact(virgin.header, virgin.cause, s); } void Adaptation::Icap::ModXactLauncher::swanSong() diff -u -r -N squid-3.1.7/src/adaptation/icap/ModXact.h squid-3.1.8/src/adaptation/icap/ModXact.h --- squid-3.1.7/src/adaptation/icap/ModXact.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/ModXact.h 2010-09-04 15:25:57.000000000 +1200 @@ -136,7 +136,7 @@ { public: - ModXact(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s); + ModXact(HttpMsg *virginHeader, HttpRequest *virginCause, ServiceRep::Pointer &s); // BodyProducer methods virtual void noteMoreBodySpaceAvailable(BodyPipe::Pointer); @@ -161,7 +161,6 @@ InOut virgin; InOut adapted; -protected: // bypasses exceptions if needed and possible virtual void callException(const std::exception &e); @@ -322,7 +321,7 @@ class ModXactLauncher: public Launcher { public: - ModXactLauncher(Adaptation::Initiator *anInitiator, HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s); + ModXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause, Adaptation::ServicePointer s); protected: virtual Xaction *createXaction(); diff -u -r -N squid-3.1.7/src/adaptation/icap/OptXact.cc squid-3.1.8/src/adaptation/icap/OptXact.cc --- squid-3.1.7/src/adaptation/icap/OptXact.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/OptXact.cc 2010-09-04 15:25:58.000000000 +1200 @@ -16,9 +16,9 @@ CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, OptXactLauncher); -Adaptation::Icap::OptXact::OptXact(Adaptation::Initiator *anInitiator, Adaptation::Icap::ServiceRep::Pointer &aService): +Adaptation::Icap::OptXact::OptXact(Adaptation::Icap::ServiceRep::Pointer &aService): AsyncJob("Adaptation::Icap::OptXact"), - Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", anInitiator, aService) + Adaptation::Icap::Xaction("Adaptation::Icap::OptXact", aService) { } @@ -111,9 +111,9 @@ /* Adaptation::Icap::OptXactLauncher */ -Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::Initiator *anInitiator, Adaptation::ServicePointer aService): +Adaptation::Icap::OptXactLauncher::OptXactLauncher(Adaptation::ServicePointer aService): AsyncJob("Adaptation::Icap::OptXactLauncher"), - Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", anInitiator, aService) + Adaptation::Icap::Launcher("Adaptation::Icap::OptXactLauncher", aService) { } @@ -122,5 +122,5 @@ Adaptation::Icap::ServiceRep::Pointer s = dynamic_cast(theService.getRaw()); Must(s != NULL); - return new Adaptation::Icap::OptXact(this, s); + return new Adaptation::Icap::OptXact(s); } diff -u -r -N squid-3.1.7/src/adaptation/icap/OptXact.h squid-3.1.8/src/adaptation/icap/OptXact.h --- squid-3.1.7/src/adaptation/icap/OptXact.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/OptXact.h 2010-09-04 15:25:58.000000000 +1200 @@ -51,7 +51,7 @@ { public: - OptXact(Adaptation::Initiator *anInitiator, ServiceRep::Pointer &aService); + OptXact(ServiceRep::Pointer &aService); protected: virtual void start(); @@ -76,7 +76,7 @@ class OptXactLauncher: public Launcher { public: - OptXactLauncher(Adaptation::Initiator *anInitiator, Adaptation::ServicePointer aService); + OptXactLauncher(Adaptation::ServicePointer aService); protected: virtual Xaction *createXaction(); diff -u -r -N squid-3.1.7/src/adaptation/icap/ServiceRep.cc squid-3.1.8/src/adaptation/icap/ServiceRep.cc --- squid-3.1.7/src/adaptation/icap/ServiceRep.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/ServiceRep.cc 2010-09-04 15:25:57.000000000 +1200 @@ -135,7 +135,7 @@ if (!detached()) updateScheduled = false; - if (detached() || theOptionsFetcher) { + if (detached() || theOptionsFetcher.set()) { debugs(93,5, HERE << "ignores options update " << status()); return; } @@ -188,7 +188,7 @@ i.callback = cb; theClients.push_back(i); - if (theOptionsFetcher || notifying) + if (theOptionsFetcher.set() || notifying) return; // do nothing, we will be picked up in noteTimeToNotify() if (needNewOptions()) @@ -200,7 +200,7 @@ void Adaptation::Icap::ServiceRep::scheduleNotification() { debugs(93,7, HERE << "will notify " << theClients.size() << " clients"); - CallJobHere(93, 5, this, Adaptation::Icap::ServiceRep::noteTimeToNotify); + CallJobHere(93, 5, this, Adaptation::Icap::ServiceRep, noteTimeToNotify); } bool Adaptation::Icap::ServiceRep::needNewOptions() const @@ -294,7 +294,7 @@ // we are receiving ICAP OPTIONS response headers here or NULL on failures void Adaptation::Icap::ServiceRep::noteAdaptationAnswer(HttpMsg *msg) { - Must(theOptionsFetcher); + Must(initiated(theOptionsFetcher)); clearAdaptation(theOptionsFetcher); Must(msg); @@ -314,13 +314,23 @@ void Adaptation::Icap::ServiceRep::noteAdaptationQueryAbort(bool) { - Must(theOptionsFetcher); + Must(initiated(theOptionsFetcher)); clearAdaptation(theOptionsFetcher); debugs(93,3, HERE << "failed to fetch options " << status()); handleNewOptions(0); } +// we (a) must keep trying to get OPTIONS and (b) are RefCounted so we +// must keep our job alive (XXX: until nobody needs us) +void Adaptation::Icap::ServiceRep::callException(const std::exception &e) +{ + clearAdaptation(theOptionsFetcher); + debugs(93,2, "ICAP probably failed to fetch options (" << e.what() << + ")" << status()); + handleNewOptions(0); +} + void Adaptation::Icap::ServiceRep::handleNewOptions(Adaptation::Icap::Options *newOptions) { // new options may be NULL @@ -337,9 +347,9 @@ Must(!theOptionsFetcher); debugs(93,6, HERE << "will get new options " << status()); - // XXX: second "this" is "self"; this works but may stop if API changes - theOptionsFetcher = initiateAdaptation(new Adaptation::Icap::OptXactLauncher(this, this)); - Must(theOptionsFetcher); + // XXX: "this" here is "self"; works until refcounting API changes + theOptionsFetcher = initiateAdaptation( + new Adaptation::Icap::OptXactLauncher(this)); // TODO: timeout in case Adaptation::Icap::OptXact never calls us back? // Such a timeout should probably be a generic AsyncStart feature. } @@ -406,10 +416,10 @@ } Adaptation::Initiate * -Adaptation::Icap::ServiceRep::makeXactLauncher(Adaptation::Initiator *initiator, - HttpMsg *virgin, HttpRequest *cause) +Adaptation::Icap::ServiceRep::makeXactLauncher(HttpMsg *virgin, + HttpRequest *cause) { - return new Adaptation::Icap::ModXactLauncher(initiator, virgin, cause, this); + return new Adaptation::Icap::ModXactLauncher(virgin, cause, this); } // returns a temporary string depicting service status, for debugging @@ -438,7 +448,7 @@ if (detached()) buf.append(",detached", 9); - if (theOptionsFetcher) + if (theOptionsFetcher.set()) buf.append(",fetch", 6); if (notifying) diff -u -r -N squid-3.1.7/src/adaptation/icap/ServiceRep.h squid-3.1.8/src/adaptation/icap/ServiceRep.h --- squid-3.1.7/src/adaptation/icap/ServiceRep.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/ServiceRep.h 2010-09-04 15:25:57.000000000 +1200 @@ -94,7 +94,7 @@ virtual bool probed() const; // see comments above virtual bool up() const; // see comments above - virtual Adaptation::Initiate *makeXactLauncher(Adaptation::Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause); + virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause); void callWhenReady(AsyncCall::Pointer &cb); @@ -107,6 +107,7 @@ //AsyncJob virtual methods virtual bool doneAll() const { return Adaptation::Initiator::doneAll() && false;} + virtual void callException(const std::exception &e); virtual void detach(); virtual bool detached() const; @@ -131,7 +132,7 @@ Clients theClients; // all clients waiting for a call back Options *theOptions; - Adaptation::Initiate *theOptionsFetcher; // pending ICAP OPTIONS transaction + CbcPointer theOptionsFetcher; // pending ICAP OPTIONS transaction time_t theLastUpdate; // time the options were last updated static const int TheSessionFailureLimit; diff -u -r -N squid-3.1.7/src/adaptation/icap/Xaction.cc squid-3.1.8/src/adaptation/icap/Xaction.cc --- squid-3.1.7/src/adaptation/icap/Xaction.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/Xaction.cc 2010-09-04 15:25:57.000000000 +1200 @@ -24,9 +24,10 @@ //CBDATA_NAMESPACED_CLASS_INIT(Adaptation::Icap, Xaction); -Adaptation::Icap::Xaction::Xaction(const char *aTypeName, Adaptation::Initiator *anInitiator, Adaptation::Icap::ServiceRep::Pointer &aService): +Adaptation::Icap::Xaction::Xaction(const char *aTypeName, + Adaptation::Icap::ServiceRep::Pointer &aService): AsyncJob(aTypeName), - Adaptation::Initiate(aTypeName, anInitiator), + Adaptation::Initiate(aTypeName), icapRequest(NULL), icapReply(NULL), attempts(0), @@ -105,7 +106,8 @@ // fake the connect callback // TODO: can we sync call Adaptation::Icap::Xaction::noteCommConnected here instead? typedef CommCbMemFunT Dialer; - Dialer dialer(this, &Adaptation::Icap::Xaction::noteCommConnected); + CbcPointer self(this); + Dialer dialer(self, &Adaptation::Icap::Xaction::noteCommConnected); dialer.params.fd = connection; dialer.params.flag = COMM_OK; // fake other parameters by copying from the existing connection @@ -136,20 +138,19 @@ // TODO: service bypass status may differ from that of a transaction typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommTimedout", - TimeoutDialer(this,&Adaptation::Icap::Xaction::noteCommTimedout)); - + AsyncCall::Pointer timeoutCall = JobCallback(93, 5, + TimeoutDialer, this, Adaptation::Icap::Xaction::noteCommTimedout); commSetTimeout(connection, TheConfig.connect_timeout( service().cfg().bypass), timeoutCall); typedef CommCbMemFunT CloseDialer; - closer = asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommClosed", - CloseDialer(this,&Adaptation::Icap::Xaction::noteCommClosed)); + closer = JobCallback(93, 5, + CloseDialer, this, Adaptation::Icap::Xaction::noteCommClosed); comm_add_close_handler(connection, closer); typedef CommCbMemFunT ConnectDialer; - connector = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommConnected", - ConnectDialer(this, &Adaptation::Icap::Xaction::noteCommConnected)); + connector = JobCallback(93,3, + ConnectDialer, this, Adaptation::Icap::Xaction::noteCommConnected); commConnectStart(connection, s.cfg().host.termedBuf(), s.cfg().port, connector); } @@ -233,8 +234,8 @@ { // comm module will free the buffer typedef CommCbMemFunT Dialer; - writer = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommWrote", - Dialer(this, &Adaptation::Icap::Xaction::noteCommWrote)); + writer = JobCallback(93,3, + Dialer, this, Adaptation::Icap::Xaction::noteCommWrote); comm_write_mbuf(connection, &buf, writer); updateTimeout(); @@ -316,8 +317,8 @@ // XXX: why does Config.Timeout lacks a write timeout? // TODO: service bypass status may differ from that of a transaction typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer call = asyncCall(93, 5, "Adaptation::Icap::Xaction::noteCommTimedout", - TimeoutDialer(this,&Adaptation::Icap::Xaction::noteCommTimedout)); + AsyncCall::Pointer call = JobCallback(93,5, + TimeoutDialer, this, Adaptation::Icap::Xaction::noteCommTimedout); commSetTimeout(connection, TheConfig.io_timeout(service().cfg().bypass), call); @@ -340,8 +341,8 @@ * here instead of reading directly into readBuf.buf. */ typedef CommCbMemFunT Dialer; - reader = asyncCall(93,3, "Adaptation::Icap::Xaction::noteCommRead", - Dialer(this, &Adaptation::Icap::Xaction::noteCommRead)); + reader = JobCallback(93,3, + Dialer, this, Adaptation::Icap::Xaction::noteCommRead); comm_read(connection, commBuf, readBuf.spaceSize(), reader); updateTimeout(); @@ -431,7 +432,7 @@ void Adaptation::Icap::Xaction::noteInitiatorAborted() { - if (theInitiator) { + if (theInitiator.set()) { clearInitiator(); mustStop("initiator aborted"); } @@ -464,8 +465,7 @@ if (commBuf) memFreeBuf(commBufSize, commBuf); - if (theInitiator) - tellQueryAborted(); + tellQueryAborted(); maybeLog(); @@ -474,12 +474,15 @@ void Adaptation::Icap::Xaction::tellQueryAborted() { - Adaptation::Icap::Launcher *l = dynamic_cast(theInitiator.ptr()); - Adaptation::Icap::XactAbortInfo abortInfo(icapRequest, icapReply, retriable(), repeatable()); - CallJob(91, 5, __FILE__, __LINE__, - "Adaptation::Icap::Launcher::noteXactAbort", - XactAbortCall(l, &Adaptation::Icap::Launcher::noteXactAbort, abortInfo) ); - clearInitiator(); + if (theInitiator.set()) { + Adaptation::Icap::XactAbortInfo abortInfo(icapRequest, icapReply, + retriable(), repeatable()); + Launcher *launcher = dynamic_cast(theInitiator.get()); + // launcher may be nil if initiator is invalid + CallJobHere1(91,5, CbcPointer(launcher), + Launcher, noteXactAbort, abortInfo); + clearInitiator(); + } } diff -u -r -N squid-3.1.7/src/adaptation/icap/Xaction.h squid-3.1.8/src/adaptation/icap/Xaction.h --- squid-3.1.7/src/adaptation/icap/Xaction.h 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/adaptation/icap/Xaction.h 2010-09-04 15:25:57.000000000 +1200 @@ -63,7 +63,7 @@ { public: - Xaction(const char *aTypeName, Adaptation::Initiator *anInitiator, ServiceRep::Pointer &aService); + Xaction(const char *aTypeName, ServiceRep::Pointer &aService); virtual ~Xaction(); void disableRetries(); @@ -125,10 +125,12 @@ // useful for debugging virtual bool fillVirginHttpHeader(MemBuf&) const; +public: // custom exception handling and end-of-call checks virtual void callException(const std::exception &e); virtual void callEnd(); +protected: // logging void setOutcome(const XactOutcome &xo); virtual void finalizeLogInfo(); diff -u -r -N squid-3.1.7/src/adaptation/Initiate.cc squid-3.1.8/src/adaptation/Initiate.cc --- squid-3.1.7/src/adaptation/Initiate.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/Initiate.cc 2010-09-04 15:25:58.000000000 +1200 @@ -6,6 +6,7 @@ #include "HttpMsg.h" #include "adaptation/Initiator.h" #include "adaptation/Initiate.h" +#include "base/AsyncJobCalls.h" namespace Adaptation { @@ -17,11 +18,13 @@ public: typedef UnaryMemFunT Parent; - AnswerDialer(Initiator *obj, Parent::Method meth, HttpMsg *msg): - Parent(obj, meth, msg) { HTTPMSGLOCK(arg1); } - AnswerDialer(const AnswerDialer &d): - Parent(d) { HTTPMSGLOCK(arg1); } + AnswerDialer(const Parent::JobPointer &job, Parent::Method meth, + HttpMsg *msg): Parent(job, meth, msg) { HTTPMSGLOCK(arg1); } + AnswerDialer(const AnswerDialer &d): Parent(d) { HTTPMSGLOCK(arg1); } virtual ~AnswerDialer() { HTTPMSGUNLOCK(arg1); } + +private: + AnswerDialer &operator =(const AnswerDialer &); // not implemented }; } // namespace Adaptation @@ -29,10 +32,8 @@ /* Initiate */ -Adaptation::Initiate::Initiate(const char *aTypeName, Initiator *anInitiator): - AsyncJob(aTypeName), theInitiator(anInitiator) +Adaptation::Initiate::Initiate(const char *aTypeName): AsyncJob(aTypeName) { - assert(theInitiator); } Adaptation::Initiate::~Initiate() @@ -42,12 +43,21 @@ // can assert(!(wasStarted && theInitiator)). } +void +Adaptation::Initiate::initiator(const CbcPointer &i) +{ + Must(!theInitiator); + Must(i.valid()); + theInitiator = i; +} + + // internal cleanup void Adaptation::Initiate::swanSong() { debugs(93, 5, HERE << "swan sings" << status()); - if (theInitiator) { + if (theInitiator.set()) { debugs(93, 3, HERE << "fatal failure; sending abort notification"); tellQueryAborted(true); // final by default } @@ -57,27 +67,22 @@ void Adaptation::Initiate::clearInitiator() { - if (theInitiator) - theInitiator.clear(); + theInitiator.clear(); } void Adaptation::Initiate::sendAnswer(HttpMsg *msg) { assert(msg); - if (theInitiator.isThere()) { - CallJob(93, 5, __FILE__, __LINE__, "Initiator::noteAdaptAnswer", - AnswerDialer(theInitiator.ptr(), &Initiator::noteAdaptationAnswer, msg)); - } + CallJob(93, 5, __FILE__, __LINE__, "Initiator::noteAdaptationAnswer", + AnswerDialer(theInitiator, &Initiator::noteAdaptationAnswer, msg)); clearInitiator(); } void Adaptation::Initiate::tellQueryAborted(bool final) { - if (theInitiator.isThere()) { - CallJobHere1(93, 5, theInitiator.ptr(), - Initiator::noteAdaptationQueryAbort, final); - } + CallJobHere1(93, 5, theInitiator, + Initiator, noteAdaptationQueryAbort, final); clearInitiator(); } @@ -85,57 +90,3 @@ { return AsyncJob::status(); // for now } - - -/* InitiatorHolder */ - -Adaptation::InitiatorHolder::InitiatorHolder(Initiator *anInitiator): - prime(0), cbdata(0) -{ - if (anInitiator) { - cbdata = cbdataReference(anInitiator->toCbdata()); - prime = anInitiator; - } -} - -Adaptation::InitiatorHolder::InitiatorHolder(const InitiatorHolder &anInitiator): - prime(0), cbdata(0) -{ - if (anInitiator != NULL && cbdataReferenceValid(anInitiator.cbdata)) { - cbdata = cbdataReference(anInitiator.cbdata); - prime = anInitiator.prime; - } -} - -Adaptation::InitiatorHolder::~InitiatorHolder() -{ - clear(); -} - -void Adaptation::InitiatorHolder::clear() -{ - if (prime) { - prime = NULL; - cbdataReferenceDone(cbdata); - } -} - -Adaptation::Initiator *Adaptation::InitiatorHolder::ptr() -{ - assert(isThere()); - return prime; -} - -bool -Adaptation::InitiatorHolder::isThere() -{ - return prime && cbdataReferenceValid(cbdata); -} - -// should not be used -Adaptation::InitiatorHolder & -Adaptation::InitiatorHolder::operator =(const InitiatorHolder &anInitiator) -{ - assert(false); - return *this; -} diff -u -r -N squid-3.1.7/src/adaptation/Initiate.h squid-3.1.8/src/adaptation/Initiate.h --- squid-3.1.7/src/adaptation/Initiate.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/Initiate.h 2010-09-04 15:25:57.000000000 +1200 @@ -1,8 +1,8 @@ #ifndef SQUID_ADAPTATION__INITIATE_H #define SQUID_ADAPTATION__INITIATE_H -#include "base/AsyncCall.h" #include "base/AsyncJob.h" +#include "base/CbcPointer.h" #include "adaptation/forward.h" class HttpMsg; @@ -10,37 +10,6 @@ namespace Adaptation { -/* Initiator holder associtates an initiator with its cbdata. It is used as - * a temporary hack to make cbdata work with multiple inheritance. We need - * this hack because we cannot know whether the initiator pointer is still - * valid without dereferencing it to call toCbdata() - * TODO: JobDialer uses the same trick. Factor out or move this code. */ -class InitiatorHolder -{ -public: - InitiatorHolder(Initiator *anInitiator); - InitiatorHolder(const InitiatorHolder &anInitiator); - ~InitiatorHolder(); - - void clear(); - - // to make comparison with NULL possible - operator void*() { return prime; } - bool operator == (void *) const { return prime == NULL; } - bool operator != (void *) const { return prime != NULL; } - bool operator !() const { return !prime; } - - bool isThere(); // we have a valid initiator pointer - Initiator *ptr(); // asserts isThere() - void *theCbdata() { return cbdata;} - -private: - InitiatorHolder &operator =(const InitiatorHolder &anInitiator); - - Initiator *prime; - void *cbdata; -}; - /* * The Initiate is a common base for queries or transactions * initiated by an Initiator. This interface exists to allow an @@ -56,9 +25,11 @@ { public: - Initiate(const char *aTypeName, Initiator *anInitiator); + Initiate(const char *aTypeName); virtual ~Initiate(); + void initiator(const CbcPointer &i); ///< sets initiator + // communication with the initiator virtual void noteInitiatorAborted() = 0; @@ -71,7 +42,7 @@ virtual const char *status() const; // for debugging - InitiatorHolder theInitiator; + CbcPointer theInitiator; private: Initiate(const Initiate &); // no definition diff -u -r -N squid-3.1.7/src/adaptation/Initiator.cc squid-3.1.8/src/adaptation/Initiator.cc --- squid-3.1.7/src/adaptation/Initiator.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/Initiator.cc 2010-09-04 15:25:57.000000000 +1200 @@ -5,27 +5,26 @@ #include "squid.h" #include "adaptation/Initiate.h" #include "adaptation/Initiator.h" +#include "base/AsyncJobCalls.h" -Adaptation::Initiate * -Adaptation::Initiator::initiateAdaptation(Adaptation::Initiate *x) +CbcPointer +Adaptation::Initiator::initiateAdaptation(Initiate *x) { - if ((x = dynamic_cast(Initiate::AsyncStart(x)))) - x = cbdataReference(x); - return x; + CbcPointer i(x); + x->initiator(this); + Start(x); + return i; } void -Adaptation::Initiator::clearAdaptation(Initiate *&x) +Adaptation::Initiator::clearAdaptation(CbcPointer &x) { - assert(x); - cbdataReferenceDone(x); + x.clear(); } void -Adaptation::Initiator::announceInitiatorAbort(Initiate *&x) +Adaptation::Initiator::announceInitiatorAbort(CbcPointer &x) { - if (x) { - CallJobHere(93, 5, x, Initiate::noteInitiatorAborted); - clearAdaptation(x); - } + CallJobHere(93, 5, x, Initiate, noteInitiatorAborted); + clearAdaptation(x); } diff -u -r -N squid-3.1.7/src/adaptation/Initiator.h squid-3.1.8/src/adaptation/Initiator.h --- squid-3.1.7/src/adaptation/Initiator.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/Initiator.h 2010-09-04 15:25:57.000000000 +1200 @@ -2,6 +2,7 @@ #define SQUID_ADAPTATION__INITIATOR_H #include "base/AsyncJob.h" +#include "base/CbcPointer.h" #include "adaptation/forward.h" /* @@ -32,13 +33,17 @@ virtual void noteAdaptationQueryAbort(bool final) = 0; protected: - Initiate *initiateAdaptation(Initiate *x); // locks and returns x + ///< starts freshly created initiate and returns a safe pointer to it + CbcPointer initiateAdaptation(Initiate *x); - // done with x (and not calling announceInitiatorAbort) - void clearAdaptation(Initiate *&x); // unlocks x + /// clears the pointer (does not call announceInitiatorAbort) + void clearAdaptation(CbcPointer &x); - // inform the transaction about abnormal termination and clear it - void announceInitiatorAbort(Initiate *&x); // unlocks x + /// inform the transaction about abnormal termination and clear the pointer + void announceInitiatorAbort(CbcPointer &x); + + /// Must(initiated(initiate)) instead of Must(initiate.set()), for clarity + bool initiated(const CbcPointer &job) const { return job.set(); } }; } // namespace Adaptation diff -u -r -N squid-3.1.7/src/adaptation/Iterator.cc squid-3.1.8/src/adaptation/Iterator.cc --- squid-3.1.7/src/adaptation/Iterator.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/Iterator.cc 2010-09-04 15:25:57.000000000 +1200 @@ -14,11 +14,11 @@ #include "adaptation/ServiceGroups.h" -Adaptation::Iterator::Iterator(Adaptation::Initiator *anInitiator, - HttpMsg *aMsg, HttpRequest *aCause, - const ServiceGroupPointer &aGroup): +Adaptation::Iterator::Iterator( + HttpMsg *aMsg, HttpRequest *aCause, + const ServiceGroupPointer &aGroup): AsyncJob("Iterator"), - Adaptation::Initiate("Iterator", anInitiator), + Adaptation::Initiate("Iterator"), theGroup(aGroup), theMsg(HTTPMSGLOCK(aMsg)), theCause(aCause ? HTTPMSGLOCK(aCause) : NULL), @@ -69,8 +69,8 @@ debugs(93,5, HERE << "using adaptation service: " << service->cfg().key); theLauncher = initiateAdaptation( - service->makeXactLauncher(this, theMsg, theCause)); - Must(theLauncher); + service->makeXactLauncher(theMsg, theCause)); + Must(initiated(theLauncher)); Must(!done()); } @@ -148,10 +148,10 @@ void Adaptation::Iterator::swanSong() { - if (theInitiator) + if (theInitiator.set()) tellQueryAborted(true); // abnormal condition that should not happen - if (theLauncher) + if (initiated(theLauncher)) clearAdaptation(theLauncher); Adaptation::Initiate::swanSong(); diff -u -r -N squid-3.1.7/src/adaptation/Iterator.h squid-3.1.8/src/adaptation/Iterator.h --- squid-3.1.7/src/adaptation/Iterator.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/adaptation/Iterator.h 2010-09-04 15:25:57.000000000 +1200 @@ -21,8 +21,7 @@ class Iterator: public Initiate, public Initiator { public: - Iterator(Adaptation::Initiator *anInitiator, - HttpMsg *virginHeader, HttpRequest *virginCause, + Iterator(HttpMsg *virginHeader, HttpRequest *virginCause, const Adaptation::ServiceGroupPointer &aGroup); virtual ~Iterator(); @@ -52,7 +51,7 @@ ServicePlan thePlan; ///< which services to use and in what order HttpMsg *theMsg; ///< the message being adapted (virgin for each step) HttpRequest *theCause; ///< the cause of the original virgin message - Adaptation::Initiate *theLauncher; ///< current transaction launcher + CbcPointer theLauncher; ///< current transaction launcher int iterations; ///< number of steps initiated bool adapted; ///< whether the virgin message has been replaced diff -u -r -N squid-3.1.7/src/adaptation/Makefile.am squid-3.1.8/src/adaptation/Makefile.am --- squid-3.1.7/src/adaptation/Makefile.am 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/adaptation/Makefile.am 2010-09-04 15:25:57.000000000 +1200 @@ -12,11 +12,6 @@ SUBDIRS += ecap endif -if USE_LOADABLE_MODULES -## LTDL headers require their local include path... -INCLUDES += $(INCLTDL) -endif - noinst_LTLIBRARIES = libadaptation.la ## start with the code shared among all adaptation schemes diff -u -r -N squid-3.1.7/src/adaptation/Makefile.in squid-3.1.8/src/adaptation/Makefile.in --- squid-3.1.7/src/adaptation/Makefile.in 2010-08-24 17:42:38.000000000 +1200 +++ squid-3.1.8/src/adaptation/Makefile.in 2010-09-04 15:26:27.000000000 +1200 @@ -35,9 +35,9 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = -@USE_ICAP_CLIENT_TRUE@am__append_1 = icap -@USE_ECAP_TRUE@am__append_2 = ecap -@USE_LOADABLE_MODULES_TRUE@am__append_3 = $(INCLTDL) +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +@USE_ICAP_CLIENT_TRUE@am__append_2 = icap +@USE_ECAP_TRUE@am__append_3 = ecap subdir = src/adaptation ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -291,8 +291,8 @@ CLEANFILES = testHeaders TESTS = testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_3) -SUBDIRS = $(am__append_1) $(am__append_2) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) +SUBDIRS = $(am__append_2) $(am__append_3) noinst_LTLIBRARIES = libadaptation.la libadaptation_la_SOURCES = \ AccessCheck.cc \ diff -u -r -N squid-3.1.7/src/adaptation/Service.h squid-3.1.8/src/adaptation/Service.h --- squid-3.1.7/src/adaptation/Service.h 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/adaptation/Service.h 2010-09-04 15:25:57.000000000 +1200 @@ -31,7 +31,7 @@ virtual bool broken() const; virtual bool up() const = 0; // see comments above - virtual Initiate *makeXactLauncher(Initiator *, HttpMsg *virginHeader, HttpRequest *virginCause) = 0; + virtual Initiate *makeXactLauncher(HttpMsg *virginHeader, HttpRequest *virginCause) = 0; typedef void Callback(void *data, Pointer &service); void callWhenReady(Callback *cb, void *data); diff -u -r -N squid-3.1.7/src/auth/Makefile.in squid-3.1.8/src/auth/Makefile.in --- squid-3.1.7/src/auth/Makefile.in 2010-08-24 17:42:39.000000000 +1200 +++ squid-3.1.8/src/auth/Makefile.in 2010-09-04 15:26:28.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/auth ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -295,7 +296,8 @@ CLEANFILES = testHeaders TESTS = testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) noinst_LTLIBRARIES = libauth.la libacls.la $(AUTH_LIBS_TO_BUILD) EXTRA_LTLIBRARIES = libbasic.la libdigest.la libntlm.la libnegotiate.la libauth_la_SOURCES = \ diff -u -r -N squid-3.1.7/src/base/AsyncJobCalls.h squid-3.1.8/src/base/AsyncJobCalls.h --- squid-3.1.7/src/base/AsyncJobCalls.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/base/AsyncJobCalls.h 2010-09-04 15:25:57.000000000 +1200 @@ -7,6 +7,66 @@ #define SQUID_ASYNCJOBCALLS_H #include "base/AsyncJob.h" +#include "base/CbcPointer.h" + +/** + \ingroup AsyncJobAPI + * This is a base class for all job call dialers. It does all the job + * dialing logic (debugging, handling exceptions, etc.) except for calling + * the job method. The latter requires knowing the number and type of method + * parameters. Thus, we add a dial() virtual method that the MemFunT templates + * below implement for us, calling the job's method with the right params. + */ +template +class JobDialer: public CallDialer +{ +public: + typedef Job DestClass; + typedef CbcPointer JobPointer; + + JobDialer(const JobPointer &aJob); + JobDialer(const JobDialer &d); + + virtual bool canDial(AsyncCall &call); + void dial(AsyncCall &call); + + JobPointer job; + +protected: + virtual void doDial() = 0; // actually calls the job method + +private: + // not implemented and should not be needed + JobDialer &operator =(const JobDialer &); +}; + +/// schedule an async job call using a dialer; use CallJobHere macros instead +template +bool +CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine, + const char *callName, const Dialer &dialer) +{ + AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer); + return ScheduleCall(fileName, fileLine, call); +} + + +#define CallJobHere(debugSection, debugLevel, job, Class, method) \ + CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \ + (#Class "::" #method), \ + JobMemFun((job), &Class::method)) + +#define CallJobHere1(debugSection, debugLevel, job, Class, method, arg1) \ + CallJob((debugSection), (debugLevel), __FILE__, __LINE__, \ + (#Class "::" #method), \ + JobMemFun((job), &Class::method, (arg1))) + + +/// Convenience macro to create a Dialer-based job callback +#define JobCallback(dbgSection, dbgLevel, Dialer, job, method) \ + asyncCall((dbgSection), (dbgLevel), #method, \ + Dialer(CbcPointer(job), &method)) + /* * *MemFunT are member function (i.e., class method) wrappers. They store @@ -24,42 +84,40 @@ // Arity names are from http://en.wikipedia.org/wiki/Arity -template -class NullaryMemFunT: public JobDialer +template +class NullaryMemFunT: public JobDialer { public: - typedef void (C::*Method)(); - explicit NullaryMemFunT(C *anObject, Method aMethod): - JobDialer(anObject), object(anObject), method(aMethod) {} + typedef void (Job::*Method)(); + explicit NullaryMemFunT(const CbcPointer &aJob, Method aMethod): + JobDialer(aJob), method(aMethod) {} virtual void print(std::ostream &os) const { os << "()"; } public: - C *object; Method method; protected: - virtual void doDial() { (object->*method)(); } + virtual void doDial() { ((&(*this->job))->*method)(); } }; -template -class UnaryMemFunT: public JobDialer +template +class UnaryMemFunT: public JobDialer { public: - typedef void (C::*Method)(Argument1); - explicit UnaryMemFunT(C *anObject, Method aMethod, const Argument1 &anArg1): - JobDialer(anObject), - object(anObject), method(aMethod), arg1(anArg1) {} + typedef void (Job::*Method)(Argument1); + explicit UnaryMemFunT(const CbcPointer &aJob, Method aMethod, + const Argument1 &anArg1): JobDialer(aJob), + method(aMethod), arg1(anArg1) {} virtual void print(std::ostream &os) const { os << '(' << arg1 << ')'; } public: - C *object; Method method; Argument1 arg1; protected: - virtual void doDial() { (object->*method)(arg1); } + virtual void doDial() { ((&(*this->job))->*method)(arg1); } }; // ... add more as needed @@ -71,17 +129,57 @@ template NullaryMemFunT -MemFun(C *object, typename NullaryMemFunT::Method method) +JobMemFun(const CbcPointer &job, typename NullaryMemFunT::Method method) { - return NullaryMemFunT(object, method); + return NullaryMemFunT(job, method); } template UnaryMemFunT -MemFun(C *object, typename UnaryMemFunT::Method method, - Argument1 arg1) +JobMemFun(const CbcPointer &job, typename UnaryMemFunT::Method method, + Argument1 arg1) +{ + return UnaryMemFunT(job, method, arg1); +} + + +// inlined methods + +template +JobDialer::JobDialer(const JobPointer &aJob): job(aJob) +{ +} + +template +JobDialer::JobDialer(const JobDialer &d): CallDialer(d), job(d.job) { - return UnaryMemFunT(object, method, arg1); +} + +template +bool +JobDialer::canDial(AsyncCall &call) +{ + if (!job) + return call.cancel("job gone"); + + return job->canBeCalled(call); +} + +template +void +JobDialer::dial(AsyncCall &call) +{ + job->callStart(call); + + try { + doDial(); + } catch (const std::exception &e) { + debugs(call.debugSection, 3, + HERE << call.name << " threw exception: " << e.what()); + job->callException(e); + } + + job->callEnd(); // may delete job } #endif /* SQUID_ASYNCJOBCALLS_H */ diff -u -r -N squid-3.1.7/src/base/AsyncJob.cc squid-3.1.8/src/base/AsyncJob.cc --- squid-3.1.7/src/base/AsyncJob.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/base/AsyncJob.cc 2010-09-04 15:25:57.000000000 +1200 @@ -3,6 +3,7 @@ */ #include "squid.h" +#include "base/AsyncJobCalls.h" #include "cbdata.h" #include "MemBuf.h" #include "TextException.h" @@ -12,10 +13,10 @@ unsigned int AsyncJob::TheLastId = 0; -AsyncJob *AsyncJob::AsyncStart(AsyncJob *job) +AsyncJob::Pointer AsyncJob::Start(AsyncJob *j) { - assert(job); - CallJobHere(93, 5, job, AsyncJob::noteStart); + AsyncJob::Pointer job(j); + CallJobHere(93, 5, job, AsyncJob, start); return job; } @@ -29,11 +30,6 @@ { } -void AsyncJob::noteStart() -{ - start(); -} - void AsyncJob::start() { } @@ -52,8 +48,9 @@ // there is no call wrapper waiting for our return, so we fake it debugs(93, 5, typeName << " will delete this, reason: " << stopReason); + CbcPointer self(this); AsyncCall::Pointer fakeCall = asyncCall(93,4, "FAKE-deleteThis", - MemFun(this, &AsyncJob::deleteThis, aReason)); + JobMemFun(self, &AsyncJob::deleteThis, aReason)); inCall = fakeCall; callEnd(); // delete fakeCall; @@ -164,60 +161,3 @@ } -/* JobDialer */ - -JobDialer::JobDialer(AsyncJob *aJob): job(NULL), lock(NULL) -{ - if (aJob) { - lock = cbdataReference(aJob->toCbdata()); - job = aJob; - } -} - -JobDialer::JobDialer(const JobDialer &d): CallDialer(d), - job(NULL), lock(NULL) -{ - if (d.lock && cbdataReferenceValid(d.lock)) { - lock = cbdataReference(d.lock); - Must(d.job); - job = d.job; - } -} - -JobDialer::~JobDialer() -{ - cbdataReferenceDone(lock); // lock may be NULL -} - - -bool -JobDialer::canDial(AsyncCall &call) -{ - if (!lock) - return call.cancel("job was gone before the call"); - - if (!cbdataReferenceValid(lock)) - return call.cancel("job gone after the call"); - - Must(job); - return job->canBeCalled(call); -} - -void -JobDialer::dial(AsyncCall &call) -{ - Must(lock && cbdataReferenceValid(lock)); // canDial() checks for this - Must(job); - - job->callStart(call); - - try { - doDial(); - } catch (const std::exception &e) { - debugs(call.debugSection, 3, - HERE << call.name << " threw exception: " << e.what()); - job->callException(e); - } - - job->callEnd(); // may delete job -} diff -u -r -N squid-3.1.7/src/base/AsyncJob.h squid-3.1.8/src/base/AsyncJob.h --- squid-3.1.7/src/base/AsyncJob.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/base/AsyncJob.h 2010-09-04 15:25:57.000000000 +1200 @@ -8,6 +8,9 @@ #include "base/AsyncCall.h" #include "TextException.h" +template +class CbcPointer; + /** \defgroup AsyncJobAPI Async-Jobs API \par @@ -29,17 +32,20 @@ */ /// \ingroup AsyncJobAPI +/// Base class for all asynchronous jobs class AsyncJob { - public: - static AsyncJob *AsyncStart(AsyncJob *job); // use this to start jobs + typedef CbcPointer Pointer; +public: AsyncJob(const char *aTypeName); virtual ~AsyncJob(); virtual void *toCbdata() = 0; - void noteStart(); // calls virtual start + + /// starts a freshly created job (i.e., makes the job asynchronous) + static Pointer Start(AsyncJob *job); protected: // XXX: temporary method to replace "delete this" in jobs-in-transition. @@ -72,56 +78,4 @@ static unsigned int TheLastId; }; - -/** - \ingroup AsyncJobAPI - * This is a base class for all job call dialers. It does all the job - * dialing logic (debugging, handling exceptions, etc.) except for calling - * the job method. The latter is not possible without templates and we - * want to keep this class simple and template-free. Thus, we add a dial() - * virtual method that the JobCallT template below will implement for us, - * calling the job. - */ -class JobDialer: public CallDialer -{ -public: - JobDialer(AsyncJob *aJob); - JobDialer(const JobDialer &d); - virtual ~JobDialer(); - - virtual bool canDial(AsyncCall &call); - void dial(AsyncCall &call); - - AsyncJob *job; - void *lock; // job's cbdata - -protected: - virtual void doDial() = 0; // actually calls the job method - -private: - // not implemented and should not be needed - JobDialer &operator =(const JobDialer &); -}; - -#include "base/AsyncJobCalls.h" - -template -bool -CallJob(int debugSection, int debugLevel, const char *fileName, int fileLine, - const char *callName, const Dialer &dialer) -{ - AsyncCall::Pointer call = asyncCall(debugSection, debugLevel, callName, dialer); - return ScheduleCall(fileName, fileLine, call); -} - - -#define CallJobHere(debugSection, debugLevel, job, method) \ - CallJob((debugSection), (debugLevel), __FILE__, __LINE__, #method, \ - MemFun((job), &method)) - -#define CallJobHere1(debugSection, debugLevel, job, method, arg1) \ - CallJob((debugSection), (debugLevel), __FILE__, __LINE__, #method, \ - MemFun((job), &method, (arg1))) - - #endif /* SQUID_ASYNC_JOB_H */ diff -u -r -N squid-3.1.7/src/base/CbcPointer.h squid-3.1.8/src/base/CbcPointer.h --- squid-3.1.7/src/base/CbcPointer.h 1970-01-01 12:00:00.000000000 +1200 +++ squid-3.1.8/src/base/CbcPointer.h 2010-09-04 15:25:58.000000000 +1200 @@ -0,0 +1,162 @@ +/* + * $Id$ + */ + +#ifndef SQUID_CBC_POINTER_H +#define SQUID_CBC_POINTER_H + +#include "TextException.h" +#include "cbdata.h" + +/** + \ingroup CBDATAAPI + * + * Safely points to a cbdata-protected class (cbc), such as an AsyncJob. + * When a cbc we communicate with disappears without + * notice or a notice has not reached us yet, this class prevents + * dereferencing the pointer to the gone cbc object. + */ +template +class CbcPointer +{ +public: + CbcPointer(); // a nil pointer + CbcPointer(Cbc *aCbc); + CbcPointer(const CbcPointer &p); + ~CbcPointer(); + + Cbc *raw() const; ///< a temporary raw Cbc pointer; may be invalid + Cbc *get() const; ///< a temporary valid raw Cbc pointer or NULL + Cbc &operator *() const; ///< a valid Cbc reference or exception + Cbc *operator ->() const; ///< a valid Cbc pointer or exception + + // no bool operator because set() != valid() + bool set() const { return cbc != NULL; } ///< was set but may be invalid + Cbc *valid() const { return get(); } ///< was set and is valid + bool operator !() const { return !valid(); } ///< invalid or was not set + bool operator ==(const CbcPointer &o) const { return lock == o.lock; } + + CbcPointer &operator =(const CbcPointer &p); + + /// support converting a child cbc pointer into a parent cbc pointer + template + CbcPointer(const CbcPointer &o): cbc(o.raw()), lock(NULL) { + if (o.valid()) + lock = cbdataReference(o->toCbdata()); + } + + /// support assigning a child cbc pointer to a parent cbc pointer + template + CbcPointer &operator =(const CbcPointer &o) { + if (this != &o) { // assignment to self + clear(); + cbc = o.raw(); // so that set() is accurate + if (o.valid()) + lock = cbdataReference(o->toCbdata()); + } + return *this; + } + + void clear(); ///< make pointer not set; does not invalidate cbdata + + std::ostream &print(std::ostream &os) const; + +private: + Cbc *cbc; // a possibly invalid pointer to a cbdata class + void *lock; // a valid pointer to cbc's cbdata or nil +}; + +template +inline +std::ostream &operator <<(std::ostream &os, const CbcPointer &p) +{ + return p.print(os); +} + +// inlined methods + +template +CbcPointer::CbcPointer(): cbc(NULL), lock(NULL) +{ +} + +template +CbcPointer::CbcPointer(Cbc *aCbc): cbc(aCbc), lock(NULL) +{ + if (cbc) + lock = cbdataReference(cbc->toCbdata()); +} + +template +CbcPointer::CbcPointer(const CbcPointer &d): cbc(d.cbc), lock(NULL) +{ + if (d.lock && cbdataReferenceValid(d.lock)) + lock = cbdataReference(d.lock); +} + +template +CbcPointer::~CbcPointer() +{ + clear(); +} + +template +CbcPointer &CbcPointer::operator =(const CbcPointer &d) +{ + if (this != &d) { // assignment to self + clear(); + cbc = d.cbc; + if (d.lock && cbdataReferenceValid(d.lock)) + lock = cbdataReference(d.lock); + } + return *this; +} + +template +void +CbcPointer::clear() +{ + cbdataReferenceDone(lock); // lock may be nil before and will be nil after + cbc = NULL; +} + +template +Cbc * +CbcPointer::raw() const +{ + return cbc; +} + +template +Cbc * +CbcPointer::get() const +{ + return (lock && cbdataReferenceValid(lock)) ? cbc : NULL; +} + +template +Cbc & +CbcPointer::operator *() const +{ + Cbc *c = get(); + Must(c); + return *c; +} + +template +Cbc * +CbcPointer::operator ->() const +{ + Cbc *c = get(); + Must(c); + return c; +} + +template +std::ostream &CbcPointer::print(std::ostream &os) const +{ + return os << cbc << '/' << lock; +} + + +#endif /* SQUID_CBC_POINTER_H */ diff -u -r -N squid-3.1.7/src/base/Makefile.am squid-3.1.8/src/base/Makefile.am --- squid-3.1.7/src/base/Makefile.am 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/base/Makefile.am 2010-09-04 15:25:57.000000000 +1200 @@ -11,4 +11,5 @@ AsyncJob.cc \ AsyncJobCalls.h \ AsyncCallQueue.cc \ - AsyncCallQueue.h + AsyncCallQueue.h \ + CbcPointer.h diff -u -r -N squid-3.1.7/src/base/Makefile.in squid-3.1.8/src/base/Makefile.in --- squid-3.1.7/src/base/Makefile.in 2010-08-24 17:42:39.000000000 +1200 +++ squid-3.1.8/src/base/Makefile.in 2010-09-04 15:26:28.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/base ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -274,13 +275,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders TESTS = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libbase.la libbase_la_SOURCES = \ AsyncCall.cc \ @@ -289,7 +285,8 @@ AsyncJob.cc \ AsyncJobCalls.h \ AsyncCallQueue.cc \ - AsyncCallQueue.h + AsyncCallQueue.h \ + CbcPointer.h all: all-am diff -u -r -N squid-3.1.7/src/BodyPipe.cc squid-3.1.8/src/BodyPipe.cc --- squid-3.1.7/src/BodyPipe.cc 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/BodyPipe.cc 2010-09-04 15:25:58.000000000 +1200 @@ -1,5 +1,6 @@ #include "squid.h" +#include "base/AsyncJobCalls.h" #include "BodyPipe.h" #include "TextException.h" @@ -40,8 +41,9 @@ public: typedef UnaryMemFunT Parent; - BodyProducerDialer(BodyProducer *aProducer, Parent::Method aHandler, - BodyPipe::Pointer bp): Parent(aProducer, aHandler, bp) {} + BodyProducerDialer(const BodyProducer::Pointer &aProducer, + Parent::Method aHandler, BodyPipe::Pointer bp): + Parent(aProducer, aHandler, bp) {} virtual bool canDial(AsyncCall &call); }; @@ -54,8 +56,9 @@ public: typedef UnaryMemFunT Parent; - BodyConsumerDialer(BodyConsumer *aConsumer, Parent::Method aHandler, - BodyPipe::Pointer bp): Parent(aConsumer, aHandler, bp) {} + BodyConsumerDialer(const BodyConsumer::Pointer &aConsumer, + Parent::Method aHandler, BodyPipe::Pointer bp): + Parent(aConsumer, aHandler, bp) {} virtual bool canDial(AsyncCall &call); }; @@ -66,7 +69,7 @@ if (!Parent::canDial(call)) return false; - BodyProducer *producer = object; + const BodyProducer::Pointer &producer = job; BodyPipe::Pointer pipe = arg1; if (!pipe->stillProducing(producer)) { debugs(call.debugSection, call.debugLevel, HERE << producer << @@ -83,7 +86,7 @@ if (!Parent::canDial(call)) return false; - BodyConsumer *consumer = object; + const BodyConsumer::Pointer &consumer = job; BodyPipe::Pointer pipe = arg1; if (!pipe->stillConsuming(consumer)) { debugs(call.debugSection, call.debugLevel, HERE << consumer << @@ -183,9 +186,9 @@ void BodyPipe::clearProducer(bool atEof) { - if (theProducer) { + if (theProducer.set()) { debugs(91,7, HERE << "clearing BodyPipe producer" << status()); - theProducer = NULL; + theProducer.clear(); if (atEof) { if (!bodySizeKnown()) theBodySize = thePutSize; @@ -215,10 +218,10 @@ } bool -BodyPipe::setConsumerIfNotLate(Consumer *aConsumer) +BodyPipe::setConsumerIfNotLate(const Consumer::Pointer &aConsumer) { assert(!theConsumer); - assert(aConsumer); + assert(aConsumer.set()); // but might be invalid // TODO: convert this into an exception and remove IfNotLate suffix // If there is something consumed already, we are in an auto-consuming mode @@ -247,9 +250,9 @@ void BodyPipe::clearConsumer() { - if (theConsumer) { + if (theConsumer.set()) { debugs(91,7, HERE << "clearing consumer" << status()); - theConsumer = NULL; + theConsumer.clear(); if (consumedSize() && !exhausted()) { AsyncCall::Pointer call= asyncCall(91, 7, "BodyProducer::noteBodyConsumerAborted", @@ -377,7 +380,7 @@ void BodyPipe::scheduleBodyDataNotification() { - if (theConsumer) { + if (theConsumer.valid()) { // TODO: allow asyncCall() to check this instead AsyncCall::Pointer call = asyncCall(91, 7, "BodyConsumer::noteMoreBodyDataAvailable", BodyConsumerDialer(theConsumer, @@ -389,7 +392,7 @@ void BodyPipe::scheduleBodyEndNotification() { - if (theConsumer) { + if (theConsumer.valid()) { // TODO: allow asyncCall() to check this instead if (bodySizeKnown() && bodySize() == thePutSize) { AsyncCall::Pointer call = asyncCall(91, 7, "BodyConsumer::noteBodyProductionEnded", @@ -423,10 +426,10 @@ outputBuffer.Printf(" %d+%d", (int)theBuf.contentSize(), (int)theBuf.spaceSize()); outputBuffer.Printf(" pipe%p", this); - if (theProducer) - outputBuffer.Printf(" prod%p", theProducer); - if (theConsumer) - outputBuffer.Printf(" cons%p", theConsumer); + if (theProducer.set()) + outputBuffer.Printf(" prod%p", theProducer.get()); + if (theConsumer.set()) + outputBuffer.Printf(" cons%p", theConsumer.get()); if (mustAutoConsume) outputBuffer.append(" A", 2); diff -u -r -N squid-3.1.7/src/BodyPipe.h squid-3.1.8/src/BodyPipe.h --- squid-3.1.7/src/BodyPipe.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/BodyPipe.h 2010-09-04 15:25:57.000000000 +1200 @@ -3,8 +3,8 @@ #define SQUID_BODY_PIPE_H #include "MemBuf.h" -#include "base/AsyncCall.h" #include "base/AsyncJob.h" +#include "base/CbcPointer.h" class BodyPipe; @@ -14,6 +14,8 @@ class BodyProducer: virtual public AsyncJob { public: + typedef CbcPointer Pointer; + BodyProducer():AsyncJob("BodyProducer") {} virtual ~BodyProducer() {} @@ -31,6 +33,8 @@ class BodyConsumer: virtual public AsyncJob { public: + typedef CbcPointer Pointer; + BodyConsumer():AsyncJob("BodyConsumer") {} virtual ~BodyConsumer() {} @@ -100,16 +104,16 @@ bool mayNeedMoreData() const { return !bodySizeKnown() || needsMoreData(); } bool needsMoreData() const { return bodySizeKnown() && unproducedSize() > 0; } uint64_t unproducedSize() const; // size of still unproduced data - bool stillProducing(const Producer *producer) const { return theProducer == producer; } + bool stillProducing(const Producer::Pointer &producer) const { return theProducer == producer; } // called by consumers - bool setConsumerIfNotLate(Consumer *aConsumer); + bool setConsumerIfNotLate(const Consumer::Pointer &aConsumer); void clearConsumer(); // aborts if still piping size_t getMoreData(MemBuf &buf); void consume(size_t size); bool expectMoreAfter(uint64_t offset) const; bool exhausted() const; // saw eof/abort and all data consumed - bool stillConsuming(const Consumer *consumer) const { return theConsumer == consumer; } + bool stillConsuming(const Consumer::Pointer &consumer) const { return theConsumer == consumer; } // start or continue consuming when there is no consumer void enableAutoConsumption(); @@ -135,8 +139,8 @@ private: int64_t theBodySize; // expected total content length, if known - Producer *theProducer; // content producer, if any - Consumer *theConsumer; // content consumer, if any + Producer::Pointer theProducer; // content producer, if any + Consumer::Pointer theConsumer; // content consumer, if any uint64_t thePutSize; // ever-increasing total uint64_t theGetSize; // ever-increasing total diff -u -r -N squid-3.1.7/src/cf.data.pre squid-3.1.8/src/cf.data.pre --- squid-3.1.7/src/cf.data.pre 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/cf.data.pre 2010-09-04 15:25:57.000000000 +1200 @@ -1314,8 +1314,8 @@ Example where normal_service_net uses the TOS value 0x00 and good_service_net uses 0x20 - acl normal_service_net src 10.0.0.0/255.255.255.0 - acl good_service_net src 10.0.1.0/255.255.255.0 + acl normal_service_net src 10.0.0.0/24 + acl good_service_net src 10.0.1.0/24 tcp_outgoing_tos 0x00 normal_service_net tcp_outgoing_tos 0x20 good_service_net @@ -1325,8 +1325,8 @@ The TOS/DSCP byte must be exactly that - a octet value 0 - 255, or "default" to use whatever default your host has. Note that in - practice often only values 0 - 63 is usable as the two highest bits - have been redefined for use by ECN (RFC3168). + practice often only multiples of 4 is usable as the two rightmost bits + have been redefined for use by ECN (RFC 3168 section 23.1). Processing proceeds in the order specified, and stops at first fully matching line. diff -u -r -N squid-3.1.7/src/client_side.cc squid-3.1.8/src/client_side.cc --- squid-3.1.7/src/client_side.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/client_side.cc 2010-09-04 15:25:57.000000000 +1200 @@ -210,8 +210,8 @@ makeSpaceAvailable(); typedef CommCbMemFunT Dialer; - reader = asyncCall(33, 5, "ConnStateData::clientReadRequest", - Dialer(this, &ConnStateData::clientReadRequest)); + reader = JobCallback(33, 5, + Dialer, this, ConnStateData::clientReadRequest); comm_read(fd, in.addressToReadInto(), getAvailableBufferLength(), reader); } @@ -1358,8 +1358,8 @@ * Set the timeout BEFORE calling clientReadRequest(). */ typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(33, 5, "ConnStateData::requestTimeout", - TimeoutDialer(this, &ConnStateData::requestTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(33, 5, + TimeoutDialer, this, ConnStateData::requestTimeout); commSetTimeout(fd, Config.Timeout.persistent_request, timeoutCall); readSomeData(); @@ -1910,8 +1910,7 @@ if (!request.parseHeader(HttpParserHdrBuf(hp), HttpParserHdrSz(hp))) return false; - return request.header.has(HDR_TRANSFER_ENCODING) && - request.header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','); + return request.header.chunked(); } @@ -2313,6 +2312,7 @@ bool notedUseOfBuffer = false; bool tePresent = false; bool deChunked = false; + bool mustReplyToOptions = false; bool unsupportedTe = false; /* We have an initial client stream in place should it be needed */ @@ -2425,8 +2425,12 @@ } else conn->cleanDechunkingRequest(); + if (method == METHOD_TRACE || method == METHOD_OPTIONS) + request->max_forwards = request->header.getInt64(HDR_MAX_FORWARDS); + + mustReplyToOptions = (method == METHOD_OPTIONS) && (request->max_forwards == 0); unsupportedTe = tePresent && !deChunked; - if (!urlCheckRequest(request) || unsupportedTe) { + if (!urlCheckRequest(request) || mustReplyToOptions || unsupportedTe) { clientStreamNode *node = context->getClientReplyContext(); clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); @@ -2928,8 +2932,8 @@ * if we don't close() here, we still need a timeout handler! */ typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(33, 5, "ConnStateData::requestTimeout", - TimeoutDialer(this,&ConnStateData::requestTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(33, 5, + TimeoutDialer, this, ConnStateData::requestTimeout); commSetTimeout(io.fd, 30, timeoutCall); /* @@ -3055,16 +3059,16 @@ connState = connStateCreate(&details->peer, &details->me, newfd, s); typedef CommCbMemFunT Dialer; - AsyncCall::Pointer call = asyncCall(33, 5, "ConnStateData::connStateClosed", - Dialer(connState, &ConnStateData::connStateClosed)); + AsyncCall::Pointer call = JobCallback(33, 5, + Dialer, connState, ConnStateData::connStateClosed); comm_add_close_handler(newfd, call); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(details->peer, FQDN_LOOKUP_IF_MISS); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(33, 5, "ConnStateData::requestTimeout", - TimeoutDialer(connState,&ConnStateData::requestTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(33, 5, + TimeoutDialer, connState, ConnStateData::requestTimeout); commSetTimeout(newfd, Config.Timeout.read, timeoutCall); #if USE_IDENT @@ -3266,16 +3270,16 @@ ConnStateData *connState = connStateCreate(details->peer, details->me, newfd, &s->http); typedef CommCbMemFunT Dialer; - AsyncCall::Pointer call = asyncCall(33, 5, "ConnStateData::connStateClosed", - Dialer(connState, &ConnStateData::connStateClosed)); + AsyncCall::Pointer call = JobCallback(33, 5, + Dialer, connState, ConnStateData::connStateClosed); comm_add_close_handler(newfd, call); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(details->peer, FQDN_LOOKUP_IF_MISS); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(33, 5, "ConnStateData::requestTimeout", - TimeoutDialer(connState,&ConnStateData::requestTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(33, 5, + TimeoutDialer, connState, ConnStateData::requestTimeout); commSetTimeout(newfd, Config.Timeout.request, timeoutCall); #if USE_IDENT @@ -3798,8 +3802,8 @@ fd_note(pinning_fd, desc); typedef CommCbMemFunT Dialer; - pinning.closeHandler = asyncCall(33, 5, "ConnStateData::clientPinnedConnectionClosed", - Dialer(this, &ConnStateData::clientPinnedConnectionClosed)); + pinning.closeHandler = JobCallback(33, 5, + Dialer, this, ConnStateData::clientPinnedConnectionClosed); comm_add_close_handler(pinning_fd, pinning.closeHandler); } diff -u -r -N squid-3.1.7/src/client_side_reply.cc squid-3.1.8/src/client_side_reply.cc --- squid-3.1.7/src/client_side_reply.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/client_side_reply.cc 2010-09-04 15:25:57.000000000 +1200 @@ -1391,7 +1391,6 @@ request->flags.proxy_keepalive = 0; } - /* Append VIA */ if (Config.onoff.via) { LOCAL_ARRAY(char, bbuf, MAX_URL + 32); @@ -1613,7 +1612,7 @@ return; } - /* TODO: handle OPTIONS request on max_forwards == 0 as well */ + // OPTIONS with Max-Forwards:0 handled in clientProcessRequest() if (context->http->request->method == METHOD_TRACE) { if (context->http->request->max_forwards == 0) { diff -u -r -N squid-3.1.7/src/client_side_request.cc squid-3.1.8/src/client_side_request.cc --- squid-3.1.7/src/client_side_request.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/client_side_request.cc 2010-09-04 15:25:57.000000000 +1200 @@ -962,9 +962,6 @@ } #endif - if (request->method == METHOD_TRACE || request->method == METHOD_OPTIONS) { - request->max_forwards = req_hdr->getInt64(HDR_MAX_FORWARDS); - } request->flags.cachable = http->request->cacheable(); @@ -1368,11 +1365,11 @@ assert(!virginHeadSource); assert(!adaptedBodySource); virginHeadSource = initiateAdaptation( - new Adaptation::Iterator(this, request, NULL, g)); + new Adaptation::Iterator(request, NULL, g)); // we could try to guess whether we can bypass this adaptation // initiation failure, but it should not really happen - assert(virginHeadSource != NULL); // Must, really + Must(initiated(virginHeadSource)); } void diff -u -r -N squid-3.1.7/src/client_side_request.h squid-3.1.8/src/client_side_request.h --- squid-3.1.7/src/client_side_request.h 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/client_side_request.h 2010-09-04 15:25:57.000000000 +1200 @@ -177,7 +177,7 @@ void endRequestSatisfaction(); private: - Adaptation::Initiate *virginHeadSource; + CbcPointer virginHeadSource; BodyPipe::Pointer adaptedBodySource; bool request_satisfaction_mode; diff -u -r -N squid-3.1.7/src/CommCalls.h squid-3.1.8/src/CommCalls.h --- squid-3.1.7/src/CommCalls.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/CommCalls.h 2010-09-04 15:25:57.000000000 +1200 @@ -141,17 +141,18 @@ // All job dialers with comm parameters are merged into one since they // all have exactly one callback argument and differ in Params type only template -class CommCbMemFunT: public JobDialer, public CommDialerParamsT +class CommCbMemFunT: public JobDialer, public CommDialerParamsT { public: typedef Params_ Params; typedef void (C::*Method)(const Params &io); - CommCbMemFunT(C *obj, Method meth): JobDialer(obj), - CommDialerParamsT(obj), object(obj), method(meth) {} + CommCbMemFunT(const CbcPointer &job, Method meth): JobDialer(job), + CommDialerParamsT(job.get()), + method(meth) {} virtual bool canDial(AsyncCall &c) { - return JobDialer::canDial(c) && + return JobDialer::canDial(c) && this->params.syncWithComm(); } @@ -162,11 +163,10 @@ } public: - C *object; Method method; protected: - virtual void doDial() { (object->*method)(this->params); } + virtual void doDial() { ((&(*this->job))->*method)(this->params); } }; diff -u -r -N squid-3.1.7/src/Common.am squid-3.1.8/src/Common.am --- squid-3.1.7/src/Common.am 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/Common.am 2010-09-04 15:25:57.000000000 +1200 @@ -20,6 +20,12 @@ -I$(top_builddir)/include \ $(SQUID_CPPUNIT_INC) +## Loadable Modules requires LTDL include paths. +## Because we need this to use the libray linking headers... +if USE_LOADABLE_MODULES +INCLUDES += $(INCLTDL) +endif + ## make all compiled sources depend on generated files ## XXX: Do we really need this? Does auto-dependency tracking work? $(OBJS): $(top_srcdir)/include/version.h $(top_builddir)/include/autoconf.h diff -u -r -N squid-3.1.7/src/dns_internal.cc squid-3.1.8/src/dns_internal.cc --- squid-3.1.7/src/dns_internal.cc 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/dns_internal.cc 2010-09-04 15:25:57.000000000 +1200 @@ -705,13 +705,15 @@ } static void -idnsInitVCConnected(int fd, const DnsLookupDetails &, comm_err_t status, int xerrno, void *data) +idnsInitVCConnected(int fd, const DnsLookupDetails &details, comm_err_t status, int xerrno, void *data) { nsvc * vc = (nsvc *)data; if (status != COMM_OK) { - char buf[MAX_IPSTRLEN]; - debugs(78, 1, "idnsInitVCConnected: Failed to connect to nameserver " << nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN) << " using TCP!"); + char buf[MAX_IPSTRLEN] = ""; + if (vc->ns < nns) + nameservers[vc->ns].S.NtoA(buf,MAX_IPSTRLEN); + debugs(78, 1, HERE << "Failed to connect to nameserver " << buf << " using TCP: " << details); comm_close(fd); return; } @@ -727,7 +729,8 @@ nsvc * vc = (nsvc *)data; delete vc->queue; delete vc->msg; - nameservers[vc->ns].vc = NULL; + if (vc->ns < nns) // XXX: idnsShutdown may have freed nameservers[] + nameservers[vc->ns].vc = NULL; cbdataFree(vc); } @@ -737,6 +740,7 @@ char buf[MAX_IPSTRLEN]; nsvc *vc = cbdataAlloc(nsvc); + assert(ns < nns); nameservers[ns].vc = vc; vc->ns = ns; @@ -776,6 +780,7 @@ static void idnsSendQueryVC(idns_query * q, int ns) { + assert(ns < nns); if (nameservers[ns].vc == NULL) idnsInitVC(ns); @@ -828,7 +833,7 @@ } else { if (DnsSocketB >= 0 && nameservers[ns].S.IsIPv6()) y = comm_udp_sendto(DnsSocketB, nameservers[ns].S, q->buf, q->sz); - else + else if (DnsSocketA) x = comm_udp_sendto(DnsSocketA, nameservers[ns].S, q->buf, q->sz); } @@ -843,16 +848,11 @@ } while ( (x<0 && y<0) && q->nsends % nns != 0); - if (!q->need_vc) { - if (y >= 0) { - fd_bytes(DnsSocketB, y, FD_WRITE); - commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0); - } - - if (x >= 0) { - fd_bytes(DnsSocketA, x, FD_WRITE); - commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0); - } + if (y > 0) { + fd_bytes(DnsSocketB, y, FD_WRITE); + } + if (x > 0) { + fd_bytes(DnsSocketA, x, FD_WRITE); } nameservers[ns].nqueries++; @@ -1139,6 +1139,10 @@ debugs(78, 3, "idnsRead: starting with FD " << fd); + // Always keep reading. This stops (or at least makes harder) several + // attacks on the DNS client. + commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0); + /* BUG (UNRESOLVED) * two code lines after returning from comm_udprecvfrom() * something overwrites the memory behind the from parameter. @@ -1185,7 +1189,14 @@ if (ns >= 0) { nameservers[ns].nreplies++; - } else if (Config.onoff.ignore_unknown_nameservers) { + } + + // Before unknown_nameservers check to avoid flooding cache.log on attacks, + // but after the ++ above to keep statistics right. + if (!lru_list.head) + continue; // Don't process replies if there is no pending query. + + if (ns < 0 && Config.onoff.ignore_unknown_nameservers) { static time_t last_warning = 0; if (squid_curtime - last_warning > 60) { @@ -1199,10 +1210,6 @@ idnsGrokReply(rbuf, len); } - - if (lru_list.head) { - commSetSelect(fd, COMM_SELECT_READ, idnsRead, NULL, 0); - } } static void @@ -1270,13 +1277,14 @@ return; } - vc->msg->size += len; // XXX should not access -> size directly + vc->msg->size += len; // XXX should not access -> size directly if (vc->msg->contentSize() < vc->msglen) { comm_read(fd, buf + len, vc->msglen - vc->msg->contentSize(), idnsReadVC, vc); return; } + assert(vc->ns < nns); debugs(78, 3, "idnsReadVC: FD " << fd << ": received " << (int) vc->msg->contentSize() << " bytes via tcp from " << nameservers[vc->ns].S << "."); @@ -1389,10 +1397,12 @@ if (DnsSocketB >= 0) { port = comm_local_port(DnsSocketB); debugs(78, 1, "DNS Socket created at " << addrB << ", FD " << DnsSocketB); + commSetSelect(DnsSocketB, COMM_SELECT_READ, idnsRead, NULL, 0); } if (DnsSocketA >= 0) { port = comm_local_port(DnsSocketA); debugs(78, 1, "DNS Socket created at " << addrA << ", FD " << DnsSocketA); + commSetSelect(DnsSocketA, COMM_SELECT_READ, idnsRead, NULL, 0); } } @@ -1458,6 +1468,7 @@ } } + // XXX: vcs are not closed/freed yet and may try to access nameservers[] idnsFreeNameservers(); idnsFreeSearchpath(); } diff -u -r -N squid-3.1.7/src/esi/Makefile.in squid-3.1.8/src/esi/Makefile.in --- squid-3.1.7/src/esi/Makefile.in 2010-08-24 17:42:40.000000000 +1200 +++ squid-3.1.8/src/esi/Makefile.in 2010-09-04 15:26:28.000000000 +1200 @@ -35,11 +35,12 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = -@HAVE_LIBEXPAT_TRUE@am__append_1 = \ +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +@HAVE_LIBEXPAT_TRUE@am__append_2 = \ @HAVE_LIBEXPAT_TRUE@ ExpatParser.cc \ @HAVE_LIBEXPAT_TRUE@ ExpatParser.h -@HAVE_LIBXML2_TRUE@am__append_2 = \ +@HAVE_LIBXML2_TRUE@am__append_3 = \ @HAVE_LIBXML2_TRUE@ Libxml2Parser.cc \ @HAVE_LIBXML2_TRUE@ Libxml2Parser.h @@ -295,12 +296,12 @@ CLEANFILES = testHeaders TESTS = testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ -I$(top_srcdir)/lib/libTrie/include \ -I$(top_builddir)/lib/libTrie/include noinst_LTLIBRARIES = libesi.la -ESI_PARSER_SOURCES = CustomParser.cc CustomParser.h $(am__append_1) \ - $(am__append_2) +ESI_PARSER_SOURCES = CustomParser.cc CustomParser.h $(am__append_2) \ + $(am__append_3) libesi_la_SOURCES = \ Assign.cc \ Assign.h \ diff -u -r -N squid-3.1.7/src/fs/Makefile.in squid-3.1.8/src/fs/Makefile.in --- squid-3.1.7/src/fs/Makefile.in 2010-08-24 17:42:40.000000000 +1200 +++ squid-3.1.8/src/fs/Makefile.in 2010-09-04 15:26:28.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/fs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -293,7 +294,8 @@ CLEANFILES = testHeaders TESTS = testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) EXTRA_LTLIBRARIES = libaufs.la libdiskd.la libcoss.la libufs.la noinst_LTLIBRARIES = $(STORE_LIBS_TO_BUILD) libfs.la diff -u -r -N squid-3.1.7/src/fs/ufs/store_io_ufs.cc squid-3.1.8/src/fs/ufs/store_io_ufs.cc --- squid-3.1.7/src/fs/ufs/store_io_ufs.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/fs/ufs/store_io_ufs.cc 2010-09-04 15:25:57.000000000 +1200 @@ -452,8 +452,13 @@ void *cbdata; - if (cbdataReferenceValidDone(q->callback_data, &cbdata)) + if (cbdataReferenceValidDone(q->callback_data, &cbdata)) { read_(q->buf, q->size, q->offset, q->callback, cbdata); + } else { + debugs(79, 2, "UFSStoreState::kickReadQueue: this: " << this << " cbdataReferenceValidDone returned false." << " closing: " << closing << " flags.try_closing: " << flags.try_closing); + delete q; + return false; + } delete q; diff -u -r -N squid-3.1.7/src/ftp.cc squid-3.1.8/src/ftp.cc --- squid-3.1.7/src/ftp.cc 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/ftp.cc 2010-09-04 15:25:57.000000000 +1200 @@ -461,8 +461,8 @@ flags.rest_supported = 1; typedef CommCbMemFunT Dialer; - AsyncCall::Pointer closer = asyncCall(9, 5, "FtpStateData::ctrlClosed", - Dialer(this, &FtpStateData::ctrlClosed)); + AsyncCall::Pointer closer = JobCallback(9, 5, + Dialer, this, FtpStateData::ctrlClosed); ctrl.opened(theFwdState->server_fd, closer); if (request->method == METHOD_PUT) @@ -1311,16 +1311,15 @@ data.read_pending = true; typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(this,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, this, FtpStateData::ftpTimeout); commSetTimeout(data.fd, Config.Timeout.read, timeoutCall); debugs(9,5,HERE << "queueing read on FD " << data.fd); typedef CommCbMemFunT Dialer; entry->delayAwareRead(data.fd, data.readBuf->space(), read_sz, - asyncCall(9, 5, "FtpStateData::dataRead", - Dialer(this, &FtpStateData::dataRead))); + JobCallback(9, 5, Dialer, this, FtpStateData::dataRead)); } void @@ -1369,8 +1368,8 @@ if (ignoreErrno(io.xerrno)) { typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(this,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, this, FtpStateData::ftpTimeout); commSetTimeout(io.fd, Config.Timeout.read, timeoutCall); maybeReadVirginBody(); @@ -1678,8 +1677,8 @@ } typedef CommCbMemFunT Dialer; - AsyncCall::Pointer call = asyncCall(9, 5, "FtpStateData::ftpWriteCommandCallback", - Dialer(this, &FtpStateData::ftpWriteCommandCallback)); + AsyncCall::Pointer call = JobCallback(9, 5, + Dialer, this, FtpStateData::ftpWriteCommandCallback); comm_write(ctrl.fd, ctrl.last_command, strlen(ctrl.last_command), @@ -1816,8 +1815,8 @@ } else { /* XXX What about Config.Timeout.read? */ typedef CommCbMemFunT Dialer; - AsyncCall::Pointer reader=asyncCall(9, 5, "FtpStateData::ftpReadControlReply", - Dialer(this, &FtpStateData::ftpReadControlReply)); + AsyncCall::Pointer reader = JobCallback(9, 5, + Dialer, this, FtpStateData::ftpReadControlReply); comm_read(ctrl.fd, ctrl.buf + ctrl.offset, ctrl.size - ctrl.offset, reader); /* * Cancel the timeout on the Data socket (if any) and @@ -1830,8 +1829,8 @@ } typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(this,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, this, FtpStateData::ftpTimeout); commSetTimeout(ctrl.fd, Config.Timeout.read, timeoutCall); } @@ -2709,8 +2708,8 @@ * dont acknowledge PASV commands. */ typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(ftpState,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, ftpState, FtpStateData::ftpTimeout); commSetTimeout(ftpState->data.fd, 15, timeoutCall); } @@ -3085,8 +3084,8 @@ comm_close(io.nfd); typedef CommCbMemFunT acceptDialer; - AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection", - acceptDialer(this, &FtpStateData::ftpAcceptDataConnection)); + AsyncCall::Pointer acceptCall = JobCallback(11, 5, + acceptDialer, this, FtpStateData::ftpAcceptDataConnection); comm_accept(data.fd, acceptCall); return; } @@ -3116,8 +3115,8 @@ commSetTimeout(ctrl.fd, -1, nullCall); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(this,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, this, FtpStateData::ftpTimeout); commSetTimeout(data.fd, Config.Timeout.read, timeoutCall); /*\todo XXX We should have a flag to track connect state... @@ -3209,8 +3208,8 @@ commSetTimeout(ctrl.fd, -1, nullCall); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(this,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, this, FtpStateData::ftpTimeout); commSetTimeout(data.fd, Config.Timeout.read, timeoutCall); @@ -3221,8 +3220,8 @@ * When client code is 150 with a hostname, Accept data channel. */ debugs(9, 3, "ftpReadStor: accepting data channel"); typedef CommCbMemFunT acceptDialer; - AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection", - acceptDialer(this, &FtpStateData::ftpAcceptDataConnection)); + AsyncCall::Pointer acceptCall = JobCallback(11, 5, + acceptDialer, this, FtpStateData::ftpAcceptDataConnection); comm_accept(data.fd, acceptCall); } else { @@ -3357,8 +3356,8 @@ } else if (code == 150) { /* Accept data channel */ typedef CommCbMemFunT acceptDialer; - AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection", - acceptDialer(ftpState, &FtpStateData::ftpAcceptDataConnection)); + AsyncCall::Pointer acceptCall = JobCallback(11, 5, + acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection); comm_accept(ftpState->data.fd, acceptCall); /* @@ -3369,8 +3368,8 @@ commSetTimeout(ftpState->ctrl.fd, -1, nullCall); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(ftpState,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, ftpState,FtpStateData::ftpTimeout); commSetTimeout(ftpState->data.fd, Config.Timeout.read, timeoutCall); return; } else if (!ftpState->flags.tried_nlst && code > 300) { @@ -3419,8 +3418,8 @@ } else if (code == 150) { /* Accept data channel */ typedef CommCbMemFunT acceptDialer; - AsyncCall::Pointer acceptCall = asyncCall(11, 5, "FtpStateData::ftpAcceptDataConnection", - acceptDialer(ftpState, &FtpStateData::ftpAcceptDataConnection)); + AsyncCall::Pointer acceptCall = JobCallback(11, 5, + acceptDialer, ftpState, FtpStateData::ftpAcceptDataConnection); comm_accept(ftpState->data.fd, acceptCall); /* * Cancel the timeout on the Control socket and establish one @@ -3430,8 +3429,8 @@ commSetTimeout(ftpState->ctrl.fd, -1, nullCall); typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(9, 5, "FtpStateData::ftpTimeout", - TimeoutDialer(ftpState,&FtpStateData::ftpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(9, 5, + TimeoutDialer, ftpState,FtpStateData::ftpTimeout); commSetTimeout(ftpState->data.fd, Config.Timeout.read, timeoutCall); } else if (code >= 300) { if (!ftpState->flags.try_slash_hack) { @@ -4041,8 +4040,7 @@ FtpStateData::dataCloser() { typedef CommCbMemFunT Dialer; - return asyncCall(9, 5, "FtpStateData::dataClosed", - Dialer(this, &FtpStateData::dataClosed)); + return JobCallback(9, 5, Dialer, this, FtpStateData::dataClosed); } /// configures the channel with a descriptor and registers a close handler diff -u -r -N squid-3.1.7/src/http.cc squid-3.1.8/src/http.cc --- squid-3.1.7/src/http.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/http.cc 2010-09-04 15:25:57.000000000 +1200 @@ -139,8 +139,8 @@ * register the handler to free HTTP state data when the FD closes */ typedef CommCbMemFunT Dialer; - closeHandler = asyncCall(9, 5, "httpStateData::httpStateConnClosed", - Dialer(this,&HttpStateData::httpStateConnClosed)); + closeHandler = JobCallback(9, 5, + Dialer, this, HttpStateData::httpStateConnClosed); comm_add_close_handler(fd, closeHandler); } @@ -729,7 +729,7 @@ } flags.chunked = 0; - if (newrep->sline.protocol == PROTO_HTTP && newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) { + if (newrep->sline.protocol == PROTO_HTTP && newrep->header.chunked()) { flags.chunked = 1; httpChunkDecoder = new ChunkedCodingParser; } @@ -1406,8 +1406,7 @@ flags.do_next_read = 0; typedef CommCbMemFunT Dialer; entry->delayAwareRead(fd, readBuf->space(read_size), read_size, - asyncCall(11, 5, "HttpStateData::readReply", - Dialer(this, &HttpStateData::readReply))); + JobCallback(11, 5, Dialer, this, HttpStateData::readReply)); } } @@ -1450,8 +1449,8 @@ * request bodies. */ typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(11, 5, "HttpStateData::httpTimeout", - TimeoutDialer(this,&HttpStateData::httpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(11, 5, + TimeoutDialer, this, HttpStateData::httpTimeout); commSetTimeout(fd, Config.Timeout.read, timeoutCall); @@ -1769,7 +1768,7 @@ case HDR_TE: /** \par TE: */ case HDR_KEEP_ALIVE: /** \par Keep-Alive: */ case HDR_PROXY_AUTHENTICATE: /** \par Proxy-Authenticate: */ - case HDR_TRAILERS: /** \par Trailers: */ + case HDR_TRAILER: /** \par Trailer: */ case HDR_UPGRADE: /** \par Upgrade: */ case HDR_TRANSFER_ENCODING: /** \par Transfer-Encoding: */ break; @@ -1976,8 +1975,8 @@ } typedef CommCbMemFunT TimeoutDialer; - AsyncCall::Pointer timeoutCall = asyncCall(11, 5, "HttpStateData::httpTimeout", - TimeoutDialer(this,&HttpStateData::httpTimeout)); + AsyncCall::Pointer timeoutCall = JobCallback(11, 5, + TimeoutDialer, this, HttpStateData::httpTimeout); commSetTimeout(fd, Config.Timeout.lifetime, timeoutCall); flags.do_next_read = 1; maybeReadVirginBody(); @@ -1986,13 +1985,13 @@ if (!startRequestBodyFlow()) // register to receive body data return false; typedef CommCbMemFunT Dialer; - Dialer dialer(this, &HttpStateData::sentRequestBody); - requestSender = asyncCall(11,5, "HttpStateData::sentRequestBody", dialer); + requestSender = JobCallback(11,5, + Dialer, this, HttpStateData::sentRequestBody); } else { assert(!requestBodySource); typedef CommCbMemFunT Dialer; - Dialer dialer(this, &HttpStateData::sendComplete); - requestSender = asyncCall(11,5, "HttpStateData::SendComplete", dialer); + requestSender = JobCallback(11,5, + Dialer, this, HttpStateData::sendComplete); } if (_peer != NULL) { @@ -2085,8 +2084,8 @@ } typedef CommCbMemFunT Dialer; - Dialer dialer(this, &HttpStateData::sendComplete); - AsyncCall::Pointer call= asyncCall(11,5, "HttpStateData::SendComplete", dialer); + AsyncCall::Pointer call = JobCallback(11,5, + Dialer, this, HttpStateData::sendComplete); comm_write(fd, "\r\n", 2, call); } return; diff -u -r -N squid-3.1.7/src/HttpHeader.cc squid-3.1.8/src/HttpHeader.cc --- squid-3.1.7/src/HttpHeader.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/HttpHeader.cc 2010-09-04 15:25:57.000000000 +1200 @@ -123,7 +123,7 @@ {"Set-Cookie", HDR_SET_COOKIE, ftStr}, {"TE", HDR_TE, ftStr}, {"Title", HDR_TITLE, ftStr}, - {"Trailers", HDR_TRAILERS, ftStr}, + {"Trailer", HDR_TRAILER, ftStr}, {"Transfer-Encoding", HDR_TRANSFER_ENCODING, ftStr}, {"Translate", HDR_TRANSLATE, ftStr}, /* for now. may need to crop */ {"Unless-Modified-Since", HDR_UNLESS_MODIFIED_SINCE, ftStr}, /* for now ignore. may need to crop */ @@ -249,7 +249,7 @@ static HttpHeaderMask HopByHopHeadersMask; static http_hdr_type HopByHopHeadersArr[] = { HDR_CONNECTION, HDR_KEEP_ALIVE, /*HDR_PROXY_AUTHENTICATE,*/ HDR_PROXY_AUTHORIZATION, - HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_PROXY_CONNECTION + HDR_TE, HDR_TRAILER, HDR_TRANSFER_ENCODING, HDR_UPGRADE, HDR_PROXY_CONNECTION }; /* header accounting */ @@ -647,6 +647,11 @@ addEntry(e); } + if (chunked()) { + // RFC 2616 section 4.4: ignore Content-Length with Transfer-Encoding + delById(HDR_CONTENT_LENGTH); + } + PROF_stop(HttpHeaderParse); return 1; /* even if no fields where found, it is a valid header */ reset: diff -u -r -N squid-3.1.7/src/HttpHeader.h squid-3.1.8/src/HttpHeader.h --- squid-3.1.7/src/HttpHeader.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/HttpHeader.h 2010-09-04 15:25:57.000000000 +1200 @@ -104,7 +104,7 @@ HDR_SET_COOKIE, HDR_TE, HDR_TITLE, - HDR_TRAILERS, + HDR_TRAILER, HDR_TRANSFER_ENCODING, HDR_TRANSLATE, /* IIS custom header we may need to cut off */ HDR_UNLESS_MODIFIED_SINCE, /* IIS custom header we may need to cut off */ @@ -255,6 +255,7 @@ int hasListMember(http_hdr_type id, const char *member, const char separator) const; int hasByNameListMember(const char *name, const char *member, const char separator) const; void removeHopByHopEntries(); + inline bool chunked() const; ///< whether message uses chunked Transfer-Encoding /* protected, do not use these, use interface functions instead */ Vector entries; /**< parsed fields in raw format */ @@ -282,4 +283,11 @@ SQUIDCEXTERN void httpHeaderCalcMask(HttpHeaderMask * mask, http_hdr_type http_hdr_type_enums[], size_t count); +inline bool +HttpHeader::chunked() const +{ + return has(HDR_TRANSFER_ENCODING) && + hasListMember(HDR_TRANSFER_ENCODING, "chunked", ','); +} + #endif /* SQUID_HTTPHEADER_H */ diff -u -r -N squid-3.1.7/src/HttpMsg.cc squid-3.1.8/src/HttpMsg.cc --- squid-3.1.7/src/HttpMsg.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/HttpMsg.cc 2010-09-04 15:25:57.000000000 +1200 @@ -321,7 +321,7 @@ int httpMsgIsPersistent(HttpVersion const &http_ver, const HttpHeader * hdr) { - if ((http_ver.major >= 1) && (http_ver.minor >= 1)) { + if (http_ver > HttpVersion(1, 0)) { /* * for modern versions of HTTP: persistent unless there is * a "Connection: close" header. @@ -402,6 +402,10 @@ hdr->req_start = hdr->req_end = -1; hdr->hdr_start = hdr->hdr_end = -1; debugs(74, 5, "httpParseInit: Request buffer is " << buf); + hdr->m_start = hdr->m_end = -1; + hdr->u_start = hdr->u_end = -1; + hdr->v_start = hdr->v_end = -1; + hdr->v_maj = hdr->v_min = 0; } #if MSGDODEBUG @@ -446,190 +450,208 @@ } #endif -/** - * Attempt to parse the request line. - * - * This will set the values in hmsg that it determines. One may end up - * with a partially-parsed buffer; the return value tells you whether - * the values are valid or not. - * - * \retval 1 if parsed correctly - * \retval 0 if more is needed - * \retval -1 if error - * - * TODO: - * * have it indicate "error" and "not enough" as two separate conditions! - * * audit this code as off-by-one errors are probably everywhere! - */ int -HttpParserParseReqLine(HttpParser *hmsg) +HttpParser::parseRequestFirstLine() { - int i = 0; - int retcode = 0; - unsigned int maj = 0, min = 0; - int last_whitespace = -1, line_end = -1; + int second_word = -1; // track the suspected URI start + int first_whitespace = -1, last_whitespace = -1; // track the first and last SP byte + int line_end = -1; // tracks the last byte BEFORE terminal \r\n or \n sequence + + debugs(74, 5, HERE << "parsing possible request: " << buf); + + // Single-pass parse: (provided we have the whole line anyways) + + req_start = 0; + if (Config.onoff.relaxed_header_parser) { + if (Config.onoff.relaxed_header_parser < 0 && buf[req_start] == ' ') + debugs(74, DBG_IMPORTANT, "WARNING: Invalid HTTP Request: " << + "Whitespace bytes received ahead of method. " << + "Ignored due to relaxed_header_parser."); + // Be tolerant of prefix spaces (other bytes are valid method values) + for (; req_start < bufsiz && buf[req_start] == ' '; req_start++); + } + req_end = -1; + for (int i = 0; i < bufsiz; i++) { + // track first and last whitespace (SP only) + if (buf[i] == ' ') { + last_whitespace = i; + if (first_whitespace < req_start) + first_whitespace = i; + } - debugs(74, 5, "httpParserParseReqLine: parsing " << hmsg->buf); + // track next non-SP/non-HT byte after first_whitespace + if (second_word < first_whitespace && buf[i] != ' ' && buf[i] != '\t') { + second_word = i; + } - PROF_start(HttpParserParseReqLine); - /* Find \r\n - end of URL+Version (and the request) */ - hmsg->req_end = -1; - for (i = 0; i < hmsg->bufsiz; i++) { - if (hmsg->buf[i] == '\n') { - hmsg->req_end = i; + // locate line terminator + if (buf[i] == '\n') { + req_end = i; + line_end = i - 1; break; } - if (i < hmsg->bufsiz - 1 && hmsg->buf[i] == '\r' && hmsg->buf[i + 1] == '\n') { - hmsg->req_end = i + 1; - break; + if (i < bufsiz - 1 && buf[i] == '\r') { + if (Config.onoff.relaxed_header_parser) { + if (Config.onoff.relaxed_header_parser < 0 && buf[i + 1] == '\r') + debugs(74, DBG_IMPORTANT, "WARNING: Invalid HTTP Request: " << + "Series of carriage-return bytes received prior to line terminator. " << + "Ignored due to relaxed_header_parser."); + + // Be tolerant of invalid multiple \r prior to terminal \n + if (buf[i + 1] == '\n' || buf[i + 1] == '\r') + line_end = i - 1; + while (i < bufsiz - 1 && buf[i + 1] == '\r') + i++; + + if (buf[i + 1] == '\n') { + req_end = i + 1; + break; + } + } else { + if (buf[i + 1] == '\n') { + req_end = i + 1; + line_end = i - 1; + break; + } + } + + // RFC 2616 section 5.1 + // "No CR or LF is allowed except in the final CRLF sequence" + return -1; } } - if (hmsg->req_end == -1) { - retcode = 0; - goto finish; - } - assert(hmsg->buf[hmsg->req_end] == '\n'); - /* Start at the beginning again */ - i = 0; - - /* Find first non-whitespace - beginning of method */ - for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++); - if (i >= hmsg->req_end) { - retcode = 0; - goto finish; - } - hmsg->m_start = i; - hmsg->req_start = i; - - /* Find first whitespace - end of method */ - for (; i < hmsg->req_end && (! xisspace(hmsg->buf[i])); i++); - if (i >= hmsg->req_end) { - retcode = 0; - goto finish; - } - hmsg->m_end = i - 1; - - /* Find first non-whitespace - beginning of URL+Version */ - for (; i < hmsg->req_end && (xisspace(hmsg->buf[i])); i++); - if (i >= hmsg->req_end) { - retcode = 0; - goto finish; - } - hmsg->u_start = i; - - /* Find \r\n or \n - thats the end of the line. Keep track of the last whitespace! */ - for (; i <= hmsg->req_end; i++) { - /* If \n - its end of line */ - if (hmsg->buf[i] == '\n') { - line_end = i; - break; - } - /* XXX could be off-by-one wrong! */ - if (hmsg->buf[i] == '\r' && (i + 1) <= hmsg->req_end && hmsg->buf[i+1] == '\n') { - line_end = i; - break; - } - /* If its a whitespace, note it as it'll delimit our version */ - if (hmsg->buf[i] == ' ' || hmsg->buf[i] == '\t') { - last_whitespace = i; - } + if (req_end == -1) { + debugs(74, 5, "Parser: retval 0: from " << req_start << + "->" << req_end << ": needs more data to complete first line."); + return 0; + } + + // NP: we have now seen EOL, more-data (0) cannot occur. + // From here on any failure is -1, success is 1 + + + // Input Validation: + + // Process what we now know about the line structure into field offsets + // generating HTTP status for any aborts as we go. + + // First non-whitespace = beginning of method + if (req_start > line_end) { + return -1; } - if (i > hmsg->req_end) { - retcode = 0; - goto finish; + m_start = req_start; + + // First whitespace = end of method + if (first_whitespace > line_end || first_whitespace < req_start) { + return -1; + } + m_end = first_whitespace - 1; + if (m_end < m_start) { + return -1; } - /* At this point we don't need the 'i' value; so we'll recycle it for version parsing */ + // First non-whitespace after first SP = beginning of URL+Version + if (second_word > line_end || second_word < req_start) { + return -1; + } + u_start = second_word; - /* - * At this point: line_end points to the first eol char (\r or \n); - * last_whitespace points to the last whitespace char in the URL. - * We know we have a full buffer here! - */ - if (last_whitespace == -1) { - maj = 0; - min = 9; - hmsg->u_end = line_end - 1; - assert(hmsg->u_end >= hmsg->u_start); + // RFC 1945: SP and version following URI are optional, marking version 0.9 + // we identify this by the last whitespace being earlier than URI start + if (last_whitespace < second_word && last_whitespace >= req_start) { + v_maj = 0; + v_min = 9; + u_end = line_end; + return 1; } else { - /* Find the first non-whitespace after last_whitespace */ - /* XXX why <= vs < ? I do need to really re-audit all of this ..*/ - for (i = last_whitespace; i <= hmsg->req_end && xisspace(hmsg->buf[i]); i++); - if (i > hmsg->req_end) { - retcode = 0; - goto finish; - } + // otherwise last whitespace is somewhere after end of URI. + u_end = last_whitespace; + // crop any trailing whitespace in the area we think of as URI + for (; u_end >= u_start && xisspace(buf[u_end]); u_end--); + } + if (u_end < u_start) { + return -1; + } - /* is it http/ ? if so, we try parsing. If not, the URL is the whole line; version is 0.9 */ - if (i + 5 >= hmsg->req_end || (strncasecmp(&hmsg->buf[i], "HTTP/", 5) != 0)) { - maj = 0; - min = 9; - hmsg->u_end = line_end - 1; - assert(hmsg->u_end >= hmsg->u_start); - } else { - /* Ok, lets try parsing! Yes, this needs refactoring! */ - hmsg->v_start = i; - i += 5; - - /* next should be 1 or more digits */ - maj = 0; - for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])) && maj < 65536; i++) { - maj = maj * 10; - maj = maj + (hmsg->buf[i]) - '0'; - } - if (maj >= 65536) { - retcode = -1; - goto finish; - } - if (i >= hmsg->req_end) { - retcode = 0; - goto finish; - } + // Last whitespace SP = before start of protocol/version + if (last_whitespace >= line_end) { + return -1; + } + v_start = last_whitespace + 1; + v_end = line_end; - /* next should be .; we -have- to have this as we have a whole line.. */ - if (hmsg->buf[i] != '.') { - retcode = 0; - goto finish; - } - if (i + 1 >= hmsg->req_end) { - retcode = 0; - goto finish; - } + // We only accept HTTP protocol requests right now. + // TODO: accept other protocols; RFC 2326 (RTSP protocol) etc + if ((v_end - v_start +1) < 5 || strncasecmp(&buf[v_start], "HTTP/", 5) != 0) { +#if USE_HTTP_VIOLATIONS + // being lax; old parser accepted strange versions + // there is a LOT of cases which are ambiguous, therefore we cannot use relaxed_header_parser here. + v_maj = 0; + v_min = 9; + u_end = line_end; + return 1; +#else + return -1; +#endif + } - /* next should be one or more digits */ - i++; - min = 0; - for (; i < hmsg->req_end && (isdigit(hmsg->buf[i])) && min < 65536; i++) { - min = min * 10; - min = min + (hmsg->buf[i]) - '0'; - } + int i = v_start + sizeof("HTTP/") -1; - if (min >= 65536) { - retcode = -1; - goto finish; - } + /* next should be 1 or more digits */ + if (!isdigit(buf[i])) { + return -1; + } + int maj = 0; + for (; i <= line_end && (isdigit(buf[i])) && maj < 65536; i++) { + maj = maj * 10; + maj = maj + (buf[i]) - '0'; + } + // catch too-big values or missing remainders + if (maj >= 65536 || i > line_end) { + return -1; + } + v_maj = maj; - /* Find whitespace, end of version */ - hmsg->v_end = i; - hmsg->u_end = last_whitespace - 1; - } + /* next should be .; we -have- to have this as we have a whole line.. */ + if (buf[i] != '.') { + return -1; + } + // catch missing minor part + if (++i > line_end) { + return -1; } + /* next should be one or more digits */ + if (!isdigit(buf[i])) { + return -1; + } + int min = 0; + for (; i <= line_end && (isdigit(buf[i])) && min < 65536; i++) { + min = min * 10; + min = min + (buf[i]) - '0'; + } + // catch too-big values or trailing garbage + if (min >= 65536 || i < line_end) { + return -1; + } + v_min = min; + /* * Rightio - we have all the schtuff. Return true; we've got enough. */ - retcode = 1; + return 1; +} -finish: - hmsg->v_maj = maj; - hmsg->v_min = min; - PROF_stop(HttpParserParseReqLine); +int +HttpParserParseReqLine(HttpParser *hmsg) +{ + PROF_start(HttpParserParseReqLine); + int retcode = hmsg->parseRequestFirstLine(); debugs(74, 5, "Parser: retval " << retcode << ": from " << hmsg->req_start << "->" << hmsg->req_end << ": method " << hmsg->m_start << "->" << hmsg->m_end << "; url " << hmsg->u_start << "->" << hmsg->u_end << - "; version " << hmsg->v_start << "->" << hmsg->v_end << " (" << maj << - "/" << min << ")"); - + "; version " << hmsg->v_start << "->" << hmsg->v_end << " (" << hmsg->v_maj << + "/" << hmsg->v_min << ")"); + PROF_stop(HttpParserParseReqLine); return retcode; } - diff -u -r -N squid-3.1.7/src/HttpMsg.h squid-3.1.8/src/HttpMsg.h --- squid-3.1.7/src/HttpMsg.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/HttpMsg.h 2010-09-04 15:25:57.000000000 +1200 @@ -123,6 +123,24 @@ class HttpParser { public: + /** + * Attempt to parse the first line of a new request message. + * + * Governed by: + * RFC 1945 section 5.1 + * RFC 2616 section 5.1 + * + * Parsing state is stored between calls. However the current implementation + * begins parsing from scratch on every call. + * The return value tells you whether the parsing state fields are valid or not. + * + * \retval -1 an error occurred. request_parse_status indicates HTTP status result. + * \retval 1 successful parse + * \retval 0 more data is needed to complete the parse + */ + int parseRequestFirstLine(); + +public: char state; const char *buf; int bufsiz; @@ -155,4 +173,42 @@ #define HTTPMSGUNLOCK(a) if(a){(a)->_unlock();(a)=NULL;} #define HTTPMSGLOCK(a) (a)->_lock() +// TODO: replace HTTPMSGLOCK with general RefCounting and delete this class +/// safe HttpMsg pointer wrapper that locks and unlocks the message +template +class HttpMsgPointerT +{ +public: + HttpMsgPointerT(): msg(NULL) {} + explicit HttpMsgPointerT(Msg *m): msg(m) { lock(); } + virtual ~HttpMsgPointerT() { unlock(); } + + HttpMsgPointerT(const HttpMsgPointerT &p): msg(p.msg) { lock(); } + HttpMsgPointerT &operator =(const HttpMsgPointerT &p) + { if (msg != p.msg) { unlock(); msg = p.msg; lock(); } return *this; } + + Msg &operator *() { return *msg; } + const Msg &operator *() const { return *msg; } + Msg *operator ->() { return msg; } + const Msg *operator ->() const { return msg; } + operator Msg *() { return msg; } + operator const Msg *() const { return msg; } + // add more as needed + +protected: + void lock() { if (msg) HTTPMSGLOCK(msg); } ///< prevent msg destruction + void unlock() { HTTPMSGUNLOCK(msg); } ///< allows/causes msg destruction + +private: + Msg *msg; +}; + +/// convenience wrapper to create HttpMsgPointerT<> object based on msg type +template +inline +HttpMsgPointerT HttpMsgPointer(Msg *msg) +{ + return HttpMsgPointerT(msg); +} + #endif /* SQUID_HTTPMSG_H */ diff -u -r -N squid-3.1.7/src/HttpReply.cc squid-3.1.8/src/HttpReply.cc --- squid-3.1.7/src/HttpReply.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/HttpReply.cc 2010-09-04 15:25:57.000000000 +1200 @@ -62,7 +62,7 @@ static http_hdr_type Denied304HeadersArr[] = { // hop-by-hop headers HDR_CONNECTION, HDR_KEEP_ALIVE, HDR_PROXY_AUTHENTICATE, HDR_PROXY_AUTHORIZATION, - HDR_TE, HDR_TRAILERS, HDR_TRANSFER_ENCODING, HDR_UPGRADE, + HDR_TE, HDR_TRAILER, HDR_TRANSFER_ENCODING, HDR_UPGRADE, // entity headers HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH, HDR_CONTENT_MD5, HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_LAST_MODIFIED @@ -540,7 +540,7 @@ expectBody = true; if (expectBody) { - if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) + if (header.chunked()) theSize = -1; else if (content_length >= 0) theSize = content_length; diff -u -r -N squid-3.1.7/src/HttpRequest.cc squid-3.1.8/src/HttpRequest.cc --- squid-3.1.7/src/HttpRequest.cc 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/HttpRequest.cc 2010-09-04 15:25:57.000000000 +1200 @@ -492,7 +492,7 @@ expectBody = Config.onoff.request_entities ? true : false; else if (method == METHOD_PUT || method == METHOD_POST) expectBody = true; - else if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) + else if (header.chunked()) expectBody = true; else if (content_length >= 0) expectBody = true; @@ -500,7 +500,7 @@ expectBody = false; if (expectBody) { - if (header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) + if (header.chunked()) theSize = -1; else if (content_length >= 0) theSize = content_length; diff -u -r -N squid-3.1.7/src/HttpVersion.h squid-3.1.8/src/HttpVersion.h --- squid-3.1.7/src/HttpVersion.h 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/HttpVersion.h 2010-09-04 15:25:57.000000000 +1200 @@ -66,6 +66,23 @@ return ((this->major != that.major) || (this->minor != that.minor)); } + bool operator <(const HttpVersion& that) const { + return (this->major < that.major || + (this->major == that.major && this->minor < that.minor)); + } + + bool operator >(const HttpVersion& that) const { + return (this->major > that.major || + (this->major == that.major && this->minor > that.minor)); + } + + bool operator <=(const HttpVersion& that) const { + return !(*this > that); + } + + bool operator >=(const HttpVersion& that) const { + return !(*this < that); + } }; #endif /* SQUID_HTTPVERSION_H */ diff -u -r -N squid-3.1.7/src/icmp/Makefile.in squid-3.1.8/src/icmp/Makefile.in --- squid-3.1.7/src/icmp/Makefile.in 2010-08-24 17:42:42.000000000 +1200 +++ squid-3.1.8/src/icmp/Makefile.in 2010-09-04 15:26:29.000000000 +1200 @@ -37,6 +37,7 @@ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = testIcmp$(EXEEXT) TESTS = testHeaders testIcmp$(EXEEXT) +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) EXTRA_PROGRAMS = pinger$(EXEEXT) testIcmp$(EXEEXT) libexec_PROGRAMS = $(am__EXEEXT_1) subdir = src/icmp @@ -306,13 +307,8 @@ AM_CFLAGS = $(SQUID_CFLAGS) AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) @ENABLE_PINGER_FALSE@PINGER = # ICMP Specific Configurations diff -u -r -N squid-3.1.7/src/ident/Makefile.in squid-3.1.8/src/ident/Makefile.in --- squid-3.1.7/src/ident/Makefile.in 2010-08-24 17:42:42.000000000 +1200 +++ squid-3.1.8/src/ident/Makefile.in 2010-09-04 15:26:29.000000000 +1200 @@ -35,6 +35,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/ident ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -274,13 +275,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders TESTS = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libident.la libident_la_SOURCES = \ AclIdent.h \ diff -u -r -N squid-3.1.7/src/ip/Makefile.in squid-3.1.8/src/ip/Makefile.in --- squid-3.1.7/src/ip/Makefile.in 2010-08-24 17:42:43.000000000 +1200 +++ squid-3.1.8/src/ip/Makefile.in 2010-09-04 15:26:29.000000000 +1200 @@ -36,6 +36,7 @@ $(top_srcdir)/src/Common.am $(top_srcdir)/src/TestHeaders.am check_PROGRAMS = testIpAddress$(EXEEXT) TESTS = testHeaders testIpAddress$(EXEEXT) +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/ip ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -287,13 +288,8 @@ AM_CFLAGS = $(SQUID_CFLAGS) AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = testHeaders -INCLUDES = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/include \ - $(SQUID_CPPUNIT_INC) - +INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) noinst_LTLIBRARIES = libip.la libip_la_SOURCES = \ IpAddress.h \ diff -u -r -N squid-3.1.7/src/Makefile.in squid-3.1.8/src/Makefile.in --- squid-3.1.7/src/Makefile.in 2010-08-24 17:42:37.000000000 +1200 +++ squid-3.1.8/src/Makefile.in 2010-09-04 15:26:26.000000000 +1200 @@ -52,8 +52,9 @@ tests/testHttpRequest$(EXEEXT) tests/testStore$(EXEEXT) \ tests/testString$(EXEEXT) tests/testURL$(EXEEXT) \ $(STORE_TESTS) -@USE_ADAPTATION_TRUE@am__append_1 = adaptation -@USE_ESI_TRUE@am__append_2 = esi +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) +@USE_ADAPTATION_TRUE@am__append_2 = adaptation +@USE_ESI_TRUE@am__append_3 = esi EXTRA_PROGRAMS = DiskIO/DiskDaemon/diskd$(EXEEXT) unlinkd$(EXEEXT) \ dnsserver$(EXEEXT) recv-announce$(EXEEXT) \ tests/testUfs$(EXEEXT) tests/testCoss$(EXEEXT) \ @@ -62,8 +63,8 @@ sbin_PROGRAMS = squid$(EXEEXT) bin_PROGRAMS = libexec_PROGRAMS = $(am__EXEEXT_1) $(DISK_PROGRAMS) $(am__EXEEXT_2) -@USE_LOADABLE_MODULES_TRUE@am__append_3 = $(LOADABLE_MODULES_SOURCES) -@USE_LOADABLE_MODULES_TRUE@am__append_4 = \ +@USE_LOADABLE_MODULES_TRUE@am__append_4 = $(LOADABLE_MODULES_SOURCES) +@USE_LOADABLE_MODULES_TRUE@am__append_5 = \ @USE_LOADABLE_MODULES_TRUE@ $(LIBLTDL) subdir = src @@ -1555,7 +1556,7 @@ test_tools.cc *.a testHeaders TESTS = $(check_PROGRAMS) testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) \ + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ -I$(top_builddir)/src AUTOMAKE_OPTIONS = subdir-objects @USE_DNSSERVER_FALSE@DNSSOURCE = dns_internal.cc DnsLookupDetails.h \ @@ -1576,8 +1577,8 @@ LoadableModules.h \ LoadableModules.cc -SUBDIRS = base acl fs repl auth ip icmp ident $(am__append_1) \ - $(am__append_2) +SUBDIRS = base acl fs repl auth ip icmp ident $(am__append_2) \ + $(am__append_3) @USE_ESI_TRUE@ESI_LOCAL_LIBS = \ @USE_ESI_TRUE@ esi/libesi.la \ @USE_ESI_TRUE@ $(top_builddir)/lib/libTrie/src/libTrie.a @@ -1793,7 +1794,7 @@ typedefs.h $(UNLINKDSOURCE) url.cc URL.h URLScheme.cc \ URLScheme.h urn.cc useragent.cc wccp.cc wccp2.cc whois.cc \ wordlist.cc wordlist.h $(WIN32_SOURCE) $(WINSVC_SOURCE) \ - $(am__append_3) + $(am__append_4) noinst_HEADERS = \ client_side_request.cci \ MemBuf.cci \ @@ -1816,7 +1817,7 @@ $(REPL_OBJS) $(DISK_LIBS) $(DISK_OS_LIBS) $(CRYPTLIB) \ $(REGEXLIB) $(SNMPLIB) ${ADAPTATION_LIBS} $(ESI_LIBS) \ $(SSLLIB) -lmiscutil $(EPOLL_LIBS) $(MINGW_LIBS) $(XTRA_LIBS) \ - $(am__append_4) + $(am__append_5) squid_DEPENDENCIES = $(top_builddir)/lib/libmiscutil.a \ $(DISK_LIBS) \ $(DISK_LINKOBJS) \ diff -u -r -N squid-3.1.7/src/repl/Makefile.in squid-3.1.8/src/repl/Makefile.in --- squid-3.1.7/src/repl/Makefile.in 2010-08-24 17:42:43.000000000 +1200 +++ squid-3.1.8/src/repl/Makefile.in 2010-09-04 15:26:29.000000000 +1200 @@ -40,6 +40,7 @@ DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \ $(top_srcdir)/src/Common.am check_PROGRAMS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) subdir = src/repl ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \ @@ -288,7 +289,8 @@ CLEANFILES = testHeaders TESTS = testHeaders INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) AUTOMAKE_OPTIONS = subdir-objects # No recursion is needed for the subdirs, we build from here. diff -u -r -N squid-3.1.7/src/Server.cc squid-3.1.8/src/Server.cc --- squid-3.1.7/src/Server.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/Server.cc 2010-09-04 15:25:57.000000000 +1200 @@ -417,8 +417,8 @@ if (requestBodySource->getMoreData(buf)) { debugs(9,3, HERE << "will write " << buf.contentSize() << " request body bytes"); typedef CommCbMemFunT Dialer; - requestSender = asyncCall(93,3, "ServerStateData::sentRequestBody", - Dialer(this, &ServerStateData::sentRequestBody)); + requestSender = JobCallback(93,3, + Dialer, this, ServerStateData::sentRequestBody); comm_write_mbuf(fd, &buf, requestSender); } else { debugs(9,3, HERE << "will wait for more request body bytes or eof"); @@ -544,8 +544,8 @@ } adaptedHeadSource = initiateAdaptation( - new Adaptation::Iterator(this, vrep, cause, group)); - startedAdaptation = adaptedHeadSource != NULL; + new Adaptation::Iterator(vrep, cause, group)); + startedAdaptation = initiated(adaptedHeadSource); Must(startedAdaptation); } diff -u -r -N squid-3.1.7/src/Server.h squid-3.1.8/src/Server.h --- squid-3.1.7/src/Server.h 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/Server.h 2010-09-04 15:25:57.000000000 +1200 @@ -186,7 +186,7 @@ #if USE_ADAPTATION BodyPipe::Pointer virginBodyDestination; /**< to provide virgin response body */ - Adaptation::Initiate *adaptedHeadSource; /**< to get adapted response headers */ + CbcPointer adaptedHeadSource; /**< to get adapted response headers */ BodyPipe::Pointer adaptedBodySource; /**< to consume adated response body */ bool adaptationAccessCheckPending; diff -u -r -N squid-3.1.7/src/SquidString.h squid-3.1.8/src/SquidString.h --- squid-3.1.7/src/SquidString.h 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/SquidString.h 2010-09-04 15:25:57.000000000 +1200 @@ -167,6 +167,8 @@ void allocBuffer(size_type sz); void setBuffer(char *buf, size_type sz); + _SQUID_INLINE_ bool nilCmp(bool, bool, int &) const; + /* never reference these directly! */ size_type size_; /* buffer size; 64K limit */ diff -u -r -N squid-3.1.7/src/String.cci squid-3.1.8/src/String.cci --- squid-3.1.7/src/String.cci 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/String.cci 2010-09-04 15:25:57.000000000 +1200 @@ -88,19 +88,31 @@ } -int -String::cmp (char const *aString) const +/// compare NULL and empty strings because str*cmp() may fail on NULL strings +/// and because we need to return consistent results for strncmp(count == 0). +bool +String::nilCmp(const bool thisIsNilOrEmpty, const bool otherIsNilOrEmpty, int &result) const { - /* strcmp fails on NULLS */ + if (!thisIsNilOrEmpty && !otherIsNilOrEmpty) + return false; // result does not matter - if (size() == 0 && (aString == NULL || aString[0] == '\0')) - return 0; + if (thisIsNilOrEmpty && otherIsNilOrEmpty) + result = 0; + else if (thisIsNilOrEmpty) + result = -1; + else // otherIsNilOrEmpty + result = +1; + + return true; +} - if (size() == 0) - return -1; - if (aString == NULL || aString[0] == '\0') - return 1; +int +String::cmp (char const *aString) const +{ + int result = 0; + if (nilCmp(!size(), (!aString || !*aString), result)) + return result; return strcmp(termedBuf(), aString); } @@ -108,19 +120,9 @@ int String::cmp (char const *aString, String::size_type count) const { - /* always the same at length 0 */ - - if (count == 0) - return 0; - - if (size() == 0 && (aString == NULL || aString[0] == '\0')) - return 0; - - if (size() == 0) - return -1; - - if (aString == NULL || aString[0] == '\0') - return 1; + int result = 0; + if (nilCmp((!size() || !count), (!aString || !*aString || !count), result)) + return result; return strncmp(termedBuf(), aString, count); } @@ -128,16 +130,9 @@ int String::cmp (String const &aString) const { - /* strcmp fails on NULLS */ - - if (size() == 0 && aString.size() == 0) - return 0; - - if (size() == 0) - return -1; - - if (aString.size() == 0) - return 1; + int result = 0; + if (nilCmp(!size(), !aString.size(), result)) + return result; return strcmp(termedBuf(), aString.termedBuf()); } @@ -145,12 +140,20 @@ int String::caseCmp(char const *aString) const { + int result = 0; + if (nilCmp(!size(), (!aString || !*aString), result)) + return result; + return strcasecmp(termedBuf(), aString); } int String::caseCmp(char const *aString, String::size_type count) const { + int result = 0; + if (nilCmp((!size() || !count), (!aString || !*aString || !count), result)) + return result; + return strncasecmp(termedBuf(), aString, count); } diff -u -r -N squid-3.1.7/src/tests/testHttpRequest.cc squid-3.1.8/src/tests/testHttpRequest.cc --- squid-3.1.7/src/tests/testHttpRequest.cc 2010-08-24 17:41:26.000000000 +1200 +++ squid-3.1.8/src/tests/testHttpRequest.cc 2010-09-04 15:25:57.000000000 +1200 @@ -209,3 +209,805 @@ input.reset(); error = HTTP_STATUS_NONE; } + +void +testHttpRequest::testParseRequestLine() +{ + MemBuf input; + HttpParser output; + input.init(); + + // TEST: Do we comply with RFC 1945 section 5.1 ? + // TEST: Do we comply with RFC 2616 section 5.1 ? + + // RFC 1945 : HTTP/0.9 simple-request + input.append("GET /\r\n", 7); + 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 /\r\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(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); + input.reset(); + + // RFC 1945 and 2616 : HTTP/1.0 full-request + input.append("GET / HTTP/1.0\r\n", 16); + 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.0\r\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(13, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.0", &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(); + + + // RFC 2616 : HTTP/1.1 full-request + input.append("GET / HTTP/1.1\r\n", 16); + 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.1\r\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(13, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // RFC 2616 : future version full-request + input.append("GET / HTTP/10.12\r\n", 18); + //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/10.12\r\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(15, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/10.12", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(10, output.v_maj); + CPPUNIT_ASSERT_EQUAL(12, output.v_min); + input.reset(); + + // space padded URL + input.append("GET / HTTP/1.1\r\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.1\r\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(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(11, output.v_start); + CPPUNIT_ASSERT_EQUAL(18, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // space padded version + // RFC 1945 and 2616 specify version is followed by CRLF. No intermediary bytes. + // NP: the terminal whitespace is a special case: invalid for even HTTP/0.9 with no version tag + input.append("GET / HTTP/1.1 \n", 16); + //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.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(13, output.u_end); + CPPUNIT_ASSERT(memcmp("/ HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // whitespace inside URI. (nasty but happens) + input.append("GET /fo o/ HTTP/1.1\n", 20); + //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 /fo o/ HTTP/1.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(9, output.u_end); + CPPUNIT_ASSERT(memcmp("/fo o/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(11, output.v_start); + CPPUNIT_ASSERT_EQUAL(18, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // additional data in buffer + input.append("GET / HTTP/1.1\nboo!", 23); + //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()-5, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / HTTP/1.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); // strangeness generated by following RFC + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(10, output.v_start); + CPPUNIT_ASSERT_EQUAL(17, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // alternative EOL sequence: NL-only + input.append("GET / HTTP/1.1\n", 15); + //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.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(13, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // alternative EOL sequence: double-NL-only + input.append("GET / HTTP/1.1\n\n", 16); + //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()-2, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / HTTP/1.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(13, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // RELAXED alternative EOL sequence: multi-CR-NL + input.append("GET / HTTP/1.1\r\r\r\n", 18); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + Config.onoff.relaxed_header_parser = 1; + // Being tolerant we can ignore and elide these apparently benign CR + 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.1\r\r\r\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(13, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // STRICT alternative EOL sequence: multi-CR-NL + input.append("GET / HTTP/1.1\r\r\r\n", 18); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + // strict mode treats these as several bare-CR in the request line which is explicitly invalid. + Config.onoff.relaxed_header_parser = 0; + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // RFC 2616 : . method + input.append(". / HTTP/1.1\n", 13); + //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(". / HTTP/1.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(0, output.m_end); + CPPUNIT_ASSERT(memcmp(".", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(2, output.u_start); + CPPUNIT_ASSERT_EQUAL(2, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(4, output.v_start); + CPPUNIT_ASSERT_EQUAL(11, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // OPTIONS with * URL + input.append("OPTIONS * HTTP/1.1\n", 19); + //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("OPTIONS * HTTP/1.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(6, output.m_end); + CPPUNIT_ASSERT(memcmp("OPTIONS", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(8, output.u_start); + CPPUNIT_ASSERT_EQUAL(8, output.u_end); + CPPUNIT_ASSERT(memcmp("*", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(10, output.v_start); + CPPUNIT_ASSERT_EQUAL(17, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // unknown method + input.append("HELLOWORLD / HTTP/1.1\n", 22); + //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("HELLOWORLD / HTTP/1.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(9, output.m_end); + CPPUNIT_ASSERT(memcmp("HELLOWORLD", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(11, output.u_start); + CPPUNIT_ASSERT_EQUAL(11, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(13, output.v_start); + CPPUNIT_ASSERT_EQUAL(20, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // This stage of the parser does not yet accept non-HTTP protocol names. + // violations mode treats them as HTTP/0.9 requests! + input.append("GET / FOO/1.0\n", 14); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); +#if USE_HTTP_VIOLATIONS + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(12, output.u_end); + CPPUNIT_ASSERT(memcmp("/ FOO/1.0", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); +#else + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + 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(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); +#endif + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / FOO/1.0\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(6, output.v_start); + CPPUNIT_ASSERT_EQUAL(12, output.v_end); + CPPUNIT_ASSERT(memcmp("FOO/1.0", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + input.reset(); + + // RELAXED space padded method (in strict mode SP is reserved so invalid as a method byte) + input.append(" GET / HTTP/1.1\n", 16); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + Config.onoff.relaxed_header_parser = 1; + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(1, output.req_start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req_end); + CPPUNIT_ASSERT(memcmp("GET / HTTP/1.1\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.m_start); + CPPUNIT_ASSERT_EQUAL(3, output.m_end); + CPPUNIT_ASSERT(memcmp("GET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(7, output.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // STRICT space padded method (in strict mode SP is reserved so invalid as a method byte) + input.append(" GET / HTTP/1.1\n", 16); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + Config.onoff.relaxed_header_parser = 0; + 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.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(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // tab padded method (NP: tab is not SP so treated as any other binary) + input.append("\tGET / HTTP/1.1\n", 16); + //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("\tGET / HTTP/1.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(3, output.m_end); + CPPUNIT_ASSERT(memcmp("\tGET", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(7, output.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + input.append("GET", 3); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + input.append("GET ", 4); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + input.append("GET / HT", 8); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + input.append("GET / HTTP/1.1", 14); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(0, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // method-only + input.append("A\n", 2); + //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("A\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // no method (but in a form which is ambiguous with HTTP/0.9 simple-request) + input.append("/ HTTP/1.0\n", 11); + //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("/ HTTP/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(0, output.m_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(2, output.u_start); + CPPUNIT_ASSERT_EQUAL(9, output.u_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); + input.reset(); + + // RELAXED no method (an invalid format) + input.append(" / HTTP/1.0\n", 12); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) + Config.onoff.relaxed_header_parser = 1; + CPPUNIT_ASSERT_EQUAL(1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(1, output.req_start); + CPPUNIT_ASSERT_EQUAL((int)input.contentSize()-1, output.req_end); + CPPUNIT_ASSERT(memcmp("/ HTTP/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.m_start); + CPPUNIT_ASSERT_EQUAL(1, output.m_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(3, output.u_start); + CPPUNIT_ASSERT_EQUAL(10, output.u_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.0", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); + input.reset(); + + // STRICT no method (an invalid format) + input.append(" / HTTP/1.0\n", 12); + //printf("TEST: '%s'\n",input.content()); + HttpParserInit(&output, input.content(), input.contentSize()); + // When tolerantly ignoring SP prefix this case becomes ambiguous with HTTP/0.9 simple-request) + Config.onoff.relaxed_header_parser = 0; + 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(" / HTTP/1.0\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // binary code in method (strange but ...) + input.append("GET\x0B / HTTP/1.1\n", 16); + //printf("TEST: %d-%d/%d '%.*s'\n", output.req_start, output.req_end, input.contentSize(), 16, 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\x0B / HTTP/1.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(3, output.m_end); + CPPUNIT_ASSERT(memcmp("GET\x0B", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(7, output.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // CR in method + // RFC 2616 sec 5.1 prohibits CR other than in terminator. + input.append("GET\r / HTTP/1.1\r\n", 16); + //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(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // binary code NUL! in method (strange but ...) + input.append("GET\0 / HTTP/1.1\n", 16); + //printf("TEST: %d-%d/%d '%.*s'\n", output.req_start, output.req_end, input.contentSize(), 16, 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\0 / HTTP/1.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(3, output.m_end); + CPPUNIT_ASSERT(memcmp("GET\0", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(5, output.u_end); + CPPUNIT_ASSERT(memcmp("/", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(7, output.v_start); + CPPUNIT_ASSERT_EQUAL(14, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.v_start],(output.v_end-output.v_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(1, output.v_maj); + CPPUNIT_ASSERT_EQUAL(1, output.v_min); + input.reset(); + + // no URL (grammer otherwise correct) + input.append("GET HTTP/1.1\n", 14); + //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.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(5, output.u_start); + CPPUNIT_ASSERT_EQUAL(12, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); + input.reset(); + + // no URL (grammer invalid, ambiguous with RFC 1945 HTTP/0.9 simple-request) + input.append("GET HTTP/1.1\n", 13); + //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.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(11, output.u_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.1", &output.buf[output.u_start],(output.u_end-output.u_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(9, output.v_min); + input.reset(); + + // no version + input.append("GET / HTTP/\n", 12); + //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/\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(10, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/", &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 major version + input.append("GET / HTTP/.1\n", 14); + //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\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(12, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/.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 version dot + input.append("GET / HTTP/11\n", 14); + //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/11\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(12, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/11", &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()); + 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.\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(12, output.v_end); + CPPUNIT_ASSERT(memcmp("HTTP/1.", &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); + //printf("TEST: binary-line\n"); + 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("\xB\xC\xE\xF\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // mixed whitespace line + // We accept non-space binary bytes for method so first \t shows up as that + // but remaining space and tabs are skipped searching for URI-start + input.append("\t \t \t\n", 6); + //printf("TEST: mixed whitespace\n"); + 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("\t \t \t\n", &output.buf[output.req_start],(output.req_end-output.req_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(0, output.m_start); + CPPUNIT_ASSERT_EQUAL(0, output.m_end); + CPPUNIT_ASSERT(memcmp("\t", &output.buf[output.m_start],(output.m_end-output.m_start+1)) == 0); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); + + // mixed whitespace line with CR middle + // CR aborts on sight, so even initial \t method is not marked as above + // (not when parsing clean with whole line available anyway) + input.append("\t \r \n", 6); + //printf("TEST: mixed whitespace with CR\n"); + HttpParserInit(&output, input.content(), input.contentSize()); + CPPUNIT_ASSERT_EQUAL(-1, HttpParserParseReqLine(&output)); + CPPUNIT_ASSERT_EQUAL(0, output.req_start); + CPPUNIT_ASSERT_EQUAL(-1, output.req_end); + CPPUNIT_ASSERT_EQUAL(-1, output.m_start); + CPPUNIT_ASSERT_EQUAL(-1, output.m_end); + CPPUNIT_ASSERT_EQUAL(-1, output.u_start); + CPPUNIT_ASSERT_EQUAL(-1, output.u_end); + CPPUNIT_ASSERT_EQUAL(-1, output.v_start); + CPPUNIT_ASSERT_EQUAL(-1, output.v_end); + CPPUNIT_ASSERT_EQUAL(0, output.v_maj); + CPPUNIT_ASSERT_EQUAL(0, output.v_min); + input.reset(); +} diff -u -r -N squid-3.1.7/src/tests/testHttpRequest.h squid-3.1.8/src/tests/testHttpRequest.h --- squid-3.1.7/src/tests/testHttpRequest.h 2010-08-24 17:41:25.000000000 +1200 +++ squid-3.1.8/src/tests/testHttpRequest.h 2010-09-04 15:25:57.000000000 +1200 @@ -15,6 +15,7 @@ CPPUNIT_TEST( testCreateFromUrl ); CPPUNIT_TEST( testIPv6HostColonBug ); CPPUNIT_TEST( testSanityCheckStartLine ); + CPPUNIT_TEST( testParseRequestLine ); CPPUNIT_TEST_SUITE_END(); public: @@ -25,6 +26,7 @@ void testCreateFromUrl(); void testIPv6HostColonBug(); void testSanityCheckStartLine(); + void testParseRequestLine(); }; #endif diff -u -r -N squid-3.1.7/src/url.cc squid-3.1.8/src/url.cc --- squid-3.1.7/src/url.cc 2010-08-24 17:41:27.000000000 +1200 +++ squid-3.1.8/src/url.cc 2010-09-04 15:25:57.000000000 +1200 @@ -38,6 +38,13 @@ #include "URLScheme.h" #include "rfc1738.h" +static HttpRequest *urlParseFinish(const HttpRequestMethod& method, + const protocol_t protocol, + const char *const urlpath, + const char *const host, + const char *const login, + const int port, + HttpRequest *request); static HttpRequest *urnParse(const HttpRequestMethod& method, char *urn); static const char valid_hostname_chars_u[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -222,6 +229,11 @@ if (sscanf(url, "%[^:]:%d", host, &port) < 1) return NULL; + } else if ((method == METHOD_OPTIONS || method == METHOD_TRACE) && + strcmp(url, "*") == 0) { + protocol = PROTO_HTTP; + port = urlDefaultPort(protocol); + return urlParseFinish(method, protocol, url, host, login, port, request); } else if (!strncmp(url, "urn:", 4)) { return urnParse(method, url); } else { @@ -402,6 +414,23 @@ } } + return urlParseFinish(method, protocol, urlpath, host, login, port, request); +} + +/** + * Update request with parsed URI data. If the request arg is + * non-NULL, put parsed values there instead of allocating a new + * HttpRequest. + */ +static HttpRequest * +urlParseFinish(const HttpRequestMethod& method, + const protocol_t protocol, + const char *const urlpath, + const char *const host, + const char *const login, + const int port, + HttpRequest *request) +{ if (NULL == request) request = new HttpRequest(method, protocol, urlpath); else { @@ -767,8 +796,10 @@ if (r->method == METHOD_CONNECT) return 1; - if (r->method == METHOD_TRACE) - return 1; + // we support OPTIONS and TRACE directed at us (with a 501 reply, for now) + // we also support forwarding OPTIONS and TRACE, except for the *-URI ones + if (r->method == METHOD_OPTIONS || r->method == METHOD_TRACE) + return (r->max_forwards == 0 || r->urlpath != "*"); if (r->method == METHOD_PURGE) return 1; diff -u -r -N squid-3.1.7/test-suite/Makefile.in squid-3.1.8/test-suite/Makefile.in --- squid-3.1.7/test-suite/Makefile.in 2010-08-24 17:42:44.000000000 +1200 +++ squid-3.1.8/test-suite/Makefile.in 2010-09-04 15:26:29.000000000 +1200 @@ -47,6 +47,7 @@ VirtualDeleteOperator$(EXEEXT) StackTest$(EXEEXT) \ refcount$(EXEEXT) splay$(EXEEXT) MemPoolTest$(EXEEXT) \ mem_node_test$(EXEEXT) mem_hdr_test$(EXEEXT) $(am__EXEEXT_2) +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) EXTRA_PROGRAMS = mem_node_test$(EXEEXT) membanger$(EXEEXT) \ splay$(EXEEXT) tcp-banger2$(EXEEXT) subdir = test-suite @@ -355,7 +356,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) AUTOMAKE_OPTIONS = subdir-objects LDADD = \ $(top_builddir)/compat/libcompat.la \ diff -u -r -N squid-3.1.7/tools/Makefile.in squid-3.1.8/tools/Makefile.in --- squid-3.1.7/tools/Makefile.in 2010-08-24 17:42:45.000000000 +1200 +++ squid-3.1.8/tools/Makefile.in 2010-09-04 15:26:30.000000000 +1200 @@ -42,6 +42,7 @@ $(top_srcdir)/src/Common.am check_PROGRAMS = TESTS = +@USE_LOADABLE_MODULES_TRUE@am__append_1 = $(INCLTDL) bin_PROGRAMS = squidclient$(EXEEXT) libexec_PROGRAMS = cachemgr$(CGIEXT)$(EXEEXT) subdir = tools @@ -310,7 +311,8 @@ AM_CXXFLAGS = $(SQUID_CXXFLAGS) CLEANFILES = stub_debug.cc time.cc INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/src \ - -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) -I$(srcdir) + -I$(top_builddir)/include $(SQUID_CPPUNIT_INC) $(am__append_1) \ + -I$(srcdir) AUTOMAKE_OPTIONS = subdir-objects # Neither of these should be disted from here.