| 19 | | my @names = qw(EWOULDBLOCK EAGAIN EINPROGRESS); |
| 20 | | my %WOULDBLOCK = |
| 21 | | (eval {require Errno} ? map {Errno->can($_)->() => 1} grep {Errno->can($_)} @names : ()), |
| 22 | | (eval {require POSIX} ? map {POSIX->can($_)->() => 1} grep {POSIX->can($_)} @names : ()); |
| 23 | | |
| 24 | | sub WOULDBLOCK { $WOULDBLOCK{$_[0]+0} } |
| | 21 | my @names = qw(EWOULDBLOCK EAGAIN EINPROGRESS); |
| | 22 | my %WOULDBLOCK = |
| | 23 | (eval {require Errno} |
| | 24 | ? map { |
| | 25 | Errno->can($_) |
| | 26 | ? (Errno->can($_)->() => 1) |
| | 27 | : (), |
| | 28 | } @names |
| | 29 | : () |
| | 30 | ), |
| | 31 | (eval {require POSIX} |
| | 32 | ? map { |
| | 33 | eval { POSIX->can($_)->() } |
| | 34 | ? (POSIX->can($_)->() => 1) |
| | 35 | : () |
| | 36 | } @names |
| | 37 | : () |
| | 38 | ); |
| | 39 | |
| | 40 | sub WOULDBLOCK { $WOULDBLOCK{$_[0]+0} } |
| 31 | | my $pack = shift; |
| 32 | | my ($sset,$handle,$writeonly) = @_; |
| 33 | | # make the handle nonblocking |
| 34 | | $handle->blocking(0); |
| 35 | | my $self = bless { |
| 36 | | outbuffer => '', |
| 37 | | sset => $sset, |
| 38 | | handle => $handle, |
| 39 | | write_limit => BUFSIZE, |
| 40 | | writeonly => $writeonly, |
| 41 | | choker => undef, |
| 42 | | choked => 0, |
| 43 | | },$pack; |
| 44 | | $self->readable(1) unless $writeonly; |
| 45 | | return $self; |
| | 47 | my $pack = shift; |
| | 48 | my ($sset,$handle,$writeonly) = @_; |
| | 49 | # make the handle nonblocking (but check for 'blocking' method first) |
| | 50 | # thanks to Jos Clijmans <jos.clijmans@recyfin.be> |
| | 51 | $handle->blocking(0) if $handle->can('blocking'); |
| | 52 | my $self = bless { |
| | 53 | outbuffer => '', |
| | 54 | sset => $sset, |
| | 55 | handle => $handle, |
| | 56 | write_limit => BUFSIZE, |
| | 57 | writeonly => $writeonly, |
| | 58 | choker => undef, |
| | 59 | choked => 0, |
| | 60 | },$pack; |
| | 61 | $self->readable(1) unless $writeonly; |
| | 62 | return $self; |
| 82 | | my $self = shift; |
| 83 | | return unless my $handle = $self->handle; # no handle |
| 84 | | return unless defined $self->{outbuffer}; # no buffer for queued data |
| 85 | | |
| 86 | | $self->{outbuffer} .= $_[0] if defined $_[0]; |
| 87 | | |
| 88 | | my $rc; |
| 89 | | if ($self->pending) { # data in the out buffer to write |
| 90 | | local $SIG{PIPE}='IGNORE'; |
| 91 | | $rc = syswrite($handle,$self->{outbuffer}); |
| 92 | | |
| 93 | | # able to write, so truncate out buffer apropriately |
| 94 | | if ($rc) { |
| 95 | | substr($self->{outbuffer},0,$rc) = ''; |
| 96 | | } elsif (WOULDBLOCK($!)) { # this is OK |
| 97 | | $rc = '0E0'; |
| 98 | | } else { # some sort of write error, such as a PIPE error |
| 99 | | return $self->bail_out($!); |
| 100 | | } |
| 101 | | } else { |
| 102 | | $rc = '0E0'; # nothing to do, but no error either |
| 103 | | } |
| 104 | | |
| 105 | | $self->adjust_state; |
| 106 | | |
| 107 | | # Result code is the number of bytes successfully transmitted |
| 108 | | return $rc; |
| | 107 | my $self = shift; |
| | 108 | return unless my $handle = $self->handle; # no handle |
| | 109 | return unless defined $self->{outbuffer}; # no buffer for queued data |
| | 110 | |
| | 111 | $self->{outbuffer} .= $_[0] if defined $_[0]; |
| | 112 | |
| | 113 | my $rc; |
| | 114 | if ($self->pending) { # data in the out buffer to write |
| | 115 | local $SIG{PIPE}='IGNORE'; |
| | 116 | # added length() to make it work on Mac. Thanks to Robin Fuller <rfuller@broadjump.com> |
| | 117 | $rc = syswrite($handle,$self->{outbuffer},length($self->{outbuffer})); |
| | 118 | |
| | 119 | # able to write, so truncate out buffer apropriately |
| | 120 | if ($rc) { |
| | 121 | substr($self->{outbuffer},0,$rc) = ''; |
| | 122 | } |
| | 123 | elsif (WOULDBLOCK($!)) { # this is OK |
| | 124 | $rc = '0E0'; |
| | 125 | } |
| | 126 | else { # some sort of write error, such as a PIPE error |
| | 127 | return $self->bail_out($!); |
| | 128 | } |
| | 129 | } |
| | 130 | else { |
| | 131 | $rc = '0E0'; # nothing to do, but no error either |
| | 132 | } |
| | 133 | |
| | 134 | $self->adjust_state; |
| | 135 | |
| | 136 | # Result code is the number of bytes successfully transmitted |
| | 137 | return $rc; |
| 115 | | my $self = shift; |
| 116 | | return unless my $handle = $self->handle; |
| 117 | | my $rc = sysread($handle,$_[0],$_[1],$_[2]||0); |
| 118 | | return $rc if defined $rc; |
| 119 | | return '0E0' if WOULDBLOCK($!); |
| 120 | | return; |
| | 144 | my $self = shift; |
| | 145 | return unless my $handle = $self->handle; |
| | 146 | my $rc = sysread($handle,$_[0],$_[1],$_[2]||0); |
| | 147 | return $rc if defined $rc; |
| | 148 | return '0E0' if WOULDBLOCK($!); |
| | 149 | return; |
| 140 | | my $self = shift; |
| 141 | | |
| 142 | | # make writable if there's anything in the out buffer |
| 143 | | $self->writable($self->pending > 0); |
| 144 | | |
| 145 | | # make readable if there's no write limit, or the amount in the out |
| 146 | | # buffer is less than the write limit. |
| 147 | | $self->choke($self->write_limit <= $self->pending) if $self->write_limit; |
| 148 | | |
| 149 | | # Try to close down the session if it is flagged |
| 150 | | # as in the closing state. |
| 151 | | $self->close if $self->{closing}; |
| | 170 | my $self = shift; |
| | 171 | |
| | 172 | # make writable if there's anything in the out buffer |
| | 173 | $self->writable($self->pending > 0); |
| | 174 | |
| | 175 | # make readable if there's no write limit, or the amount in the out |
| | 176 | # buffer is less than the write limit. |
| | 177 | $self->choke($self->write_limit <= $self->pending) if $self->write_limit; |
| | 178 | |
| | 179 | # Try to close down the session if it is flagged |
| | 180 | # as in the closing state. |
| | 181 | $self->close if $self->{closing}; |
| 158 | | my $self = shift; |
| 159 | | my $do_choke = shift; |
| 160 | | return if $self->{choked} == $do_choke; # no change in state |
| 161 | | if (ref $self->set_choke eq 'CODE') { |
| 162 | | $self->set_choke->($self,$do_choke); |
| 163 | | } else { |
| 164 | | $self->readable(!$do_choke); |
| 165 | | } |
| 166 | | $self->{choked} = $do_choke; |
| | 188 | my $self = shift; |
| | 189 | my $do_choke = shift; |
| | 190 | return if $self->{choked} == $do_choke; # no change in state |
| | 191 | if (ref $self->set_choke eq 'CODE') { |
| | 192 | $self->set_choke->($self,$do_choke); |
| | 193 | } |
| | 194 | else { |
| | 195 | $self->readable(!$do_choke); |
| | 196 | } |
| | 197 | $self->{choked} = $do_choke; |