I finally managed to fix ipv6 support in my software. Unfortunately, now it crashes on every ipv4 only machine. Here is the faulty subroutine:
sub init
{
my ($self, %opts) = @_;
# server options defaults
my %defaults = (StartBackground => 0, ServerPort => 3000);
# set options or use defaults
map { $self->{$_} = (exists $opts{$_} ? $opts{$_} : $defaults{$_}) }
keys %defaults;
$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);
return $self;
}
The problem here is in the second last line:
$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);
As on ipv4 only machine it dies complaining about a not supported address family (which is the second parameter passed to the new function).
Basically, what I need to do is:
if (it_supports_ipv6()) {
$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6);
}
else {
$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'});
}
But how to implement a function like it_supports_ipv6()?
I tried with eval with the following syntax, but it doesn’t work:
my $ipv6_success = eval { $self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'}, Socket::AF_INET6); };
if (!defined($ipv6_success)) {
$self->{'server'} = HTTP::AppServer::Base->new($self->{'ServerPort'});
}
The logic is that I’ve read in eval doc that it returns undef if the expression causes the program to die.
I’m working on a Linux machine.
Don’t trust the
has_ipv6()function inParanoid::Network::Socket. It returns false positive as it just checks if Perl supports it, but this isn’t enough at all (the system, as example, could lack ipv6 kernel module loaded).I ended up with the following function and it seems to work fine.