removed the memory leakage a bit better on connects
authorminima <minima>
Tue, 13 Mar 2001 19:54:55 +0000 (19:54 +0000)
committerminima <minima>
Tue, 13 Mar 2001 19:54:55 +0000 (19:54 +0000)
perl/DXChannel.pm
perl/DXVars.pm.issue
perl/ExtMsg.pm
perl/Msg.pm
perl/Timer.pm
perl/cluster.pl

index 3e32f429cfe39e745bae74f3f3283ce160a342d4..808b4821206fb6ddc91cd3eaa1d232f8bb1a082d 100644 (file)
@@ -33,9 +33,10 @@ use DXDebug;
 use Filter;
 
 use strict;
-use vars qw(%channels %valid @ISA);
+use vars qw(%channels %valid @ISA $count);
 
 %channels = ();
+$count = 0;
 
 %valid = (
                  call => '0,Callsign',
@@ -96,20 +97,13 @@ use vars qw(%channels %valid @ISA);
 sub DESTROY
 {
        my $self = shift;
-       undef $self->{user};
-       undef $self->{conn};
-       undef $self->{loc};
-       undef $self->{pagedata};
-       undef $self->{group};
-       undef $self->{delayed};
-       undef $self->{annfilter};
-       undef $self->{wwvfilter};
-       undef $self->{spotsfilter};
-       undef $self->{inannfilter};
-       undef $self->{inwwvfilter};
-       undef $self->{inspotsfilter};
-       undef $self->{passwd};
-       undef $self->{node};
+       for (keys %$self) {
+               if (ref($self->{$_})) {
+                       delete $self->{$_};
+               }
+       }
+       dbg('chan', "DXChannel $self->{call} destroyed ($count)");
+       $count--;
 }
 
 # create a new channel object [$obj = DXChannel->new($call, $msg_conn_obj, $user_obj)]
@@ -135,6 +129,8 @@ sub alloc
        $self->{lang} = $main::lang if !$self->{lang};
        $self->{func} = "";
 
+       $count++;
+       dbg('chan', "DXChannel $self->{call} created ($count)");
        bless $self, $pkg; 
        return $channels{$call} = $self;
 }
index 42feb2ead469a3f9c343a87b661ca742b51d0027..90f2fe198412f8ac6ee71523f0033bc5faea1d1c 100644 (file)
@@ -87,4 +87,4 @@ $userfn = "$data/users";
 $motd = "$data/motd";
 
 # are we debugging ?
-@debug = ('chan', 'state', 'msg', 'cron', 'connect');
+@debug = qw(chan state msg cron connect);
index 8772955350f78c72381c37a3d2b4dcf95210c74e..a601d4edfa01c0a09da64a74859e50ffdd9d94c6 100644 (file)
@@ -66,10 +66,7 @@ sub dequeue
                        } 
                }
                if ($conn->{state} eq 'WC' && exists $conn->{cmd} && @{$conn->{cmd}} == 0) {
-                       $conn->{state} = 'C';
-                       &{$conn->{rproc}}($conn, "O$conn->{call}|telnet");
-                       delete $conn->{cmd};
-                       $conn->{timeout}->del if $conn->{timeout};
+                       $conn->to_connected($conn->{call}, 'O', 'telnet');
                }
        } elsif ($conn->{msg} =~ /\n/) {
                my @lines = split /\r?\n/, $conn->{msg};
@@ -89,9 +86,7 @@ sub dequeue
                        } elsif ($conn->{state} eq 'WL' ) {
                                $msg = uc $msg;
                                if (is_callsign($msg)) {
-                                       &{$conn->{rproc}}($conn, "A$msg|telnet");
-                                       _send_file($conn, "$main::data/connected");
-                                       $conn->{state} = 'C';
+                                       $conn->to_connected($msg, 'A', 'telnet');
                                } else {
                                        $conn->send_now("Sorry $msg is an invalid callsign");
                                        $conn->disconnect;
@@ -100,10 +95,7 @@ sub dequeue
                                if (exists $conn->{cmd} && @{$conn->{cmd}}) {
                                        $conn->_docmd($msg);
                                        if ($conn->{state} eq 'WC' && exists $conn->{cmd} &&  @{$conn->{cmd}} == 0) {
-                                               $conn->{state} = 'C';
-                                               &{$conn->{rproc}}($conn, "O$conn->{call}|telnet");
-                                               delete $conn->{cmd};
-                                               $conn->{timeout}->del if $conn->{timeout};
+                                               $conn->to_connected($conn->{call}, 'O', 'telnet');
                                        }
                                }
                        }
@@ -111,6 +103,18 @@ sub dequeue
        }
 }
 
+sub to_connected
+{
+       my ($conn, $call, $dir, $sort) = @_;
+       $conn->{state} = 'C';
+       $conn->conns($call);
+       delete $conn->{cmd};
+       $conn->{timeout}->del if $conn->{timeout};
+       delete $conn->{timeout};
+       $conn->_send_file("$main::data/connected");
+       &{$conn->{rproc}}($conn, "$dir$call|$sort");
+}
+
 sub new_client {
        my $server_conn = shift;
     my $sock = $server_conn->{sock}->accept();
@@ -120,7 +124,7 @@ sub new_client {
     my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost} = $sock->peerhost(), $conn->{peerport} = $sock->peerport());
        if ($eproc) {
                $conn->{eproc} = $eproc;
-        set_event_handler ($sock, "error" => $eproc);
+        Msg::set_event_handler ($sock, "error" => $eproc);
        }
     if ($rproc) {
         $conn->{rproc} = $rproc;
@@ -131,8 +135,9 @@ sub new_client {
 #              $conn->send_raw("\xff\xfe\x01\xff\xfc\x01\ff\fd\x22");
 #              $conn->send_raw("\xff\xfa\x22\x01\x01\xff\xf0");
 #              $conn->send_raw("\xFF\xFC\x01");
-               _send_file($conn, "$main::data/issue");
+               $conn->_send_file("$main::data/issue");
                $conn->send_raw("login: ");
+               $conn->_dotimeout(60);
     } else { 
         $conn->disconnect();
     }
@@ -142,7 +147,7 @@ sub start_connect
 {
        my $call = shift;
        my $fn = shift;
-       my $conn = ExtMsg->new(\&main::rec); 
+       my $conn = ExtMsg->new(\&main::new_channel); 
        $conn->conns($call);
        
        my $f = new IO::File $fn;
@@ -222,9 +227,9 @@ sub _dotimeout
        my $conn = shift;
        my $val = shift;
        dbg('connect', "timeout set to $val");
-       my $old = $conn->{timeout}->del if $conn->{timeout};
-       $conn->{timeout} = Timer->new($val, sub{ &_timeout($conn) });
+       $conn->{timeout}->del if $conn->{timeout};
        $conn->{timeval} = $val;
+       $conn->{timeout} = Timer->new($val, sub{ &_timedout($conn) });
 }
 
 sub _dolineend
@@ -264,10 +269,12 @@ sub _dochat
        unshift @{$conn->{cmd}}, $cmd;
 }
 
-sub _timeout
+sub _timedout
 {
        my $conn = shift;
        dbg('connect', "timed out after $conn->{timeval} seconds");
+       $conn->{timeout}->del;
+       delete $conn->{timeout};
        $conn->disconnect;
 }
 
@@ -277,10 +284,11 @@ sub _doclient
        my $conn = shift;
        my $line = shift;
        my @f = split /\s+/, $line;
-       $conn->{call} = uc $f[0] if $f[0];
+       my $call = uc $f[0] if $f[0];
+       $conn->conns($call);
        $conn->{csort} = $f[1] if $f[1];
        $conn->{state} = 'C';
-       &{$conn->{rproc}}($conn, "O$conn->{call}|telnet");
+       &{$conn->{rproc}}($conn, "O$call|telnet");
        delete $conn->{cmd};
        $conn->{timeout}->del if $conn->{timeout};
 }
index 449f1790ca8dcb1b0156e06c31d402784264320a..c730773aff702f9c1cbb4d79cad00932dd2f5036 100644 (file)
@@ -62,6 +62,13 @@ sub set_error
        set_event_handler($conn->{sock}, error => $callback) if exists $conn->{sock};
 }
 
+sub set_rproc
+{
+       my $conn = shift;
+       my $callback = shift;
+       $conn->{rproc} = $callback;
+}
+
 sub blocking
 {
        my $flags = fcntl ($_[0], F_GETFL, 0);
@@ -136,8 +143,8 @@ sub connect {
        $conn->{sock} = $sock;
     
     if ($conn->{rproc}) {
-        my $callback = sub {_rcv($conn)};
-        set_event_handler ($sock, "read" => $callback);
+        my $callback = sub {$conn->_rcv};
+        set_event_handler ($sock, read => $callback);
     }
     return $conn;
 }
@@ -149,9 +156,6 @@ sub disconnect {
        $conn->{disconnecting} = 1;
     my $sock = delete $conn->{sock};
        $conn->{state} = 'E';
-       delete $conn->{cmd};
-       delete $conn->{eproc};
-       delete $conn->{rproc};
        $conn->{timeout}->del if $conn->{timeout};
 
        # be careful to delete the correct one
@@ -164,9 +168,18 @@ sub disconnect {
        dbg('connll', "Connection $call disconnected");
        
     set_event_handler ($sock, read => undef, write => undef, error => undef);
+
        unless ($^O =~ /^MS/i) {
                kill 'TERM', $conn->{pid} if exists $conn->{pid};
        }
+
+       # get rid of any references
+       for (keys %$conn) {
+               if (ref($conn->{$_})) {
+                       delete $conn->{$_};
+               }
+       }
+
        return unless defined($sock);
     shutdown($sock, 3);
        close($sock);
@@ -183,7 +196,7 @@ sub send_later {
     $conn->enqueue($msg);
     my $sock = $conn->{sock};
     return unless defined($sock);
-    set_event_handler ($sock, "write" => sub {$conn->_send(0)});
+    set_event_handler ($sock, write => sub {$conn->_send(0)});
 }
 
 sub enqueue {
@@ -240,9 +253,9 @@ sub _send {
     }
     # Call me back if queue has not been drained.
     if (@$rq) {
-        set_event_handler ($sock, "write" => sub {$conn->_send(0)});
+        set_event_handler ($sock, write => sub {$conn->_send(0)});
     } else {
-        set_event_handler ($sock, "write" => undef);
+        set_event_handler ($sock, write => undef);
                if (exists $conn->{close_on_empty}) {
                        &{$conn->{eproc}}($conn, undef) if exists $conn->{eproc};
                        $conn->disconnect; 
@@ -276,7 +289,7 @@ sub new_server {
                                           Proto     => 'tcp',
                                           Reuse     => 1);
     die "Could not create socket: $! \n" unless $self->{sock};
-    set_event_handler ($self->{sock}, "read" => sub { $self->new_client }  );
+    set_event_handler ($self->{sock}, read => sub { $self->new_client }  );
        return $self;
 }
 
@@ -321,8 +334,8 @@ sub _rcv {                     # Complement to _send
 
 FINISH:
     if (defined $bytes_read && $bytes_read == 0) {
-               &{$conn->{eproc}}($conn, undef) if exists $conn->{eproc};
-               $conn->disconnect();
+               &{$conn->{eproc}}($conn, $!) if exists $conn->{eproc};
+               $conn->disconnect;
     } else {
                $conn->dequeue if exists $conn->{msg};
        }
@@ -337,12 +350,12 @@ sub new_client {
        $conn->{sort} = 'Incoming';
        if ($eproc) {
                $conn->{eproc} = $eproc;
-        set_event_handler ($sock, "error" => $eproc);
+        set_event_handler ($sock, error => $eproc);
        }
     if ($rproc) {
         $conn->{rproc} = $rproc;
-        my $callback = sub {_rcv($conn)};
-        set_event_handler ($sock, "read" => $callback);
+        my $callback = sub {$conn->_rcv};
+        set_event_handler ($sock, read => $callback);
     } else {  # Login failed
                &{$conn->{eproc}}($conn, undef) if exists $conn->{eproc};
         $conn->disconnect();
@@ -352,7 +365,7 @@ sub new_client {
 sub close_server
 {
        my $conn = shift;
-       set_event_handler ($conn->{sock}, "read" => undef);
+       set_event_handler ($conn->{sock}, read => undef, write => undef, error => undef );
        $conn->{sock}->close;
 }
 
index 8969756f550706bb942e7bc3e7c6f2bb93054841..0c44278e05067723a8d0a5e25df430af2ada801c 100644 (file)
 
 package Timer;
 
-use vars qw(@timerchain);
+use vars qw(@timerchain $notimers);
+use DXDebug;
 
 @timerchain = ();
+$notimers = 0;
 
 sub new
 {
@@ -22,15 +24,16 @@ sub new
        my $self = bless { t=>$time + time, proc=>$proc }, $class;
        $self->{interval} = $time if $recur;
        push @timerchain, $self;
+       $notimers++;
+       dbg('connll', "Timer created ($notimers)");
        return $self;
 }
 
 sub del
 {
        my $self = shift;
-       my $old = delete $self->{proc};
+       delete $self->{proc};
        @timerchain = grep {$_ != $self} @timerchain;
-       return $old;
 }
 
 sub handler
@@ -46,4 +49,9 @@ sub handler
        }
 }
 
+sub DESTROY
+{
+       dbg('connll', "Timer destroyed ($notimers)");
+       $notimers--;
+}
 1;
index eef7a40cd02d4fa5c970517192c35d3aba9aa689..e062b65ed7c7184808042c4d51c23018af931901 100755 (executable)
@@ -74,9 +74,9 @@ use Local;
 
 package main;
 
-#use strict;
-#use vars qw(@inqueue $systime $version $starttime $lockfn @outstanding_connects $zombies $root
-#                 $lang $myalias @debug $userfn $clusteraddr $clusterport $mycall $decease );
+use strict;
+use vars qw(@inqueue $systime $version $starttime $lockfn @outstanding_connects $zombies $root
+                  @listeners $lang $myalias @debug $userfn $clusteraddr $clusterport $mycall $decease );
 
 @inqueue = ();                                 # the main input queue, an array of hashes
 $systime = 0;                                  # the time now (in seconds)
@@ -101,66 +101,73 @@ sub already_conn
 sub error_handler
 {
        my $dxchan = shift;
+       $dxchan->{conn}->set_error(undef) if exists $dxchan->{conn};
        $dxchan->disconnect;
 }
 
 # handle incoming messages
-sub rec
+sub new_channel
 {
        my ($conn, $msg) = @_;
-       my $dxchan = DXChannel->get_by_cnum($conn); # get the dxconnnect object for this message
        my ($sort, $call, $line) = DXChannel::decode_input(0, $msg);
        return unless defined $sort;
        
        # set up the basic channel info
-       if (!defined $dxchan) {
-
-               # is there one already connected to me - locally? 
-               my $user = DXUser->get($call);
-               if ($sort ne 'O' && Msg->conns($call)) {
-                       my $mess = DXM::msg($lang, ($user && $user->is_node) ? 'concluster' : 'conother', $call, $main::mycall);
-                       already_conn($conn, $call, $mess);
-                       return;
-               }
-               
-               # is there one already connected elsewhere in the cluster?
-               if ($user) {
-                       if (($user->is_node || $call eq $myalias) && !DXCluster->get_exact($call)) {
-                               ;
-                       } else {
-                               if (my $ref = DXCluster->get_exact($call)) {
-                                       my $mess = DXM::msg($lang, 'concluster', $call, $ref->mynode->call);
-                                       already_conn($conn, $call, $mess);
-                                       return;
-                               }
-                       }
-                       $user->{lang} = $main::lang if !$user->{lang}; # to autoupdate old systems
+       # is there one already connected to me - locally? 
+       my $user = DXUser->get($call);
+       if ($sort ne 'O' && Msg->conns($call)) {
+               my $mess = DXM::msg($lang, ($user && $user->is_node) ? 'concluster' : 'conother', $call, $main::mycall);
+               already_conn($conn, $call, $mess);
+               return;
+       }
+       
+       # is there one already connected elsewhere in the cluster?
+       if ($user) {
+               if (($user->is_node || $call eq $myalias) && !DXCluster->get_exact($call)) {
+                       ;
                } else {
                        if (my $ref = DXCluster->get_exact($call)) {
                                my $mess = DXM::msg($lang, 'concluster', $call, $ref->mynode->call);
                                already_conn($conn, $call, $mess);
                                return;
                        }
-                       $user = DXUser->new($call);
                }
-
-               # is he locked out ?
-               if ($user->lockout) {
-                       Log('DXCommand', "$call is locked out, disconnected");
-                       $conn->disconnect;
+               $user->{lang} = $main::lang if !$user->{lang}; # to autoupdate old systems
+       } else {
+               if (my $ref = DXCluster->get_exact($call)) {
+                       my $mess = DXM::msg($lang, 'concluster', $call, $ref->mynode->call);
+                       already_conn($conn, $call, $mess);
                        return;
                }
-
-               # mark him up
-               $conn->conns($call) unless $sort eq 'O';
-               $conn->set_error(sub {error_handler($dxchan)});
-               
-               # create the channel
-               $dxchan = DXCommandmode->new($call, $conn, $user) if $user->is_user;
-               $dxchan = DXProt->new($call, $conn, $user) if $user->is_node;
-               $dxchan = BBS->new($call, $conn, $user) if $user->is_bbs;
-               die "Invalid sort of user on $call = $sort" if !$dxchan;
+               $user = DXUser->new($call);
+       }
+       
+       # is he locked out ?
+       if ($user->lockout) {
+               Log('DXCommand', "$call is locked out, disconnected");
+               $conn->disconnect;
+               return;
        }
+
+       # create the channel
+       my $dxchan;
+       $dxchan = DXCommandmode->new($call, $conn, $user) if $user->is_user;
+       $dxchan = DXProt->new($call, $conn, $user) if $user->is_node;
+       $dxchan = BBS->new($call, $conn, $user) if $user->is_bbs;
+       die "Invalid sort of user on $call = $sort" if !$dxchan;
+
+       # check that the conn has a callsign
+       $conn->conns($call) if $conn->isa('IntMsg');
+
+       # set callbacks
+       $conn->set_error(sub {error_handler($dxchan)});
+       $conn->set_rproc(sub {my ($conn,$msg) = @_; rec($dxchan, $conn, $msg);});
+       rec($dxchan, $conn, $msg);
+}
+
+sub rec        
+{
+       my ($dxchan, $conn, $msg) = @_;
        
        # queue the message and the channel object for later processing
        if (defined $msg) {
@@ -173,7 +180,7 @@ sub rec
 
 sub login
 {
-       return \&rec;
+       return \&new_channel;
 }
 
 # cease running this program, close down all the connections nicely
@@ -268,7 +275,6 @@ sub process_inqueue
                $dxchan->normal($line);
                $dxchan->disconnect if ($dxchan->{state} eq 'bye');
        } elsif ($sort eq 'Z') {
-               $dxchan->conn(undef);
                $dxchan->disconnect;
        } elsif ($sort eq 'D') {
                ;                       # ignored (an echo)