start the Aranea additions
authorminima <minima>
Mon, 24 Jan 2005 09:08:54 +0000 (09:08 +0000)
committerminima <minima>
Mon, 24 Jan 2005 09:08:54 +0000 (09:08 +0000)
perl/AGWMsg.pm
perl/AMsg.pm
perl/Aranea.pm [new file with mode: 0644]
perl/DXChannel.pm
perl/DXProt.pm
perl/ExtMsg.pm
perl/IntMsg.pm
perl/Thingy.pm
perl/Thingy/Hello.pm [new file with mode: 0644]
perl/Verify.pm
perl/cluster.pl

index f6fc50747f9a5fa005099630777770e4cdec2986..cb64177e20931cf5bb5c067bc36a26f13c4e235c 100644 (file)
@@ -104,6 +104,11 @@ sub finish
        }
 }
 
+sub login
+{
+       goto &main::login;        # save some writing, this was the default
+}
+
 sub active
 {
        return $sock;
index 06d281d13f95e89292503e37a0c03d22eac5fbab..19fe9208818f28a075e6264fcb9353059c11566a 100644 (file)
@@ -4,19 +4,22 @@
 #
 # $Id$
 #
-# Copyright (c) 2001 - Dirk Koopman G1TLH
+# Copyright (c) 2005 - Dirk Koopman G1TLH
 #
 
+use strict;
+
 package AMsg;
 
-use strict;
 use Msg;
 use DXVars;
 use DXUtil;
 use DXDebug;
-use IO::File;
-use IO::Socket;
-use IPC::Open3;
+use Aranea;
+use Verify;
+use DXLog;
+use Thingy;
+use Thingy::Hello;
 
 use vars qw($VERSION $BRANCH);
 $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
@@ -26,41 +29,13 @@ $main::branch += $BRANCH;
 
 use vars qw(@ISA $deftimeout);
 
-@ISA = qw(ExtMsg);
+@ISA = qw(ExtMsg Msg);
 $deftimeout = 60;
 
 sub enqueue
 {
        my ($conn, $msg) = @_;
-       unless ($msg =~ /^[ABZ]/) {
-               if ($msg =~ /^E[-\w]+\|([01])/ && $conn->{csort} eq 'telnet') {
-                       $conn->{echo} = $1;
-                       if ($1) {
-#                              $conn->send_raw("\xFF\xFC\x01");
-                       } else {
-#                              $conn->send_raw("\xFF\xFB\x01");
-                       }
-               } else {
-                       $msg =~ s/^[-\w]+\|//;
-                       push (@{$conn->{outqueue}}, $msg . $conn->{lineend});
-               }
-       }
-}
-
-sub send_raw
-{
-       my ($conn, $msg) = @_;
-    my $sock = $conn->{sock};
-    return unless defined($sock);
-       push (@{$conn->{outqueue}}, $msg);
-       dbg("connect $conn->{cnum}: $msg") if $conn->{state} ne 'C' && isdbg('connect');
-    Msg::set_event_handler ($sock, "write" => sub {$conn->_send(0)});
-}
-
-sub echo
-{
-       my $conn = shift;
-       $conn->{echo} = shift;
+       push (@{$conn->{outqueue}}, $msg . $conn->{lineend});
 }
 
 sub dequeue
@@ -71,7 +46,7 @@ sub dequeue
        if ($conn->{csort} eq 'ax25' && exists $conn->{msg}) {
                $conn->{msg} =~ s/\cM/\cJ/g;
        }
-       if ($conn->{state} eq 'WC') {
+       if ($conn->{state} eq 'WC' ) {
                if (exists $conn->{cmd}) {
                        if (@{$conn->{cmd}}) {
                                dbg("connect $conn->{cnum}: $conn->{msg}") if isdbg('connect');
@@ -90,38 +65,13 @@ sub dequeue
                }
                while (defined ($msg = shift @lines)) {
                        dbg("connect $conn->{cnum}: $msg") if $conn->{state} ne 'C' && isdbg('connect');
-               
-                       $msg =~ s/\xff\xfa.*\xff\xf0|\xff[\xf0-\xfe].//g; # remove telnet options
-#                      $msg =~ s/[\x00-\x08\x0a-\x19\x1b-\x1f\x80-\x9f]/./g;         # immutable CSI sequence + control characters
-                       
                        if ($conn->{state} eq 'C') {
-                               &{$conn->{rproc}}($conn, "I$conn->{call}|$msg");
-                       } elsif ($conn->{state} eq 'WL' ) {
-                               $msg = uc $msg;
-                               if (is_callsign($msg) && $msg !~ m|/| ) {
-                                       my $sort = $conn->{csort};
-                                       $sort = 'local' if $conn->{peerhost} eq "127.0.0.1";
-                                       my $uref;
-                                       if ($main::passwdreq || ($uref = DXUser->get_current($msg)) && $uref->passwd ) {
-                                               $conn->conns($msg);
-                                               $conn->{state} = 'WP';
-                                               $conn->{decho} = $conn->{echo};
-                                               $conn->{echo} = 0;
-                                               $conn->send_raw('password: ');
-                                       } else {
-                                               $conn->to_connected($msg, 'A', $sort);
-                                       }
-                               } else {
-                                       $conn->send_now("Sorry $msg is an invalid callsign");
-                                       $conn->disconnect;
-                               }
-                       } elsif ($conn->{state} eq 'WP' ) {
+                               &{$conn->{rproc}}($conn, $msg);
+                       } elsif ($conn->{state} eq 'WA' ) {
                                my $uref = DXUser->get_current($conn->{call});
                                $msg =~ s/[\r\n]+$//;
                                if ($uref && $msg eq $uref->passwd) {
                                        my $sort = $conn->{csort};
-                                       $conn->{echo} = $conn->{decho};
-                                       delete $conn->{decho};
                                        $sort = 'local' if $conn->{peerhost} eq "127.0.0.1";
                                        $conn->{usedpasswd} = 1;
                                        $conn->to_connected($conn->{call}, 'A', $sort);
@@ -138,7 +88,7 @@ sub dequeue
                                }
                        }
                }
-       }
+       } 
 }
 
 sub to_connected
@@ -151,7 +101,141 @@ sub to_connected
        delete $conn->{timeout};
        $conn->nolinger;
        &{$conn->{rproc}}($conn, "$dir$call|$sort");
-       $conn->_send_file("$main::data/connected") unless $conn->{outgoing};
 }
 
+sub login
+{
+       return \&new_channel;
+}
 
+sub new_client {
+       my $server_conn = shift;
+    my $sock = $server_conn->{sock}->accept();
+       if ($sock) {
+               my $conn = $server_conn->new($server_conn->{rproc});
+               $conn->{sock} = $sock;
+               $conn->nolinger;
+               Msg::blocking($sock, 0);
+               $conn->{blocking} = 0;
+               eval {$conn->{peerhost} = $sock->peerhost};
+               if ($@) {
+                       dbg($@) if isdbg('connll');
+                       $conn->disconnect;
+               } else {
+                       eval {$conn->{peerport} = $sock->peerport};
+                       $conn->{peerport} = 0 if $@;
+                       my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost}, $conn->{peerport});
+                       dbg("accept $conn->{cnum} from $conn->{peerhost} $conn->{peerport}") if isdbg('connll');
+                       if ($eproc) {
+                               $conn->{eproc} = $eproc;
+                               Msg::set_event_handler ($sock, "error" => $eproc);
+                       }
+                       if ($rproc) {
+                               $conn->{rproc} = $rproc;
+                               my $callback = sub {$conn->_rcv};
+                               Msg::set_event_handler ($sock, "read" => $callback);
+                               $conn->_dotimeout(60);
+                               $conn->{echo} = 0;
+                       } else { 
+                               &{$conn->{eproc}}() if $conn->{eproc};
+                               $conn->disconnect();
+                       }
+                       Log('Aranea', "Incoming connection from $conn->{peerhost}");
+                       $conn->{outgoing} = 0;
+                       $conn->{state} = 'WH';          # wait for return authorize
+                       my $thing = $conn->{lastthing} = Thingy::Hello->new(origin=>$main::mycall, group=>'ROUTE');
+                       $thing->send($conn, 'Aranea');
+               }
+       } else {
+               dbg("ExtMsg: error on accept ($!)") if isdbg('err');
+       }
+}
+
+sub start_connect
+{
+       my $call = shift;
+       my $fn = shift;
+       my $conn = AMsg->new(\&new_channel); 
+       $conn->{outgoing} = 1;
+       $conn->conns($call);
+       
+       my $f = new IO::File $fn;
+       push @{$conn->{cmd}}, <$f>;
+       $f->close;
+       $conn->{state} = 'WC';
+       $conn->_dotimeout($deftimeout);
+       $conn->_docmd;
+}
+
+# 
+# happens next on receive 
+#
+
+sub new_channel
+{
+       my ($conn, $msg) = @_;
+       my $thing = Aranea::input($msg);
+       return unless defined $thing;
+
+       my $call = $thing->{origin};
+       unless (is_callsign($call)) {
+               main::already_conn($conn, $call, DXM::msg($main::lang, "illcall", $call));
+               return;
+       }
+
+       # set up the basic channel info
+       # is there one already connected to me - locally? 
+       my $user = DXUser->get_current($call);
+       my $dxchan = DXChannel->get($call);
+       if ($dxchan) {
+               if ($main::bumpexisting) {
+                       my $ip = $conn->{peerhost} || 'unknown';
+                       $dxchan->send_now('D', DXM::msg($main::lang, 'conbump', $call, $ip));
+                       Log('DXCommand', "$call bumped off by $ip, disconnected");
+                       dbg("$call bumped off by $ip, disconnected");
+                       $dxchan->disconnect;
+               } else {
+                       main::already_conn($conn, $call, DXM::msg($main::lang, 'conother', $call, $main::mycall));
+                       return;
+               }
+       }
+
+       # is he locked out ?
+       my $basecall = $call;
+       $basecall =~ s/-\d+$//;
+       my $baseuser = DXUser->get_current($basecall);
+       my $lock = $user->lockout if $user;
+       if ($baseuser && $baseuser->lockout || $lock) {
+               if (!$user || !defined $lock || $lock) {
+                       my $host = $conn->{peerhost} || "unknown";
+                       Log('DXCommand', "$call on $host is locked out, disconnected");
+                       $conn->disconnect;
+                       return;
+               }
+       }
+       
+       if ($user) {
+               $user->{lang} = $main::lang if !$user->{lang}; # to autoupdate old systems
+       } else {
+               $user = DXUser->new($call);
+       }
+       
+       # create the channel
+       $dxchan = Aranea->new($call, $conn, $user);
+
+       # check that the conn has a callsign
+       $conn->conns($call) if $conn->isa('IntMsg');
+
+       # set callbacks
+       $conn->set_error(sub {main::error_handler($dxchan)});
+       $conn->set_rproc(sub {my ($conn,$msg) = @_; $dxchan->rec($msg)});
+       $dxchan->rec($msg);
+}
+
+sub send
+{
+       my $conn = shift;
+       for (@_) {
+               $conn->send_later($_);
+       }
+}
diff --git a/perl/Aranea.pm b/perl/Aranea.pm
new file mode 100644 (file)
index 0000000..1d0a912
--- /dev/null
@@ -0,0 +1,232 @@
+#
+# The new protocol for real at last
+#
+# $Id$
+#
+# Copyright (c) 2005 Dirk Koopman G1TLH
+#
+
+package Aranea;
+
+use strict;
+
+use DXUtil;
+use DXChannel;
+use DXUser;
+use DXM;
+use DXLog;
+use DXDebug;
+use Filter;
+use Time::HiRes qw(gettimeofday tv_interval);
+use DXHash;
+use Route;
+use Route::Node;
+use Script;
+use Verify;
+use DXDupe;
+
+use vars qw($VERSION $BRANCH);
+$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
+$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/  || (0,0));
+$main::build += $VERSION;
+$main::branch += $BRANCH;
+
+use vars qw(@ISA $ntpflag $dupeage);
+
+@ISA = qw(DXChannel);
+
+$ntpflag = 0;                                  # should be set in startup if NTP in use
+$dupeage = 12*60*60;                   # duplicates stored half a day 
+
+my $seqno = 0;
+my $dayno = 0;
+
+sub init
+{
+
+}
+
+sub new
+{
+       my $self = DXChannel::alloc(@_);
+
+       # add this node to the table, the values get filled in later
+       my $pkg = shift;
+       my $call = shift;
+       $main::routeroot->add($call, '5000', Route::here(1)) if $call ne $main::mycall;
+       $self->{'sort'} = 'W';
+       return $self;
+}
+
+sub start
+{
+       my ($self, $line, $sort) = @_;
+       my $call = $self->{call};
+       my $user = $self->{user};
+
+       # log it
+       my $host = $self->{conn}->{peerhost} || "unknown";
+       Log('Aranea', "$call connected from $host");
+       
+       # remember type of connection
+       $self->{consort} = $line;
+       $self->{outbound} = $sort eq 'O';
+       my $priv = $user->priv;
+       $priv = $user->priv(1) unless $priv;
+       $self->{priv} = $priv;     # other clusters can always be 'normal' users
+       $self->{lang} = $user->lang || 'en';
+       $self->{consort} = $line;       # save the connection type
+       $self->{here} = 1;
+       $self->{width} = 80;
+
+       # sort out registration
+       $self->{registered} = 1;
+
+       # get the output filters
+       $self->{spotsfilter} = Filter::read_in('spots', $call, 0) || Filter::read_in('spots', 'node_default', 0);
+       $self->{wwvfilter} = Filter::read_in('wwv', $call, 0) || Filter::read_in('wwv', 'node_default', 0);
+       $self->{wcyfilter} = Filter::read_in('wcy', $call, 0) || Filter::read_in('wcy', 'node_default', 0);
+       $self->{annfilter} = Filter::read_in('ann', $call, 0) || Filter::read_in('ann', 'node_default', 0) ;
+       $self->{routefilter} = Filter::read_in('route', $call, 0) || Filter::read_in('route', 'node_default', 0) unless $self->{isolate} ;
+
+
+       # get the INPUT filters (these only pertain to Clusters)
+       $self->{inspotsfilter} = Filter::read_in('spots', $call, 1) || Filter::read_in('spots', 'node_default', 1);
+       $self->{inwwvfilter} = Filter::read_in('wwv', $call, 1) || Filter::read_in('wwv', 'node_default', 1);
+       $self->{inwcyfilter} = Filter::read_in('wcy', $call, 1) || Filter::read_in('wcy', 'node_default', 1);
+       $self->{inannfilter} = Filter::read_in('ann', $call, 1) || Filter::read_in('ann', 'node_default', 1);
+       $self->{inroutefilter} = Filter::read_in('route', $call, 1) || Filter::read_in('route', 'node_default', 1) unless $self->{isolate};
+       
+       $self->conn->echo(0) if $self->conn->can('echo');
+       
+       # ping neighbour node stuff
+       my $ping = $user->pingint;
+       $ping = $DXProt::pingint unless defined $ping;
+       $self->{pingint} = $ping;
+       $self->{nopings} = $user->nopings || $DXProt::obscount;
+       $self->{pingtime} = [ ];
+       $self->{pingave} = 999;
+       $self->{metric} ||= 100;
+       $self->{lastping} = $main::systime;
+       
+       $self->state('init');
+       $self->{pc50_t} = $main::systime;
+
+       # send info to all logged in thingies
+       $self->tell_login('loginn');
+
+       # run a script send the output to the debug file
+       my $script = new Script(lc $call) || new Script('node_default');
+       $script->run($self) if $script;
+       $self->send("Hello?");
+}
+
+#
+# This is the normal despatcher
+#
+sub normal
+{
+       my ($self, $line) = @_;
+
+       
+}
+
+#
+# periodic processing
+#
+
+sub process
+{
+
+       # calc day number
+       $dayno = (gmtime($main::systime))[3];
+}
+
+# 
+# generate new header (this is a general subroutine, not a method
+# because it has to be used before a channel is fully initialised).
+#
+
+sub genheader
+{
+       my $mycall = shift;
+       my $to = shift;
+       my $from = shift;
+       
+       my $date = ((($dayno << 1) | $ntpflag) << 18) |  ($main::systime % 86400);
+       my $r = "$mycall,$to," . sprintf('%06X%04X,0', $date, $seqno);
+       $r .= ",$from" if $from;
+       $seqno++;
+       $seqno = 0 if $seqno > 0x0ffff;
+       return $r;
+}
+
+# subroutines to encode and decode values in lists 
+sub tencode
+{
+       my $s = shift;
+       $s =~ s/([\%=|,\x00-\x1f\x7f-\xff])/sprintf("%%%02X", ord($1))/eg; 
+       return $s;
+}
+
+sub tdecode
+{
+       my $s = shift;
+       $s =~ s/\%([0-9A-F][0-9A-F])/chr(hex($1))/eg;
+       return $s;
+}
+
+sub genmsg
+{
+       my $thing = shift;
+       my $name = shift;
+       my $head = genheader($thing->{origin}, 
+                                                ($thing->{group} || $thing->{touser} || $thing->{tonode}),
+                                                ($thing->{user} || $thing->{fromuser} || $thing->{fromnode})
+                                               );
+       my $data = "$name,";
+       while (@_) {
+               my $k = lc shift;
+               my $v = tencode(shift);
+               $data .= "$k=$v,";
+       }
+       chop $data;
+       return "$head|$data";
+}
+
+sub input
+{
+       my $line = shift;
+       my ($head, $data) = split /\|/, $line, 2;
+       return unless $head && $data;
+       my ($origin, $group, $dts, $hop, $user) = split /,/, $head;
+       return if DXDupe::add("Ara,$origin,$dts", $dupeage);
+       $hop++;
+       my ($cmd, $rdata) = split /,/, $data, 2;
+       my $class = 'Thingy::' . ucfirst $cmd;
+       my $thing;
+       
+       # create the appropriate Thingy
+       if (defined *$class) {
+               $thing = $class->new();
+
+               # reconstitute the header but wth hop increased by one
+               $head = join(',', $origin, $group, $dts, $hop);
+               $head .= ",$user" if $user;
+               $thing->{Aranea} = "$head|$data";
+
+               # store useful data
+               $thing->{origin} = $origin;
+               $thing->{group} = $group;
+               $thing->{time} = decode_dts($dts);
+               $thing->{user} = $user if $user;
+               $thing->{hopsaway} = $hop; 
+               
+               while (my ($k,$v) = split /,/, $rdata) {
+                       $thing->{$k} = tdecode($v);
+               }
+       }
+       return $thing;
+}
+
+1;
index ca3afd6f1277bcc617e5d4a4321d5d1d16f12f25..acd4245c6cddebd8edcfd2aa6ccffd6a5c2beaab 100644 (file)
@@ -117,6 +117,7 @@ $count = 0;
                  ve7cc => '0,VE7CC program special,yesno',
                  lastmsgpoll => '0,Last Msg Poll,atime',
                  inscript => '9,In a script,yesno',
+                 inqueue => '9,Input Queue,parray',
                 );
 
 use vars qw($VERSION $BRANCH);
@@ -168,6 +169,7 @@ sub alloc
                $self->{itu} = $dxcc[1]->itu;
                $self->{cq} = $dxcc[1]->cq;                                             
        }
+       $self->{inqueue} = [];
 
        $count++;
        dbg("DXChannel $self->{call} created ($count)") if isdbg('chan');
@@ -175,6 +177,16 @@ sub alloc
        return $channels{$call} = $self;
 }
 
+sub rec        
+{
+       my ($self, $msg) = @_;
+       
+       # queue the message and the channel object for later processing
+       if (defined $msg) {
+               push @{$self->{inqueue}}, $msg;
+       }
+}
+
 # obtain a channel object by callsign [$obj = DXChannel->get($call)]
 sub get
 {
@@ -185,7 +197,6 @@ sub get
 # obtain all the channel objects
 sub get_all
 {
-       my ($pkg) = @_;
        return values(%channels);
 }
 
@@ -255,7 +266,7 @@ sub is_bbs
 sub is_node
 {
        my $self = shift;
-       return $self->{'sort'} =~ /[ACRSX]/;
+       return $self->{'sort'} =~ /[ACRSXW]/;
 }
 # is it an ak1a node ?
 sub is_ak1a
@@ -278,6 +289,13 @@ sub is_clx
        return $self->{'sort'} eq 'C';
 }
 
+# it is Aranea
+sub is_aranea
+{
+       my $self = shift;
+       return $self->{'sort'} eq 'W';
+}
+
 # is it a spider node
 sub is_spider
 {
@@ -439,7 +457,6 @@ sub disconnect
        my $self = shift;
        my $user = $self->{user};
        
-       main::clean_inqueue($self);          # clear out any remaining incoming frames
        $user->close() if defined $user;
        $self->{conn}->disconnect;
        $self->del();
@@ -551,7 +568,7 @@ sub broadcast_nodes
 {
        my $s = shift;                          # the line to be rebroadcast
        my @except = @_;                        # to all channels EXCEPT these (dxchannel refs)
-       my @dxchan = DXChannel::get_all_nodes();
+       my @dxchan = get_all_nodes();
        my $dxchan;
        
        # send it if it isn't the except list and isn't isolated and still has a hop count
@@ -571,7 +588,7 @@ sub broadcast_all_nodes
 {
        my $s = shift;                          # the line to be rebroadcast
        my @except = @_;                        # to all channels EXCEPT these (dxchannel refs)
-       my @dxchan = DXChannel::get_all_nodes();
+       my @dxchan = get_all_nodes();
        my $dxchan;
        
        # send it if it isn't the except list and isn't isolated and still has a hop count
@@ -592,7 +609,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 = DXChannel::get_all_users();
+       my @dxchan = get_all_users();
        my $dxchan;
        my @out;
        
@@ -636,6 +653,42 @@ sub broadcast_list
        }
 }
 
+sub process
+{
+       foreach my $dxchan (get_all()) {
+
+               while (my $data = shift @{$dxchan->{inqueue}}) {
+                       my ($sort, $call, $line) = $dxchan->decode_input($data);
+                       next unless defined $sort;
+
+                       # do the really sexy console interface bit! (Who is going to do the TK interface then?)
+                       dbg("<- $sort $call $line") if $sort ne 'D' && isdbg('chan');
+                       if ($dxchan->{disconnecting}) {
+                               dbg('In disconnection, ignored');
+                               next;
+                       }
+
+                       # handle A records
+                       my $user = $dxchan->user;
+                       if ($sort eq 'A' || $sort eq 'O') {
+                               $dxchan->start($line, $sort);
+                       } elsif ($sort eq 'I') {
+                               die "\$user not defined for $call" if !defined $user;
+                       
+                               # normal input
+                               $dxchan->normal($line);
+                       } elsif ($sort eq 'Z') {
+                               $dxchan->disconnect;
+                       } elsif ($sort eq 'D') {
+                               ;                               # ignored (an echo)
+                       } elsif ($sort eq 'G') {
+                               $dxchan->enhanced($line);
+                       } else {
+                               print STDERR atime, " Unknown command letter ($sort) received from $call\n";
+                       }
+               }
+       }
+}
 
 #no strict;
 sub AUTOLOAD
index 48410eb2ffb50082c87320193086e67b9237dea6..5e324fa47f2af7656ebbff28e7fbcccadb834557 100644 (file)
@@ -48,7 +48,7 @@ $main::branch += $BRANCH;
 use vars qw($pc11_max_age $pc23_max_age $last_pc50 $eph_restime $eph_info_restime $eph_pc34_restime
                        $last_hour $last10 %eph  %pings %rcmds $ann_to_talk
                        $pingint $obscount %pc19list $chatdupeage $chatimportfn
-                       $investigation_int $pc19_version 
+                       $investigation_int $pc19_version $myprot_version
                        %nodehops $baddx $badspotter $badnode $censorpc $rspfcheck
                        $allowzero $decode_dk0wcy $send_opernam @checklist);
 
@@ -206,6 +206,21 @@ sub init
 {
        do "$main::data/hop_table.pl" if -e "$main::data/hop_table.pl";
        confess $@ if $@;
+
+       my $user = DXUser->get($main::mycall);
+       die "User $main::mycall not setup or disappeared RTFM" unless $user;
+       
+       $myprot_version += $main::version*100;
+       $main::me = DXProt->new($main::mycall, 0, $user); 
+       $main::me->{here} = 1;
+       $main::me->{state} = "indifferent";
+       $main::me->{sort} = 'S';    # S for spider
+       $main::me->{priv} = 9;
+       $main::me->{metric} = 0;
+       $main::me->{pingave} = 0;
+       $main::me->{registered} = 1;
+       $main::me->{version} = $main::version;
+       $main::me->{build} = $main::build;
 }
 
 #
index f1472789152fbfc3836142577d8831e86a4b591e..133a1513acdef46cba5bb2cefc808f601e104716 100644 (file)
@@ -32,6 +32,11 @@ use vars qw(@ISA $deftimeout);
 @ISA = qw(Msg);
 $deftimeout = 60;
 
+sub login
+{
+       goto &main::login;        # save some writing, this was the default
+}
+
 sub enqueue
 {
        my ($conn, $msg) = @_;
index a940347d311366227a069b07e1d03ad9b79f0f28..0318c2b3bddb3a26b3f0525573f102c246132d58 100644 (file)
@@ -23,6 +23,11 @@ use vars qw(@ISA);
 
 @ISA = qw(Msg);
 
+sub login
+{
+       goto &main::login;        # save some writing, this was the default
+}
+
 sub enqueue
 {
        my ($conn, $msg) = @_;
index 885e7f0f5f4c0dc1a210a449390b5025978d7c87..2483d2732705a8f566ae359ca86fd8a194d98167 100644 (file)
@@ -8,6 +8,8 @@
 # Copyright (c) 2004 Dirk Koopman G1TLH
 #
 
+use strict;
+
 package Thingy;
 
 use vars qw($VERSION $BRANCH);
@@ -16,36 +18,43 @@ $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/  || (0,0))
 $main::build += $VERSION;
 $main::branch += $BRANCH;
 
-
 use DXChannel;
 use DXDebug;
 
-use vars qw(@queue);
-@queue = ();                                   # the thingy queue
-
 # we expect all thingies to be subclassed
 sub new
 {
        my $class = shift;
-       my $self = {@_};
+       my $thing = {@_};
        
-       bless $self, $class;
-       return $self;
+       bless $thing, $class;
+       return $thing;
 }
 
-# add the Thingy to the queue
-sub add
+# send it out in the format asked for, if available
+sub send
 {
-       push @queue, shift;
+       my $thing = shift;
+       my $chan = shift;
+       my $class;
+       if (@_) {
+               $class = shift;
+       } elsif ($chan->isa('DXChannel')) {
+               $class = ref $chan;
+       }
+
+       # generate the line which may (or not) be cached
+       my @out;
+       if (my $ref = $thing->{class}) {
+               push @out, ref $ref ? @$ref : $ref;
+       } else {
+               no strict 'refs';
+               my $sub = "gen_$class";
+               push @out, $thing->$sub if $thing->can($sub);
+       }
+       $chan->send(@out) if @out;
 }
 
-# dispatch Thingies to action it.
-sub process
-{
-       my $t = pop @queue if @queue;
-
-       $t->process if $t;
-}
 
 1;
 
diff --git a/perl/Thingy/Hello.pm b/perl/Thingy/Hello.pm
new file mode 100644 (file)
index 0000000..111abf8
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# Hello Thingy handling
+#
+# $Id$
+#
+# Copyright (c) 2005 Dirk Koopman G1TLH
+#
+
+use strict;
+
+package Thingy::Hello;
+
+use vars qw($VERSION $BRANCH);
+$VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
+$BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/  || (0,0));
+$main::build += $VERSION;
+$main::branch += $BRANCH;
+
+use DXChannel;
+use DXDebug;
+use Verify;
+use Thingy;
+
+use vars qw(@ISA);
+@ISA = qw(Thingy);
+
+sub gen_Aranea
+{
+       my $thing = shift;
+       unless ($thing->{Aranea}) {
+               my $auth = $thing->{auth} = Verify->new($main::mycall, $main::systime);
+               $thing->{Aranea} = Aranea::genmsg($thing, 'HELLO', sw=>'DXSpider',
+                                                                                 v=>$main::version,
+                                                                                 b=>$main::build,
+                                                                                 auth=>$auth->challenge($main::me->user->passphrase)
+                                                                         );
+       }
+       return $thing->{Aranea};
+}
+
+sub from_Aranea
+{
+       my $line = shift;
+       my $thing = Aranea::input($line);
+       return unless $thing;
+}
+1;
index 58694eb5d1e7be6837ea21c90bf098357830b884..5e0fffe1d7e38e3a38927d23caf5f09b262b5a1d 100644 (file)
@@ -7,16 +7,14 @@
 # $Id$
 # 
 
+use strict;
+
 package Verify;
 
-use DXChannel;
 use DXUtil;
 use DXDebug;
-use Time::HiRes qw(gettimeofday);
 use Digest::SHA1 qw(sha1_base64);
 
-use strict;
-
 use vars qw($VERSION $BRANCH);
 $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
 $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/  || (0,0));
@@ -27,35 +25,48 @@ sub new
 {
        my $class = shift;
        my $self = bless {}, ref($class) || $class; 
-       $self->{seed} = shift if @_;
+       if (@_) {
+               $self->newseed(@_);
+               $self->newsalt;
+       }
        return $self;
 }
 
-sub challenge
+sub newseed
 {
        my $self = shift;
-       my @t = gettimeofday();
-       my $r = unpack("xxNxx", pack("d", rand));
-       @t = map {$_ ^ $r} @t;
-       dbg("challenge r: $r seed: $t[0] $t[1]" ) if isdbg('verify');
-       $r = unpack("xxNxx", pack("d", rand));
-       @t = map {$_ ^ $r} @t;
-       dbg("challenge r: $r seed: $t[0] $t[1]" ) if isdbg('verify');
-       return $self->{seed} = sha1_base64(@t, gettimeofday, rand, rand, rand, @_);
+       return $self->{seed} = sha1_base64('RbG4tST2dYPWnh6bfAaq7pPSL04', @_);
 }
 
-sub response
+sub newsalt
 {
        my $self = shift;
-       return sha1_base64($self->{seed}, @_);
+       return $self->{salt} = substr sha1_base64($self->{seed}, rand, rand, rand), 0, 6;
+}
+
+sub challenge
+{
+       my $self = shift;
+       return $self->{salt} . sha1_base64($self->{salt}, $self->{seed}, @_);
 }
 
 sub verify
 {
        my $self = shift;
        my $answer = shift;
-       my $p = sha1_base64($self->{seed}, @_);
+       my $p = sha1_base64($self->{salt}, $self->{seed}, @_);
        return $p eq $answer;
 }
 
+sub seed
+{
+       my $self = shift;
+       return @_ ? $self->{seed} = shift : $self->{seed};
+}
+
+sub salt
+{
+       my $self = shift;
+       return @_ ? $self->{salt} = shift : $self->{salt};
+}
 1;
index 20726684de2c7bbbd8f77d583dbe654a41e6d470..1448ba9180a73748bf3faaa48cd131e47e884182 100755 (executable)
@@ -68,7 +68,7 @@ use DXCommandmode;
 use DXProtVars;
 use DXProtout;
 use DXProt;
-use QXProt;
+use Aranea;
 use DXMsg;
 use DXCron;
 use DXConnect;
@@ -226,29 +226,10 @@ sub new_channel
 
        # set callbacks
        $conn->set_error(sub {error_handler($dxchan)});
-       $conn->set_rproc(sub {my ($conn,$msg) = @_; rec($dxchan, $conn, $msg);});
-       rec($dxchan, $conn, $msg);
+       $conn->set_rproc(sub {my ($conn,$msg) = @_; $dxchan->rec($msg);});
+       $dxchan->rec($msg);
 }
 
-sub rec        
-{
-       my ($dxchan, $conn, $msg) = @_;
-       
-       # queue the message and the channel object for later processing
-       if (defined $msg) {
-               my $self = bless {}, "inqueue";
-               $self->{dxchan} = $dxchan;
-               $self->{data} = $msg;
-               push @inqueue, $self;
-       }
-}
-
-# remove any outstanding entries on the inqueue after a disconnection (usually)
-sub clean_inqueue
-{
-       my $dxchan = shift;
-       @inqueue = grep {$_->{dxchan} != $dxchan} @inqueue;
-}
 
 sub login
 {
@@ -325,45 +306,6 @@ sub reap
 
 # this is where the input queue is dealt with and things are dispatched off to other parts of
 # the cluster
-sub process_inqueue
-{
-       while (@inqueue) {
-               my $self = shift @inqueue;
-               return if !$self;
-
-               my $data = $self->{data};
-               my $dxchan = $self->{dxchan};
-               my $error;
-               my ($sort, $call, $line) = DXChannel::decode_input($dxchan, $data);
-               return unless defined $sort;
-       
-               # do the really sexy console interface bit! (Who is going to do the TK interface then?)
-               dbg("<- $sort $call $line") if $sort ne 'D' && isdbg('chan');
-               if ($self->{disconnecting}) {
-                       dbg('In disconnection, ignored');
-                       next;
-               }
-               
-               # handle A records
-               my $user = $dxchan->user;
-               if ($sort eq 'A' || $sort eq 'O') {
-                       $dxchan->start($line, $sort);  
-               } elsif ($sort eq 'I') {
-                       die "\$user not defined for $call" if !defined $user;
-
-                       # normal input
-                       $dxchan->normal($line);
-               } elsif ($sort eq 'Z') {
-                       $dxchan->disconnect;
-               } elsif ($sort eq 'D') {
-                       ;                                       # ignored (an echo)
-               } elsif ($sort eq 'G') {
-                       $dxchan->enhanced($line);
-               } else {
-                       print STDERR atime, " Unknown command letter ($sort) received from $call\n";
-               }
-       }
-}
 
 sub uptime
 {
@@ -438,10 +380,12 @@ dbg("Internal port: $clusteraddr $clusterport using IntMsg");
 foreach my $l (@main::listen) {
        no strict 'refs';
        my $pkg = $l->[2] || 'ExtMsg';
-       $conn = $pkg->new_server($l->[0], $l->[1], \&login);
-       $conn->conns("Server $l->[0]/$l->[1] using $pkg");
+       my $login = $l->[3] || 'login'; 
+       
+       $conn = $pkg->new_server($l->[0], $l->[1], \&{"${pkg}::${login}"});
+       $conn->conns("Server $l->[0]/$l->[1] using ${pkg}::${login}");
        push @listeners, $conn;
-       dbg("External Port: $l->[0] $l->[1] using $pkg");
+       dbg("External Port: $l->[0] $l->[1] using ${pkg}::${login}");
 }
 
 dbg("AGW Listener") if $AGWMsg::enable;
@@ -501,7 +445,7 @@ Spot->init();
 # initialise the protocol engine
 dbg("Start Protocol Engines ...");
 DXProt->init();
-QXProt->init();
+Aranea->init();
 
 # put in a DXCluster node for us here so we can add users and take them away
 $routeroot = Route::Node->new($mycall, $version*100+5300, Route::here($main::me->here)|Route::conf($main::me->conf));
@@ -545,7 +489,9 @@ for (;;) {
        
        Msg->event_loop(10, 0.010);
        my $timenow = time;
-       process_inqueue();                      # read in lines from the input queue and despatch them
+
+       DXChannel::process();
+       
 #      $DB::trace = 0;
        
        # do timed stuff, ongoing processing happens one a second
@@ -555,7 +501,7 @@ for (;;) {
                DXCron::process();      # do cron jobs
                DXCommandmode::process(); # process ongoing command mode stuff
                DXProt::process();              # process ongoing ak1a pcxx stuff
-               QXProt::process();
+               Aranea::process();
                DXConnect::process();
                DXMsg::process();
                DXDb::process();
@@ -563,9 +509,6 @@ for (;;) {
                DXDupe::process();
                AGWMsg::process();
 
-               # this where things really start to happen (in DXSpider 2)
-               Thingy::process();
-               
                eval { 
                        Local::process();       # do any localised processing
                };