6 # Copyright (c) Dirk Koopman, G1TLH
17 use Time::HiRes qw(gettimeofday tv_interval);
19 use vars qw($VERSION $BRANCH @ISA %pings);
20 $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
21 $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0));
22 $main::build += $VERSION;
23 $main::branch += $BRANCH;
26 %pings = (); # outstanding ping requests outbound
38 unless (exists $self->{'-pcxx'}) {
39 $self->{'-pcxx'} = DXProt::pc51($self->{to}, $self->{o}, $self->{s});
41 return $self->{'-pcxx'};
44 # add a ping request to the ping queues
47 my ($dxchan, $to, $via) = @_;
48 my $from = $dxchan->call;
49 my $ref = $pings{$to} || [];
51 my $self = DXXml::Ping->new(to=>$to, '-hirestime'=>[ gettimeofday ], s=>'1');
52 $self->{u} = $from unless $from eq $main::mycall;
53 $self->{'-via'} = $via if $via && DXChannel::get($via);
54 $self->{o} = $main::mycall;
55 $self->{id} = $self->nextid;
56 $self->route($dxchan);
60 my $u = DXUser->get_current($to);
62 $u->lastping(($via || $from), $main::systime);
69 my $fromdxchan = shift;
78 # it's a reply, look in the ping list for this one
79 my $ref = $pings{$from};
82 my $tochan = DXChannel::get($from);
85 my $dxchan = DXChannel::get($r->{to});
87 my $t = tv_interval($r->{'-hirestime'}, [ gettimeofday ]);
88 if ($dxchan->is_user) {
89 my $s = sprintf "%.2f", $t;
90 my $ave = sprintf "%.2f", $tochan ? ($tochan->{pingave} || $t) : $t;
91 $dxchan->send($dxchan->msg('pingi', $from, $s, $ave))
92 } elsif ($dxchan->is_node) {
94 my $nopings = $tochan->user->nopings || $DXProt::obscount;
95 push @{$tochan->{pingtime}}, $t;
96 shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6;
98 # cope with a missed ping, this means you must set the pingint large enough
99 if ($t > $tochan->{pingint} && $t < 2 * $tochan->{pingint} ) {
100 $t -= $tochan->{pingint};
103 # calc smoothed RTT a la TCP
104 if (@{$tochan->{pingtime}} == 1) {
105 $tochan->{pingave} = $t;
107 $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6);
109 $tochan->{nopings} = $nopings; # pump up the timer
110 if (my $ivp = Investigate::get($from, $fromdxchan->{call})) {
113 } elsif (my $rref = Route::Node::get($r->{to})) {
114 if (my $ivp = Investigate::get($from, $fromdxchan->{to})) {