]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Integrate delayer helper with build system
authorFrancesco Chemolli <kinkie@squid-cache.org>
Sun, 11 May 2014 19:12:35 +0000 (21:12 +0200)
committerFrancesco Chemolli <kinkie@squid-cache.org>
Sun, 11 May 2014 19:12:35 +0000 (21:12 +0200)
configure.ac
helpers/external_acl/Makefile.am
helpers/external_acl/delayer/Makefile.am [new file with mode: 0644]
helpers/external_acl/delayer/delayer.pl.in [new file with mode: 0755]
helpers/external_acl/delayer/required.m4 [new file with mode: 0755]
helpers/external_acl/modules.m4

index 46b76499afccbc89912b115ed2e7d664355cd109..22e3980e187954b8c2c4149ebaf6d171ca941cd5 100644 (file)
@@ -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
index e5d5ba43138d3682703ce1be6a87b34638c47f4d..15d0a5ac44d556d3ff6dd738a1769f28f0d65545 100644 (file)
@@ -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 (file)
index 0000000..45a0112
--- /dev/null
@@ -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 (executable)
index 0000000..65745b3
--- /dev/null
@@ -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 <kinkie@squid-cache.org>
+
+=head1 COPYRIGHT
+
+(C) 2014 Francesco Chemolli <kinkie@squid-cache.org>
+
+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
+<squid-users@squid-cache.org>
+
+=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<squid>(8), B<GPL>(7), B<Squid Wiki> http://wiki.squid-cache.org/ ,
+B<Squid Configuration Manual> 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 <file>, --log <file>: log output to named file instead of stderr (implies debug)
+  -w <num>, --wait <num> delay each request by this number milliseconds
+
+AUTHOR: Francesco Chemolli <kinkie\@squid-cache.org>
+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 (executable)
index 0000000..f7eac4a
--- /dev/null
@@ -0,0 +1,3 @@
+if test "x$PERL" != "x" -a "x$POD2MAN" != "x"; then
+  BUILD_HELPER="delayer"
+fi
index 4a4f30bc35c94c95a1f334cfcaa06eb98d1fe182..cc27153839804c2b432aefffa98d8e640b2ed344 100644 (file)
@@ -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])