App-BCSSH
view release on metacpan or search on metacpan
lib/App/BCSSH/Proxy.pm view on Meta::CPAN
package App::BCSSH::Proxy;
use Moo;
use File::Temp ();
use IO::Select;
use IO::Socket::UNIX;
use App::BCSSH::Message;
use Try::Tiny;
has agent_path => (is => 'ro');
has handlers => (is => 'ro', default => sub { { } } );
has umask => (is => 'ro', default => sub { 0077 } );
has _temp_dir => (is => 'lazy', init_arg => undef);
sub _build__temp_dir {
my $self = shift;
my $old_mask = umask($self->umask);
my $dir = File::Temp->newdir(TMPDIR => 1);
umask($old_mask);
return $dir;
}
has socket_path => (is => 'ro', lazy => 1, default => sub { $_[0]->_temp_dir . '/agent-proxy' } );
has _select => (is => 'ro', default => sub { IO::Select->new });
has server_socket => (is => 'lazy');
sub _build_server_socket {
my $self = shift;
unlink $self->socket_path;
my $old_mask = umask($self->umask);
my $server = IO::Socket::UNIX->new(
Local => $self->socket_path,
Listen => 10,
) or die "$!";
umask($old_mask);
$self->_select->add($server);
return $server;
}
has _clients => (is => 'ro', default => sub { { } });
sub proxy {
my ($self, $parent_fh) = @_;
my $done;
local $SIG{$_} = sub { $done = 1 } for qw(HUP INT TERM QUIT);
my $select = $self->_select;
$select->add($parent_fh)
if $parent_fh;
my $server = $self->server_socket;
my $clients = $self->_clients;
until ($done) {
for my $socket ($select->can_read) {
if ($parent_fh && $socket == $parent_fh) {
$done = 1;
}
elsif ($socket == $server) {
$self->new_client($socket);
}
elsif ($socket->sysread(my $buf, 4096)) {
$self->read_message($clients->{$socket}, $buf);
}
else {
$self->close_client($clients->{$socket}{client});
}
}
}
for my $client (values %$clients) {
$self->close_client($client->{client});
}
$select->remove($parent_fh)
if $parent_fh;
( run in 1.628 second using v1.01-cache-2.11-cpan-39bf76dae61 )