X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXProt.pm;h=7a9e4ca15f108f0374fdcee54eb91d856082584b;hb=43a8ee12581aa51eb93cd8958b429077f22df76d;hp=981d5d860605ff02206b78856e3b7334fbee01ad;hpb=c73895f5ea983497905ce9acc12615e3f35f870a;p=spider.git diff --git a/perl/DXProt.pm b/perl/DXProt.pm index 981d5d86..7a9e4ca1 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -27,7 +27,6 @@ use DXDb; use AnnTalk; use Geomag; use WCY; -use Time::HiRes qw(gettimeofday tv_interval); use BadWords; use DXHash; use Route; @@ -50,13 +49,14 @@ use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restim $pingint $obscount %pc19list $chatdupeage $chatimportfn $investigation_int $pc19_version $myprot_version %nodehops $baddx $badspotter $badnode $censorpc $rspfcheck - $allowzero $decode_dk0wcy $send_opernam @checklist); + $allowzero $decode_dk0wcy $send_opernam @checklist + $eph_pc15_restime + ); $pc11_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc11 $pc23_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc23 $last_hour = time; # last time I did an hourly periodic update -%pings = (); # outstanding ping requests outbound %rcmds = (); # outstanding rcmd requests outbound %nodehops = (); # node specific hop control %pc19list = (); # list of outstanding PC19s that haven't had PC16s on them @@ -71,6 +71,7 @@ $ann_to_talk = 1; $rspfcheck = 1; $eph_restime = 180; $eph_info_restime = 60*60; +$eph_pc15_restime = 6*60; $eph_pc34_restime = 30; $pingint = 5*60; $obscount = 2; @@ -234,6 +235,14 @@ sub new # add this node to the table, the values get filled in later my $pkg = shift; my $call = shift; + + # if we have an entry already, then send a PC21 to all connect + # old style connections, because we are about to get the real deal + if (my $ref = Route::Node::get($call)) { + dbg("ROUTE: $call is already in the routing table, deleting") if isdbg('route'); + my @rout = $ref->delete; + $self->route_pc21($main::mycall, undef, @rout) if @rout; + } $main::routeroot->add($call, '5000', Route::here(1)) if $call ne $main::mycall; return $self; @@ -299,7 +308,7 @@ sub start $self->{pingave} = 999; $self->{metric} ||= 100; $self->{lastping} = $main::systime; - + # send initialisation string unless ($self->{outbound}) { $self->sendinit; @@ -326,21 +335,6 @@ sub sendinit $self->send(pc18()); } -sub removepc90 -{ - $_[0] =~ s/^PC90\^[-A-Z0-9]+\^\d+\^//; - $_[0] =~ s/^PC91\^[-A-Z0-9]+\^\d+\^[-A-Z0-9]+\^//; -} - -#sub send -#{ -# my $self = shift; -# while (@_) { -# my $line = shift; -# $self->SUPER::send($line); -# } -#} - # # This is the normal pcxx despatcher # @@ -348,8 +342,10 @@ sub normal { my ($self, $line) = @_; - # remove any incoming PC90 frames - removepc90($line); + if ($line =~ '^<\w+\s' && $main::do_xml) { + DXXml::normal($self, $line); + return; + } my @field = split /\^/, $line; return unless @field; @@ -490,6 +486,18 @@ sub handle_11 # rsfp check # return if $rspfcheck and !$self->rspfcheck(1, $_[7], $_[6]); + + # is the spotted callsign blank? This should really be trapped earlier but it + # could break other protocol sentences. Also check for lower case characters. + if ($_[2] =~ /^\s*$/) { + dbg("PCPROT: blank callsign, dropped") if isdbg('chanerr'); + return; + } + if ($_[2] =~ /[a-z]/) { + dbg("PCPROT: lowercase characters, dropped") if isdbg('chanerr'); + return; + } + # if this is a 'nodx' node then ignore it if ($badnode->in($_[7])) { @@ -701,6 +709,23 @@ sub handle_12 $self->route($_[2], $line); } } + + +sub handle_15 +{ + my $self = shift; + my $pcno = shift; + my $line = shift; + my $origin = shift; + + if (eph_dup($line, $eph_pc15_restime)) { + dbg("PCPROT: Ephemeral dup, dropped") if isdbg('chanerr'); + } else { + unless ($self->{isolate}) { + DXChannel::broadcast_nodes($line, $self) if $line =~ /\^H\d+\^?~?$/; # send it to everyone but me + } + } +} # incoming user sub handle_16 @@ -722,7 +747,11 @@ sub handle_16 } # is it me? if ($ncall eq $main::mycall) { - dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); + dbg("PCPROT: trying to alter my config from outside!") if isdbg('chanerr'); + return; + } + if (DXChannel::get($ncall) && $ncall ne $self->{call}) { + dbg("PCPROT: trying to alter locally connected $ncall from $self->{call}, ignored") if isdbg('chanerr'); return; } @@ -846,9 +875,12 @@ sub handle_16 push @rout, $parent->add_user($call, $flags); } + # send info to all logged in thingies + $self->tell_login('loginu', "$ncall: $call") if DXUser->get_current($ncall)->is_local_node; + $self->tell_buddies('loginb', $call, $ncall); # add this station to the user database, if required - $call =~ s/-\d+$//o; # remove ssid for users +# $call =~ s/-\d+$//o; # remove ssid for users my $user = DXUser->get_current($call); $user = DXUser->new($call) if !$user; $user->homenode($parent->call) if !$user->homenode; @@ -917,6 +949,10 @@ sub handle_17 $parent = Route->new($ncall); # throw away } + # send info to all logged in thingies + $self->tell_login('logoutu', "$ncall: $ucall") if DXUser->get_current($ncall)->is_local_node; + $self->tell_buddies('logoutb', $ucall, $ncall); + if (eph_dup($line)) { dbg("PCPROT: dup PC17 detected") if isdbg('chanerr'); return; @@ -946,6 +982,7 @@ sub handle_18 $self->user->put; $self->sort('S'); } + $self->{handle_xml}++ if DXXml::available() && $_[1] =~ /\bxml\b/; } else { $self->version(50.0); $self->version($_[2] / 100) if $_[2] && $_[2] =~ /^\d+$/; @@ -1014,6 +1051,7 @@ sub handle_19 # check for sane parameters # $ver = 5000 if $ver eq '0000'; + next unless $ver && $ver =~ /^\d+$/; next if $ver < 5000; # only works with version 5 software next if length $call < 3; # min 3 letter callsigns next if $call eq $main::mycall; @@ -1560,48 +1598,7 @@ sub handle_51 if ($flag == 1) { $self->send(pc51($from, $to, '0')); } else { - # it's a reply, look in the ping list for this one - my $ref = $pings{$from}; - if ($ref) { - my $tochan = DXChannel::get($from); - while (@$ref) { - my $r = shift @$ref; - my $dxchan = DXChannel::get($r->{call}); - next unless $dxchan; - my $t = tv_interval($r->{t}, [ gettimeofday ]); - if ($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)) - } elsif ($dxchan->is_node) { - if ($tochan) { - my $nopings = $tochan->user->nopings || $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 - if (my $ivp = Investigate::get($from, $self->{call})) { - $ivp->handle_ping; - } - } elsif (my $rref = Route::Node::get($r->{call})) { - if (my $ivp = Investigate::get($from, $self->{call})) { - $ivp->handle_ping; - } - } - } - } - } + DXXml::Ping::handle_ping_reply($self, $from); } } else { @@ -1726,7 +1723,8 @@ sub process } foreach $dxchan (@dxchan) { - next unless $dxchan->is_node(); + next unless $dxchan->is_node; + next if $dxchan->handle_xml; next if $dxchan == $main::me; # send the pc50 @@ -1737,9 +1735,10 @@ sub process if ($dxchan->{nopings} <= 0) { $dxchan->disconnect; } else { - addping($main::mycall, $dxchan->call); + DXXml::Ping::add($main::me, $dxchan->call); $dxchan->{nopings} -= 1; $dxchan->{lastping} = $t; + $dxchan->{lastping} += $dxchan->{pingint} / 2 unless @{$dxchan->{pingtime}}; } } } @@ -2194,29 +2193,6 @@ sub load_hops return (); } - -# add a ping request to the ping queues -sub addping -{ - my ($from, $to, $via) = @_; - my $ref = $pings{$to} || []; - my $r = {}; - $r->{call} = $from; - $r->{t} = [ gettimeofday ]; - if ($via && (my $dxchan = DXChannel::get($via))) { - $dxchan->send(pc51($to, $main::mycall, 1)); - } else { - route(undef, $to, pc51($to, $main::mycall, 1)); - } - push @$ref, $r; - $pings{$to} = $ref; - my $u = DXUser->get_current($to); - if ($u) { - $u->lastping(($via || $from), $main::systime); - $u->put; - } -} - sub process_rcmd { my ($self, $tonode, $fromnode, $user, $cmd) = @_;