Skip Menu |

This queue is for tickets about the IO-Async CPAN distribution.

Report information
The Basics
Id: 73388
Status: resolved
Priority: 0/
Queue: IO-Async

People
Owner: Nobody in particular
Requestors: leonerd-cpan [...] leonerd.org.uk
Cc:
AdminCc:

Bug Information
Severity: Wishlist
Broken in: 0.45
Fixed in:
  • 0.46_002
  • 0.47



Subject: Listener IPV6_V6ONLY control
Hard to do IPv4+IPv6-clean listening sockets in a portable manner. Need control of the IPV6_V6ONLY sockopt. Consider $listener->listen( addr => { family => "inet6", port => 1234, ip => "::", v6only => 0 }, ... ); -- Paul Evans
This is made more complicated by the fact that it's a sockopt, which will need special handling in ->unpack_addrinfo() -- Paul Evans
This may also be somewhat easier with IO::Socket::IP -- Paul Evans
On Tue Dec 20 15:20:26 2011, PEVANS wrote: Show quoted text
> Hard to do IPv4+IPv6-clean listening sockets in a portable manner. Need > control of the IPV6_V6ONLY sockopt. > > Consider > > $listener->listen( > addr => { family => "inet6", port => 1234, ip => "::", v6only => 0 }, > ... > );
Added now, as $listener->listen( addr => { family => "inet6", ... }, v6only => 1, ); -- Paul Evans
Subject: rt73388.patch
=== modified file 'lib/IO/Async/Listener.pm' --- lib/IO/Async/Listener.pm 2012-03-12 19:01:27 +0000 +++ lib/IO/Async/Listener.pm 2012-03-18 15:08:40 +0000 @@ -15,7 +15,11 @@ use POSIX qw( EAGAIN ); -use Socket qw( sockaddr_family SOL_SOCKET SO_ACCEPTCONN SO_REUSEADDR SO_TYPE ); +use Socket qw( + sockaddr_family + SOL_SOCKET SO_ACCEPTCONN SO_REUSEADDR SO_TYPE + AF_INET6 IPPROTO_IPV6 IPV6_V6ONLY +); use Carp; @@ -389,6 +393,13 @@ Optional. If true or not supplied then the C<SO_REUSEADDR> socket option will be set. To prevent this, pass a false value such as 0. +=item v6only => BOOL + +Optional. If defined, sets or clears the C<IPV6_V6ONLY> socket option on +C<PF_INET6> sockets. This option disables the ability of C<PF_INET6> socket to +accept connections from C<AF_INET> addresses. Not all operating systems allow +this option to be disabled. + =back As a convenience, it also supports a C<handle> argument, which is passed @@ -430,6 +441,8 @@ my $reuseaddr = 1; $reuseaddr = 0 if defined $params{reuseaddr} and not $params{reuseaddr}; + my $v6only = $params{v6only}; + my ( $listenerr, $binderr, $sockopterr, $socketerr ); foreach my $addr ( @$addrlist ) { @@ -439,27 +452,35 @@ unless( $sock = $loop->socket( $family, $socktype, $proto ) ) { $socketerr = $!; - $on_fail->( "socket", $family, $socktype, $proto, $! ) if $on_fail; + $on_fail->( socket => $family, $socktype, $proto, $! ) if $on_fail; next; } if( $reuseaddr ) { unless( $sock->sockopt( SO_REUSEADDR, 1 ) ) { $sockopterr = $!; - $on_fail->( "sockopt", $sock, SO_REUSEADDR, 1, $! ) if $on_fail; + $on_fail->( sockopt => $sock, SO_REUSEADDR, 1, $! ) if $on_fail; + next; + } + } + + if( defined $v6only and $family == AF_INET6 ) { + unless( $sock->setsockopt( IPPROTO_IPV6, IPV6_V6ONLY, $v6only ) ) { + $sockopterr = $!; + $on_fail->( sockopt => $sock, IPV6_V6ONLY, $v6only, $! ) if $on_fail; next; } } unless( $sock->bind( $address ) ) { $binderr = $!; - $on_fail->( "bind", $sock, $address, $! ) if $on_fail; + $on_fail->( bind => $sock, $address, $! ) if $on_fail; next; } unless( $sock->listen( $queuesize ) ) { $listenerr = $!; - $on_fail->( "listen", $sock, $queuesize, $! ) if $on_fail; + $on_fail->( listen => $sock, $queuesize, $! ) if $on_fail; next; }