X-Git-Url: http://dxcluster.net/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2FDXProt.pm;h=bf2d5ed30395899d488fa4f2315f190c930d71fd;hb=5756741d9682667ae5b0442c4e6f609bd481b6eb;hp=7064dc7f84736a7e8bd1f51880dd0846b06d0b57;hpb=3e1e7b56903a67dde9ea8ecebbc507fcf9bbb402;p=spider.git diff --git a/perl/DXProt.pm b/perl/DXProt.pm index 7064dc7f..bf2d5ed3 100644 --- a/perl/DXProt.pm +++ b/perl/DXProt.pm @@ -33,6 +33,10 @@ use Route; use Route::Node; use Script; use DXProtHandle; +use DXCIDR; + +use Time::HiRes qw(gettimeofday tv_interval); +use DXSubprocess; use strict; @@ -46,7 +50,8 @@ use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restim %pc92_find $pc92_find_timeout $pc92_short_update_period $next_pc92_obs_timeout $pc92_slug_changes $last_pc92_slug $pc92_extnode_update_period $pc50_interval - $pc92_keepalive_period + $pc92_keepalive_period $senderverify $pc92_ad_enabled + $pc92c_ipaddr_enable ); $pc11_max_age = 1*3600; # the maximum age for an incoming 'real-time' pc11 @@ -79,7 +84,10 @@ $pc92_extnode_update_period = 1*60*60; # the update period for external nodes $pc92_keepalive_period = 1*60*60; # frequency of PC92 K (keepalive) records %pc92_find = (); # outstanding pc92 find operations $pc92_find_timeout = 30; # maximum time to wait for a reply - +$senderverify = 0; # 1 = check spotter is on node it says it is and check ip address if available +; # 2 = do 1 and dump if check +$pc92_ad_enabled = 1; # send pc92 A & D records. +$pc92c_ipaddr_enable = 0; # add the local ip address info to each callsign in a PC92 C @checklist = ( @@ -232,7 +240,8 @@ sub update_pc92_keepalive sub init { - do "$main::data/hop_table.pl" if -e "$main::data/hop_table.pl"; + my $fn = localdata("hop_table.pl"); + do $fn if -e $fn; confess $@ if $@; my $user = DXUser::get($main::mycall); @@ -250,6 +259,7 @@ sub init $main::me->{version} = $main::version; $main::me->{build} = $main::build; $main::me->{do_pc9x} = 1; + $main::me->{hostname} = $main::clusteraddr; $main::me->update_pc92_next($pc92_short_update_period); $main::me->update_pc92_keepalive; } @@ -290,8 +300,9 @@ sub start # log it my $host = $self->{conn}->peerhost; $host ||= "AGW Port #$self->{conn}->{agwport}" if exists $self->{conn}->{agwport}; + $host ||= $host if is_ipaddr($host); $host ||= "unknown"; - + $self->{hostname} = $host if is_ipaddr($host); Log('DXProt', "$call connected from $host"); # remember type of connection @@ -420,14 +431,15 @@ sub normal } } + my $origin = $self->{call}; + if (defined &Local::pcprot) { my $r; - eval { $r = Local::pcprot($self, $pcno, $line, @field); }; + eval { $r = Local::pcprot($self, $pcno, $line, $origin, \@field); }; return if $r; # i.e don't process it } # send it out for processing - my $origin = $self->{call}; no strict 'subs'; my $sub = "handle_$pcno"; @@ -531,6 +543,8 @@ sub process if ($main::systime - 3600 > $last_hour) { $last_hour = $main::systime; } + + pc11_process(); } # @@ -555,6 +569,8 @@ sub send_dx_spot foreach $dxchan (@dxchan) { next if $dxchan == $main::me; next if $dxchan == $self && $self->is_node; + next if $dxchan == $self; + next if $dxchan->is_rbn; if ($line =~ /PC61/ && !($dxchan->is_spider || $dxchan->is_user)) { unless ($pc11) { my @f = split /\^/, $line; @@ -615,6 +631,7 @@ sub send_wwv_spot foreach $dxchan (@dxchan) { next if $dxchan == $main::me; next if $dxchan == $self && $self->is_node; + next if $dxchan->is_rbn; my $routeit; my ($filter, $hops); @@ -649,6 +666,7 @@ sub send_wcy_spot foreach $dxchan (@dxchan) { next if $dxchan == $main::me; next if $dxchan == $self; + next if $dxchan->is_rbn; $dxchan->wcy($line, $self->{isolate}, @_, $self->{call}, @dxcc); } @@ -724,6 +742,7 @@ sub send_announce } Log('ann', $target, $from, $text); + AnnTalk::add_anncache('ann', $target, $from, $text); # send it if it isn't the except list and isn't isolated and still has a hop count # taking into account filtering and so on @@ -732,6 +751,7 @@ sub send_announce next if $dxchan == $self && $self->is_node; next if $from_pc9x && $dxchan->{do_pc9x}; next if $target eq 'LOCAL' && $dxchan->is_node; + next if $dxchan->is_rbn; $dxchan->announce($line, $self->{isolate}, $to, $target, $text, @_, $self->{call}, @a[0..2], @b[0..2]); } @@ -804,6 +824,7 @@ sub send_chat next unless $dxchan->is_spider && $dxchan->do_pc9x; next if $target eq 'LOCAL'; } + next if $dxchan->is_rbn; $dxchan->chat($line, $self->{isolate}, $target, $_[1], $text, @_, $self->{call}, @a[0..2], @b[0..2]); @@ -860,11 +881,11 @@ sub send_local_config my @remotenodes; if ($self->{isolate}) { - dbg("send_local_config: isolated"); + dbg("$self->{call} send_local_config: isolated"); @localnodes = ( $main::routeroot ); $self->send_route($main::mycall, \&pc19, 1, $main::routeroot); } elsif ($self->{do_pc9x}) { - dbg("send_local_config: doing pc9x"); + dbg("$self->{call} send_local_config: doing pc9x"); my $node = Route::Node::get($self->{call}); # $self->send_last_pc92_config($main::routeroot); # $self->send(pc92a($main::routeroot, $node)) unless $main::routeroot->last_PC92C =~ /$self->{call}/; @@ -875,7 +896,7 @@ sub send_local_config # and are not themselves isolated, this to make sure that isolated nodes # don't appear outside of this node - dbg("send_local_config: traditional"); + dbg("$self->{call} send_local_config: traditional"); # send locally connected nodes my @dxchan = grep { $_->call ne $main::mycall && $_ != $self && !$_->{isolate} } DXChannel::get_all_nodes(); @@ -917,7 +938,7 @@ sub gen_my_pc92_config clear_pc92_changes(); # remove any slugged data, we are generating it as now my @dxchan = grep { $_->call ne $main::mycall && !$_->{isolate} } DXChannel::get_all(); dbg("ROUTE: all dxchan: " . join(',', map{$_->{call}} @dxchan)) if isdbg('routelow'); - my @localnodes = map { my $r = Route::get($_->{call}); $r ? $r : () } @dxchan; + my @localnodes = map { my $r = Route::get($_->{call}); ($_->is_node || $_->is_user) && $r ? $r : () } @dxchan; dbg("ROUTE: localnodes: " . join(',', map{$_->{call}} @localnodes)) if isdbg('routelow'); return pc92c($node, @localnodes); } else { @@ -1063,7 +1084,7 @@ sub get_hops { my $pcno = shift; my $hops = $DXProt::hopcount{$pcno}; - $hops = $DXProt::def_hopcount if !$hops; + $hops = $DXProt::def_hopcount unless $hops; return "H$hops"; } @@ -1113,6 +1134,7 @@ sub load_hops sub process_rcmd { my ($self, $tonode, $fromnode, $user, $cmd) = @_; + if ($tonode eq $main::mycall) { my $ref = DXUser::get_current($fromnode); unless ($ref && UNIVERSAL::isa($ref, 'DXUser')) { @@ -1120,19 +1142,25 @@ sub process_rcmd $self->send_rcmd_reply($main::mycall, $fromnode, $user, "sorry...!"); return; } + Log('rcmd', 'in', ($ref->{priv}||0), $fromnode, $cmd, $user); my $cref = Route::Node::get($fromnode); unless ($cref && UNIVERSAL::isa($cref, 'Route')) { dbg("DXProt process_rcmd: Route $fromnode isn't a reference (tell G1TLH)"); $self->send_rcmd_reply($main::mycall, $fromnode, $user, "sorry...!"); return; } - Log('rcmd', 'in', ($ref->{priv}||0), $fromnode, $cmd); if ($cmd !~ /^\s*rcmd/i && $ref->homenode && $cref->call eq $ref->homenode) { # not allowed to relay RCMDS! if ($ref->{priv}) { # you have to have SOME privilege, the commands have further filtering $self->{remotecmd} = 1; # for the benefit of any command that needs to know my $oldpriv = $self->{priv}; - $self->{priv} = $ref->{priv}; # assume the user's privilege level + $self->{priv} = 1; # set a maximum privilege + + # park homenode and user for any spawned command that run_cmd may do. + $self->{_rcmd_user} = $user; + $self->{_rcmd_fromnode} = $fromnode; my @in = (DXCommandmode::run_cmd($self, $cmd)); + delete $self->{_rcmd_fromnode}; + delete $self->{_rcmd_user}; $self->{priv} = $oldpriv; $self->send_rcmd_reply($main::mycall, $fromnode, $user, @in); delete $self->{remotecmd}; @@ -1152,6 +1180,119 @@ sub process_rcmd } } + +sub send_rcmd_reply +{ + my $self = shift; + my $tonode = shift; + my $fromnode = shift; + my $user = shift; + while (@_) { + my $line = shift; + $line =~ s/\s*$//; + Log('rcmd', 'out', $fromnode, $line, $user); + if ($self->is_clx) { + $self->send(pc85($main::mycall, $fromnode, $user, "$main::mycall:$line")); + } else { + $self->send(pc35($main::mycall, $fromnode, "$main::mycall:$line")); + } + } +} + +# Punt off a long running command into a separate process - this will be caused by an rcmd from outside +# +# This is called from commands to run some potentially long running +# function. The process forks and then runs the function and returns +# the result back to the cmd. +# +# NOTE: this merely forks the current process and then runs the cmd in that (current) context. +# IT DOES NOT START UP SOME NEW PROGRAM AND RELIES ON THE FACT THAT IT IS RUNNING DXSPIDER +# THE CURRENT CONTEXT!! +# +# call: $self->spawn_cmd($original_cmd_line, \, [cb => sub{...}], [prefix => "cmd> "], [progress => 0|1], [args => [...]]); +sub spawn_cmd +{ + my $self = shift; + my $line = shift; + my $cmdref = shift; + my $call = $self->{call}; + my %args = @_; + my @out; + + my $cb = delete $args{cb}; + my $prefix = delete $args{prefix}; + my $progress = delete $args{progress}; + my $args = delete $args{args} || []; + my $t0 = [gettimeofday]; + + # remembered from process_cmd when spawn_cmd was called thru DXCommandmode::run_cmd which was called by process_rcmd + my $fromnode = $self->{_rcmd_fromnode}; + my $user = $self->{_rcmd_user}; + + no strict 'refs'; + + my $fc = DXSubprocess->new; + + # just behave normally if something has set the "one-shot" _nospawn in the channel + if ($self->{_nospawn}) { + eval { @out = $cmdref->(@$args); }; + if ($@) { + DXDebug::dbgprintring(25); + push @out, DXDebug::shortmess($@); + } + return @out; + } + + # $fc->serializer(\&encode_json); +# $fc->deserializer(\&decode_json); + $fc->run( + sub { + my $subpro = shift; + if (isdbg('progress')) { + my $s = qq{line: "$line"}; + $s .= ", args: " . join(', ', map { defined $_ ? qq{'$_'} : q{'undef'} } @$args) if $args && @$args; + dbg($s); + } + eval { @out = $cmdref->(@$args); }; + if ($@) { + DXDebug::dbgprintring(25); + push @out, DXDebug::shortmess($@); + } + return @out; + }, +# $args, + sub { + my ($fc, $err, @res) = @_; + my $self = DXChannel::get($call); + return unless $self; + + if ($err) { + my $s = "DXCommand::spawn_cmd: call $call error $err"; + dbg($s) if isdbg('chan'); + if ($fromnode && $user) { + $self->send_rcmd_reply($main::mycall, $fromnode, $user, $s); + } else { + $self->send($s); + } + return; + } + if ($cb) { + # transform output if required + @res = $cb->($self, @res); + } + if (@res) { + if ($fromnode && $user) { + $self->send_rcmd_reply($main::mycall, $fromnode, $user, @res); + } else { + $self->send(@res); + } + } + diffms("rcmd from $user on $call", $line, $t0, scalar @res) if isdbg('progress'); + }); + + return @out; +} + sub process_rcmd_reply { my ($self, $tonode, $fromnode, $user, $line) = @_; @@ -1177,23 +1318,7 @@ sub process_rcmd_reply } } -sub send_rcmd_reply -{ - my $self = shift; - my $tonode = shift; - my $fromnode = shift; - my $user = shift; - while (@_) { - my $line = shift; - $line =~ s/\s*$//; - Log('rcmd', 'out', $fromnode, $line); - if ($self->is_clx) { - $self->send(pc85($main::mycall, $fromnode, $user, "$main::mycall:$line")); - } else { - $self->send(pc35($main::mycall, $fromnode, "$main::mycall:$line")); - } - } -} + # add a rcmd request to the rcmd queues sub addrcmd @@ -1298,12 +1423,13 @@ sub talk { my ($self, $from, $to, $via, $line, $origin) = @_; + my $ipaddr = DXCommandmode::alias_localhost($self->hostname || '127.0.0.1'); if ($self->{do_pc9x}) { - $self->send(pc93($to, $from, $via, $line)); + $self->send(pc93($to, $from, $via, $line, undef, $ipaddr)); } else { $self->send(pc10($from, $to, $via, $line, $origin)); } - Log('talk', $to, $from, '>' . ($via || $origin || $self->call), $line) unless $origin && $origin ne $main::mycall; + Log('talk', $to, $from, '>' . ($via || $origin || $self->call), $line, $ipaddr) unless $origin && $origin ne $main::mycall; } # send it if it isn't the except list and isn't isolated and still has a hop count @@ -1521,6 +1647,7 @@ sub route_pc92c my $self = shift; my $origin = shift; my $line = shift; + broadcast_route_pc9x($self, $origin, \&pc92c, $line, 1, @_); } @@ -1529,6 +1656,7 @@ sub route_pc92a my $self = shift; my $origin = shift; my $line = shift; + return unless $pc92_ad_enabled; broadcast_route_pc9x($self, $origin, \&pc92a, $line, 1, @_); } @@ -1537,6 +1665,7 @@ sub route_pc92d my $self = shift; my $origin = shift; my $line = shift; + return unless $pc92_ad_enabled; broadcast_route_pc9x($self, $origin, \&pc92d, $line, 1, @_); } @@ -1657,7 +1786,9 @@ sub import_chat my $via = $target; $via = '*' if $target eq 'ALL' || $target eq 'SYSOP'; Log('ann', $target, $main::mycall, $text); - $main::me->normal(DXProt::pc93($target, $main::mycall, $via, $text)); + AnnTalk::add_anncache('ann', $target, $main::mycall, $text); + my $ipaddr = DXCommandmode::alias_localhost($main::me->hostname || '127.0.0.1'); + $main::me->normal(DXProt::pc93($target, $main::mycall, $via, $text, undef, $ipaddr)); } else { DXCommandmode::send_chats($main::me, $target, $text); } @@ -1688,5 +1819,8 @@ sub clean_pc92_find { } + + + 1; __END__