Skip to content

Instantly share code, notes, and snippets.

@woosley
Created July 19, 2011 12:08
Show Gist options
  • Save woosley/1092111 to your computer and use it in GitHub Desktop.
Save woosley/1092111 to your computer and use it in GitHub Desktop.
POE port forward
#!/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};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment