X-Git-Url: http://gb7djk.dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXProtHandle.pm;h=fcc30cfe2255ce9b71cf9db3d935b8b50b413e6d;hb=2712b7f62c605559eba46781d793a63591a7d5d3;hp=df2957a18e5b5c699be7b2e6c042b0cab4cd2e86;hpb=ad7e69f78ee4c0593e1d7576a7c1fd3b13931f84;p=spider.git diff --git a/perl/DXProtHandle.pm b/perl/DXProtHandle.pm index df2957a1..fcc30cfe 100644 --- a/perl/DXProtHandle.pm +++ b/perl/DXProtHandle.pm @@ -413,6 +413,7 @@ sub handle_16 dbg("PCPROT: don't send users to $self->{call}") if isdbg('chanerr'); return; } + # is it me? if ($ncall eq $main::mycall) { dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); @@ -428,11 +429,6 @@ sub handle_16 return; } - unless ($h) { - dbg("PCPROT: non-local PC16, ignored") if isdbg('chanerr'); - return; - } - my $parent = Route::Node::get($ncall); if ($parent) { @@ -444,6 +440,15 @@ sub handle_16 # input filter if required return unless $self->in_filter_route($parent); + } else { + $parent = Route::Node->new($ncall); + } + + unless ($h) { + if ($parent->via_pc92) { + dbg("PCPROT: non-local node controlled by PC92, ignored") if isdbg('chanerr'); + return; + } } my $i; @@ -474,9 +479,10 @@ sub handle_16 $r->flags($flags); $au = $r; } - push @rout, $r if $au; + push @rout, $r if $h && $au; } else { - push @rout, $parent->add_user($call, $flags); + my @ans = $parent->add_user($call, $flags); + push @rout, @ans if $h && @ans; } # send info to all logged in thingies @@ -493,8 +499,8 @@ sub handle_16 $user->put; } if (@rout) { - $self->route_pc16($origin, $line, $parent, @rout); - $self->route_pc92a($main::mycall, undef, $parent, @rout) if $self->{state} eq 'normal'; + $self->route_pc16($origin, $line, $parent, @rout) if @rout; +# $self->route_pc92a($main::mycall, undef, $parent, @rout) if $h && $self->{state} eq 'normal'; } } @@ -516,6 +522,7 @@ sub handle_17 dbg("PCPROT: don't send users to $self->{call}") if isdbg('chanerr'); return; } + if ($ncall eq $main::mycall) { dbg("PCPROT: trying to alter config on this node from outside!") if isdbg('chanerr'); return; @@ -543,6 +550,19 @@ sub handle_17 return; } + $dxchan = DXChannel::get($ncall); + unless ($dxchan) { + if ($parent->via_pc92) { + dbg("PCPROT: non-local node controlled by PC92, ignored") if isdbg('chanerr'); + return; + } + } + + if (DXChannel::get($ucall)) { + dbg("PCPROT: trying do disconnect local user, ignored") if isdbg('chanerr'); + return; + } + # input filter if required and then remove user if present if ($parent) { # return unless $self->in_filter_route($parent); @@ -562,7 +582,7 @@ sub handle_17 $uref = Route->new($ucall) unless $uref; # throw away $self->route_pc17($origin, $line, $parent, $uref); - $self->route_pc92d($main::mycall, undef, $parent, $uref); +# $self->route_pc92d($main::mycall, undef, $parent, $uref) if $dxchan; } # link request @@ -585,8 +605,9 @@ sub handle_18 $self->user->put; $self->sort('S'); } - $self->{handle_xml}++ if DXXml::available() && $_[1] =~ /\bxml\b/; - $self->{do_pc92}++ if $_[1] =~ /\bpc92\b/; + $self->{handle_xml}++ if DXXml::available() && $_[1] =~ /\bxml/; + my ($pc9x) = $_[1] =~ /\bpc9\[(\d+)\]/; + $self->{do_pc92}++ if defined $pc9x && $pc9x =~ /2/; } else { $self->version(50.0); $self->version($_[2] / 100) if $_[2] && $_[2] =~ /^\d+$/; @@ -630,7 +651,7 @@ sub handle_19 my $newline = "PC19^"; # new routing list - my @rout; + my (@rout, @pc92out); # first get the INTERFACE node my $parent = Route::Node::get($self->{call}); @@ -640,6 +661,8 @@ sub handle_19 return; } + my $h; + # parse the PC19 # # We are making a major change from now on. We are only going to accept @@ -669,10 +692,15 @@ sub handle_19 next if $call eq $main::mycall; # check that this PC19 isn't trying to alter the wrong dxchan + $h = 0; my $dxchan = DXChannel::get($call); - if ($dxchan && $dxchan != $self) { - dbg("PCPROT: PC19 from $self->{call} trying to alter wrong locally connected $call, ignored!") if isdbg('chanerr'); - next; + if ($dxchan) { + if ($dxchan == $self) { + $h = 1; + } else { + dbg("PCPROT: PC19 from $self->{call} trying to alter wrong locally connected $call, ignored!") if isdbg('chanerr'); + next; + } } my $user = check_add_node($call); @@ -684,9 +712,11 @@ sub handle_19 RouteDB::update($call, $self->{call}, $dxchan ? 1 : undef); - unless ($dxchan) { - dbg("PCPROT: PC19 not directly connected, ignored") if isdbg('chanerr'); - next; + unless ($h) { + if ($parent->via_pc92) { + dbg("PCPROT: non-local node controlled by PC92, ignored") if isdbg('chanerr'); + next; + } } my $r = Route::Node::get($call); @@ -715,6 +745,7 @@ sub handle_19 my $ar = $parent->add($call, $ver, $flags); $user->wantroutepc19(1) unless defined $user->wantroutepc19; push @rout, $ar if $ar; + push @pc92out, $r if $h; } else { next; } @@ -735,7 +766,9 @@ sub handle_19 if (@rout) { $self->route_pc21($self->{call}, $line, @rout); $self->route_pc19($self->{call}, $line, @rout); - $self->route_pc92a($main::mycall, $line, $main::routeroot, @rout) if $self->{state} eq 'normal'; + } + if (@pc92out) { + $self->route_pc92a($main::mycall, $line, $main::routeroot, @pc92out) if $self->{state} eq 'normal'; } } @@ -744,13 +777,8 @@ sub send_delayed_pc92 my $self = shift; # send out delayed PC92 config for this node if it is external - unless ($self->{do_pc92}) { - my $node = Route::Node::get($self->{call}); - if ($node) { - my @rout = map {my $r = Route::User::get($_); $r ? ($r) : ()} $node->users; - $self->route_pc92c($main::mycall, undef, $node, @rout); - } - } + my $line = $main::me->gen_my_pc92_config; + $self->broadcast_route_pc9x($main::mycall, undef, $line, 0); } # send local configuration @@ -760,6 +788,13 @@ sub handle_20 my $pcno = shift; my $line = shift; my $origin = shift; + + if ($self->{do_pc92} && $self->{state} ne 'init92') { + dbg("PCPROT: disconnecting because login call not sent in any pc92") if isdbg('chanerr'); + $self->send("**** You logged in with $self->{call} but that is NOT your \$mycall"); + $self->disconnect; + return; + } $self->send_local_config(); $self->send(pc22()); $self->state('normal'); @@ -802,6 +837,11 @@ sub handle_21 my $node = Route::Node::get($call); if ($node) { + if ($node->via_pc92) { + dbg("PCPROT: controlled by PC92, ignored") if isdbg('chanerr'); + return; + } + my $dxchan = DXChannel::get($call); if ($dxchan && $dxchan != $self) { dbg("PCPROT: PC21 from $self->{call} trying to alter locally connected $call, ignored!") if isdbg('chanerr'); @@ -822,7 +862,7 @@ sub handle_21 if (@rout) { $self->route_pc21($origin, $line, @rout); - $self->route_pc92d($main::mycall, $line, $main::routeroot, @rout); +# $self->route_pc92d($main::mycall, $line, $main::routeroot, @rout); } } @@ -833,10 +873,27 @@ sub handle_22 my $pcno = shift; my $line = shift; my $origin = shift; - $self->state('normal'); - $self->{lastping} = 0; - $self->send_delayed_pc92 + if ($self->{do_pc92}) { + if ($self->{state} ne 'init92') { + dbg("PCPROT: disconnecting because login call not sent in any pc92") if isdbg('chanerr'); + $self->send("**** You logged in with $self->{call} but that is NOT your \$mycall"); + $self->disconnect; + return; + } +# my $ref = Route::Node::get($self->{call}); +# if ($ref) { +# $main::me->route_pc92a($main::mycall, undef, $main::routeroot, $ref); +# } else { +# dbg("PCPROT: disconnecting because pc92 for $self->{call} received") if isdbg('chanerr'); +# $self->disconnect; +# return; +# } +# } else { + $self->send_delayed_pc92; + } + $self->{lastping} = 0; + $self->state('normal'); } # WWV info @@ -1321,13 +1378,15 @@ sub _add_thingy { my $parent = shift; my $s = shift; - my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($s); + my ($call, $is_node, $is_extnode, $here, $version, $build) = @$s; my @rout; if ($call) { if ($is_node) { + dbg("ROUTE: added node $call to " . $parent->call) if isdbg('routelow'); @rout = $parent->add($call, $version, Route::here($here)); } else { + dbg("ROUTE: added user $call to " . $parent->call) if isdbg('routelow'); @rout = $parent->add_user($call, Route::here($here)); } } @@ -1338,14 +1397,16 @@ sub _del_thingy { my $parent = shift; my $s = shift; - my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($s); + my ($call, $is_node, $is_extnode, $here, $version, $build) = @$s; my @rout; if ($call) { if ($is_node) { my $nref = Route::Node::get($call); + dbg("ROUTE: deleting node $call from " . $parent->call) if isdbg('routelow'); @rout = $nref->del($parent) if $nref; } else { my $uref = Route::User::get($call); + dbg("ROUTE: deleting user $call from " . $parent->call) if isdbg('routelow'); @rout = $parent->del_user($uref) if $uref; } } @@ -1373,21 +1434,19 @@ sub check_pc9x_t my $t = shift; my $pc = shift; my $create = shift; - + my $parent = ref $call ? $call : Route::Node::get($call); if ($parent) { my $lastid = $parent->lastid->{$pc} || 0; - $t += 86400 if $t < $lastid - 43200; - if ($lastid >= $t) { + if ($lastid + $main::systime_daystart >= $t + $main::systime_daystart) { dbg("PCPROT: dup / old id on $call <= $lastid, ignored") if isdbg('chanerr'); return; } - $t -= 86400 if $t >= 86400; } elsif ($create) { $parent = Route::Node->new($call); } $parent->lastid->{$pc} = $t; - + return $parent; } @@ -1399,6 +1458,8 @@ sub handle_92 my $line = shift; my $origin = shift; + my (@radd, @rdel); + $self->{do_pc92} ||= 1; my $pcall = $_[1]; @@ -1408,37 +1469,48 @@ sub handle_92 } my $t = $_[2]; my $sort = $_[3]; - - my @ent = grep {$_ && /^[0-7]/} @_[4 .. $#_]; + my @ent = map {[ _decode_pc92_call($_) ]} grep {$_ && /^[0-7]/} @_[4 .. $#_]; if ($pcall eq $main::mycall) { dbg("PCPROT: looped back, ignored") if isdbg('chanerr'); return; } + if ($pcall eq $self->{call} && $self->{state} eq 'init') { + $self->state('init92'); + } + my $parent = check_pc9x_t($pcall, $t, 92, 1) || return; + my $oparent = $parent; $parent->lastid->{92} = $t; $parent->do_pc92(1); + $parent->via_pc92(1); if (@ent) { # look at the first one which will always be a node of some sort # and update any information that needs to be done. - my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($ent[0]); + my ($call, $is_node, $is_extnode, $here, $version, $build) = @{$ent[0]}; if ($call && $is_node) { if ($call eq $main::mycall) { dbg("PCPROT: looped back on node entry, ignored") if isdbg('chanerr'); return; } if ($is_extnode) { + # this is only accepted from my "self" + if (DXChannel::get($call) && $call ne $self->{call}) { + dbg("PCPROT: locally connected node config for $call from other another node $self->{call}, ignored") if isdbg('chanerr'); + return; + } # reparent to external node (note that we must have received a 'C' or 'A' record # from the true parent node for this external before we get one for the this node unless ($parent = Route::Node::get($call)) { dbg("PCPROT: no previous C or A for this external node received, ignored") if isdbg('chanerr'); return; } - my $parent = check_pc9x_t($call, $t, 92) || return; + $parent = check_pc9x_t($call, $t, 92) || return; + $parent->via_pc92(1); } } else { dbg("PCPROT: must be mycall or external node as first entry, ignored") if isdbg('chanerr'); @@ -1450,25 +1522,43 @@ sub handle_92 shift @ent; } - my (@radd, @rdel); - + # do a pass through removing any references to either locally connected nodes or mycall + my @nent; + for (@ent) { + next unless $_; + if ($_->[0] eq $main::mycall || DXChannel::get($_->[0])) { + dbg("PCPROT: $_->[0] refers to locally connected node, ignored") if isdbg('chanerr'); + next; + } + push @nent, $_; + } + if ($sort eq 'A') { - for (@ent) { + for (@nent) { push @radd, _add_thingy($parent, $_); } } elsif ($sort eq 'D') { - for (@ent) { + for (@nent) { push @rdel, _del_thingy($parent, $_); } } elsif ($sort eq 'C') { my (@nodes, @users); - for (@ent) { - my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_); - if ($call) { - if ($is_node) { - push @nodes, $call; + + # we only reset obscounts on config records + $oparent->reset_obs; + dbg("ROUTE: reset obscount on $pcall now " . $oparent->obscount) if isdbg('route'); + if ($oparent != $parent) { + $parent->reset_obs; + dbg("ROUTE: reset obscount on $parent->{call} now " . $parent->obscount) if isdbg('route'); + } + + foreach my $r (@nent) { +# my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_); + if ($r->[0]) { + if ($r->[1]) { + push @nodes, $r->[0]; } else { - push @users, $call; + push @users, $r->[0]; } } else { dbg("DXPROT: pc92 call entry '$_' not decoded, ignored") if isdbg('chanerr'); @@ -1477,13 +1567,20 @@ sub handle_92 my ($dnodes, $dusers, $nnodes, $nusers) = $parent->calc_config_changes(\@nodes, \@users); - for (@ent) { - my ($call, $is_node, $is_extnode, $here, $version, $build) = _decode_pc92_call($_); + # add users here + foreach my $r (@nent) { + my $call = $r->[0]; if ($call) { - push @radd,_add_thingy($parent, $_) if grep $call eq $_, (@$nnodes, @$nusers); - push @rdel,_del_thingy($parent, $_) if grep $call eq $_, (@$dnodes, @$dusers); + push @radd,_add_thingy($parent, $r) if grep $call eq $_, (@$nnodes, @$nusers); } } + # del users here + foreach my $r (@$dnodes) { + push @rdel,_del_thingy($parent, [$r, 1]); + } + foreach my $r (@$dusers) { + push @rdel,_del_thingy($parent, [$r, 0]); + } } else { dbg("PCPROT: unknown action '$sort', ignored") if isdbg('chanerr'); return;