});
}, sub {
my ($fh) = @_;
# could call $fh->bind etc. here
15
};
Example: connect to a UNIX domain socket.
tcp_connect "unix/", "/tmp/.X11-unix/X0", sub {
...
}
=cut
sub tcp_connect($$$;$) {
my ($host, $port, $connect, $prepare) = @_;
# see http://cr.yp.to/docs/connect.html for some background
# also http://advogato.org/article/672.html
my %state = ( fh => undef );
# name/service to type/sockaddr resolution
resolve_sockaddr $host, $port, 0, 0, 0, sub {
my @target = @_;
$state{next} = sub {
return unless exists $state{fh};
my $target = shift @target
or do {
%state = ();
return $connect->();
};
my ($domain, $type, $proto, $sockaddr) = @$target;
# socket creation
socket $state{fh}, $domain, $type, $proto
or return $state{next}();
fh_nonblocking $state{fh}, 1;
my $timeout = $prepare && $prepare->($state{fh});
$timeout ||= 30 if AnyEvent::WIN32;
$state{to} = AnyEvent->timer (after => $timeout, cb => sub {
$! = &Errno::ETIMEDOUT;
$state{next}();
}) if $timeout;
# called when the connect was successful, which,
# in theory, could be the case immediately (but never is in practise)
my $connected = sub {
delete $state{ww};
delete $state{to};
# we are connected, or maybe there was an error
if (my $sin = getpeername $state{fh}) {
my ($port, $host) = unpack_sockaddr $sin;
my $guard = guard {
%state = ();
};
$connect->($state{fh}, format_address $host, $port, sub {
$guard->cancel;
$state{next}();
});
} else {
# dummy read to fetch real error code
sysread $state{fh}, my $buf, 1 if $! == &Errno::ENOTCONN;
$state{next}();
}
};
# now connect
if (connect $state{fh}, $sockaddr) {
$connected->();
} elsif ($! == &Errno::EINPROGRESS # POSIX
|| $! == &Errno::EWOULDBLOCK
# WSAEINPROGRESS intentionally not checked - it means something else entirely
|| $! == AnyEvent::Util::WSAEINVAL # not convinced, but doesn't hurt
|| $! == AnyEvent::Util::WSAEWOULDBLOCK) {
$state{ww} = AnyEvent->io (fh => $state{fh}, poll => 'w', cb => $connected);
} else {
$state{next}();
}
};
$! = &Errno::ENXIO;
$state{next}();
};
defined wantarray && guard { %state = () }
}
=7= |