package Net::Proxy::Connector;
use strict;
use warnings;
use Carp;
use Scalar::Util qw( refaddr );
use Net::Proxy;
my %PROXY_OF;
my $BUFFSIZE = 4096;
#
# the most basic possible constructor
#
sub new {
my ( $class, $args ) = @_;
my $self = bless $args ? {%$args} : {}, $class;
$self->init() if $self->can('init');
delete $self->{_proxy_}; # this link back is now unnecessary
return $self;
}
#
# Each Connector is managed by a Net::Proxy object
#
sub set_proxy {
my ( $self, $proxy ) = @_;
croak "$proxy is not a Net::Proxy object"
if !UNIVERSAL::isa( $proxy, 'Net::Proxy' );
return $PROXY_OF{ refaddr $self } = $proxy;
}
sub get_proxy { return $PROXY_OF{ refaddr $_[0] }; }
sub is_in {
my $id = refaddr $_[0];
return $id == refaddr $PROXY_OF{$id}->in_connector();
}
sub is_out {
my $id = refaddr $_[0];
return $id == refaddr $PROXY_OF{$id}->out_connector();
}
#
# the method that creates all the sockets
#
sub new_connection_on {
my ( $self, $listener ) = @_;
Net::Proxy->notice(
'New connection on ' . Net::Proxy->get_nick($listener) );
# call the actual Connector method
my $sock = eval { $self->accept_from($listener); };
if( $@ ) {
Net::Proxy->error( $@ );
return;
}
Net::Proxy->set_connector( $sock, $self );
Net::Proxy->set_buffer( $sock, '' );
Net::Proxy->set_callback( $sock, $self->{hook} ) if $self->{hook};
Net::Proxy->watch_reader_sockets($sock);
# connect to the destination
my $out = $self->get_proxy()->out_connector();
$out->_out_connect_from($sock);
# update the stats
$self->get_proxy()->stat_inc_opened();
return;
}
sub _out_connect_from {
my ( $self, $sock ) = @_;
my $peer = eval { $self->connect(); };
if ($@) { # connect() dies if the connection fails
$@ =~ s/ at .*?\z//s;
warn "connect() failed with error '$@'\n";
Net::Proxy->close_sockets($sock);
return;
}
if ($peer) { # $peer is undef for Net::Proxy::Connector::dummy
Net::Proxy->watch_reader_sockets($peer);
Net::Proxy->set_connector( $peer, $self );
Net::Proxy->set_buffer( $peer, '' );
Net::Proxy->set_callback( $peer, $self->{hook} ) if $self->{hook};
Net::Proxy->set_nick( $peer,
$peer->sockhost() . ':'
. $peer->sockport() . ' -> '
. $peer->peerhost() . ':'
. $peer->peerport() );
Net::Proxy->notice( 'Connected ' . Net::Proxy->get_nick( $peer ) );
Net::Proxy->set_peer( $peer, $sock );
Net::Proxy->set_peer( $sock, $peer );
Net::Proxy->notice( 'Peered '
. Net::Proxy->get_nick($sock) . ' with '
. Net::Proxy->get_nick($peer) );
}
=1= |