6 # Copyright (c) Dirk Koopman, G1TLH
16 use Time::HiRes qw(gettimeofday tv_interval);
18 use vars qw(@ISA %pings);
20 %pings = (); # outstanding ping requests outbound
27 if ($self->{to} eq $main::mycall) {
28 if ($self->{s} eq '1') {
29 my $rep = DXXml::Ping->new(to=>$self->{o},
34 $dxchan->send($rep->toxml);
35 if ($dxchan->{outgoing} && abs($dxchan->{lastping} - $main::systime) < 15) {
36 $dxchan->{lastping} += $dxchan->{pingint} / 2;
39 handle_ping_reply($dxchan, $self->{o}, $self->{ot}, $self->{oid});
42 $self->route($dxchan);
49 unless (exists $self->{'-pcxx'}) {
50 $self->{'-pcxx'} = DXProt::pc51($self->{to}, $self->{o}, $self->{s});
52 return $self->{'-pcxx'};
55 # add a ping request to the ping queues
58 my ($dxchan, $to, $via) = @_;
59 my $from = $dxchan->call;
60 my $ref = $pings{$to} || [];
62 my $self = DXXml::Ping->new(to=>$to, '-hirestime'=>[ gettimeofday ], s=>'1');
63 $self->{u} = $from unless $from eq $main::mycall;
64 $self->{'-via'} = $via if $via && DXChannel::get($via);
65 $self->{o} = $main::mycall;
66 $self->route($dxchan);
70 my $u = DXUser->get_current($to);
72 $u->lastping(($via || $from), $main::systime);
79 my $fromdxchan = shift;
90 # it's a reply, look in the ping list for this one
91 my $ref = $pings{$from};
94 my $tochan = DXChannel::get($from);
97 my $dxchan = DXChannel::get($r->{o});
99 my $t = tv_interval($r->{'-hirestime'}, [ gettimeofday ]);
100 if ($dxchan->is_node) {
102 my $nopings = $tochan->user->nopings || $DXProt::obscount;
103 push @{$tochan->{pingtime}}, $t;
104 shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6;
106 # cope with a missed ping, this means you must set the pingint large enough
107 if ($t > $tochan->{pingint} && $t < 2 * $tochan->{pingint} ) {
108 $t -= $tochan->{pingint};
111 # calc smoothed RTT a la TCP
112 if (@{$tochan->{pingtime}} == 1) {
113 $tochan->{pingave} = $t;
115 $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6);
117 $tochan->{nopings} = $nopings; # pump up the timer
119 _handle_believe($from, $fromdxchan->{call});
121 if (exists $r->{u} && ($dxchan = DXChannel::get($r->{u})) && $dxchan->is_user) {
122 my $s = sprintf "%.2f", $t;
123 my $ave = sprintf "%.2f", $tochan ? ($tochan->{pingave} || $t) : $t;
124 $dxchan->send($dxchan->msg('pingi', $from, $s, $ave))
131 my ($from, $via) = @_;
133 my $user = DXUser->get_current($from);
135 $user->set_believe($via);