Skip to content

Instantly share code, notes, and snippets.

@ilyaevseev
Last active August 29, 2015 14:17
Show Gist options
  • Save ilyaevseev/5a586472010c3bc5e0af to your computer and use it in GitHub Desktop.
Save ilyaevseev/5a586472010c3bc5e0af to your computer and use it in GitHub Desktop.
Proxy between single uplink and multiple clients. Implements http://ru-root.livejournal.com/2617418.html -- Proxy transmits requests from all clients to uplink connection. All responses are sent to all clients.
#!/usr/bin/perl
use strict;
use warnings;
# apt-get install libio-async-loop-epoll-perl
use IO::Async::Loop::Epoll;
use IO::Async::Socket;
use constant {
DEFAULT_UPLINK_PORT => 1234,
DEFAULT_LISTEN_PORT => 1235,
};
my $uplink_host;
my $uplink_port;
my $listen_port;
my $uplink_stream;
my %client_streams;
my $loop = IO::Async::Loop::Epoll->new;
$loop->connect(
host => $uplink_host ||= '127.0.0.1',
service => $uplink_port ||= DEFAULT_UPLINK_PORT,
socktype => 'stream',
on_stream => sub {
my $uplink_stream = shift;
$uplink_stream->configure(
on_read => sub {
my ($self, $bufref, $eof) = @_;
$_->write($bufref) foreach keys %client_streams;
$$bufref = "";
return 0;
},
on_close => sub {
$loop->stop
},
);
$loop->add($uplink_stream);
},
on_connect_error => sub { die "FATAL: Cannot connect to uplink.\n" },
on_resolve_error => sub { die "FATAL: Cannot resolve - $_[0]\n" },
);
$loop->listen(
service => $listen_port || DEFAULT_LISTEN_PORT,
socktype => 'stream',
on_listen_error => sub { die "FATAL: Cannot listen.\n" },
on_resolve_error => sub { die "FATAL: Cannot resolve - $_[0]\n" },
on_stream => sub {
my ($self_listener, $stream) = @_;
$client_streams{$stream} = 1;
$stream->configure(
on_read => sub {
my ($self, $bufref, $eof) = @_;
$uplink_stream->write($bufref);
$$bufref = "";
return 0;
},
on_closed => sub {
my $self = shift;
delete $client_streams{$self};
}
);
$loop->add($stream);
},
);
$loop->loop_forever;
__END__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment