X-Git-Url: http://dxcluster.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=perl%2Fclient.pl;h=ddf3fd3ba6adba52f6ed6f19ccab464d613dbd05;hb=dc016a0633cdb15d29b9a71fdec2c230fbad201b;hp=a7185ab208de387c0a58df593ca3c4597e2a5151;hpb=de6161942af879983173417d630b6327b50a423a;p=spider.git diff --git a/perl/client.pl b/perl/client.pl index a7185ab2..ddf3fd3b 100755 --- a/perl/client.pl +++ b/perl/client.pl @@ -41,19 +41,20 @@ BEGIN { use Msg; use DXVars; use DXDebug; -use Net::Telnet qw(TELOPT_ECHO); +use DXUtil; +use Net::Telnet qw(TELOPT_ECHO TELOPT_BINARY); use IO::File; use IO::Socket; use IPC::Open2; -use Carp qw{cluck}; # cease communications sub cease { my $sendz = shift; - if ($conn && $sendz) { - $conn->send_now("Z$call|bye...\n"); - } +# if ($conn && $sendz) { +# $conn->send_now("Z$call|bye..."); +# sleep(1); +# } $stdout->flush if $stdout; if ($pid) { dbg('connect', "killing $pid"); @@ -62,6 +63,9 @@ sub cease dbgclose(); # $SIG{__WARN__} = sub {my $a = shift; cluck($a); }; sleep(1); + + # do we need this ? + $conn->disconnect if $conn; exit(0); } @@ -84,10 +88,13 @@ sub setmode { if ($mode == 1) { $mynl = "\r"; + $out_lineend = "\r"; } else { $mynl = "\n"; + $out_lineend = "\r\n"; } $/ = $mynl; + $out_lineend = $mynl; } # handle incoming messages @@ -95,15 +102,17 @@ sub rec_socket { my ($con, $msg, $err) = @_; if (defined $err && $err) { - cease(1); + cease(0); } if (defined $msg) { - my ($sort, $call, $line) = $msg =~ /^(\w)([A-Z0-9\-]+)\|(.*)$/; + my ($sort, $call, $line) = $msg =~ /^(\w)([^\|]+)\|(.*)$/; if ($sort eq 'D') { my $snl = $mynl; my $newsavenl = ""; $snl = "" if $mode == 0; + $snl = "\r\n" if $mode == 3; + $snl = "\n" if $mode == 2; if ($mode == 2 && $line =~ />$/) { $newsavenl = $snl; $snl = ' '; @@ -113,6 +122,8 @@ sub rec_socket if ($buffered) { if (length $outqueue >= $client_buffer_lth) { print $stdout $outqueue; + pop @echo while (@echo > $maxecho); + push @echo, $outqueue; $outqueue = ""; } $outqueue .= "$savenl$line$snl"; @@ -138,12 +149,22 @@ sub rec_socket } elsif ($sort eq 'B') { if ($buffered && $outqueue) { print $stdout $outqueue; + pop @echo while(@echo > $maxecho); + push @echo, $outqueue; $outqueue = ""; } $buffered = $line; # set buffered or unbuffered } elsif ($sort eq 'Z') { # end, disconnect, go, away ..... cease(0); - } + } + + # ****************************************************** + # ****************************************************** + # any other sorts that might happen are silently ignored. + # ****************************************************** + # ****************************************************** + } else { + cease(0); } $lasttime = time; } @@ -167,8 +188,9 @@ sub rec_stdin cease(1); } elsif ($r > 0) { if ($mode) { - $buf =~ s/\r/\n/og if $mode == 1; - $buf =~ s/\r\n/\n/og if $mode == 2; + $buf =~ s/\r/\n/g if $mode == 1; + $buf =~ s/[\r\x00]//g if $mode == 2 || $mode == 3; + $dangle = !($buf =~ /\n$/); if ($buf eq "\n") { @lines = (" "); @@ -184,6 +206,7 @@ sub rec_stdin unshift @lines, ($lastbit . $first) if ($first); foreach $first (@lines) { # print "send_now $call $first\n"; + next if grep {$_ eq $first } @echo; $conn->send_later("I$call|$first"); } $lastbit = $buf; @@ -208,19 +231,19 @@ sub doconnect my ($host, $port) = split /\s+/, $line; $port = 23 if !$port; -# if ($port == 23) { - - $sock = new Net::Telnet (Timeout => $timeout, Port => $port); - $sock->option_callback(\&optioncb); - $sock->output_record_separator(''); -# $sock->option_log('option_log'); -# $sock->dump_log('dump'); - $sock->option_accept(Dont => TELOPT_ECHO, Wont => TELOPT_ECHO); - $sock->open($host) or die "Can't connect to $host port $port $!"; -# } else { -# $sock = IO::Socket::INET->new(PeerAddr => "$host:$port", Proto => 'tcp') -# or die "Can't connect to $host port $port $!"; -# } + $sock = new Net::Telnet (Timeout => $timeout, Port => $port); + $sock->option_callback(\&optioncb); + $sock->output_record_separator(''); + $sock->option_accept(Dont => TELOPT_ECHO, Wont => TELOPT_ECHO); + $sock->open($host) or die "Can't connect to $host port $port $!"; + if ($port == 23) { + $sock->telnetmode(1); + $sock->option_send(Dont => TELOPT_ECHO, Wont => TELOPT_ECHO) if $port == 23; + } else { + $sock->telnetmode(0); + } + $sock->binmode(0); + $mode = 3; } elsif ($sort eq 'ax25' || $sort eq 'prog') { my @args = split /\s+/, $line; $rfh = new IO::File; @@ -230,6 +253,7 @@ sub doconnect die "no transmit channel $!" unless $wfh; dbg('connect', "got pid $pid"); $wfh->autoflush(1); + $mode = 1; } else { die "invalid type of connection ($sort)"; } @@ -250,6 +274,16 @@ sub dotimeout $timeout = $val; } +sub dolineend +{ + my $val = shift; + $out_lineend = $val; + $out_lineend =~ s/\\r/\r/g; + $out_lineend =~ s/\\n/\n/g; + dbg('connect', "lineend set to $val "); + $out_lineend = $mynl unless $out_lineend; +} + sub dochat { my ($expect, $send) = @_; @@ -263,14 +297,23 @@ sub dochat if ($csort eq 'telnet') { $line = $sock->get(); cease(11) unless $line; # the socket has gone away? - $line =~ s/\r\n/\n/og; + if (length $line == 0) { + dbg('connect', "received 0 length line, aborting..."); + cease(11); + } + $line =~ s/\r//g; chomp; } elsif ($csort eq 'ax25' || $csort eq 'prog') { local $/ = "\r"; $line = <$rfh>; - $line =~ s/\r//og; + if (length $line == 0) { + dbg('connect', "received 0 length line, aborting..."); + cease(11); + } + $line =~ s/\r/\n/g; + chomp; } - dbg('connect', "received \"$line\""); + dbg('connect', map { "received \"$_\"" } split /\n/, $line); if ($abort && $line =~ /$abort/i) { dbg('connect', "aborted on /$abort/"); cease(11); @@ -280,9 +323,10 @@ sub dochat } if ($send) { if ($csort eq 'telnet') { +# local $\ = $out_lineend; $sock->print("$send\n"); } elsif ($csort eq 'ax25') { - local $\ = "\r"; + local $\ = $out_lineend; $wfh->print("$send"); } dbg('connect', "sent \"$send\""); @@ -295,6 +339,14 @@ sub timeout cease(0); } +# handle callsign and connection type firtling +sub doclient +{ + my $line = shift; + my @f = split /\s+/, $line; + $call = uc $f[0] if $f[0]; + $csort = $f[1] if $f[1]; +} # # initialisation @@ -313,10 +365,12 @@ $savenl = ""; # an NL that has been saved from last time $timeout = 60; # default timeout for connects $abort = ""; # the current abort string $cpath = "$root/connect"; # the basic connect directory +$maxecho = 5; # length of max echo queue $pid = 0; # the pid of the child program $csort = ""; # the connection type $sock = 0; # connection socket +$out_lineend = $mynl; # connection lineending (used for outgoing connects) $stdin = *STDIN; $stdout = *STDOUT; @@ -349,7 +403,7 @@ $stdout->autoflush(1); $SIG{'INT'} = \&sig_term; $SIG{'TERM'} = \&sig_term; -$SIG{'HUP'} = 'IGNORE'; +$SIG{'HUP'} = \&sig_term; $SIG{'CHLD'} = \&sig_chld; $SIG{'ALRM'} = \&timeout; @@ -360,6 +414,9 @@ if ($loginreq) { my $user; my $s; + $connsort = 'telnet' if $connsort eq 'local'; + setmode(); + if (-e "$data/issue") { open(I, "$data/issue") or die; local $/ = undef; @@ -370,51 +427,25 @@ if ($loginreq) { $stdout->print($issue) if $issue; } - - use DXUser; - - DXUser->init($userfn); - # allow a login from an existing user. I could create a user but # I want to check for valid callsigns and I don't have the # necessary info / regular expression yet - for ($state = 0; $state < 2; ) { - alarm($timeout); + alarm($timeout); - if ($state == 0) { - $stdout->print('login: '); - $stdout->flush(); - local $\ = $nl; - $s = $stdin->getline(); - chomp $s; - $s =~ s/\s+//og; - $s =~ s/-\d+$//o; # no ssids! - cease(0) unless $s gt ' '; - $call = uc $s; - $user = DXUser->get($call); - $state = 1; - } elsif ($state == 1) { - $stdout->print('password: '); - $stdout->flush(); - local $\ = $nl; - $s = $stdin->getline(); - chomp $s; - $state = 2; - if (!$user || ($user->passwd && $user->passwd ne $s)) { - $stdout->print("sorry...$nl"); - cease(0); - } - } - } -} - -# handle callsign and connection type firtling -sub doclient -{ - my $line = shift; - my @f = split /\s+/, $line; - $call = uc $f[0] if $f[0]; - $csort = $f[1] if $f[1]; + $stdout->print('login: '); + $stdout->flush(); + local $\ = $mynl; + $s = $stdin->getline(); + chomp $s; + $s =~ s/\s+//og; + $s =~ s/-\d+$//o; # no ssids! + cease(0) unless $s && $s gt ' '; + unless (is_callsign($s)) { + $stdout->print("Sorry, $s is an invalid callsign"); + cease(0); + } + $call = uc $s; + alarm(0); } # is this an out going connection? @@ -434,8 +465,10 @@ if ($connsort eq "connect") { doconnect($1, $2) if /^\s*co\w*\s+(\w+)\s+(.*)$/io; doabort($1) if /^\s*a\w*\s+(.*)/io; dotimeout($1) if /^\s*t\w*\s+(\d+)/io; - dochat($1, $2) if /\s*\'(.*)\'\s+\'(.*)\'/io; - if (/\s*cl\w+\s+(.*)/io) { + dolineend($1) if /^\s*[Ll]\w*\s+\'((?:\\[rn])+)\'/; + dochat($1, $2) if /^\s*\'(.*)\'\s+\'(.*)\'/io; + + if (/^\s*cl\w+\s+(.*)/io) { doclient($1); last; } @@ -464,14 +497,29 @@ if ($connsort eq "connect") { $outbound = 1; $connsort = $csort; $stdout->autoflush(1); + $mode = ($connsort eq 'ax25') ? 1 : $mode; close STDIN; close STDOUT; close STDERR; } -$mode = ($connsort eq 'ax25') ? 1 : 2; setmode(); +# adjust the callsign if it has an SSID, SSID <= 8 are legal > 8 are netrom connections +$call =~ s/-0$//; # strip off -0 as this is equiv to just call on its own +my ($scall, $ssid) = split /-/, $call; +$ssid = undef unless $ssid && $ssid =~ /^\d+$/; +if ($ssid) { + $ssid = 15 if $ssid > 15; + if ($connsort eq 'ax25') { + if ($ssid > 8) { + $ssid = 15 - $ssid; + } + } + $call = "$scall-$ssid"; +} + + $conn = Msg->connect("$clusteraddr", $clusterport, \&rec_socket); if (! $conn) { if (-r "$data/offline") {