3 # A thing that implements dxcluster 'protocol'
5 # This is a perl module/program that sits on the end of a dxcluster
6 # 'protocol' connection and deals with anything that might come along.
8 # this program is called by ax25d and gets raw ax25 text on its input
10 # Copyright (c) 1998 Dirk Koopman G1TLH
26 @inqueue = (); # the main input queue, an array of hashes
27 $systime = 0; # the time now (in seconds)
29 # handle disconnections
33 return if !defined $dxchan;
34 my $user = $dxchan->{user};
35 my $conn = $dxchan->{conn};
36 if ($user->{sort} eq 'A') { # and here (when I find out how to write it!)
39 $dxchan->user_finish();
41 $user->close() if defined $user;
42 $conn->disconnect() if defined $conn;
46 # handle incoming messages
49 my ($conn, $msg, $err) = @_;
50 my $dxchan = DXChannel->get_by_cnum($conn); # get the dxconnnect object for this message
52 if (defined $err && $err) {
53 disconnect($dxchan) if defined $dxchan;
57 # set up the basic channel info - this needs a bit more thought - there is duplication here
58 if (!defined $dxchan) {
59 my ($sort, $call, $line) = $msg =~ /^(\w)(\S+)\|(.*)$/;
60 my $user = DXUser->get($call);
61 $user = DXUser->new($call) if !defined $user;
62 $dxchan = DXChannel->new($call, $conn, $user);
65 # queue the message and the channel object for later processing
67 my $self = bless {}, "inqueue";
68 $self->{dxchan} = $dxchan;
79 # cease running this program, close down all the connections nicely
83 foreach $dxchan (DXChannel->get_all()) {
89 # this is where the input queue is dealt with and things are dispatched off to other parts of
93 my $self = shift @inqueue;
96 my $data = $self->{data};
97 my $dxchan = $self->{dxchan};
98 my ($sort, $call, $line) = $data =~ /^(\w)(\S+)\|(.*)$/;
100 # do the really sexy console interface bit! (Who is going to do the TK interface then?)
101 print DEBUG atime, " < $sort $call $line\n" if defined DEBUG;
102 print "< $sort $call $line\n";
105 my $user = $dxchan->{user};
107 $user->{sort} = 'U' if !defined $user->{sort};
108 if ($user->{sort} eq 'A') {
109 $dxchan->pc_start($line);
111 $dxchan->user_start($line);
113 } elsif ($sort eq 'D') {
114 die "\$user not defined for $call" if !defined $user;
115 if ($user->{sort} eq 'A') { # we will have a symbolic ref to a proc here
116 $dxchan->pc_normal($line);
118 $dxchan->user_normal($line);
120 } elsif ($sort eq 'Z') {
123 print STDERR atime, " Unknown command letter ($sort) received from $call\n";
127 #############################################################
129 # The start of the main line of code
131 #############################################################
133 # open the debug file, set various FHs to be unbuffered
134 open(DEBUG, ">>$debugfn") or die "can't open $debugfn($!)";
135 select DEBUG; $| = 1;
136 select STDOUT; $| = 1;
138 # initialise User file system
139 DXUser->init($userfn);
141 # start listening for incoming messages/connects
142 Msg->new_server("$clusteraddr", $clusterport, \&login);
145 $SIG{'INT'} = \&cease;
146 $SIG{'TERM'} = \&cease;
147 $SIG{'HUP'} = 'IGNORE';
149 # this, such as it is, is the main loop!
152 Msg->event_loop(1, 0.001);
154 if ($timenow != $systime) {
159 process_inqueue(); # read in lines from the input queue and despatch them
160 DXCommandmode::user_process(); # process ongoing command mode stuff
161 DXProt::pc_process(); # process ongoing ak1a pcxx stuff