From: Francesco Chemolli Date: Sun, 11 May 2014 19:12:35 +0000 (+0200) Subject: Integrate delayer helper with build system X-Git-Tag: SQUID_3_5_0_1~233^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ec1fac73b1a98ceccc1cf556baa1e83411cb03c7;p=thirdparty%2Fsquid.git Integrate delayer helper with build system --- diff --git a/configure.ac b/configure.ac index 46b76499af..22e3980e18 100644 --- a/configure.ac +++ b/configure.ac @@ -3504,6 +3504,7 @@ AC_CONFIG_FILES([ helpers/negotiate_auth/wrapper/Makefile helpers/external_acl/Makefile helpers/external_acl/AD_group/Makefile + helpers/external_acl/delayer/Makefile helpers/external_acl/eDirectory_userip/Makefile helpers/external_acl/file_userip/Makefile helpers/external_acl/kerberos_ldap_group/Makefile diff --git a/helpers/external_acl/Makefile.am b/helpers/external_acl/Makefile.am index e5d5ba4313..15d0a5ac44 100644 --- a/helpers/external_acl/Makefile.am +++ b/helpers/external_acl/Makefile.am @@ -1,5 +1,6 @@ DIST_SUBDIRS= \ AD_group \ + delayer \ eDirectory_userip \ file_userip \ kerberos_ldap_group \ diff --git a/helpers/external_acl/delayer/Makefile.am b/helpers/external_acl/delayer/Makefile.am new file mode 100644 index 0000000000..45a0112b0b --- /dev/null +++ b/helpers/external_acl/delayer/Makefile.am @@ -0,0 +1,12 @@ +include $(top_srcdir)/src/Common.am + +libexec_SCRIPTS = delayer +CLEANFILES += delayer delayer.8 +man_MANS = delayer.8 +EXTRA_DIST = delayer.pl.in delayer.8 required.m4 + +delayer.8: delayer + pod2man delayer delayer.8 + +delayer: delayer.pl.in + $(subst_perlshell) diff --git a/helpers/external_acl/delayer/delayer.pl.in b/helpers/external_acl/delayer/delayer.pl.in new file mode 100755 index 0000000000..65745b3933 --- /dev/null +++ b/helpers/external_acl/delayer/delayer.pl.in @@ -0,0 +1,257 @@ +#!@PERL@ +=pod + +=head1 NAME + +delayer - Squid external acl helper adding artificial delay to requests + +=head1 SYNOPSIS + +delayer [--help] [--debug] [--log file] [--wait msec] + +=head1 OPTIONS + +=over 8 + +=item B<--help> or B<-h> + +Print help message to stdout + +=item B<--debug> or B<-d> + +Emit debugging output to STDERR and ultimately cache.log + +=item B<--log /path/to/file> or B<-l /path/to/file> + +Emit debugging output to specified file instead of STDERR. Also turns on debugging + +=item B<--wait msec> or B<-w msec> + +Delay each request by the specified amount of msec. +Unless this option is specified, by default each submitted request +will be delayed by half a second (500 msec). + +=back + +=head1 DESCRIPTION + +Squid external acl helper; causes squid to delay responding to HTTP requests. + +By carefully crafting the ACLs of a Squid setup it is possible to +selectively delay requests received by a proxy. After the configured amount +of time, it will always return "true". + +=head1 CONFIGURATION + +To engage it, this snippet of configuration template can be used in squid.conf: + + external_acl_type delayer concurrency=100000 children-max=2 children-startup=1 children-idle=1 cache=10 %URI /path/to/delayer -w 200 + acl delay external delayer + http_access allow acl1 acl2 acl3 delay !all + +It is important that the acl referencing the delayer be the penultimate clause in the +http_access line. It will cause delay to all requests that match all the +preceding acls in the line. The !all clause at the end of the line will make it +so that no traffic is authorized by this ACL, only the delay to evaluate +the delay clause will be inserted before evaluating following http_access lines. +It is also important to place the http_access line carefully in the sequence +of all http_access_lines; it should be near the beginning, but be careful +not to insert unwanted slow acls (especially proxy_auth). + +It is possible to customize how delay is calculated for each request by +modifying the "calc_delay" PERL function in the script, documentation on this +is embedded in the source code comments. + +=head1 AUTHOR + +This software is written by Francesco Chemolli + +=head1 COPYRIGHT + +(C) 2014 Francesco Chemolli + +This program is free software. You may redistribute copies of it under the +terms of the GNU General Public License version 2, or (at your opinion) any +later version. + +=head1 QUESTIONS + +Questions on this code are best addressed on the Squid-users mailing list + + +=head1 REPORTING BUGS + +Bug reports need to be made in English. +See http://wiki.squid-cache.org/SquidFaq/BugReporting for details of what you +need to include with your bug report. +Report bugs or bug fixes using http://bugs.squid-cache.org/ + +=head1 SEE ALSO + +B(8), B(7), B http://wiki.squid-cache.org/ , +B http://www.squid-cache.org/Doc/config/ + +=cut + +use strict; +use warnings; +use Getopt::Long qw(:config auto_version auto_help); +use Data::Dumper; +use Time::HiRes qw(gettimeofday tv_interval); + +# options handling +my %opts = (); #for getopt +my $debug = 0; #debug +my $logfile = *STDERR; #filehandle to logfile +my $logfilename; +my $delay = 500; #in milliseconds. Configurable with the -w option. +#for custom delay algorithms, you can customize the dispatch_request function + +#calculate the delay for the request. +# Gets as input the verbatim full line received from squid +# (channel number and all, as configured in squid.conf) and returns +# a floating point number >= 0 which is the delay to be applied to the request +# in seconds. +# Notice that in order to have efficient data structures, the delay is +# assumed to be monotonously growing. In other words, a long-delay +# item will stall the queue until completed. Supporting generic delays +# requires transforming @queue from a FIFO to a priority queue. +sub calc_delay { + return $delay; +} + +GetOptions("debug|d" => \$debug, + "wait|w=i" => \$delay, + "log|l=s" => \$logfilename) +or die("Error in parsing command line arguments"); +if (defined $opts{h}) { + HELP_MESSAGE(); + exit 0; +} +$delay /= 1000.0; # transform msec into sec +if ($logfilename) { + open ($logfile,">>", "$opts{l}"); + $debug=1; +} + +my @p=split(/[\\\/]/,$0); +my $prg_basename=pop @p; +$prg_basename .= "[$$]"; +undef @p; +my $reqid=0; #sequence number for requests + +# variables initialization for select +my $rvec = ''; +vec($rvec,0,1) = 1; #stdin +my ($nfound, $rd, $nread, $req); + +#requests queue +my @queue = (); # array of references to hashes, with keys chan, when, req, reqid + +# signal handlers +$SIG{HUP} = \&dump_state; + +#disable IO buffering +$| = 1; +my $fh=select($logfile); $|=1; select($fh); undef($fh); + +# takes a result from a gettimeofday call and turns it into a +# floating-point number suitable for approximate time calculations and select +sub fract_time { + return $_[0]+$_[1]/1000000; +} + +sub dispatch_request { + my $r = $_[0]; + chomp $r; + &debug("got request: '$r'"); + my %evt = (); + my @fields; + @fields = split (/\s+/, $r); + $evt{when} = &calc_delay($r)+fract_time(gettimeofday()); + $evt{reqid}=$reqid++; + $evt{req} = $r; + $evt{chan} = $fields[0]; + &debug("Dispatching: reqid $evt{reqid}, chan $evt{chan}, when $evt{when}, raw {$evt{req}}"); + push @queue,\%evt; +} + +sub next_event { + my $now = fract_time(gettimeofday()); + if (@queue) { + my $when = $queue[0]->{when} - $now; + &debug("Next event is in $when seconds"); + return $when; + } + &debug("No events in queue"); + return undef; +} + +sub handle_events { + my $now = fract_time(gettimeofday()); + while ( @queue ) { + &debug("Queue length is $#queue"); + last if ($queue[0]->{when} > $now); + my %evt = %{shift @queue}; + &debug("Event: reqid $evt{reqid}, chan $evt{chan}, when $evt{when}, raw {$evt{req}}"); + print $evt{chan} , " OK\n"; + } +} + +# main loop +while(1) { + &debug("selecting"); + $nfound = select($rd = $rvec,undef,undef,&next_event()); + &debug("found $nfound bits set"); + if ($nfound == -1 ) { + next if ($!{ERESTART} || $!{EAGAIN} || $!{EINTR}); + &debug("error in select: $!"); + exit 1; + } + if (vec($rd,0,1)==1) { #got stuff from stdin + my $d; #data + $nread = sysread(STDIN,$d,40960); # read 40kb + # clear the signal-bit, stdin is special + vec($rd,0,1) = 0; + if ($nread==0) { + &debug("nothing read from stdin, exiting"); + exit 0; + } + my $i; + while ($i = index($d,"\n")) { #BUG: assumption of no spill-over + last if ($i == -1); + &dispatch_request(substr($d,0,$i)); + $d=substr($d,$i+1); + } + } + &handle_events(); +} + +my $doc = <<_EOF; +delay-adding external acl helper +authorizes all requests, adding a delay before doing so. +supports multiplexed helper protocol. +Options: + -h, --help: this help message + -d, --debug: enable debug output + -l , --log : log output to named file instead of stderr (implies debug) + -w , --wait delay each request by this number milliseconds + +AUTHOR: Francesco Chemolli +Licensed under the terms of the GNU GPL v2 or later (see source for details) +_EOF +our $VERSION = "1.0"; + +sub HELP_MESSAGE { + print STDERR $doc; +} + +sub dump_state { + $SIG{HUP} = \&dump_state; + print STDERR "Queue:\n",Dumper(\@queue),"\n"; +} + +sub debug { + return unless ($debug); + print $logfile $prg_basename , ": ", @_, "\n"; +} diff --git a/helpers/external_acl/delayer/required.m4 b/helpers/external_acl/delayer/required.m4 new file mode 100755 index 0000000000..f7eac4af62 --- /dev/null +++ b/helpers/external_acl/delayer/required.m4 @@ -0,0 +1,3 @@ +if test "x$PERL" != "x" -a "x$POD2MAN" != "x"; then + BUILD_HELPER="delayer" +fi diff --git a/helpers/external_acl/modules.m4 b/helpers/external_acl/modules.m4 index 4a4f30bc35..cc27153839 100644 --- a/helpers/external_acl/modules.m4 +++ b/helpers/external_acl/modules.m4 @@ -27,6 +27,9 @@ if test "x$enable_external_acl_helpers" != "xno" ; then elif test "x$helper" = "xLM_group" ; then m4_include([helpers/external_acl/LM_group/required.m4]) + elif test "x$helper" = "xdelayer" ; then + m4_include([helpers/external_acl/delayer/required.m4]) + elif test "x$helper" = "xSQL_session" ; then m4_include([helpers/external_acl/SQL_session/required.m4])