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);
26 main::mkver($VERSION = q$Revision$);
28 use vars qw(@ISA $deftimeout);
30 @ISA = qw(ExtMsg Msg);
35 my ($conn, $msg) = @_;
36 push (@{$conn->{outqueue}}, $msg . $conn->{lineend});
44 if ($conn->{csort} eq 'ax25' && exists $conn->{msg}) {
45 $conn->{msg} =~ s/\cM/\cJ/g;
47 if ($conn->{state} eq 'WC' ) {
48 if (exists $conn->{cmd}) {
49 if (@{$conn->{cmd}}) {
50 dbg("connect $conn->{cnum}: $conn->{msg}") if isdbg('connect');
51 $conn->_docmd($conn->{msg});
54 if ($conn->{state} eq 'WC' && exists $conn->{cmd} && @{$conn->{cmd}} == 0) {
55 $conn->{state} = 'WH';
57 } elsif ($conn->{msg} =~ /\cJ/) {
58 my @lines = $conn->{msg} =~ /([^\cM\cJ]*)\cM?\cJ/g;
59 if ($conn->{msg} =~ /\cJ$/) {
62 $conn->{msg} =~ s/([^\cM\cJ]*)\cM?\cJ//g;
64 while (defined ($msg = shift @lines)) {
65 dbg("connect $conn->{cnum}: $msg") if $conn->{state} ne 'C' && isdbg('connect');
66 if ($conn->{state} eq 'C') {
67 &{$conn->{rproc}}($conn, $msg);
68 } elsif ($conn->{state} eq 'WH' ) {
69 # this is the first stage that we have a callsign
72 if ($msg =~ m{|HELLO,}) {
73 # a possibly valid HELLO line, process it
74 $conn->new_channel($msg);
76 } elsif ($conn->{state} eq 'WC') {
77 if (exists $conn->{cmd} && @{$conn->{cmd}}) {
79 if ($conn->{state} eq 'WC' && exists $conn->{cmd} && @{$conn->{cmd}} == 0) {
80 $conn->{state} = 'WH';
94 my $server_conn = shift;
95 my $sock = $server_conn->{sock}->accept();
97 my $conn = $server_conn->new($server_conn->{rproc});
98 $conn->{sock} = $sock;
100 Msg::blocking($sock, 0);
101 $conn->{blocking} = 0;
102 eval {$conn->{peerhost} = $sock->peerhost};
104 dbg($@) if isdbg('connll');
107 eval {$conn->{peerport} = $sock->peerport};
108 $conn->{peerport} = 0 if $@;
109 my ($rproc, $eproc) = &{$server_conn->{rproc}} ($conn, $conn->{peerhost}, $conn->{peerport});
110 dbg("accept $conn->{cnum} from $conn->{peerhost} $conn->{peerport}") if isdbg('connll');
112 $conn->{eproc} = $eproc;
113 Msg::set_event_handler ($sock, "error" => $eproc);
116 $conn->{rproc} = $rproc;
117 my $callback = sub {$conn->_rcv};
118 Msg::set_event_handler ($sock, "read" => $callback);
119 $conn->_dotimeout(60);
122 &{$conn->{eproc}}() if $conn->{eproc};
125 Log('Aranea', "Incoming connection from $conn->{peerhost}");
126 $conn->{outbound} = 0;
127 $conn->{state} = 'WH'; # wait for return authorize
128 my $thing = $conn->{lastthing} = Thingy::Hello->new();
130 $thing->send($conn, 'Aranea');
131 dbg("-> D $conn->{peerhost} $thing->{Aranea}") if isdbg('chan');
134 dbg("ExtMsg: error on accept ($!)") if isdbg('err');
138 sub set_newchannel_rproc
141 $conn->{rproc} = \&new_channel;
142 $conn->{state} = 'WH';
146 # happens next on receive
151 my ($conn, $msg) = @_;
152 my $call = $conn->{call} || $conn->{peerhost};
154 dbg("<- I $call $msg") if isdbg('chan');
156 my $thing = Aranea::input($msg);
158 dbg("Invalid thingy: $msg from $conn->{peerhost}");
159 $conn->send_now("Sorry");
164 $call = $thing->{origin};
165 unless (is_callsign($call)) {
166 main::already_conn($conn, $call, DXM::msg($main::lang, "illcall", $call));
170 # set up the basic channel info
171 # is there one already connected to me - locally?
172 my $user = DXUser->get_current($call);
173 my $dxchan = DXChannel->get($call);
175 if ($main::bumpexisting && $call ne $main::mycall) {
176 my $ip = $conn->{peerhost} || 'unknown';
177 $dxchan->send_now('D', DXM::msg($main::lang, 'conbump', $call, $ip));
178 Log('DXCommand', "$call bumped off by $ip, disconnected");
179 dbg("$call bumped off by $ip, disconnected");
182 main::already_conn($conn, $call, DXM::msg($main::lang, 'conother', $call, $main::mycall));
188 my $basecall = $call;
189 $basecall =~ s/-\d+$//;
190 my $baseuser = DXUser->get_current($basecall);
191 my $lock = $user->lockout if $user;
192 if ($baseuser && $baseuser->lockout || $lock) {
193 if (!$user || !defined $lock || $lock) {
194 my $host = $conn->{peerhost} || "unknown";
195 Log('DXCommand', "$call on $host is locked out, disconnected");
202 $user->{lang} = $main::lang if !$user->{lang}; # to autoupdate old systems
204 $user = DXUser->new($call);
208 $dxchan = Aranea->new($call, $conn, $user);
210 # check that the conn has a callsign
214 $conn->set_error(sub {main::error_handler($dxchan)});
215 $conn->set_rproc(sub {my ($conn,$msg) = @_; $dxchan->rec($msg)});
216 $conn->{state} = 'C';
218 $conn->{timeout}->del if $conn->{timeout};
219 delete $conn->{timeout};
221 $thing->handle($dxchan);
228 $conn->send_later($_);