+if ($debug) { open DEBUG, ">& STDERR" or die $!; }
+
+our @fields_in= qw(seconds accepted refused rejected duplicate
+ accepted_size duplicate_size);
+our $tmpl_in= join ':',@fields_in;
+our %details= (
+ 'in' => {
+ Step => 60,
+ DstArguments => "7200:0:U",
+ Xff => 0.5,
+ Archives => [ [ 3600*4, 60 ], # 4hr, 1min resolution
+ [ 3600*25, 180 ], # 25h, 3min resolution
+ [ 86400*14*5, 3600 ], # 14wks, 1hr resolution
+ [ 86400*370*2, 3600*24 ] ], # 2yr+, 1day resolution
+ }
+);
+
+our ($time,$host,$peer,$conn,$stats);
+
+sub path_rrd ($) {
+ my ($inout) = @_;
+ return "${outpfx}${host}${sep}${peer}_${inout}.rrd";
+}
+
+sub perhaps_create_rrd ($$) {
+ my ($inout, $fields) = @_;
+ my $path= path_rrd($inout);
+ return if stat $path;
+ $!==&ENOENT or die "$path $!";
+ my $details= $details{$inout};
+
+ my @sargs= ($path, '--start','now-1y', '--step',$details->{Step});
+ my @largs;
+ push @largs, "DS:$_:ABSOLUTE:$details->{DstArguments}" foreach @$fields;
+ foreach (@{ $details->{Archives} }) {
+ my ($whole,$reso) = @$_;
+ my $steps= $reso / $details->{Step};
+ my $rows= $whole / $reso;
+ push @largs, "RRA:AVERAGE:$details->{Xff}:$steps:$rows";
+ }
+ print DEBUG join(" \\\n ", "creating @sargs", @largs),"\n";
+ RRDs::create(@sargs,@largs);
+ my $err= RRDs::error;
+ die "$err [@sargs @largs]" if defined $err;
+}
+
+sub update_rrd ($$$) {
+ my ($inout,$tmpl,$vals) = @_;
+ my $path= path_rrd($inout);
+ my @args= ($path, '--template',$tmpl, join(':',$time,@$vals));
+ print DEBUG "update @args\n";
+ RRDs::update(@args);
+ my $err= RRDs::error;
+ die "$err [@args]" if defined $err;
+}
+
+our %in_conns;
+
+sub inbound_connected () {
+ #print "$host $peer $conn START\n";
+ perhaps_create_rrd('in',\@fields_in);
+ $in_conns{$host,$peer,$conn} = [ (0) x @fields_in ];
+}
+sub inbound_closed () {
+ #print "$host $peer $conn STOP\n";
+ delete $in_conns{$host,$peer,$conn};
+}
+sub inbound_stats () {
+ $_= $stats.' ';
+ my %s;
+ s/(?<=[a-z]) (?=[a-z])/_/g;
+ my $hpc= $in_conns{$host,$peer,$conn};
+ if (!$hpc) {
+ perhaps_create_rrd('in',\@fields_in);
+ $in_conns{$host,$peer,$conn}= $hpc= [ (undef) x @fields_in ];
+ }
+ while (s/^([a-z_]+) (\d+)\s//) { $s{$1}= $2; }
+ my @v;
+ foreach my $f (@fields_in) {
+ my $this= $s{$f};
+ if (!defined $this) {
+ delete $hpc->[@v];
+ push @v, 'U';
+ next;
+ }
+ my $last= $hpc->[@v];
+ $hpc->[@v]= $this;
+ push @v, defined($last) ? $this - $last : 'U';
+ }
+ update_rrd('in',$tmpl_in,\@v);
+}
+
+sub outbound_stats () {
+ print "$host $peer OUT $stats\n";
+}
+