AnyEvent-SOCKS-Client
view release on metacpan or search on metacpan
lib/AnyEvent/SOCKS/Client.pm view on Meta::CPAN
}
});
}
sub auth{
my( $self, $method ) = @_;
my $that = $self->{chain}->[0] ;
if( $method == AUTH_LOGIN and $that->{login} and $that->{password}){
$self->{hd}->push_write(
pack('CC', 5, length $that->{login} ) . $that->{login}
. pack('C', length $that->{password}) . $that->{password}
);
$self->{hd}->push_read( chunk => 2, sub{
my $status = unpack('xC', $_[1]) ;
if( $status == 0 ){
$self->connect_cmd ;
return ;
}
AE::log "error" => "Bad login or password";
});
return ;
}
AE::log "error" => "Auth method $method not implemented!";
}
sub connect_cmd{
my( $self ) = @_ ;
my $next = $self->{chain}->[1] ;
my( $host, $port ) = $next
? ( $next->{host}, $next->{port} )
: ( $self->{dst_host}, $self->{dst_port} ) ;
my ($cmd, $ip );
if( $ip = parse_ipv4($host) ){
AE::log "debug" => "Connect IPv4: $host";
$cmd = pack('CCCCA4n', 5, CMD_CONNECT, 0, TYPE_IP4, $ip, $port);
}
elsif( $ip = parse_ipv6($host) ){
AE::log "debug" => "Connect IPv6: $host";
$cmd = pack('CCCCA16n', 5, CMD_CONNECT, 0, TYPE_IP6, $ip, $port);
}
else{
AE::log "debug" => "Connect hostname: $host";
$cmd = pack('CCCCCA*n', 5, CMD_CONNECT, 0, TYPE_FQDN , length $host, $host, $port);
}
$self->{hd}->push_write( $cmd );
$self->{hd}->push_read( chunk => 4, sub{
my( $status, $type ) = unpack( 'xCxC', $_[1] );
unless( $status == 0 ){
AE::log "error" => "Connect cmd rejected: status is $status" ;
return ;
}
$self->connect_cmd_finalize( $type );
});
}
sub connect_cmd_finalize{
my( $self, $type ) = @_ ;
AE::log "debug" => "Connect cmd done, bind atype is $type";
if($type == TYPE_IP4){
$self->{hd}->push_read( chunk => 6, sub{
my( $host, $port) = unpack( "a4n", $_[1] );
$self->socks_connect_done( format_ipv4( $host ), $port );
});
}
elsif($type == TYPE_IP6){
$self->{hd}->push_read( chunk => 18, sub{
my( $host, $port) = unpack( "a16n", $_[1] );
$self->socks_connect_done( format_ipv6( $host ) , $port );
});
}
elsif($type == TYPE_FQDN){
# read 1 byte (fqdn len)
# then read fqdn and port
$self->{hd}->push_read( chunk => 1, sub{
my $fqdn_len = unpack( 'C', $_[1] ) ;
$self->{hd}->push_read( chunk => $fqdn_len + 2 , sub{
my $host = substr( $_[1], 0, $fqdn_len ) ;
my $port = unpack('n', substr( $_[1], -2) );
$self->socks_connect_done( $host, $port );
});
});
}
else{
AE::log "error" => "Unknown atype $type";
}
}
sub socks_connect_done{
my( $self, $bind_host, $bind_port ) = @_;
my $that = shift @{ $self->{chain} }; # shift = move forward in chain
AE::log "debug" => "Done with server socks$that->{v}://$that->{host}:$that->{port} , bound to $bind_host:$bind_port";
if( @{ $self->{chain} } ){
$self->handshake ;
return ;
}
AE::log "debug" => "Giving up fh and returning to void...";
my( $fh, $c_cb ) = ( $self->{hd}->fh, delete $self->{c_cb} );
$self->DESTROY;
$c_cb->( $fh );
}
sub DESTROY {
my $self = shift ;
AE::log "debug" => "Kitten saver called";
undef $self->{_guard};
$self->{hd}->destroy if( $self->{hd} and not $self->{hd}->destroyed );
$self->{c_cb}->() if( $self->{c_cb} );
undef %$self;
bless $self, __PACKAGE__ . '::destroyed';
}
=head1 AUTHOR
Zlobus, C<< <zlobus at cpan.org> >>
=head1 BUGS
Please report any bugs or feature requests to C<bug-anyevent-socks-client at rt.cpan.org>, or through
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=AnyEvent-SOCKS-Client>. I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.
=head1 SUPPORT
You can find documentation for this module with the perldoc command.
perldoc AnyEvent::SOCKS::Client
You can also look for information at:
=over 4
=item * RT: CPAN's request tracker (report bugs here)
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=AnyEvent-SOCKS-Client>
=item * AnnoCPAN: Annotated CPAN documentation
L<http://annocpan.org/dist/AnyEvent-SOCKS-Client>
=item * CPAN Ratings
L<http://cpanratings.perl.org/d/AnyEvent-SOCKS-Client>
=item * Search CPAN
( run in 1.503 second using v1.01-cache-2.11-cpan-140bd7fdf52 )