X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXXml%2FPing.pm;h=270587198928773eba4b9e1dd72f722aa593a324;hb=ab811a0c902225075a9bd69749f65594079433a9;hp=26dd864e26e3c3429d29ca8241ed42b78021569f;hpb=af378e74088394d9c70a9a01d67a311cf4774d96;p=spider.git diff --git a/perl/DXXml/Ping.pm b/perl/DXXml/Ping.pm index 26dd864e..27058719 100644 --- a/perl/DXXml/Ping.pm +++ b/perl/DXXml/Ping.pm @@ -1,7 +1,7 @@ # # XML Ping handler # -# $Id$ +# # # Copyright (c) Dirk Koopman, G1TLH # @@ -13,20 +13,134 @@ package DXXml::Ping; use DXDebug; use DXProt; use IsoTime; +use Time::HiRes qw(gettimeofday tv_interval); +use Route::Node; -use vars qw($VERSION $BRANCH @ISA); -$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ ); -$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0)); -$main::build += $VERSION; -$main::branch += $BRANCH; - +use vars qw(@ISA %pings); @ISA = qw(DXXml); +%pings = (); # outstanding ping requests outbound sub handle_input { my $self = shift; my $dxchan = shift; + if ($self->{to} eq $main::mycall) { + if ($self->{s} eq '1') { + my $rep = DXXml::Ping->new(to=>$self->{o}, + s=>'0', + oid=>$self->{id}, + ot=>$self->{t} + ); + $dxchan->send($rep->toxml); + if ($dxchan->{outgoing} && abs($dxchan->{lastping} - $main::systime) < 15) { + $dxchan->{lastping} += $dxchan->{pingint} / 2; + } + } else { + handle_ping_reply($dxchan, $self->{o}, $self->{ot}, $self->{oid}); + } + } else { + $self->route($dxchan); + } +} + +sub topcxx +{ + my $self = shift; + unless (exists $self->{'-pcxx'}) { + $self->{'-pcxx'} = DXProt::pc51($self->{to}, $self->{o}, $self->{s}); + } + return $self->{'-pcxx'}; +} + +# add a ping request to the ping queues +sub add +{ + my ($dxchan, $to, $via) = @_; + my $from = $dxchan->call; + my $ref = $pings{$to} || []; + my $r = {}; + my $self = DXXml::Ping->new(to=>$to, '-hirestime'=>[ gettimeofday ], s=>'1'); + $self->{u} = $from unless $from eq $main::mycall; + $self->{'-via'} = $via if $via && DXChannel::get($via); + $self->{o} = $main::mycall; + $self->route($dxchan); + + push @$ref, $self; + $pings{$to} = $ref; + my $u = DXUser::get_current($to); + if ($u) { + $u->lastping(($via || $from), $main::systime); + $u->put; + } } +sub handle_ping_reply +{ + my $fromdxchan = shift; + my $from = shift; + my $ot = shift; + my $oid = shift; + my $fromxml; + + if (ref $from) { + $fromxml = $from; + $from = $from->{o}; + } + + # it's a reply, look in the ping list for this one + my $ref = $pings{$from}; + return unless $ref; + + my $tochan = DXChannel::get($from); + while (@$ref) { + my $r = shift @$ref; + my $dxchan = DXChannel::get($r->{o}); + next unless $dxchan; + my $t = tv_interval($r->{'-hirestime'}, [ gettimeofday ]); + if ($dxchan->is_node) { + if ($tochan) { + my $nopings = $tochan->user->nopings || $DXProt::obscount; + push @{$tochan->{pingtime}}, $t; + shift @{$tochan->{pingtime}} if @{$tochan->{pingtime}} > 6; + + # cope with a missed ping, this means you must set the pingint large enough + if ($t > $tochan->{pingint} && $t < 2 * $tochan->{pingint} ) { + $t -= $tochan->{pingint}; + } + + # calc smoothed RTT a la TCP + if (@{$tochan->{pingtime}} == 1) { + $tochan->{pingave} = $t; + } else { + $tochan->{pingave} = $tochan->{pingave} + (($t - $tochan->{pingave}) / 6); + } + $tochan->{nopings} = $nopings; # pump up the timer + dbg("ROUTE: $tochan->{call} ping obscount reset to $tochan->{nopings}") if isdbg('obscount'); + my $nref = Route::Node::get($tochan->{call}); + if ($nref) { + my $n = $nref->reset_obs; + dbg("ROUTE: reset obscount on $tochan->{call} to $n (ping)") if isdbg('obscount'); + } + } + _handle_believe($from, $fromdxchan->{call}); + } + if (exists $r->{u} && ($dxchan = DXChannel::get($r->{u})) && $dxchan->is_user) { + my $s = sprintf "%.2f", $t; + my $ave = sprintf "%.2f", $tochan ? ($tochan->{pingave} || $t) : $t; + $dxchan->send($dxchan->msg('pingi', $from, $s, $ave)) + } + } +} + +sub _handle_believe +{ + my ($from, $via) = @_; + + my $user = DXUser::get_current($from); + if ($user) { + $user->set_believe($via); + $user->put; + } +} 1;