*** empty log message ***
[spider.git] / perl / DXProt.pm
index 9a4f367339a7699459028bcec4bb813a2e36afb7..a6b4270fc9dd652a1536512acbe94352ce2045bc 100644 (file)
@@ -43,7 +43,7 @@ $main::build += $VERSION;
 $main::branch += $BRANCH;
 
 use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restime $eph_pc34_restime
-                       $last_hour $last10 %eph  %pings %rcmds $ann_to_talk
+                       $last_hour $last10 %eph %rcmds $ann_to_talk
                        %nodehops $baddx $badspotter $badnode $censorpc $rspfcheck
                        $allowzero $decode_dk0wcy $send_opernam @checklist);
 
@@ -51,7 +51,6 @@ $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
 $censorpc = 1;                                 # Do a BadWords::check on text fields and reject things
@@ -255,9 +254,9 @@ sub start
        
        # ping neighbour node stuff
        my $ping = $user->pingint;
-       $ping = 5*60 unless defined $ping;
+       $ping = $DXChannel::pingint unless defined $ping;
        $self->{pingint} = $ping;
-       $self->{nopings} = $user->nopings || 2;
+       $self->{nopings} = $user->nopings || $DXChannel::obscount;
        $self->{pingtime} = [ ];
        $self->{pingave} = 999;
        $self->{metric} ||= 100;
@@ -471,7 +470,7 @@ sub normal
                        # this goes after the input filtering, but before the add
                        # so that if it is input filtered, it isn't added to the dup
                        # list. This allows it to come in from a "legitimate" source
-                       if (Spot::dup($field[1], $field[2], $d, $field[5])) {
+                       if (Spot::dup($field[1], $field[2], $d, $field[5], $field[6])) {
                                dbg("PCPROT: Duplicate Spot ignored\n") if isdbg('chanerr');
                                return;
                        }
@@ -511,9 +510,9 @@ sub normal
                                                # send the rcmd but we aren't interested in the replies...
                                                my $dxchan = $node->dxchan;
                                                if ($dxchan && $dxchan->is_clx) {
-                                                       route(undef, $to, pc84($main::mycall, $to, $main::mycall, $cmd));
+                                                       DXChannel::route(undef, $to, pc84($main::mycall, $to, $main::mycall, $cmd));
                                                } else {
-                                                       route(undef, $to, pc34($main::mycall, $to, $cmd));
+                                                       DXChannel::route(undef, $to, pc34($main::mycall, $to, $cmd));
                                                }
                                                if ($to ne $field[7]) {
                                                        $to = $field[7];
@@ -521,9 +520,9 @@ sub normal
                                                        if ($node) {
                                                                $dxchan = $node->dxchan;
                                                                if ($dxchan && $dxchan->is_clx) {
-                                                                       route(undef, $to, pc84($main::mycall, $to, $main::mycall, $cmd));
+                                                                       DXChannel::route(undef, $to, pc84($main::mycall, $to, $main::mycall, $cmd));
                                                                } else {
-                                                                       route(undef, $to, pc34($main::mycall, $to, $cmd));
+                                                                       DXChannel::route(undef, $to, pc34($main::mycall, $to, $cmd));
                                                                }
                                                        }
                                                }
@@ -625,6 +624,12 @@ sub normal
                        my $ncall = $field[1];
                        my $newline = "PC16^";
                        
+                       # do I want users from this channel?
+                       unless ($self->user->wantpc16) {
+                               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');
                                return;
@@ -640,10 +645,15 @@ sub normal
                                return;
                        }
 
+                       my ($hops) = $field[-1] =~ /H(\d+)/;
+                       my $thing = Thingy::Route->new(fromnode => $ncall, fromdxchan => $self, pcline=>$line, hops=>$hops);
+                       
+
                        # input filter if required
                        return unless $self->in_filter_route($parent);
                        
                        my $i;
+                       my @list;
                        my @rout;
                        for ($i = 2; $i < $#field; $i++) {
                                my ($call, $conf, $here) = $field[$i] =~ /^(\S+) (\S) (\d)/o;
@@ -662,33 +672,14 @@ sub normal
                                        next;
                                }
                                
-                               $r = Route::User::get($call);
                                my $flags = Route::here($here)|Route::conf($conf);
-                               
-                               if ($r) {
-                                       if ($r->flags != $flags) {
-                                               $r->flags($flags);
-                                               push @rout, $r;
-                                       }
-                                       $r->addparent($parent);
-                               } else {
-                                       push @rout, $parent->add_user($call, $flags);
-                               }
-                               
-                               # add this station to the user database, if required
-                               $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;
-                               $user->node($parent->call);
-                               $user->lastin($main::systime) unless DXChannel->get($call);
-                               $user->put;
+                               $r = Route::User::new($call, $ncall, $flags);
+                               push @list, $r;
                        }
-                       
-                       # queue up any messages (look for privates only)
-                       DXMsg::queue_msg(1) if $self->state eq 'normal';     
 
-                       $self->route_pc16($parent, @rout) if @rout;
+                       $thing->list(\@list);
+                       $thing->add;
+                       $thing->route;
                        return;
                }
                
@@ -699,6 +690,11 @@ sub normal
 
                        eph_del_regex("^PC16\\^$ncall.*$ucall");
                        
+                       # do I want users from this channel?
+                       unless ($self->user->wantpc16) {
+                               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;
@@ -775,14 +771,19 @@ sub normal
 
                        # new routing list
                        my @rout;
-                       my $parent = Route::Node::get($self->{call});
+                       my $ncall = $self->{call};
+                       my $parent = Route::Node::get($ncall);
                        unless ($parent) {
-                               dbg("DXPROT: my parent $self->{call} has disappeared");
+                               dbg("DXPROT: my parent $ncall has disappeared");
                                $self->disconnect;
                                return;
                        }
 
+                       my ($hops) = $field[-1] =~ /H(\d+)/;
+                       my $thing = Thingy::Route->new(fromnode=>$ncall, fromdxchan => $self, pcline=>$line, hops=>$hops);
+
                        # parse the PC19
+                       my @list;
                        for ($i = 1; $i < $#field-1; $i += 4) {
                                my $here = $field[$i];
                                my $call = uc $field[$i+1];
@@ -805,59 +806,15 @@ sub normal
                                        next;
                                }
 
-                               # update it if required
-                               my $r = Route::Node::get($call);
-                               my $flags = Route::here($here)|Route::conf($conf);
-                               if ($r) {
-                                       my $ar;
-                                       if ($call ne $parent->call) {
-                                               if ($self->in_filter_route($r)) {
-                                                       $ar = $parent->add($call, $ver, $flags);
-                                                       push @rout, $ar if $ar;
-                                               } else {
-                                                       next;
-                                               }
-                                       }
-                                       if ($r->version ne $ver || $r->flags != $flags) {
-                                               $r->version($ver);
-                                               $r->flags($flags);
-                                               push @rout, $r unless $ar;
-                                       }
-                               } else {
-                                       if ($call eq $self->{call}) {
-                                               dbg("DXPROT: my channel route for $call has disappeared");
-                                               next;
-                                       };
-                                       
-                                       my $new = Route->new($call);          # throw away
-                                   if ($self->in_filter_route($new)) {
-                                               my $r = $parent->add($call, $ver, $flags);
-                                               push @rout, $r;
-                                       } else {
-                                               next;
-                                       }
-                               }
-
-                               # unbusy and stop and outgoing mail (ie if somehow we receive another PC19 without a disconnect)
-                               my $mref = DXMsg::get_busy($call);
-                               $mref->stop_msg($call) if $mref;
-                               
-                               # add this station to the user database, if required (don't remove SSID from nodes)
-                               my $user = DXUser->get_current($call);
-                               if (!$user) {
-                                       $user = DXUser->new($call);
-                                       $user->sort('A');
-                                       $user->priv(1);                   # I have relented and defaulted nodes
-                                       $user->lockout(1);
-                                       $user->homenode($call);
-                                       $user->node($call);
-                               }
-                               $user->lastin($main::systime) unless DXChannel->get($call);
-                               $user->put;
+                               # decide whether we want this or not?
+                               my $r = Route::Node->new($call, $ver, $flags);
+                               push @list, $r if $call ne $ncall && $self->in_filter_route($r);
+                       }
+                       if (@list) {
+                               $thing->list(\@list);
+                               $thing->add;
+                               $thing->route;
                        }
-
-
-                       $self->route_pc19(@rout) if @rout;
                        return;
                }
                
@@ -1155,40 +1112,7 @@ sub normal
                                        $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 || 2;
-                                                                       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
-                                                               }
-                                                       } 
-                                               }
-                                       }
+                                       $self->handlepingreply($from);
                                }
                        } else {
                                if (eph_dup($line)) {
@@ -1289,7 +1213,7 @@ sub process
        }
 
        foreach $dxchan (@dxchan) {
-               next unless $dxchan->is_node();
+               next unless $dxchan->is_op();
                next if $dxchan == $main::me;
 
                # send the pc50 or PC90
@@ -1300,7 +1224,7 @@ sub process
                        if ($dxchan->{nopings} <= 0) {
                                $dxchan->disconnect;
                        } else {
-                               addping($main::mycall, $dxchan->call);
+                               $dxchan->addping($main::mycall, $dxchan->call);
                                $dxchan->{nopings} -= 1;
                                $dxchan->{lastping} = $t;
                        }
@@ -1329,7 +1253,6 @@ sub process
 # some active measures
 #
 
-
 sub send_dx_spot
 {
        my $self = shift;
@@ -1498,24 +1421,27 @@ sub send_announce
 
        # obtain country codes etc 
        my ($ann_dxcc, $ann_itu, $ann_cq, $org_dxcc, $org_itu, $org_cq) = (0..0);
+       my ($ann_state, $org_state) = ("", "");
        my @dxcc = Prefix::extract($_[0]);
        if (@dxcc > 0) {
                $ann_dxcc = $dxcc[1]->dxcc;
                $ann_itu = $dxcc[1]->itu;
                $ann_cq = $dxcc[1]->cq;                                         
+               $ann_state = $dxcc[1]->state;
        }
        @dxcc = Prefix::extract($_[4]);
        if (@dxcc > 0) {
                $org_dxcc = $dxcc[1]->dxcc;
                $org_itu = $dxcc[1]->itu;
                $org_cq = $dxcc[1]->cq;                                         
+               $org_state = $dxcc[1]->state;
        }
 
        if ($self->{inannfilter}) {
                my ($filter, $hops) = 
                        $self->{inannfilter}->it(@_, $self->{call}, 
                                                                         $ann_dxcc, $ann_itu, $ann_cq,
-                                                                        $org_dxcc, $org_itu, $org_cq);
+                                                                        $org_dxcc, $org_itu, $org_cq, $ann_state, $org_state);
                unless ($filter) {
                        dbg("PCPROT: Rejected by input announce filter") if isdbg('chanerr');
                        return;
@@ -1559,7 +1485,7 @@ sub announce
 sub send_local_config
 {
        my $self = shift;
-       my $n;
+       my $node;
        my @nodes;
        my @localnodes;
        my @remotenodes;
@@ -1578,60 +1504,27 @@ sub send_local_config
                my @intcalls = map { $_->nodes } @localnodes if @localnodes;
                my $ref = Route::Node::get($self->{call});
                my @rnodes = $ref->nodes;
-               for my $n (@intcalls) {
-                       push @remotenodes, Route::Node::get($n) unless grep $n eq $_, @rnodes;
+               for my $node (@intcalls) {
+                       push @remotenodes, Route::Node::get($node) unless grep $node eq $_, @rnodes;
                }
                unshift @localnodes, $main::routeroot;
        }
        
 
-       send_route($self, \&pc19, scalar(@localnodes)+scalar(@remotenodes), @localnodes, @remotenodes);
+       $self->send_route(\&pc19, scalar(@localnodes)+scalar(@remotenodes), @localnodes, @remotenodes);
        
        # get all the users connected on the above nodes and send them out
-       foreach $n (@localnodes, @remotenodes) {
-               if ($n) {
-                       send_route($self, \&pc16, 1, $n, map {my $r = Route::User::get($_); $r ? ($r) : ()} $n->users);
+       foreach $node (@localnodes, @remotenodes) {
+               if ($node) {
+                       $self->send_route(\&pc16, 1, $node, 
+                                                         map {my $r = Route::User::get($_); $r ? ($r) : ()} $node->users)
+                               if $self->user->wantsendpc16;
                } else {
                        dbg("sent a null value") if isdbg('chanerr');
                }
        }
 }
 
-#
-# route a message down an appropriate interface for a callsign
-#
-# is called route(to, pcline);
-#
-sub route
-{
-       my ($self, $call, $line) = @_;
-
-       if (ref $self && $call eq $self->{call}) {
-               dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chanerr');
-               return;
-       }
-
-       # always send it down the local interface if available
-       my $dxchan = DXChannel->get($call);
-       unless ($dxchan) {
-               my $cl = Route::get($call);
-               $dxchan = $cl->dxchan if $cl;
-               if (ref $dxchan) {
-                       if (ref $self && $dxchan eq $self) {
-                               dbg("PCPROT: Trying to route back to source, dropped") if isdbg('chanerr');
-                               return;
-                       }
-               }
-       }
-       if ($dxchan) {
-               my $routeit = adjust_hops($dxchan, $line);   # adjust its hop count by node name
-               if ($routeit) {
-                       $dxchan->send($routeit) unless $dxchan == $main::me;
-               }
-       } else {
-               dbg("PCPROT: No route available, dropped") if isdbg('chanerr');
-       }
-}
 
 #
 # obtain the hops from the list for this callsign and pc no 
@@ -1687,21 +1580,7 @@ sub load_hops
        return $self->msg('lh1') unless -e "$main::data/hop_table.pl";
        do "$main::data/hop_table.pl";
        return $@ if $@;
-       return 0;
-}
-
-
-# add a ping request to the ping queues
-sub addping
-{
-       my ($from, $to) = @_;
-       my $ref = $pings{$to} || [];
-       my $r = {};
-       $r->{call} = $from;
-       $r->{t} = [ gettimeofday ];
-       route(undef, $to, pc51($to, $main::mycall, 1));
-       push @$ref, $r;
-       $pings{$to} = $ref;
+       return ();
 }
 
 sub process_rcmd
@@ -1793,9 +1672,9 @@ sub addrcmd
        my $ref = Route::Node::get($to);
        my $dxchan = $ref->dxchan;
        if ($dxchan && $dxchan->is_clx) {
-               route(undef, $to, pc84($main::mycall, $to, $self->{call}, $cmd));
+               DXChannel::route(undef, $to, pc84($main::mycall, $to, $self->{call}, $cmd));
        } else {
-               route(undef, $to, pc34($main::mycall, $to, $cmd));
+               DXChannel::route(undef, $to, pc34($main::mycall, $to, $cmd));
        }
 }
 
@@ -1831,9 +1710,6 @@ sub disconnect
                $self->route_pc21(@rout) if @rout;
        }
 
-       # remove outstanding pings
-       delete $pings{$call};
-       
        # I was the last node visited
     $self->user->node($main::mycall);
 
@@ -1875,7 +1751,7 @@ sub send_route
                if (!$self->{isolate} && $self->{routefilter}) {
                        $filter = undef;
                        if ($r) {
-                               ($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq);
+                               ($filter, $hops) = $self->{routefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq, $self->{state}, $r->{state});
                                if ($filter) {
                                        push @rin, $r;
                                } else {
@@ -1915,7 +1791,8 @@ sub broadcast_route
                        next if $dxchan == $self;
                        next if $dxchan == $main::me;
                        next if $dxchan->user->wantnp;
-                       
+                       next if ($generate == \&pc16 || $generate==\&pc17) && !$dxchan->user->wantsendpc16;
                        $dxchan->send_route($generate, @_);
                }
        }
@@ -1924,12 +1801,14 @@ sub broadcast_route
 sub route_pc16
 {
        my $self = shift;
+       return unless $self->user->wantpc16;
        broadcast_route($self, \&pc16, 1, @_);
 }
 
 sub route_pc17
 {
        my $self = shift;
+       return unless $self->user->wantpc16;
        broadcast_route($self, \&pc17, 1, @_);
 }
 
@@ -1976,12 +1855,25 @@ sub in_filter_route
        my ($filter, $hops) = (1, 1);
        
        if ($self->{inroutefilter}) {
-               ($filter, $hops) = $self->{inroutefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq);
+               ($filter, $hops) = $self->{inroutefilter}->it($self->{call}, $self->{dxcc}, $self->{itu}, $self->{cq}, $r->call, $r->dxcc, $r->itu, $r->cq, $self->state, $r->state);
                dbg("PCPROT: $self->{call}/" . $r->call . ' rejected by in_filter_route') if !$filter && isdbg('chanerr');
        }
        return $filter;
 }
 
+# add a ping request to the ping queues
+sub addping
+{
+       my ($self, $from, $to) = @_;
+       my $ref = $DXChannel::pings{$to} || [];
+       my $r = {};
+       $r->{call} = $from;
+       $r->{t} = [ gettimeofday ];
+       DXChannel::route(undef, $to, pc51($to, $main::mycall, 1));
+       push @$ref, $r;
+       $DXCHannel::pings{$to} = $ref;
+}
+
 sub eph_dup
 {
        my $s = shift;