ARCv2

 view release on metacpan or  search on metacpan

lib/Arc/Connection.pm  view on Meta::CPAN

package Arc::Connection;

use strict;
use warnings;
use Carp;
use MIME::Base64;
use Arc qw(LOG_AUTH LOG_USER LOG_ERR LOG_CMD LOG_SIDE LOG_DEBUG);
use Authen::SASL;

@Arc::Connection::ISA = qw(Arc);

sub members 
{
	my $this = shift;
	return { %{$this->SUPER::members},
		# private:
			__sasl => undef,   # Authen::SASL Handle
			__linequeue => [], # internal line buffer (idea From Net::Cmd)
			__partial => "",   # a partial line (idea From Net::Cmd)
		# protected:
			_connection => undef,    # IO::Socket for the ARCv2 Connection
			_cmdclientsock => undef, # IO::Socket for the command connection (encrypted)
			_select => undef,        # IO::Select for the ARCv2 Connection
			
			_authenticated => 0,     # Are we authenticated
			#_sasl => undef,         # Authen::SASL::Cyrus Handle
			#_saslmech => "",        # SASL mechnanism used at authentication
			
			_cmdparameter => undef,   # parameter after the command
			_expectedcmds => undef,   # array, which ARCv2 protocol commands are allowed to come next
			_connected => 0,          # are we connected
			_username => "anonymous", # username extracted from SASL

		# public:
			protocol => undef, # Which protocol is used (0 = ARC/2.0, 1 = ARC/2.1)

			timeout => undef,  # timeout for all connections (ARCv2 and command) in seconds
			service => undef,  # name of the server (for SASL)
	};
}

sub _Init
{
	my $this = shift;
		 
	return $this->_SetError("Initialization failed.") unless $this->SUPER::_Init(@_);
	
	# timeout
#	unless (defined $this->{timeout}) {
#		$this->Log(LOG_SIDE,"Setting timeout to 30 secs since no time specified.");
#		$this->{timeout} = 30;
#	}		  
	
	return $this->_SetError("No service name for SASL authentication specified.") 
		unless defined $this->{service};
		
	return 1; 
}

## initializes command connection. (protocol)
## Starts listen on the Command socket and sends the B<CMDPASV> command.
##out> true if everything went like expected, otherwise false.
##eg> $this->_CommandConnection();
sub _CommandConnection
{
	my $this = shift;

	my $consock = IO::Socket::INET->new(
				Listen    => 1,
				Proto     => 'tcp',
				LocalAddr => $this->{_connection}->sockhost,
				ReuseAddr => 1,
	) || return $this->_SetError("Socket creation for CommandConnection failed.");

	unless ($this->_SendCommand("CMDPASV",$consock->sockhost.':'.$consock->sockport)) {
		return;
	}

	my $sel = new IO::Select($consock);

	if (my @socks = $sel->can_read(10)) {
		foreach my $sock (@socks) {
			if ($sock == $consock) {
				$this->{_cmdclientsock} = $consock->accept() || last;
				return 1;
			}
		}
	} else {
		return $this->_SetError("No CommandConnection received (Client died?).");
	}	
}

## function for reading and writing on the command connection.
## This function is always used by the C<Arc::Connection::Server> to handle 

lib/Arc/Connection.pm  view on Meta::CPAN


## send the ARCv2 SASL command. (protocol)
## This function encodes the output from sasl_*_start and sasl_*_step with Base-64 and sends
## it to the other side
##in> $saslstr
##out> true if successful, otherwise false
##eg> $this->_Sasl($sasl->client_start());
sub _Sasl
{
	my ($this,$str) = @_;
	return $this->_SendCommand("SASL",encode_base64($str,""));
}

## initialize sasl.
## This function initializes the C<__sasl> member with an object
## of C<Authen::SASL>.
##out> true if successful, otherwise false
##eg> $this->_PrepareAuthentication() || return;
sub _PrepareAuthentication
{
	my $this = shift;
	
	# Authen::SASL Instance creation
	$this->{__sasl} = Authen::SASL->new(
		mechanism => "".$this->{_saslmech},
	);

	if (!defined $this->{__sasl}) {
		return $this->_SetError("SASL error. No SASL object created.");
	}
	return 1;
}

## are we connected?
##out> true, if the ARCv2 control connection is connected, otherwise false
##eg> last unless $arc->IsConnected;
sub IsConnected
{
	my $this = shift;
	return $this->{_connected};
}


sub clean
{
	my $this = shift;
	delete $this->{__sasl};
	$this->{__linequeue} = [];
	$this->{__partial} = ""; 
	
	$this->{_authenticated} = 0;
	$this->{_sasl} = undef;
	$this->{_saslmech} = "";

	$this->{_cmdparameter} = undef;
	$this->{_expectedcmds} = undef;
	$this->{_connected} = 0;
	$this->{_username} = "anonymous";
	$this->{_error} = undef;		

# public:
	$this->{protocol} = undef;
}

1;



( run in 1.079 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )