NAME
Socket::GetAddrInfo
- RFC 2553's getaddrinfo
and getnameinfo
functions.
SYNOPSIS
use Socket qw( SOCK_STREAM );
use Socket::GetAddrInfo qw( getaddrinfo getnameinfo );
use IO::Socket;
my $sock;
my %hints = ( socktype => SOCK_STREAM );
my ( $err, @res ) = getaddrinfo( "www.google.com", "www", \%hints );
die "Cannot resolve name - $err" if $err;
while( my $ai = shift @res ) {
$sock = IO::Socket->new();
$sock->socket( $ai->{family}, $ai->{socktype}, $ai->{protocol} ) or
undef $sock, next;
$sock->connect( $ai->{addr} ) or undef $sock, next;
last;
}
if( $sock ) {
my ( $err, $host, $service ) = getnameinfo( $sock->peername );
print "Connected to $host:$service\n" if !$err;
}
DESCRIPTION
The RFC 2553 functions getaddrinfo
and getnameinfo
provide an abstracted way to convert between a pair of host name/service name and socket addresses, or vice versa. getaddrinfo
converts names into a set of arguments to pass to the socket()
and connect()
syscalls, and getnameinfo
converts a socket address back into its host name/service name pair.
These functions provide a useful interface for performing either of these name resolution operation, without having to deal with IPv4/IPv6 transparency, or whether the underlying host can support IPv6 at all, or other such issues. However, not all platforms can support the underlying calls at the C layer, which means a dilema for authors wishing to write forward-compatible code. Either to support these functions, and cause the code not to work on older platforms, or stick to the older "legacy" resolvers such as gethostbyname()
, which means the code becomes more portable.
This module attempts to solve this problem, by detecting at compiletime whether the underlying OS will support these functions. If it does not, the module will use pure-perl emulations of the functions using the legacy resolver functions instead. The emulations support the same interface as the real functions, and behave as close as is resonably possible to emulate using the legacy resolvers. See Socket::GetAddrInfo::Emul for details on the limits of this emulation.
As of Perl version 5.14.0, Perl already supports getaddrinfo
in core. On such a system, this module simply uses the functions provided by Socket
, and does not need to use its own compiled XS, or pure-perl legacy emulation.
EXPORT TAGS
The following tags may be imported by use Socket::GetAddrInfo qw( :tag )
:
- AI
-
Imports all of the
AI_*
constants forgetaddrinfo
flags - NI
-
Imports all of the
NI_*
constants forgetnameinfo
flags - EAI
-
Imports all of the
EAI_*
for error values - constants
-
Imports all of the above constants
FUNCTIONS
( $err, @res ) = getaddrinfo( $host, $service, $hints )
When given both host and service, this function attempts to resolve the host name to a set of network addresses, and the service name into a protocol and port number, and then returns a list of address structures suitable to connect() to it.
When given just a host name, this function attempts to resolve it to a set of network addresses, and then returns a list of these addresses in the returned structures.
When given just a service name, this function attempts to resolve it to a protocol and port number, and then returns a list of address structures that represent it suitable to bind() to.
When given neither name, it generates an error.
The optional $hints
parameter can be passed a HASH reference to indicate how the results are generated. It may contain any of the following four fields:
- flags => INT
-
A bitfield containing
AI_*
constants - family => INT
-
Restrict to only generating addresses in this address family
- socktype => INT
-
Restrict to only generating addresses of this socket type
- protocol => INT
-
Restrict to only generating addresses for this protocol
Errors are indicated by the $err
value returned; which will be non-zero in numeric context, and contain a string error message as a string. The value can be compared against any of the EAI_*
constants to determine what the error is. Rather than explicitly checking, see also Socket::GetAddrInfo::Strict which provides functions that throw exceptions on errors.
If no error occurs, @res
will contain HASH references, each representing one address. It will contain the following five fields:
- family => INT
-
The address family (e.g. AF_INET)
- socktype => INT
-
The socket type (e.g. SOCK_STREAM)
- protocol => INT
-
The protocol (e.g. IPPROTO_TCP)
- addr => STRING
-
The address in a packed string (such as would be returned by pack_sockaddr_in)
- canonname => STRING
-
The canonical name for the host if the
AI_CANONNAME
flag was provided, orundef
otherwise. This field will only be present on the first returned address.
( $err, $host, $service ) = getnameinfo( $addr, $flags )
This function attempts to resolve the given socket address into a pair of host and service names.
The optional $flags
parameter is a bitfield containing NI_*
constants.
Errors are indicated by the $err
value returned; which will be non-zero in numeric context, and contain a string error message as a string. The value can be compared against any of the EAI_*
constants to determine what the error is. Rather than explicitly checking, see also Socket::GetAddrInfo::Strict which provides functions that throw exceptions on errors.
BUILDING WITHOUT XS CODE
In some environments it may be preferred not to build the XS implementation, leaving a choice only of the core or pure-perl emulation implementations.
$ PERL_SOCKET_GETADDRINFO_NO_BUILD_XS=1 perl Build.PL
BUGS
Appears to FAIL on older Darwin machines (e.g.
osvers=8.11.1
). The failure mode occurs in t/02getnameinfo.t and appears to relate to an endian bug; expecting to receive80
and instead receiving20480
(which is a 16-bit80
byte-swapped).
SEE ALSO
http://tools.ietf.org/html/rfc2553 - Basic Socket Interface Extensions for IPv6
ACKNOWLEDGEMENTS
Christian Hansen <chansen@cpan.org> - for help with some XS features and Win32 build fixes.
Zefram <zefram@fysh.org> - for help with fixing some bugs in the XS code.
Reini Urban <rurban@cpan.org> - for help with older perls and more Win32 build fixes.
AUTHOR
Paul Evans <leonerd@leonerd.org.uk>