App-ReslirpTunnel

 view release on metacpan or  search on metacpan

lib/App/ReslirpTunnel/ElevatedSlave.pm  view on Meta::CPAN


sub _hello__rpc {
    return { status => "ok" }
}

sub _run {
    my $self = shift;

    while (1) {
        $self->_log(debug => "Waiting for request");
        my $request = $self->{rpc}->recv_packet();

        my $cmd = $request->{cmd};
        $self->_log(debug => "Received request: $cmd");
        my $method = "_${cmd}__rpc";
        my ($r, $fd);
        eval {
            $r = $self->$method($request->{args}) // {};
            $r->{status} //= "ok";
            $fd = delete $r->{fd};
            if (defined $fd) {
                $r->{fd_follows} = 1;
            }
        };
        if ($@) {
            $r = { status => "error", error => $@ };
        }
        $self->{rpc}->send_packet($r);
        if (defined $fd) {
            $self->{rpc}->send_fd($fd);
        }
        $self->_log(debug => "Request completed with status $r->{status}");
        last if ($r->{status} eq 'bye');
    }
    $self->_log(info => "Bye bye!");
}

sub new {
    my ($class, %args) = @_;
    my $self = { socket => $args{socket} };
    bless $self, $class;

    $self->_init_logger(log_level => $args{log_level},
                        log_to_stderr => $args{log_to_stderr},
                        log_file => $args{log_file},
                        log_uid => $args{log_uid},
                        log_prefix => "ReslirpTunnel::ElevatedSlave");

    $self->{rpc} = App::ReslirpTunnel::RPC->new($args{socket});
    $self->_log(info => "Evalated slave started");
    $self
}

sub _init_logger {
    my ($self, %args) = @_;
    # We need to open a different log file for the elevated slave as
    # we are running under a different user (root) and don't have
    # permission to write to the user's log file.

    $args{log_file} =~ s/((?:\.[^\.]+)?)$/.elevated$1/ if defined $args{log_file};
    $self->SUPER::_init_logger(%args);
}

sub _hex2arg {
    my $hex = shift;
    my $arg = pack("H*", $hex);
    # warn "$hex --> $arg\n";
    utf8::decode($arg);
    return $arg;
}

sub start {
    # Recover socket from the file descriptor passed by the parent
    POSIX::dup2(1, 3);
    POSIX::dup2(2, 1);

    $SIG{INT} = 'IGNORE';

    # Detach from the controlling terminal
    POSIX::setsid();

    my $pid = fork;
    if (defined $pid and $pid == 0) {
        my $socket = IO::Socket::UNIX->new_from_fd(3, "r+")
            or die "Failed to create socket: $!";

        my $dont_close_stdio = _hex2arg(shift @main::ARGV);
        my $log_level = _hex2arg(shift @main::ARGV);
        my $log_to_stderr = _hex2arg(shift @main::ARGV);
        my $log_file = ($log_to_stderr ? undef : _hex2arg(shift @main::ARGV));
        my $log_uid = ($log_to_stderr ? undef : _hex2arg(shift @main::ARGV));

        unless ($dont_close_stdio) {
            open STDIN, '<', '/dev/null';
            open STDOUT, '>', '/dev/null';
            open STDERR, '>', '/dev/null' unless $log_to_stderr;
        }

        my $server = __PACKAGE__->new(socket => $socket,
                                      dont_close_stdio => $dont_close_stdio,
                                      log_level => $log_level,
                                      log_to_stderr => $log_to_stderr,
                                      log_file => $log_file,
                                      log_uid => $log_uid);
        $server->_run();
    }
    POSIX::_exit(0);
}
1;



( run in 0.688 second using v1.01-cache-2.11-cpan-b301d465b3d )