File Coverage

blib/lib/Devel/REPL/Client/Select.pm
Criterion Covered Total %
statement 19 64 29.6
branch 1 36 2.7
condition 0 9 0.0
subroutine 7 12 58.3
pod 0 4 0.0
total 27 125 21.6


line stmt bran cond sub pod time code
1             package Devel::REPL::Client::Select;
2              
3 1     1   756 use strict;
  1         1  
  1         24  
4 1     1   4 use warnings;
  1         1  
  1         20  
5              
6 1     1   3 use IO::Select;
  1         1  
  1         24  
7 1     1   3 use IO::Socket;
  1         1  
  1         4  
8 1     1   814 use Term::ReadKey;
  1         2753  
  1         85  
9              
10             use constant {
11 1         492 EOT => "\x04",
12 1     1   5 };
  1         1  
13              
14             my $RESTORE_READMODE;
15              
16             END {
17 1 50   1   9 ReadMode 0, \*STDIN if $RESTORE_READMODE;
18             }
19              
20             sub new {
21 0     0 0   my ($class, %args) = @_;
22             my $self = bless {
23             port => $args{port},
24             path => $args{path},
25             mode => $args{mode},
26 0           socket => undef,
27             }, $class;
28              
29 0           return $self;
30             }
31              
32             sub listen {
33 0     0 0   my ($self) = @_;
34              
35 0 0         if ($self->{port}) {
    0          
36             $self->{socket} = IO::Socket::INET->new(
37             Listen => 1,
38             LocalAddr => '127.0.0.1',
39             LocalPort => $self->{port},
40 0           Proto => 'tcp',
41             ReuseAddr => 1,
42             );
43             } elsif ($self->{path}) {
44 0 0         if (-S $self->{path}) {
45 0 0         unlink $self->{path} or die "Unable to unlink stale socket: $!";
46             }
47              
48             $self->{socket} = IO::Socket::UNIX->new(
49             Local => $self->{path},
50 0           );
51 0 0 0       if ($self->{socket} && defined $self->{mode}) {
52             chmod $self->{mode}, $self->{path}
53 0 0         or $self->{socket} = undef;
54             }
55 0 0         if ($self->{socket}) {
56             $self->{socket}->listen(1)
57 0 0         or $self->{socket} = undef;
58             }
59             }
60              
61 0 0         die "Unable to start listening: $!" unless $self->{socket};
62             }
63              
64             sub accept_and_process {
65 0     0 0   my ($self) = @_;
66 0           my $client = $self->{socket}->accept;
67              
68 0           $RESTORE_READMODE = 1;
69 0           ReadMode 3, \*STDIN;
70              
71 0           my $fds = IO::Select->new;
72              
73 0           $fds->add($client, \*STDIN);
74 0           $client->blocking(0);
75              
76 0           for (;;) {
77 0           my ($rd, undef, $err) = IO::Select->select($fds, undef, $fds, 10);
78              
79 0 0 0       if ($err && @$err) {
80 0           die "One of the handles became invalid";
81             }
82              
83 0           for my $hnd (@$rd) {
84 0 0         if ($hnd == $client) {
85 0           _from_to($client, \*STDOUT);
86             }
87 0 0         if ($hnd == \*STDIN) {
88 0           while (defined(my $key = ReadKey -1, \*STDIN)) {
89 0           my $ok = do {
90 0           local $SIG{PIPE} = 'IGNORE';
91 0           syswrite $client, $key;
92             };
93 0 0         die "Error during write: $!" if !defined $ok;
94 0 0         if ($key eq EOT) {
95 0           syswrite *STDOUT, "^D\n";
96 0           return;
97             }
98             }
99             }
100             }
101             }
102             }
103              
104             sub _from_to {
105 0     0     my ($from, $to) = @_;
106 0           my $buff;
107              
108 0           my $count = sysread $from, $buff, 1000;
109 0 0         die "Error during read: $!" if !defined $count;
110 0           my $written = syswrite $to, $buff, $count;
111 0 0 0       die "Error during write: $!" if !defined $written || $written != $count;
112             }
113              
114             sub close {
115 0     0 0   my ($self) = @_;
116              
117 0 0         $self->{socket}->close if $self->{socket};
118             }
119              
120             1;