2 # This class implements the new style comms for Aranea
3 # communications for Msg.pm
7 # Copyright (c) 2005 - Dirk Koopman G1TLH
24 use vars qw($VERSION $BRANCH);
25 $VERSION = sprintf( "%d.%03d", q$Revision$ =~ /(\d+)\.(\d+)/ );
26 $BRANCH = sprintf( "%d.%03d", q$Revision$ =~ /\d+\.\d+\.(\d+)\.(\d+)/ || (0,0));
27 $main::build += $VERSION;
28 $main::branch += $BRANCH;
30 use vars qw(@ISA $deftimeout);
32 @ISA = qw(ExtMsg Msg);
37 my ($conn, $msg) = @_;
38 push (@{$conn->{outqueue}}, $msg . $conn->{lineend});
46 if ($conn->{csort} eq 'ax25' && exists $conn->{msg}) {
47 $conn->{msg} =~ s/\cM/\cJ/g;
49 if ($conn->{state} eq 'WC' ) {
50 if (exists $conn->{cmd}) {
51 if (@{$conn->{cmd}}) {
52 dbg("connect $conn->{cnum}: $conn->{msg}") if isdbg('connect');
53 $conn->_docmd($conn->{msg});
56 if ($conn->{state} eq 'WC' && exists $conn->{cmd} && @{$conn->{cmd}} == 0) {
57 $conn->{state} = 'WH';
59 } elsif ($conn->{msg} =~ /\cJ/) {
60 my @lines = $conn->{msg} =~ /([^\cM\cJ]*)\cM?\cJ/g;
61 if ($conn->{msg} =~ /\cJ$/) {
64 $conn->{msg} =~ s/([^\cM\cJ]*)\cM?\cJ//g;
66 while (defined ($msg = shift @lines)) {
67 dbg("connect $conn->{cnum}: $msg") if $conn->{state} ne 'C' && isdbg('connect');
68 if ($conn->{state} eq 'C') {
69 &{$conn->{rproc}}($conn, $msg);
70 } elsif ($conn->{state} eq 'WH' ) {
71 # this is the first stage that we have a callsign
74 if ($msg =~ m{RT,[0-9A-F,]+|HELLO}) {
75 # a possibly valid HELLO line, process it
76 $conn->new_channel($msg);
78 } elsif ($conn->{state} eq 'WC') {
79 if (exists $conn->{cmd} && @{$conn->{cmd}}) {
81 if ($conn->{state} eq 'WC' && exists $conn->{cmd} && @{$conn->{cmd}} == 0) {
82 $conn->{state} = 'WH';
96 my $server_conn = shift;
97 my $sock = $server_conn->{sock}->accept();
99 my $conn = $server_conn->new($server_conn->{rproc});
100 $conn->{sock} = $sock;
102 Msg::blocking($sock, 0);
103 $conn->{blocking} = 0;
104 eval {$conn->{peerhost} = $sock->peerhost};
106 dbg($@) if isdbg('connll');
109 eval {$conn->{peerport} = $sock->peerport};
110 $conn->{peerport} = 0 if $@;
111 my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost}, $conn->{peerport});
112 dbg("accept $conn->{cnum} from $conn->{peerhost} $conn->{peerport}") if isdbg('connll');
114 $conn->{eproc} = $eproc;
115 Msg::set_event_handler ($sock, "error" => $eproc);
118 $conn->{rproc} = $rproc;
119 my $callback = sub {$conn->_rcv};
120 Msg::set_event_handler ($sock, "read" => $callback);
121 $conn->_dotimeout(60);
124 &{$conn->{eproc}}() if $conn->{eproc};
127 Log('Aranea', "Incoming connection from $conn->{peerhost}");
128 $conn->{outbound} = 0;
129 $conn->{state} = 'WH'; # wait for return authorize
130 my $thing = $conn->{lastthing} = Thingy::Hello->new();
132 $thing->send($conn, 'Aranea');
133 dbg("-> D $conn->{peerhost} $thing->{Aranea}") if isdbg('chan');
136 dbg("ExtMsg: error on accept ($!)") if isdbg('err');
140 sub set_newchannel_rproc
143 $conn->{rproc} = \&new_channel;
144 $conn->{state} = 'WH';
148 # happens next on receive
153 my ($conn, $msg) = @_;
154 my $call = $conn->{call} || $conn->{peerhost};
156 dbg("<- I $call $msg") if isdbg('chan');
158 my $thing = Aranea::input($msg);
160 dbg("Invalid thingy: $msg from $conn->{peerhost}");
161 $conn->send_now("Sorry");
166 $call = $thing->{origin};
167 unless (is_callsign($call)) {
168 main::already_conn($conn, $call, DXM::msg($main::lang, "illcall", $call));
172 # set up the basic channel info
173 # is there one already connected to me - locally?
174 my $user = DXUser->get_current($call);
175 my $dxchan = DXChannel->get($call);
177 if ($main::bumpexisting && $call ne $main::mycall) {
178 my $ip = $conn->{peerhost} || 'unknown';
179 $dxchan->send_now('D', DXM::msg($main::lang, 'conbump', $call, $ip));
180 Log('DXCommand', "$call bumped off by $ip, disconnected");
181 dbg("$call bumped off by $ip, disconnected");
184 main::already_conn($conn, $call, DXM::msg($main::lang, 'conother', $call, $main::mycall));
190 my $basecall = $call;
191 $basecall =~ s/-\d+$//;
192 my $baseuser = DXUser->get_current($basecall);
193 my $lock = $user->lockout if $user;
194 if ($baseuser && $baseuser->lockout || $lock) {
195 if (!$user || !defined $lock || $lock) {
196 my $host = $conn->{peerhost} || "unknown";
197 Log('DXCommand', "$call on $host is locked out, disconnected");
204 $user->{lang} = $main::lang if !$user->{lang}; # to autoupdate old systems
206 $user = DXUser->new($call);
210 $dxchan = Aranea->new($call, $conn, $user);
212 # check that the conn has a callsign
216 $conn->set_error(sub {main::error_handler($dxchan)});
217 $conn->set_rproc(sub {my ($conn,$msg) = @_; $dxchan->rec($msg)});
218 $conn->{state} = 'C';
220 $conn->{timeout}->del if $conn->{timeout};
221 delete $conn->{timeout};
223 $thing->handle($dxchan);
230 $conn->send_later($_);