package IO::Socket::Socks::Wrapper; use strict; use Socket; use base 'Exporter'; our $VERSION = 0.01; our @EXPORT_OK = 'connect'; sub import { my $pkg = shift; while(my ($module, $cfg) = splice @_, 0, 2) { unless(defined $cfg) { $cfg = $module; $module = undef; } if($module) { # override connect() in the package eval "require $module" or die $@; if($module->isa('IO::Socket::INET')) { *connect = sub(*$) { local(*IO::Socket::INET::connect) = sub(*$) { _connect(@_, $cfg); }; my $self = shift; my $ref = ref($self); no strict 'refs'; foreach my $parent (@{$ref.'::ISA'}) { if($parent->isa('IO::Socket::INET')) { bless $self, $parent; $self->connect(@_); bless $self, $ref; return $self; } } } } else { *connect = sub(*$) { _connect(@_, $cfg); } } $pkg->export($module, 'connect'); } else { # override connect() globally *connect = sub(*$) { _connect(@_, $cfg); }; $pkg->export('CORE::GLOBAL', 'connect'); } } } sub _connect { my ($socket, $name, $cfg) = @_; my $ref = ref($socket); return CORE::connect( $socket, $name ) if (($ref && $socket->isa('IO::Socket::Socks')) || !$cfg); my ($port, $host) = sockaddr_in($name); $host = inet_ntoa($host); # global overriding will not work with `use' pragma require IO::Socket::Socks; IO::Socket::Socks->new_from_socket( $socket, ConnectAddr => $host, ConnectPort => $port, %$cfg ) or return; bless $socket, $ref if $ref && $ref ne 'GLOB'; } 1;