ARCv2
view release on metacpan or search on metacpan
lib/Arc/Connection.pm view on Meta::CPAN
my $client = ref ($this) eq "Arc::Connection::Client";
my $netsock = $this->{_cmdclientsock};
# $this->_Debug("ReadWriteBinary (C:",$client,") locin: ",$locin->fileno,", locout:",$locout->fileno,", net: ",$netsock->fileno);
my $sel = new IO::Select($netsock,$locin);
my $lwsel = new IO::Select($locout);
my $nwsel = new IO::Select($netsock);
my $buf;
my $stop = 0;
while (my @rs = $sel->can_read) {
foreach my $r (@rs) {
# Something is readable.
my $ret = $r->sysread($buf,4096);
# If no data received, this read socket is closed
# We don't want to listen to it anymore
unless ($ret) {
$sel->remove($r);
# If there is nothing to read anymore
# we will never write to the other socket again.
if ($r->fileno == $locin->fileno) {
$stop = 1 unless $client;
shutdown($netsock,1); # Close write connection
} elsif ($r->fileno == $netsock->fileno) {
# on client-side the netsock is closed only
# if the command on server side has ended.
# so game over
$stop = 1 if $client;
close($locout) unless $stop; # Local pipe is not needed anymore
}
last if $stop;
} else {
# select the appropriate write-"select"
my $tsel = $r->fileno == $locin->fileno ? $nwsel : $lwsel;
# encryption, decode or encode
$buf = $r->fileno == $locin->fileno ?
$this->{_sasl}->encode($buf) :
$this->{_sasl}->decode($buf);
# sometimes SASL replies NULL if something is missing
# this is normal behaviour, the next buf will complete it
next unless $buf;
# if nothing is writeable, gameover
last unless (my @ws = $tsel->can_write);
last unless ($ws[0]->syswrite($buf));
}
}
last if $stop;
}
# $this->_Debug("RW Binary ended.");
return 1;
}
## send a line. (protocol)
## This function sends a command line to the ARCv2 socket.
##in> ... (line)
##out> true if writing has succeeded, otherwise false.
##eg> $this->_SendLine($cmd,"test");
sub _SendLine
{
my $this = shift;
return unless @_;
my $line = join("",@_);
$line =~ s/\r//g;
$line =~ s/\n/ /g;
return $this->_SetError("SendLine only available when connection and select is set.") unless $this->{_connected};
if ($this->{_select}->can_write($this->{timeout})) {
$this->_Debug(substr ($line,0,30),"..");
$line .= "\015\012";
# encrypt if necessary
$line = $this->{_sasl}->encode($line)
if $this->{_authenticated} == 1 and $this->{protocol} == 1;
return $this->{_connection}->syswrite($line,4096) > 0;
} else {
$this->{_connected} = 0;
$this->{_connection}->close;
return $this->_SetError("Sending timed out.");
}
}
## send a command. (protocol)
## Send a command to the ARCv2 socket.
##in> $cmd, $parameter
##out> true if successful, otherwise false
##eg> $this->_SendCommand("CMDPASV",$consock->sockhost.':'.$consock->sockport);
sub _SendCommand
{
my $this = shift;
my ($cmd,$msg) = @_;
my $ret = 1;
$ret = $this->_SetError("Sending command $cmd failed.") unless $this->_SendLine($cmd,defined $msg ? " ".$msg : "");
return $ret;
}
## receive a line (command). (protocol)
## This function receives data from the ARCv2 connection and
## fills the internal C<__linequeue> and C<__partial>. It returns
## a line from the internal buffer if there is any. It also handles
## timeouts and "connection closed by foreign host"'s.
##out> true (and the line) if everything worked fine, otherwise false (undef)
##eg> if (my $line = $this->_RecvLine()) { ... }
sub _RecvLine
{
my $this = shift;
return shift @{$this->{__linequeue}} if scalar @{$this->{__linequeue}};
# no connection is set not connected
return $this->_SetError("RecvCommand only Available when connection and select is set.") unless $this->{_connected};
my $partial = defined($this->{__partial}) ? $this->{__partial} : "";
my $buf = "";
until (scalar @{$this->{__linequeue}}) {
( run in 2.790 seconds using v1.01-cache-2.11-cpan-7fcb06a456a )