1. Incorporated sh/st, (un)set/lockout, forward/opername from Iain G0RDI
[spider.git] / perl / DXProt.pm
index ed5e417150724e9c1bb91ce75efeee1a4de2cba8..4fce82985ecb0a57c656f63ccf6c9b86e7adb757 100644 (file)
@@ -24,18 +24,21 @@ use DXProtout;
 use Carp;
 
 use strict;
-use vars qw($me $pc11_max_age $pc11_dup_age %dup $last_hour);
+use vars qw($me $pc11_max_age $pc11_dup_age %dup $last_hour %pings %rcmds);
 
 $me = undef;                                   # the channel id for this cluster
 $pc11_max_age = 1*3600;                        # the maximum age for an incoming 'real-time' pc11
 $pc11_dup_age = 24*3600;               # the maximum time to keep the dup list for
 %dup = ();                                             # the pc11 and 26 dup hash 
 $last_hour = time;                             # last time I did an hourly periodic update
+%pings = ();                    # outstanding ping requests outbound
+%rcmds = ();                    # outstanding rcmd requests outbound
 
 sub init
 {
        my $user = DXUser->get($main::mycall);
        $me = DXProt->new($main::mycall, undef, $user); 
+       $me->{here} = 1;
        #  $me->{sort} = 'M';    # M for me
 }
 
@@ -77,6 +80,7 @@ sub start
        }
        $self->state('init');
        $self->pc50_t(time);
+
        Log('DXProt', "$call connected");
 }
 
@@ -216,6 +220,7 @@ sub normal
                                my $user = DXUser->get_current($call);
                                $user = DXUser->new($call) if !$user;
                                $user->node($node->call);
+                               $user->lastin($main::systime);
                                $user->homenode($node->call) if !$user->homenode;
                                $user->put;
                        }
@@ -266,6 +271,7 @@ sub normal
                                        $user->sort('A');
                                        $user->node($call);
                                        $user->homenode($call);
+                                       $user->lastin($main::systime);
                                        $user->put;
                                }
                        }
@@ -345,12 +351,11 @@ sub normal
                
                if ($pcno == 35) {              # remote command replies
                        if ($field[1] eq $main::mycall) {
-                               my $s = DXChannel::get($main::myalias); 
-                               my @ref = grep { $_->pc34to eq $field[2] } DXChannel::get_all(); # people that have rcmded someone
-                               push @ref, $s if $s;
-                               
-                               foreach (@ref) {
-                                       $_->send($field[3]);
+                               my $s = $rcmds{$field[2]};
+                               if ($s) {
+                                       my $dxchan = DXChannel->get($s->{call});
+                                       $dxchan->send($field[3]) if $dxchan;
+                                       delete $rcmds{$field[2]} if !$dxchan;
                                }
                        } else {
                                route($field[1], $line);
@@ -386,13 +391,9 @@ sub normal
                        } elsif ($field[2] == 2) {
                                $user->qth($field[3]);
                        } elsif ($field[2] == 3) {
-                               my ($latd, $latm, $latl, $longd, $longm, $longl) = split /\s+/, $field[3];
-                               $longd += ($longm/60);
-                               $longd = 0-$longd if (uc $longl) eq 'W'; 
-                               $user->long($longd);
-                               $latd += ($latm/60);
-                               $latd = 0-$latd if (uc $latl) eq 'S';
-                               $user->lat($latd);
+                               my ($lat, $long) = DXBearing::stoll($field[3]);
+                               $user->lat($lat);
+                               $user->long($long);
                        } elsif ($field[2] == 4) {
                                $user->homenode($field[3]);
                        }
@@ -432,8 +433,18 @@ sub normal
                        # is it for us?
                        if ($field[1] eq $main::mycall) {
                                my $flag = $field[3];
-                               $flag ^= 1;
-                               $self->send($self->pc51($field[2], $field[1], $flag));
+                               if ($flag == 1) {
+                                       $self->send(pc51($field[2], $field[1], '0'));
+                               } else {
+                                       # 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;
+                                       }
+                               }
+                               
                        } else {
                                # route down an appropriate thingy
                                route($field[1], $line);
@@ -498,10 +509,11 @@ sub process
 sub finish
 {
        my $self = shift;
-       my $ref = DXCluster->get_exact($self->call);
+       my $call = $self->call;
+       my $ref = DXCluster->get_exact($call);
        
        # unbusy and stop and outgoing mail
-       my $mref = DXMsg::get_busy($self->call);
+       my $mref = DXMsg::get_busy($call);
        $mref->stop_msg($self) if $mref;
        
        # broadcast to all other nodes that all the nodes connected to via me are gone
@@ -509,14 +521,18 @@ sub finish
        my $node;
        
        foreach $node (@gonenodes) {
-               next if $node->call eq $self->call; 
+               next if $node->call eq $call; 
                broadcast_ak1a(pc21($node->call, 'Gone'), $self); # done like this 'cos DXNodes don't have a pc21 method
                $node->del();
        }
+
+       # remove outstanding pings
+       delete $pings{$call};
        
        # now broadcast to all other ak1a nodes that I have gone
-       broadcast_ak1a(pc21($self->call, 'Gone.'), $self);
-       Log('DXProt', $self->call . " Disconnected");
+       broadcast_ak1a(pc21($call, 'Gone.'), $self);
+       
+       Log('DXProt', $call . " Disconnected");
        $ref->del() if $ref;
 }
 
@@ -591,6 +607,7 @@ sub broadcast_users
        
        foreach $chan (@chan) {
                next if grep $chan == $_, @except;
+               $s =~ s/\a//og if !$chan->{beep};
                $chan->send($s);                # send it if it isn't the except list
        }
 }
@@ -663,5 +680,30 @@ sub unpad
        $s =~ s/^\s+|\s+$//;
        return $s;
 }
+
+# add a ping request to the ping queues
+sub addping
+{
+       my ($from, $to) = @_;
+       my $ref = $pings{$to};
+       $ref = $pings{$to} = [] if !$ref;
+       my $r = {};
+       $r->{call} = $from;
+       $r->{t} = $main::systime;
+       route($to, pc51($to, $main::mycall, 1));
+       push @$ref, $r;
+}
+
+# add a rcmd request to the rcmd queues
+sub addrcmd
+{
+       my ($from, $to, $cmd) = @_;
+       my $r = {};
+       $r->{call} = $from;
+       $r->{t} = $main::systime;
+       $r->{cmd} = $cmd;
+       route($to, pc34($main::mycall, $to, $cmd));
+       $rcmds{$to} = $r;
+}
 1;
 __END__