#!/usr/bin/env raku
subset Host of Str;
subset Port of UInt where 0 <= * <= 65_535;
unit sub MAIN(
Host :b(:$bind) = '127.0.0.1', #= Bind to this address
Port :p(:$port) = 8888, #= Bind to this port
Bool :d(:$debug) = False, #= Show debug messages
*@cmd, #= Command to run
);
note "Missing command\n$*USAGE" and exit 1 unless @cmd.elems;
react {
whenever IO::Socket::Async.listen: $bind, $port -> $client {
say "[+] New client on ", .peer-host, ":", .peer-port given $client;
my $proc = Proc::Async.new: :w, |@cmd;
# proc related IO
whenever $proc.ready { say "[+] Started process: {@cmd[0]}({$_})" }
whenever $proc.Supply(:bin) {
say "client.print: ", $_.decode.raku if $debug;
await $client.print: $_.decode;
}
whenever $proc.start {
say 'Proc finished: exitcode=', .exitcode, ' signal=', .signal;
$client.close;
}
# client socket related IO
whenever $client.Supply(:bin) {
say "proc.print: ", $_.decode.raku if $debug;
await $proc.print: $_.decode;
LAST {
say "[-] Lost client from ", .peer-host, ":", .peer-port given $client;
$proc.close-stdin;
$proc.kill(9);
}
}
}
whenever signal(SIGINT) { say "\r[-] bye !"; done }
say "[*] Listening on $bind:$port";
}