Acme-Sort-Sleep
view release on metacpan or search on metacpan
local/lib/perl5/IO/Async/Internals/Connector.pm view on Meta::CPAN
# You may distribute under the terms of either the GNU General Public License
# or the Artistic License (the same terms as Perl itself)
#
# (C) Paul Evans, 2008-2013 -- leonerd@leonerd.org.uk
package # hide from CPAN
IO::Async::Internals::Connector;
use strict;
use warnings;
our $VERSION = '0.70';
use Scalar::Util qw( weaken );
use POSIX qw( EINPROGRESS );
use Socket qw( SOL_SOCKET SO_ERROR );
use Future 0.21;
use Future::Utils 0.18 qw( try_repeat_until_success );
use IO::Async::OS;
use Carp;
use constant CONNECT_EWOULDLBOCK => IO::Async::OS->HAVE_CONNECT_EWOULDBLOCK;
# Internal constructor
sub new
{
my $class = shift;
my ( %params ) = @_;
my $loop = delete $params{loop} or croak "Expected a 'loop'";
my $self = bless {}, $class;
weaken( $self->{loop} = $loop );
return $self;
}
## Utility function
sub _get_sock_err
{
my ( $sock ) = @_;
my $err = $sock->getsockopt( SOL_SOCKET, SO_ERROR );
if( defined $err ) {
# 0 means no error, but is still defined
return undef if !$err;
$! = $err;
return $!;
}
# It seems we can't call getsockopt to query SO_ERROR. We'll try getpeername
if( defined getpeername( $sock ) ) {
return undef;
}
my $peername_errno = $!+0;
my $peername_errstr = "$!";
# Not connected so we know this ought to fail
if( read( $sock, my $buff, 1 ) ) {
# That was most unexpected. getpeername fails because we're not
# connected, yet read succeeds.
warn "getpeername fails with $peername_errno ($peername_errstr) but read is successful\n";
warn "Please see http://rt.cpan.org/Ticket/Display.html?id=38382\n";
$! = $peername_errno;
return $!;
}
return $!;
}
sub _connect_addresses
{
my $self = shift;
my ( $addrlist, $on_fail ) = @_;
my $loop = $self->{loop};
my ( $connecterr, $binderr, $socketerr );
my $future = try_repeat_until_success {
my $addr = shift;
my ( $family, $socktype, $protocol, $localaddr, $peeraddr ) =
@{$addr}{qw( family socktype protocol localaddr peeraddr )};
my $sock = IO::Async::OS->socket( $family, $socktype, $protocol );
if( !$sock ) {
$socketerr = $!;
( run in 1.378 second using v1.01-cache-2.11-cpan-39bf76dae61 )