Apache-HTTunnel
view release on metacpan or search on metacpan
Client/lib/HTTunnel/Client.pm view on Meta::CPAN
return $this ;
}
sub connect {
my $this = shift ;
my $proto = shift || 'tcp' ;
my $host = shift || 'localhost' ;
my $port = shift || 0 ;
my $timeout = shift || 15 ;
$this->{__PACKAGE__}->{proto} = $proto ;
my $fhid = $this->_execute(
'connect',
[$proto, $host, $port, $timeout],
) ;
if ($proto eq 'tcp'){
my ($addr, $port) = () ;
($addr, $port, $fhid) = split(':', $fhid, 3) ;
$this->{__PACKAGE__}->{fhid} = $fhid ;
$this->{__PACKAGE__}->{peer_info} = "$addr:$port" ;
}
else {
$this->{__PACKAGE__}->{fhid} = $fhid ;
}
return 1 ;
}
sub read {
my $this = shift ;
my $len = shift || 0 ;
my $timeout = shift || 15 ;
my $lifeline = shift ;
my $lifeline_action = shift || sub {die("lifeline cut\n")} ;
croak("HTTunnel::Client object is not connected") unless $this->{__PACKAGE__}->{fhid} ;
while (1){
if ($lifeline){
my @ready = IO::Select->new($lifeline)->can_read(0) ;
if (scalar(@ready)){
$lifeline_action->() ;
return undef ;
}
}
my $addr = undef ;
my $port = undef ;
my $data = undef ;
eval {
$data = $this->_execute(
'read',
[$this->{__PACKAGE__}->{fhid}, $this->{__PACKAGE__}->{proto}, $len, $timeout],
) ;
if ($this->{__PACKAGE__}->{proto} eq 'udp'){
($addr, $port, $data) = split(':', $data, 3) ;
$this->{__PACKAGE__}->{peer_info} = "$addr:$port" ;
}
} ;
if ((ref($@))&&(UNIVERSAL::isa($@, "HTTunnel::Client::TimeoutException"))){
next ;
}
elsif ($@){
die("$@\n") ;
}
return $data ;
}
}
sub get_peer_info {
my $this = shift ;
return $this->{__PACKAGE__}->{peer_info} ;
}
sub print {
my $this = shift ;
my @data = shift ;
croak("HTTunnel::Client object is not connected") unless $this->{__PACKAGE__}->{fhid} ;
$this->_execute(
'write',
[$this->{__PACKAGE__}->{fhid}, $this->{__PACKAGE__}->{proto}],
join("", @data),
) ;
return 1 ;
}
sub close {
my $this = shift ;
if ($this->{__PACKAGE__}->{fhid}){
$this->_execute(
'close',
[$this->{__PACKAGE__}->{fhid}],
) ;
$this->{__PACKAGE__}->{fhid} = undef ;
return 1 ;
}
return 0 ;
}
sub _execute {
my $this = shift ;
my $cmd = shift ;
my $args = shift ;
my $data = shift ;
if ($this->{__PACKAGE__}->{pid} != $$){
# Reset the connection cache since we probably have forked.
if ($this->conn_cache()){
$this->conn_cache({total_capacity => 1}) ;
}
$this->{__PACKAGE__}->{pid} = $$ ;
}
my $req = HTTP::Request::Common::POST(
join("/", $this->{__PACKAGE__}->{url}, $cmd, @{$args}),
{"Content-Length" => length($data || '')},
"content" => $data
) ;
$req->protocol("HTTP/1.1") ;
$this->request_callback($req) ;
my $resp = $this->request($req) ;
$this->response_callback($resp) ;
if ($resp->code() != RC_OK()){
croak("HTTP error : " . $resp->code() . " (" . $resp->message() . ")") ;
}
my $content = $resp->content() ;
my $code = substr($content, 0, 3) ;
if ($code eq 'err'){
croak("Apache::HTTunnel error: " . substr($content, 3)) ;
}
elsif ($code eq 'okn'){
return undef ;
}
elsif ($code eq 'okd'){
return substr($content, 3) ;
}
elsif ($code eq 'okt'){
die(bless({}, "HTTunnel::Client::TimeoutException")) ;
}
else{
croak("Invalid Apache::HTTunnel response code '$code'") ;
}
}
sub request_callback {
my $shift = shift ;
my $req = shift ;
}
sub response_callback {
my $shift = shift ;
my $res = shift ;
}
1 ;
( run in 1.137 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )