add localhost client aliasing on spots and PC92A
[spider.git] / perl / Msg.pm
index e3385d9166585436dad106bd94e8b94aa6b0c411..c81273e29b329a5070b2bd53e34e7371564e3c68 100644 (file)
@@ -18,17 +18,18 @@ use Mojo::IOLoop;
 use Mojo::IOLoop::Stream;
 
 use DXDebug;
-use Timer;
+use DXTimer;
 
-use vars qw($now %conns $noconns $cnum $total_in $total_out $connect_timeout $disc_waittime);
+use vars qw($now %conns $noconns $cnum $total_in $total_out $total_lines_in $total_lines_out $connect_timeout $disc_waittime);
 
 $total_in = $total_out = 0;
+$total_lines_in = $total_lines_out = 0;
 
 $now = time;
 
 $cnum = 0;
 $connect_timeout = 5;
-$disc_waittime = 3;
+$disc_waittime = 1.5;
 
 our %delqueue;
 
@@ -43,15 +44,19 @@ sub new
        my $class = $obj || $pkg;
 
     my $conn = {
-        rproc => $rproc,
-               inqueue => [],
-               outqueue => [],
-               state => 0,
-               lineend => "\r\n",
-               csort => 'telnet',
-               timeval => 60,
-               blocking => 0,
-               cnum => (($cnum < 999) ? (++$cnum) : ($cnum = 1)),
+                               rproc => $rproc,
+                               inqueue => [],
+                               outqueue => [],
+                               state => 0,
+                               lineend => "\r\n",
+                               csort => 'telnet',
+                               timeval => 60,
+                               blocking => 0,
+                               cnum => (($cnum < 999) ? (++$cnum) : ($cnum = 1)),
+                               linesin => 0,
+                               linesout => 0,
+                               datain => 0,
+                               dataout => 0,
     };
 
        $noconns++;
@@ -128,9 +133,28 @@ sub peerhost
                $conn->{peerhost} ||= $conn->{sock}->handle->peerhost if $conn->{sock};
                $conn->{peerhost} ||= 'UNKNOWN';
        }
+       $conn->{peerhost} =~ s/^::ffff://;
        return $conn->{peerhost};
 }
 
+sub sockhost
+{
+       my $conn = shift;
+       unless ($conn->{sockhost}) {
+               $conn->{sockhost} ||= 'ax25' if $conn->ax25;
+               $conn->{sockhost} ||= $conn->{sock}->handle->sockhost if $conn->{sock};
+               $conn->{sockhost} ||= 'UNKNOWN';
+       }
+       $conn->{sockhost} =~ s/^::ffff://;
+       if (! defined $main::localhost_alias_ipv4 && $conn->{sockhost} =~ /\./ && $conn->{sockhost} !~ /^127\./) {
+               $main::localhost_alias_ipv4 = $conn->{sockhost};
+               dbg("Msg: localhost_alias_ipv4 = '$main::localhost_alias_ipv4'");
+       } elsif (! defined $main::localhost_alias_ipv6 && $conn->{sockhost} =~ /:/ && $conn->{sockhost} !~ /^::1$/) {
+               $main::localhost_alias_ipv6 = $conn->{sockhost};
+               dbg("Msg: localhost_alias_ipv6 = '$main::localhost_alias_ipv6'");
+       }
+       return $conn->{sockhost};
+}
 #-----------------------------------------------------------------
 # Send side routines
 
@@ -146,7 +170,8 @@ sub _on_connect
        $sock->timeout(0);
        $sock->start;
        $conn->{peerhost} = eval { $handle->peerhost; };
-       dbg((ref $conn) . " connected $conn->{cnum} to $conn->{peerhost}:$conn->{peerport}") if isdbg('connll');
+       $conn->{sockhost} = eval { $handle->sockhost; };
+       dbg((ref $conn) . " connected $conn->{cnum}:$conn->{sockhost} to $conn->{peerhost}:$conn->{peerport}") if isdbg('conn') || isdbg ('connect');
        if ($conn->{on_connect}) {
                &{$conn->{on_connect}}($conn, $handle);
        }
@@ -177,9 +202,18 @@ sub connect {
        
        my $sock;
        $conn->{sock} = $sock = Mojo::IOLoop::Client->new;
-       $sock->on(connect => sub {$conn->_on_connect($_[1])} );
-       $sock->on(error => sub {&{$conn->{eproc}}($conn, $_[1]) if exists $conn->{eproc}; $conn->disconnect});
-       $sock->on(close => sub {$conn->disconnect});
+       $sock->on(connect => sub {
+                                 $conn->_on_connect($_[1])
+                         } );
+       $sock->on(error => sub {
+                                 &{$conn->{eproc}}($conn, $_[1]) if exists $conn->{eproc};
+                                 delete $conn->{sock};
+                                 $conn->disconnect
+                         });
+       $sock->on(close => sub {
+                                 delete $conn->{sock};
+                                 $conn->disconnect}
+                        );
 
        # copy any args like on_connect, on_disconnect etc
        while (my ($k, $v) = each %args) {
@@ -244,41 +278,42 @@ sub disconnect
 {
        my $conn = shift;
        my $count = $conn->{disconnecting}++;
-       if (isdbg('connll')) {
-               my ($pkg, $fn, $line) = caller;
-               dbg((ref $conn) . "::disconnect on call $conn->{call} attempt $conn->{disconnecting} called from ${pkg}::${fn} line $line ");
+       my $dbg = isdbg('connll');
+       my ($pkg, $fn, $line) = caller if $dbg;
+
+       if ($count >= 2) {
+               dbgtrace((ref $conn) . "::disconnect on call $conn->{call} attempt $conn->{disconnecting} called from ${pkg}::${fn} line $line FORCING CLOSE ") if $dbg;
+               _close_it($conn);
+               return;
        }
+       dbg((ref $conn) . "::disconnect on call $conn->{call} attempt $conn->{disconnecting} called from ${pkg}::${fn} line $line ") if $dbg;
        return if $count;
 
-       
+       # remove this conn from the active queue
+       # be careful to delete the correct one
+       my $call;
+       if ($call = $conn->{call}) {
+               my $ref = $conns{$call};
+               delete $conns{$call} if $ref && $ref == $conn;
+       }
+       $call ||= 'unallocated';
+
+       $delqueue{$conn} = $conn; # save this connection until everything is finished
        my $sock = $conn->{sock};
        if ($sock) {
-
-               # remove me from the active list
-               my $call;
-               if ($call = $conn->{call}) {
-                       my $ref = $conns{$call};
-                       delete $conns{$call} if $ref && $ref == $conn;
+               if ($sock->{buffer}) {
+                       my $lth = length $sock->{buffer};
+                       Mojo::IOLoop->timer($disc_waittime, sub {
+                                                                       dbg("Buffer contained $lth characters, coordinated for $disc_waittime secs, now disconnecting $call") if $dbg;
+                                                                       _close_it($conn);
+                                                               });
+               } else {
+                       dbg("Buffer empty, just close $call") if $dbg;
+                       _close_it($conn);
                }
-               $conn->{delay} = Mojo::IOLoop->delay (
-#                               Mojo::IOLoop->delay (
-                                                                                         sub {
-                                                                                                 my $delay = shift;
-                                                                                                 dbg("before drain $call");
-                                                                                                 $sock->on(drain => $delay->begin);
-                                                                                                 1;
-                                                                                         },
-                                                                                         sub {
-                                                                                                 my $delay = shift;
-                                                                                                 _close_it($conn);
-                                                                                                 1;
-                                                                                         }
-                                                                                        );
-               $conn->{delay}->wait;
-               
-               $delqueue{$conn} = $conn; # save this connection until everything is finished
-       } else {
-               dbg((ref $conn) . " socket missing on $conn->{call}") if isdbg('connll');
+       }
+       else {
+               dbg((ref $conn) . " socket missing on $conn->{call}") if $dbg;
                _close_it($conn);
        }
 }
@@ -290,18 +325,13 @@ sub _close_it
        $conn->{state} = 'E';
        $conn->{timeout}->del if $conn->{timeout};
 
+       my $call = $conn->{call};
+
        if (isdbg('connll')) {
                my ($pkg, $fn, $line) = caller;
                dbg((ref $conn) . "::_close_it on call $conn->{call} attempt $conn->{disconnecting} called from ${pkg}::${fn} line $line ");
        }
 
-       # be careful to delete the correct one
-       my $call;
-       if ($call = $conn->{call}) {
-               my $ref = $conns{$call};
-               delete $conns{$call} if $ref && $ref == $conn;
-       }
-       $call ||= 'unallocated';
 
        dbg((ref $conn) . " Connection $conn->{cnum} $call starting to close") if isdbg('connll');
        
@@ -311,7 +341,7 @@ sub _close_it
 
        if ($sock) {
                dbg((ref $conn) . " Connection $conn->{cnum} $call closing gracefully") if isdbg('connll');
-               $sock->close_gracefully;
+               $sock->close_gracefully if $sock->can('close_gracefully');
        }
        
        # get rid of any references
@@ -341,13 +371,14 @@ sub _send_stuff
                my $lth = length $data;
                my $call = $conn->{call} || 'none';
                if (isdbg('raw')) {
-                       if (isdbg('raw')) {
-                               dbgdump('raw', "$call send $lth: ", $lth);
-                       }
+                       dbgdump('raw', "$call send $lth:", $data);
                }
                if (defined $sock) {
                        $sock->write($data);
                        $total_out += $lth;
+                       $conn->{dataout} += $lth;
+                       ++$conn->{linesout};
+                       ++$total_lines_out;
                } else {
                        dbg("_send_stuff $call ending data ignored: $data");
                }
@@ -423,6 +454,8 @@ sub dequeue
                } else {
                        $conn->{msg} = pop @lines;
                }
+               $conn->{linesin} += @lines;
+               $total_lines_in += @lines;
                for (@lines) {
                        last if $conn->{disconnecting};
                        &{$conn->{rproc}}($conn, defined $_ ? $_ : '');
@@ -435,11 +468,11 @@ sub _rcv {                     # Complement to _send
        my $msg = shift;
     my $sock = $conn->{sock};
     return unless defined($sock);
-       return if $conn->{disconnecting};
+       return if $conn->{disonnecting};
 
        $total_in += length $msg;
+       $conn->{datain} += length $msg;
 
-       my @lines;
        if (isdbg('raw')) {
                my $call = $conn->{call} || 'none';
                my $lth = length $msg;
@@ -478,9 +511,11 @@ sub new_client {
        $sock->on(read => sub {$conn->_rcv($_[1])});
        $sock->timeout(0);
        $sock->start;
-       dbg((ref $conn) . "accept $conn->{cnum} from $conn->{peerhost} $conn->{peerport}") if isdbg('connll');
-
-       my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost} = $handle->peerhost, $conn->{peerport} = $handle->peerport);
+       $conn->{peerhost} = $handle->peerhost || 'unknown';
+       $conn->{peerport} = $handle->peerport || 0;
+       $conn->{sockhost} = $handle->sockhost || '';
+       dbg((ref $conn) . " accept $conn->{cnum}:$conn->{sockhost} from $conn->{peerhost}:$conn->{peerport}") if isdbg('conn') || isdbg('connect');
+       my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost}, $conn->{peerport});
        $conn->{sort} = 'Incoming';
        if ($eproc) {
                $conn->{eproc} = $eproc;
@@ -547,8 +582,7 @@ sub DESTROY
 
        if (isdbg('connll')) {
                my ($pkg, $fn, $line) = caller;
-               dbg((ref $conn) . "::DESTROY on call $call called from ${pkg}::${fn} line $line ");
-               
+               dbgtrace((ref $conn) . "::DESTROY on call $call called from ${pkg}::${fn} line $line ");
        }
 
        my $call = $conn->{call} || 'unallocated';
@@ -557,7 +591,8 @@ sub DESTROY
        my $sock = $conn->{sock};
 
        if ($sock) {
-               $sock->close_gracefully;
+               $sock->close_gracefully if $sock->can('close_gracefully');
+               delete $conn->{sock};
        }
        
        $noconns--;