App-Termcast

 view release on metacpan or  search on metacpan

lib/App/Termcast.pm  view on Meta::CPAN

                $socket->recv($buf, 4096);
                if (!defined $buf || length $buf == 0) {
                    ReadMode(0, $self->input)
                        if $self->_has_term && $self->_term->_raw_mode;
                    Carp::croak("Invalid password");
                }
                elsif ($buf ne ('hello, ' . $self->user . "\n")) {
                    ReadMode(0, $self->input)
                        if $self->_has_term && $self->_term->_raw_mode;
                    Carp::carp("Unknown login response from server: $buf");
                    ReadMode(5, $self->input)
                        if $self->_has_term && $self->_term->_raw_mode;
                }
            }
        }
    }

    ReadMode(5, $self->input)
        if $self->_has_term && $self->_term->_raw_mode;
    return $socket;
}

before clear_socket => sub {
    my $self = shift;
    Carp::carp("Lost connection to server ($!), reconnecting...");
    $self->socket->close;
    ReadMode(0, $self->input)
        if $self->_has_term && $self->_term->_raw_mode;
};

sub _new_socket {
    my $self = shift;
    $self->_term->remove_input_handle($self->socket);
    $self->clear_socket;
    $self->_term->add_input_handle($self->socket);
}

has _needs_termsize_update => (
    traits  => ['NoGetopt'],
    is      => 'rw',
    isa     => 'Bool',
    default => 0,
);

has _term => (
    is        => 'ro',
    does      => 'Term::Filter',
    lazy      => 1,
    predicate => '_has_term',
    default   => sub {
        my $_self = shift;
        weaken(my $self = $_self);
        # XXX using ::Callback for now because we need to be able to
        # instantiate App::Termcast objects without initializing the terminal
        # (in case of just calling write_to_termcast). This should
        # eventually be deprecated in favor of moving the termcast interaction
        # code out to an App::Termcast::Writer module or something, and
        # this module should be a simple wrapper that combines that module
        # with Term::Filter.
        Term::Filter::Callback->new(
            callbacks => {
                setup => sub {
                    my ($term) = @_;
                    $term->add_input_handle($self->socket);
                },
                winch => sub {
                    # for the sake of sending a clear to the client anyway
                    syswrite $self->output, "\e[H\e[2J";
                    $self->_needs_termsize_update(1);
                },
                read_error => sub {
                    my ($term, $fh) = @_;
                    if ($fh == $self->socket) {
                        $self->_new_socket;
                    }
                },
                read => sub {
                    my ($term, $fh) = @_;
                    if ($fh == $self->socket) {
                        my $got = $term->_read_from_handle(
                            $self->socket, "socket"
                        );
                        $self->_new_socket unless defined $got;

                        if ($self->bell_on_watcher) {
                            # something better to do here?
                            syswrite $self->output, "\a";
                        }
                    }
                },
                munge_output => sub {
                    my ($term, $buf) = @_;
                    $self->write_to_termcast($buf);
                    $buf;
                },
            },
        );
    },
    handles => [ 'run', 'input', 'output' ],
);


sub write_to_termcast {
    my $self = shift;
    my ($buf) = @_;

    my $socket = $self->socket;
    my $select = IO::Select->new($socket);

    my (undef, $w, $e) = IO::Select->select(
        undef, $select, $select, $self->timeout,
    );

    my $err;

    for my $fh (@$e) {
        if ($fh == $socket) {
            $err = 1;
        }
    }



( run in 1.343 second using v1.01-cache-2.11-cpan-cdf2f3d4e48 )