Skip to content

Instantly share code, notes, and snippets.

@igorcoding
Created June 5, 2015 14:21
Show Gist options
  • Save igorcoding/3e7293548db3c44f3c6f to your computer and use it in GitHub Desktop.
Save igorcoding/3e7293548db3c44f3c6f to your computer and use it in GitHub Desktop.
use 5.010;
use strict;
use warnings;
use AnyEvent;
use AnyEvent::Handle;
use AnyEvent::Socket;
use AnyEvent::Log;
use Data::Dumper;
$AnyEvent::Log::FILTER->level("info");
sub start_server {
my ($server_port, $remote_host, $remote_port) = @_;
# say Dumper \@_;
my $cb = pop;
my %handlers;
my $w; $w = AnyEvent->signal (
signal => "INT",
cb => sub {
undef $w;
AE::log info => "Shutting down...";
for my $k (keys %handlers) {
$handlers{$k}->destroy;
}
%handlers = ();
undef %handlers;
$cb->();
}
);
tcp_server undef, $server_port, sub {
my ($client_fh, $host, $port) = @_;
AE::log info => "Client connected: $host:$port.";
tcp_connect $remote_host, $remote_port, sub {
my ($remote_fh) = @_ or die "$remote_host:$remote_port connect failed: $!";
AE::log info => "Connected to remote host: $remote_host:$remote_port.";
my $remote_hdl;
my $client_hdl;
my $destroy = sub {
$remote_hdl->destroy;
$client_hdl->destroy;
delete @handlers{$remote_hdl, $client_hdl};
};
$remote_hdl = new AnyEvent::Handle(
fh => $remote_fh,
on_error => sub {
my ($hdl, $fatal, $msg) = @_;
AE::log error => $msg;
$destroy->();
},
on_eof => sub {
my $hdl = shift;
AE::log info => "Remote host $remote_host:$remote_port disconnected.";
$destroy->();
}
);
$handlers{$remote_hdl} = $remote_hdl;
$client_hdl = new AnyEvent::Handle(
fh => $client_fh,
on_error => sub {
my ($hdl, $fatal, $msg) = @_;
AE::log error => $msg;
$destroy->();
},
on_eof => sub {
my $hdl = shift;
AE::log info => "Client $host:$port disconnected.";
$destroy->();
}
);
$handlers{$client_hdl} = $client_hdl;
$client_hdl->on_read(sub {
my $rbuf = $client_hdl->rbuf;
$client_hdl->rbuf = '';
$remote_hdl->push_write($rbuf);
});
$remote_hdl->on_read(sub {
my $rbuf = $remote_hdl->rbuf;
$remote_hdl->rbuf = '';
$client_hdl->push_write($rbuf);
});
};
}, sub {
my ($fh, $thishost, $thisport) = @_;
AE::log info => "Listening on $thishost:$thisport.";
};
}
sub main {
my ($port, $remote_host, $remote_port) = @ARGV;
my $cv = AE::cv();
start_server($port, $remote_host, $remote_port, sub {
$cv->send();
});
$cv->recv();
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment