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 )