| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #  You may distribute under the terms of either the GNU General Public License | 
| 2 |  |  |  |  |  |  | #  or the Artistic License (the same terms as Perl itself) | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | #  (C) Paul Evans, 2010-2021 -- leonerd@leonerd.org.uk | 
| 5 |  |  |  |  |  |  |  | 
| 6 |  |  |  |  |  |  | package Net::Async::Tangence::Client::via::sshunix 0.16; | 
| 7 |  |  |  |  |  |  |  | 
| 8 | 1 |  |  | 1 |  | 777 | use v5.14; | 
|  | 1 |  |  |  |  | 3 |  | 
| 9 | 1 |  |  | 1 |  | 4 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 29 |  | 
| 10 |  |  |  |  |  |  |  | 
| 11 |  |  |  |  |  |  | # A tiny program we can run remotely to connect STDIN/STDOUT to a UNIX socket | 
| 12 |  |  |  |  |  |  | # given as $ARGV[0] | 
| 13 | 1 |  |  | 1 |  | 4 | use constant _NC_MICRO => <<'EOPERL'; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 260 |  | 
| 14 |  |  |  |  |  |  | use Socket qw( AF_UNIX SOCK_STREAM pack_sockaddr_un ); | 
| 15 |  |  |  |  |  |  | use IO::Handle; | 
| 16 |  |  |  |  |  |  | socket(my $socket, AF_UNIX, SOCK_STREAM, 0) or die "socket(AF_UNIX): $!\n"; | 
| 17 |  |  |  |  |  |  | connect($socket, pack_sockaddr_un($ARGV[0])) or die "connect $ARGV[0]: $!\n"; | 
| 18 |  |  |  |  |  |  | my $fd = fileno($socket); | 
| 19 |  |  |  |  |  |  | $socket->blocking(0); $socket->autoflush(1); | 
| 20 |  |  |  |  |  |  | STDIN->blocking(0); STDOUT->autoflush(1); | 
| 21 |  |  |  |  |  |  | my $rin = ""; | 
| 22 |  |  |  |  |  |  | vec($rin, 0, 1) = 1; | 
| 23 |  |  |  |  |  |  | vec($rin, $fd, 1) = 1; | 
| 24 |  |  |  |  |  |  | print "READY"; | 
| 25 |  |  |  |  |  |  | while(1) { | 
| 26 |  |  |  |  |  |  | select(my $rout = $rin, undef, undef, undef); | 
| 27 |  |  |  |  |  |  | if(vec($rout, 0, 1)) { | 
| 28 |  |  |  |  |  |  | sysread STDIN, my $buffer, 8192 or last; | 
| 29 |  |  |  |  |  |  | print $socket $buffer; | 
| 30 |  |  |  |  |  |  | } | 
| 31 |  |  |  |  |  |  | if(vec($rout, $fd, 1)) { | 
| 32 |  |  |  |  |  |  | sysread $socket, my $buffer, 8192 or last; | 
| 33 |  |  |  |  |  |  | print $buffer; | 
| 34 |  |  |  |  |  |  | } | 
| 35 |  |  |  |  |  |  | } | 
| 36 |  |  |  |  |  |  | EOPERL | 
| 37 |  |  |  |  |  |  |  | 
| 38 |  |  |  |  |  |  | sub connect | 
| 39 |  |  |  |  |  |  | { | 
| 40 | 0 |  |  | 0 | 0 |  | my $client = shift; | 
| 41 | 0 |  |  |  |  |  | my ( $uri, %args ) = @_; | 
| 42 |  |  |  |  |  |  |  | 
| 43 | 0 |  |  |  |  |  | my $host = $uri->authority; | 
| 44 | 0 |  |  |  |  |  | my $path = $uri->path; | 
| 45 |  |  |  |  |  |  | # Path will start with a leading /; we need to trim that | 
| 46 | 0 |  |  |  |  |  | $path =~ s{^/}{}; | 
| 47 |  |  |  |  |  |  |  | 
| 48 | 0 |  |  |  |  |  | my @sshargs; | 
| 49 | 0 | 0 | 0 |  |  |  | push @sshargs, "-4" if $args{family} and $args{family} eq "inet4"; | 
| 50 | 0 | 0 | 0 |  |  |  | push @sshargs, "-6" if $args{family} and $args{family} eq "inet6"; | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | return $client->connect_exec( | 
| 53 |  |  |  |  |  |  | # Tell the remote perl we're going to send it a program on STDIN | 
| 54 |  |  |  |  |  |  | [ 'ssh', @sshargs, $host, 'perl', '-', $path ] | 
| 55 |  |  |  |  |  |  | )->then( sub { | 
| 56 | 0 |  |  | 0 |  |  | $client->write( _NC_MICRO . "\n__END__\n" ); | 
| 57 | 0 |  |  |  |  |  | my $f = $client->new_future; | 
| 58 |  |  |  |  |  |  |  | 
| 59 |  |  |  |  |  |  | $client->configure( on_read => sub { | 
| 60 | 0 |  |  |  |  |  | my ( $self, $buffref, $eof ) = @_; | 
| 61 | 0 | 0 |  |  |  |  | return 0 unless $$buffref =~ s/READY//; | 
| 62 | 0 |  |  |  |  |  | $self->configure( on_read => undef ); | 
| 63 | 0 |  |  |  |  |  | $f->done; | 
| 64 | 0 |  |  |  |  |  | return 0; | 
| 65 | 0 |  |  |  |  |  | } ); | 
| 66 |  |  |  |  |  |  |  | 
| 67 | 0 |  |  |  |  |  | return $f; | 
| 68 | 0 |  |  |  |  |  | }); | 
| 69 |  |  |  |  |  |  | } | 
| 70 |  |  |  |  |  |  |  | 
| 71 |  |  |  |  |  |  | 0x55AA; |