do non blocking connects
[spider.git] / perl / DXChannel.pm
index dce4fb5002bb1d277b76527e9e3e81749565cf1a..3e32f429cfe39e745bae74f3f3283ce160a342d4 100644 (file)
@@ -4,7 +4,7 @@
 # This is the base class for all channel operations, which is everything to do 
 # with input and output really.
 #
-# The instance variable in the outside world will be generally be called $dxchann
+# The instance variable in the outside world will be generally be called $dxchan
 #
 # This class is 'inherited' (if that is the goobledegook for what I am doing)
 # by various other modules. The point to understand is that the 'instance variable'
@@ -17,9 +17,9 @@
 #
 # PLEASE NOTE - I am a C programmer using this as a method of learning perl
 # firstly and OO about ninthly (if you don't like the design and you can't 
-# improve it with better OO by make it smaller and more efficient, then tough). 
+# improve it with better OO and thus make it smaller and more efficient, then tough). 
 #
-# Copyright (c) 1998 - Dirk Koopman G1TLH
+# Copyright (c) 1998-2000 - Dirk Koopman G1TLH
 #
 # $Id$
 #
@@ -28,12 +28,12 @@ package DXChannel;
 use Msg;
 use DXM;
 use DXUtil;
+use DXVars;
 use DXDebug;
 use Filter;
-use Carp;
 
 use strict;
-use vars qw(%channels %valid);
+use vars qw(%channels %valid @ISA);
 
 %channels = ();
 
@@ -52,6 +52,7 @@ use vars qw(%channels %valid);
                  consort => '5,Connection Type',
                  'sort' => '5,Type of Channel',
                  wwv => '0,Want WWV,yesno',
+                 wcy => '0,Want WCY,yesno',
                  wx => '0,Want WX,yesno',
                  talk => '0,Want Talk,yesno',
                  ann => '0,Want Announce,yesno',
@@ -73,17 +74,22 @@ use vars qw(%channels %valid);
                  delayed => '5,Delayed messages,parray',
                  annfilter => '5,Announce Filter',
                  wwvfilter => '5,WWV Filter',
-                 spotfilter => '5,Spot Filter',
+                 wcyfilter => '5,WCY Filter',
+                 spotsfilter => '5,Spot Filter',
                  inannfilter => '5,Input Ann Filter',
                  inwwvfilter => '5,Input WWV Filter',
-                 inspotfilter => '5,Input Spot Filter',
+                 inwcyfilter => '5,Input WCY Filter',
+                 inspotsfilter => '5,Input Spot Filter',
                  passwd => '9,Passwd List,parray',
-                 pingint => '9,Ping Interval ',
-                 nopings => '9,Ping Obs Count',
-                 lastping => '9,Ping last sent,atime',
-          pingrec => '9,Pings no rec',
-                 pingtime => '9,Ping totaltime',
+                 pingint => '5,Ping Interval ',
+                 nopings => '5,Ping Obs Count',
+                 lastping => '5,Ping last sent,atime',
+                 pingtime => '5,Ping totaltime,parray',
                  pingave => '0,Ping ave time',
+                 logininfo => '9,Login info req,yesno',
+                 talklist => '0,Talk List,parray',
+                 cluster => '5,Cluster data',
+                 isbasic => '9,Internal Connection', 
                 );
 
 # object destruction
@@ -98,11 +104,12 @@ sub DESTROY
        undef $self->{delayed};
        undef $self->{annfilter};
        undef $self->{wwvfilter};
-       undef $self->{spotfilter};
+       undef $self->{spotsfilter};
        undef $self->{inannfilter};
        undef $self->{inwwvfilter};
-       undef $self->{inspotfilter};
+       undef $self->{inspotsfilter};
        undef $self->{passwd};
+       undef $self->{node};
 }
 
 # create a new channel object [$obj = DXChannel->new($call, $msg_conn_obj, $user_obj)]
@@ -120,6 +127,7 @@ sub alloc
                $self->{lang} = $user->lang;
                $user->new_group() if !$user->group;
                $self->{group} = $user->group;
+               $self->{sort} = $user->sort;
        }
        $self->{startt} = $self->{t} = time;
        $self->{state} = 0;
@@ -127,11 +135,6 @@ sub alloc
        $self->{lang} = $main::lang if !$self->{lang};
        $self->{func} = "";
 
-       # get the filters
-       $self->{spotfilter} = Filter::read_in('spots', $call, 0);
-       $self->{wwvfilter} = Filter::read_in('wwv', $call, 0);
-       $self->{annfilter} = Filter::read_in('ann', $call, 0);
-
        bless $self, $pkg; 
        return $channels{$call} = $self;
 }
@@ -150,6 +153,41 @@ sub get_all
        return values(%channels);
 }
 
+#
+# gimme all the ak1a nodes
+#
+sub get_all_nodes
+{
+       my $ref;
+       my @out;
+       foreach $ref (values %channels) {
+               push @out, $ref if $ref->is_node;
+       }
+       return @out;
+}
+
+# return a list of all users
+sub get_all_users
+{
+       my $ref;
+       my @out;
+       foreach $ref (values %channels) {
+               push @out, $ref if $ref->is_user;
+       }
+       return @out;
+}
+
+# return a list of all user callsigns
+sub get_all_user_calls
+{
+       my $ref;
+       my @out;
+       foreach $ref (values %channels) {
+               push @out, $ref->{call} if $ref->is_user;
+       }
+       return @out;
+}
+
 # obtain a channel object by searching for its connection reference
 sub get_by_cnum
 {
@@ -178,7 +216,12 @@ sub is_bbs
        return $self->{'sort'} eq 'B';
 }
 
-# is it an ak1a cluster ?
+sub is_node
+{
+       my $self = shift;
+       return $self->{'sort'} =~ /[ACRSX]/;
+}
+# is it an ak1a node ?
 sub is_ak1a
 {
        my $self = shift;
@@ -192,13 +235,34 @@ sub is_user
        return $self->{'sort'} eq 'U';
 }
 
-# is it a connect type
-sub is_connect
+# is it a clx node
+sub is_clx
 {
        my $self = shift;
        return $self->{'sort'} eq 'C';
 }
 
+# is it a spider node
+sub is_spider
+{
+       my $self = shift;
+       return $self->{'sort'} eq 'S';
+}
+
+# is it a DXNet node
+sub is_dxnet
+{
+       my $self = shift;
+       return $self->{'sort'} eq 'X';
+}
+
+# is it a ar-cluster node
+sub is_arcluster
+{
+       my $self = shift;
+       return $self->{'sort'} eq 'R';
+}
+
 # for perl 5.004's benefit
 sub sort
 {
@@ -217,7 +281,7 @@ sub send_now
        my $call = $self->{call};
        
        for (@_) {
-               chomp;
+#              chomp;
         my @lines = split /\n/;
                for (@lines) {
                        $conn->send_now("$sort$call|$_");
@@ -238,7 +302,7 @@ sub send                                            # this is always later and always data
        my $call = $self->{call};
 
        for (@_) {
-               chomp;
+#              chomp;
         my @lines = split /\n/;
                for (@lines) {
                        $conn->send_later("D$call|$_");
@@ -293,7 +357,7 @@ sub state
                dbg('state', "$self->{call} channel func $self->{func} state $self->{oldstate} -> $self->{state}\n");
 
                # if there is any queued up broadcasts then splurge them out here
-               if ($self->{delayed} && ($self->{state} eq 'prompt' || $self->{state} eq 'convers')) {
+               if ($self->{delayed} && ($self->{state} eq 'prompt' || $self->{state} eq 'talk')) {
                        $self->send (@{$self->{delayed}});
                        delete $self->{delayed};
                }
@@ -306,13 +370,11 @@ sub disconnect
 {
        my $self = shift;
        my $user = $self->{user};
-       my $conn = $self->{conn};
        my $call = $self->{call};
        
-       $self->finish();
-       $conn->send_now("Z$call|bye") if $conn; # this will cause 'client' to disconnect
+       $self->finish;
        $user->close() if defined $user;
-       $conn->disconnect() if $conn;
+       $self->{conn}->disconnect;
        $self->del();
 }
 
@@ -332,6 +394,22 @@ sub closeall
        }
 }
 
+#
+# Tell all the users that we have come in or out (if they want to know)
+#
+sub tell_login
+{
+       my ($self, $m) = @_;
+       
+       # send info to all logged in thingies
+       my @dxchan = get_all_users();
+       my $dxchan;
+       foreach $dxchan (@dxchan) {
+               next if $dxchan == $self;
+               $dxchan->send($dxchan->msg($m, $self->{call})) if $dxchan->{logininfo};
+       }
+}
+
 # various access routines
 
 #
@@ -353,6 +431,30 @@ sub field_prompt
        return $valid{$ele};
 }
 
+# take a standard input message and decode it into its standard parts
+sub decode_input
+{
+       my $dxchan = shift;
+       my $data = shift;
+       my ($sort, $call, $line) = $data =~ /^([A-Z])([A-Z0-9\-]{3,9})\|(.*)$/;
+
+       my $chcall = (ref $dxchan) ? $dxchan->call : "UN.KNOWN";
+       
+       # the above regexp must work
+       unless (defined $sort && defined $call && defined $line) {
+#              $data =~ s/([\x00-\x1f\x7f-\xff])/uc sprintf("%%%02x",ord($1))/eg;
+               dbg('err', "DUFF Line on $chcall: $data");
+               return ();
+       }
+
+       if(ref($dxchan) && $call ne $chcall) {
+               dbg('err', "DUFF Line come in for $call on wrong channel $chcall" );
+               return();
+       }
+       
+       return ($sort, $call, $line);
+}
+
 no strict;
 sub AUTOLOAD
 {
@@ -362,8 +464,13 @@ sub AUTOLOAD
        $name =~ s/.*:://o;
   
        confess "Non-existant field '$AUTOLOAD'" if !$valid{$name};
-       @_ ? $self->{$name} = shift : $self->{$name} ;
+
+       # this clever line of code creates a subroutine which takes over from autoload
+       # from OO Perl - Conway
+       *{$AUTOLOAD} = sub {@_ > 1 ? $_[0]->{$name} = $_[1] : $_[0]->{$name}} ;
+    @_ ? $self->{$name} = shift : $self->{$name} ;
 }
 
+
 1;
 __END__;