added loginfo stuff
[spider.git] / perl / DXProt.pm
index b2978b5c330110f3eb4d9d757867ee602d277749..64727b8a7d993b3e9ba480ac1871ae780dcaf922 100644 (file)
@@ -24,6 +24,8 @@ use DXProtout;
 use DXDebug;
 use Filter;
 use Local;
+use DXDb;
+use Time::HiRes qw(gettimeofday tv_interval);
 
 use Carp;
 
@@ -37,10 +39,10 @@ $me = undef;                                        # the channel id for this cluster
 $decode_dk0wcy = undef;                        # if set use this callsign to decode announces from the EU WWV data beacon
 $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
-$pc11_dup_age = 24*3600;               # the maximum time to keep the spot dup list for
-$pc23_dup_age = 24*3600;               # the maximum time to keep the wwv dup list for
-$pc12_dup_age = 12*3600;               # the maximum time to keep the ann dup list for
-$pc12_dup_lth = 72;                            # the length of ANN text to save for deduping 
+$pc11_dup_age = 3*3600;                        # the maximum time to keep the spot dup list for
+$pc23_dup_age = 3*3600;                        # the maximum time to keep the wwv dup list for
+$pc12_dup_age = 24*3600;               # the maximum time to keep the ann dup list for
+$pc12_dup_lth = 60;                            # the length of ANN text to save for deduping 
 %spotdup = ();                             # the pc11 and 26 dup hash 
 %wwvdup = ();                              # the pc23 and 27 dup hash
 %anndup = ();                               # the PC12 dup hash
@@ -50,6 +52,7 @@ $last_hour = time;                            # last time I did an hourly periodic update
 %nodehops = ();                 # node specific hop control
 @baddx = ();                    # list of illegal spotted callsigns
 
+
 $baddxfn = "$main::data/baddx.pl";
 
 sub init
@@ -123,14 +126,29 @@ sub start
        $self->send_now('B',"0");
        $self->send_now('E',"0");
        
+       # ping neighbour node stuff
+       my $ping = $user->pingint;
+       $ping = 5*60 unless defined $ping;
+       $self->pingint($ping);
+       $self->nopings($user->nopings || 2);
+       $self->pingtime([ ]);
+
        # send initialisation string
-       if (!$self->{outbound}) {
+       unless ($self->{outbound}) {
                $self->send(pc38()) if DXNode->get_all();
                $self->send(pc18());
+               $self->lastping($main::systime);
+       } else {
+               # remove from outstanding connects queue
+               @main::outstanding_connects = grep {$_->{call} ne $call} @main::outstanding_connects;
+               $self->lastping($main::systime + $self->pingint / 2);
        }
        $self->state('init');
        $self->pc50_t(time);
 
+       # send info to all logged in thingies
+       $self->tell_login('loginn');
+
        Log('DXProt', "$call connected");
 }
 
@@ -267,7 +285,7 @@ sub normal
                if ($pcno == 12) {              # announces
                        # announce duplicate checking
                        my $text = substr(uc unpad($field[3]), 0, $pc12_dup_lth);
-                       my $dupkey = $field[1].$field[2].$text.$field[4].$field[6];
+                       my $dupkey = $field[1].$field[2].$text;
                        if ($anndup{$dupkey}) {
                                dbg('chan', "Duplicate Announce ignored\n");
                                return;
@@ -291,7 +309,7 @@ sub normal
                                if ($decode_dk0wcy && $field[1] eq $decode_dk0wcy) {
                                        my ($hour, $k, $next, $a, $r, $sfi, $alarm) = $field[3] =~ /^Aurora Beacon\s+(\d+)UTC,\s+Kiel\s+K=(\d+),.*ed\s+K=(\d+),\s+A=(\d+),\s+R=(\d+),\s+SFI=(\d+),.*larm:\s+(\w+)/;
                                        $alarm = ($alarm =~ /^Y/i) ? ', Aurora in DE' : ''; 
-                                       my $wwv = Geomag::update($main::systime, $hour, $sfi, $a, $k, "R=$r, Next K=$next$alarm", $decode_dk0wcy, $field[5], $r);
+                                       my $wwv = Geomag::update($main::systime, $hour, $sfi, $a, $k, "R=$r, Next K=$next$alarm", $decode_dk0wcy, $field[5], $r) if $sfi && $r;
                                }
                                
                        } else {
@@ -515,7 +533,7 @@ sub normal
                                dbg('chan', "Dup WWV Spot ignored\n");
                                return;
                        }
-                       if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 900 || $field[2] < 0 || $field[2] > 23) {
+                       if (($pcno == 23 && $d < $main::systime - $pc23_max_age) || $d > $main::systime + 1500 || $field[2] < 0 || $field[2] > 23) {
                                dbg('chan', "WWV Date ($field[1] $field[2]) out of range");
                                return;
                        }
@@ -670,11 +688,7 @@ sub normal
                        last SWITCH;
                }
                if ($pcno == 37 || $pcno == 44 || $pcno == 45 || $pcno == 46 || $pcno == 47) {
-                       if ($field[1] eq $main::mycall) {
-                               ;
-                       } else {
-                               $self->route($field[1], $line);
-                       }
+                       DXDb::process($self, $line);
                        return;
                }
                
@@ -699,12 +713,31 @@ sub normal
                                        # it's a reply, look in the ping list for this one
                                        my $ref = $pings{$field[2]};
                                        if ($ref) {
-                                               my $r = shift @$ref;
-                                               my $dxchan = DXChannel->get($r->{call});
-                                               $dxchan->send($dxchan->msg('pingi', $field[2], atime($main::systime), $main::systime - $r->{t})) if $dxchan;
+                                               my $tochan =  DXChannel->get($field[2]);
+                                               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', $field[2], $s, $ave))
+                                                       } elsif ($dxchan->is_ak1a) {
+                                                               if ($tochan) {
+                                                                       $tochan->nopings(3); # pump up the timer
+                                                                       push @{$tochan->pingtime}, $t;
+                                                                       shift @{$tochan->pingtime} if @{$tochan->pingtime} > 6;
+                                                                       my $st;
+                                                                       for (@{$tochan->pingtime}) {
+                                                                               $st += $_;
+                                                                       }
+                                                                       $tochan->{pingave} = $st / @{$tochan->pingtime};
+                                                               }
+                                                       } 
+                                               }
                                        }
                                }
-                               
                        } else {
                                # route down an appropriate thingy
                                $self->route($field[1], $line);
@@ -721,7 +754,7 @@ sub normal
         #        REBROADCAST!!!!
         #
         
-       if (!$self->{isolate}) {
+       unless ($self->{isolate}) {
                broadcast_ak1a($line, $self); # send it to everyone but me
        }
 }
@@ -744,6 +777,17 @@ sub process
                if ($t >= $dxchan->pc50_t + $DXProt::pc50_interval) {
                        $dxchan->send(pc50());
                        $dxchan->pc50_t($t);
+               } 
+
+               # send a ping out on this channel
+               if ($dxchan->pingint && $t >= $dxchan->pingint + $dxchan->lastping) {
+                       if ($dxchan->nopings <= 0) {
+                               $dxchan->disconnect;
+                       } else {
+                               addping($main::mycall, $dxchan->call);
+                               $dxchan->nopings($dxchan->nopings - 1);
+                               $dxchan->lastping($t);
+                       }
                }
        }
        
@@ -776,6 +820,8 @@ sub finish
        my $call = $self->call;
        my $ref = DXCluster->get_exact($call);
        
+       $self->send_now("D", DXProt::pc39($main::mycall, $self->msg('disc1', "System Op")));
+       
        # unbusy and stop and outgoing mail
        my $mref = DXMsg::get_busy($call);
        $mref->stop_msg($call) if $mref;
@@ -795,7 +841,10 @@ sub finish
        
        # now broadcast to all other ak1a nodes that I have gone
        broadcast_ak1a(pc21($call, 'Gone.'), $self) unless $self->{isolate};
-       
+
+       # send info to all logged in thingies
+       $self->tell_login('logoutn');
+
        Log('DXProt', $call . " Disconnected");
        $ref->del() if $ref;
 }
@@ -1006,7 +1055,10 @@ sub route
        my ($self, $call, $line) = @_;
        my $cl = DXCluster->get_exact($call);
        if ($cl) {       # don't route it back down itself
-               return if ref $self && $call eq $self->{call};
+               if (ref $self && $call eq $self->{call}) {
+                       dbg('chan', "Trying to route back to source, dropped");
+                       return;
+               }
                my $hops;
                my $dxchan = $cl->{dxchan};
                if ($dxchan) {
@@ -1024,7 +1076,7 @@ sub broadcast_ak1a
 {
        my $s = shift;                          # the line to be rebroadcast
        my @except = @_;                        # to all channels EXCEPT these (dxchannel refs)
-       my @dxchan = get_all_ak1a();
+       my @dxchan = DXChannel::get_all_ak1a();
        my $dxchan;
        
        # send it if it isn't the except list and isn't isolated and still has a hop count
@@ -1041,7 +1093,7 @@ sub broadcast_all_ak1a
 {
        my $s = shift;                          # the line to be rebroadcast
        my @except = @_;                        # to all channels EXCEPT these (dxchannel refs)
-       my @dxchan = get_all_ak1a();
+       my @dxchan = DXChannel::get_all_ak1a();
        my $dxchan;
        
        # send it if it isn't the except list and isn't isolated and still has a hop count
@@ -1060,7 +1112,7 @@ sub broadcast_users
        my $sort = shift;           # the type of transmission
        my $fref = shift;           # a reference to an object to filter on
        my @except = @_;                        # to all channels EXCEPT these (dxchannel refs)
-       my @dxchan = get_all_users();
+       my @dxchan = DXChannel::get_all_users();
        my $dxchan;
        my @out;
        
@@ -1101,43 +1153,6 @@ sub broadcast_list
        }
 }
 
-#
-# gimme all the ak1a nodes
-#
-sub get_all_ak1a
-{
-       my @list = DXChannel->get_all();
-       my $ref;
-       my @out;
-       foreach $ref (@list) {
-               push @out, $ref if $ref->is_ak1a;
-       }
-       return @out;
-}
-
-# return a list of all users
-sub get_all_users
-{
-       my @list = DXChannel->get_all();
-       my $ref;
-       my @out;
-       foreach $ref (@list) {
-               push @out, $ref if $ref->is_user;
-       }
-       return @out;
-}
-
-# return a list of all user callsigns
-sub get_all_user_calls
-{
-       my @list = DXChannel->get_all();
-       my $ref;
-       my @out;
-       foreach $ref (@list) {
-               push @out, $ref->call if $ref->is_user;
-       }
-       return @out;
-}
 
 #
 # obtain the hops from the list for this callsign and pc no 
@@ -1208,13 +1223,13 @@ sub unpad
 sub addping
 {
        my ($from, $to) = @_;
-       my $ref = $pings{$to};
-       $ref = $pings{$to} = [] if !$ref;
+       my $ref = $pings{$to} || [];
        my $r = {};
        $r->{call} = $from;
-       $r->{t} = $main::systime;
+       $r->{t} = [ gettimeofday ];
        route(undef, $to, pc51($to, $main::mycall, 1));
        push @$ref, $r;
+       $pings{$to} = $ref;
 }
 
 # add a rcmd request to the rcmd queues