AnyEvent
view release on metacpan or search on metacpan
lib/AnyEvent/Socket.pm view on Meta::CPAN
tcp_server "unix/", "/tmp/mydir/mysocket", sub {
my ($fh) = @_;
};
=item $guard = AnyEvent::Socket::tcp_bind $host, $service, $done_cb[, $prepare_cb]
Same as C<tcp_server>, except it doesn't call C<accept> in a loop for you
but simply passes the listen socket to the C<$done_cb>. This is useful
when you want to have a convenient set up for your listen socket, but want
to do the C<accept>'ing yourself, for example, in another process.
In case of an error, C<tcp_bind> either croaks, or passes C<undef> to the
C<$done_cb>.
In non-void context, a guard will be returned. It will clean up/unlink the
listening socket when destroyed. In void context, no automatic clean up
might be performed.
=cut
sub _tcp_bind($$$;$) {
my ($host, $service, $done, $prepare) = @_;
$host = $AnyEvent::PROTOCOL{ipv4} < $AnyEvent::PROTOCOL{ipv6} && AF_INET6
? "::" : "0"
unless defined $host;
my $ipn = parse_address $host
or Carp::croak "tcp_bind: cannot parse '$host' as host address";
my $af = address_family $ipn;
my %state;
# win32 perl is too stupid to get this right :/
Carp::croak "tcp_bind: AF_UNIX address family not supported on win32"
if AnyEvent::WIN32 && $af == AF_UNIX;
socket my $fh, $af, SOCK_STREAM, 0
or Carp::croak "tcp_bind: $!";
$state{fh} = $fh;
if ($af == AF_INET || $af == AF_INET6) {
setsockopt $fh, SOL_SOCKET, SO_REUSEADDR, 1
or Carp::croak "tcp_bind: so_reuseaddr: $!"
unless AnyEvent::WIN32; # work around windows bug
unless ($service =~ /^\d*$/) {
$service = (getservbyname $service, "tcp")[2]
or Carp::croak "tcp_bind: unknown service '$service'"
}
} elsif ($af == AF_UNIX) {
unlink $service;
}
bind $fh, pack_sockaddr $service, $ipn
or Carp::croak "tcp_bind: $!";
if ($af == AF_UNIX and defined wantarray) {
# this is racy, but is not designed to be foolproof, just best-effort
my $ino = (lstat $service)[1];
$state{unlink} = guard {
unlink $service
if (lstat $service)[1] == $ino;
};
}
AnyEvent::fh_unblock $fh;
my $len;
if ($prepare) {
my ($service, $host) = unpack_sockaddr getsockname $fh;
$len = $prepare && $prepare->($fh, format_address $host, $service);
}
$len ||= 128;
listen $fh, $len
or Carp::croak "tcp_bind: $!";
$done->(\%state);
defined wantarray
? guard { %state = () } # clear fh, unlink
: ()
}
sub tcp_bind($$$;$) {
my ($host, $service, $done, $prepare) = @_;
_tcp_bind $host, $service, sub {
$done->(delete shift->{fh});
}, $prepare
}
sub tcp_server($$$;$) {
my ($host, $service, $accept, $prepare) = @_;
_tcp_bind $host, $service, sub {
my $rstate = shift;
$rstate->{aw} = AE::io $rstate->{fh}, 0, sub {
# this closure keeps $state alive
while ($rstate->{fh} && (my $peer = accept my $fh, $rstate->{fh})) {
AnyEvent::fh_unblock $fh; # POSIX requires inheritance, the outside world does not
my ($service, $host) = unpack_sockaddr $peer;
$accept->($fh, format_address $host, $service);
}
};
}, $prepare
}
=item tcp_nodelay $fh, $enable
Enables (or disables) the C<TCP_NODELAY> socket option (also known as
Nagle's algorithm). Returns false on error, true otherwise.
=cut
( run in 0.730 second using v1.01-cache-2.11-cpan-39bf76dae61 )