ARCv2
view release on metacpan or search on metacpan
lib/Arc/Connection/Client.pm view on Meta::CPAN
package Arc::Connection::Client;
use strict;
use warnings;
use Carp;
use IO::Socket::INET;
use IO::Select;
use Arc qw(LOG_AUTH LOG_USER LOG_ERR LOG_CMD LOG_SIDE LOG_DEBUG);
use Arc::Connection;
use MIME::Base64;
@Arc::Connection::Client::ISA = qw(Arc::Connection);
sub members
{
my $this = shift;
return { %{$this->SUPER::members},
logfileprefix => "client",
logdestination => "stderr",
sasl_cb_user => $ENV{'USER'}, # SASL Callback for username (PLAIN and some other mechs only)
sasl_cb_auth => $ENV{'USER'}, # SASL Callback for authname (PLAIN and some other mechs only)
sasl_cb_pass => "", # SASL Callback for password (PLAIN and some other mechs only)
server => undef, # Server to connect to
port => undef, # Port to connect to
sasl_mechanism => undef, # use this mechanism for authentication
server_sasl_mechanisms => [], # filled by the sasl mechanisms
protocol => 1, # Which protocol type the shall use.
};
}
sub _Init
{
my $this = shift;
return 0 unless $this->SUPER::_Init(@_);
# server
return $this->_SetError("No ARCv2 server given.") unless defined $this->{server};
# port
unless (defined $this->{port}) {
$this->Log(LOG_SIDE,"No port specified. Using $Arc::DefaultPort.");
$this->{port} = $Arc::DefaultPort;
}
# sasl mech
$this->Log(LOG_SIDE,"No sasl mechanism specified. Using the one supplied by the server.")
unless defined $this->{sasl_mechanism};
}
## connects to the server
##out> true when succesful, otherwise false
##eg> $this->_Connect();
sub _Connect
{
my $this = shift;
$this->{_connection} = new IO::Socket::INET(
PeerAddr => $this->{server},
PeerPort => $this->{port},
Type => SOCK_STREAM,
) || return $this->_SetError("Could not create Client socket: $! $@.");
# Fill the connected Socket into the select object
$this->{_select} = new IO::Select($this->{_connection})
|| return $this->_SetError("Select creation failed.");
$this->{_connection}->autoflush(0);
$this->{_connected} = 1;
return 1;
}
## initialize the protocol.
## Sends the initial protocol message ARC/2.0
##out> true when succesful, otherwise false
##eg> $this->_InitARC2();
sub _InitARC2
{
my $this = shift;
@{$this->{_expectedcmds}} = qw(ERR AUTH);
$this->{_authenticated} = 0;
return $this->_SendCommand ("ARC/2.".$this->{protocol});
}
lib/Arc/Connection/Client.pm view on Meta::CPAN
##eg> last unless $this->CommandWrite();
sub CommandWrite
{
my $this = shift;
return $this->_SetError("There is no command running.") unless defined $this->{_cmdclientsock};
return unless @_;
my $str = join("",@_);
$str = $this->{_sasl}->encode($str);
return $this->{_cmdclientsock}->syswrite($str);
}
## close the write part of the netsock.
## This function closes the write-part of the command connection.
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> last unless $arc->CommandEOF();
sub CommandEOF
{
my $this = shift;
return $this->_SetError("There is no command running.") unless defined $this->{_cmdclientsock};
return shutdown($this->{_cmdclientsock},1);
}
## read data from the Command connection.
##out> if successful the received data is returned, otherwise false.
##eg> while (my $data = $arc->CommandRead()) { ... }
sub CommandRead
{
my $this = shift;
return $this->_SetError("There is no command running.") unless defined $this->{_cmdclientsock};
my $sel = new IO::Select ( $this->{_cmdclientsock} );
my $buf;
while ($sel->can_read($this->{timeout})) {
return unless $this->{_cmdclientsock}->sysread($buf,1024);
$buf = $this->{_sasl}->decode($buf);
next unless $buf; # SASL incomplete decode
return $buf;
}
return;
}
## end the command on the server side.
## Closes the command connection and ends the command.
##out> true if successful, false if not. (IsError is set appropriatly)
##eg> $arc->CommandEnd();
sub CommandEnd
{
my $this = shift;
return $this->_SetError("There is no command running.") unless defined $this->{_cmdclientsock};
if ($this->{protocol} == 1) {
# encrypted protocol and command connection, don't lose synchronized sasl_de/encode
$this->CommandEOF();
while ($_ = $this->CommandRead()) { $this->_Debug("read text: ".$_); };
}
$this->{_cmdclientsock}->close();
$this->{_cmdclientsock} = undef;
while (my $cmd = $this->_RecvCommand()) {
last unless $this->_ProcessLine($cmd);
last if $cmd eq "DONE";
}
return if $this->{_error};
return 1;
}
return 1;
( run in 1.141 second using v1.01-cache-2.11-cpan-d80b1682f3f )