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 )