#!/usr/bin/perl use strict; use warnings; use Smart::Comments; use POE qw/Wheel::SocketFactory Wheel::ReadWrite Filter::Stream Driver::SysRW/; POE::Session->create( inline_states => { _start => \&_create_socket, on_client_accept => \&client_accept, on_server_error => \&server_error, on_client_error => \&client_error, }, ); POE::Kernel->run; sub _create_socket { my ($kernel, $heap) = @_[KERNEL, HEAP]; $heap->{server} = POE::Wheel::SocketFactory->new( BindPort => '10086', Reuse => 1, SuccessEvent => 'on_client_accept', FailureEvent => 'on_server_error', ); } sub client_accept { my ($client, $heap) = @_[ARG0, HEAP]; #create new session handle remote host POE::Session->create( inline_states => { _start => \&connect_to_remote, on_remote_connect => \&remote_connected, on_remote_fail => \&remote_fail, forward_out => \&forward_out, forward_in => \&forward_in, remote_flush => \&remote_flush, }, args => [$client], ); } sub connect_to_remote { my ($heap, $local_socket) = @_[HEAP, ARG0]; #create socket connect to port we want to forward my $remote = POE::Wheel::SocketFactory->new( RemoteAddress => 'localhost', RemotePort => '80', SuccessEvent => 'on_remote_connect', FailureEvent => 'on_remote_fail', ); $heap->{remote} = $remote; # create wheel to read the local socket $heap->{local_wheel} = POE::Wheel::ReadWrite->new( Handle => $local_socket, Filter => POE::Filter::Stream->new(), InputEvent => 'forward_out', ); $heap->{local_socket} = $local_socket; } sub remote_connected { my ($heap, $socket) = @_[HEAP, ARG0]; my $wheel = POE::Wheel::ReadWrite->new( Handle => $socket, Driver => POE::Driver::SysRW->new(), Filter => POE::Filter::Stream->new(), InputEvent => 'forward_in', #FlushedEvent => 'remote_flush', ); $heap->{remote_wheel} = $wheel; } sub server_erorr { my ($operation, $errnum, $errstr) = @_[ARG0, ARG1, ARG2]; warn "server opeartion: $operation failed with number: $errnum\n\t string: $errstr"; delete $_[HEAP]{server}; } sub client_error { my $id = $_[ARG3]; delete $_[HEAP]{client}{$id}{x}; } sub forward_out { my ($heap, $data, $wheel) = @_[HEAP, ARG0]; $heap->{remote_wheel}->put($data); } sub forward_in { my ($heap, $data) = @_[HEAP, ARG0]; $heap->{local_wheel}->put($data); $_[KERNEL]->yield('remote_flush') } sub port_fail { print "failed to connnect to port\n"; } sub remote_fail { delete $_[HEAP]->{remote}; } sub remote_flush { my $heap = $_[HEAP]; print "remote flushed\n"; print "remote have no remote\n" if !exists $heap->{remote}; if (!$heap->{remote_wheel}->get_driver_out_octets) { $heap->{remote_wheel}->flush; delete $heap->{remote}; $heap->{local_wheel}->put("remote server Disconnected\n"); #delete $heap->{local_wheel}; $heap->{local_socket}->flush ; close $heap->{local_socket}; } }