if (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 eq $_[0]) {
return "::";
} elsif (v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1 eq $_[0]) {
return "::1";
} elsif (v0.0.0.0.0.0.0.0.0.0.0.0 eq substr $_[0], 0, 12) {
# v4compatible
return "::" . format_address substr $_[0], 12;
} elsif (v0.0.0.0.0.0.0.0.0.0.255.255 eq substr $_[0], 0, 12) {
# v4mapped
return "::ffff:" . format_address substr $_[0], 12;
} elsif (v0.0.0.0.0.0.0.0.255.255.0.0 eq substr $_[0], 0, 12) {
# v4translated
return "::ffff:0:" . format_address substr $_[0], 12;
} else {
my $ip = sprintf "%x:%x:%x:%x:%x:%x:%x:%x", unpack "n8", $_[0];
# this is rather sucky, I admit
$ip =~ s/^0:(?:0:)*(0$)?/::/
or $ip =~ s/(:0){7}$/::/ or $ip =~ s/(:0){7}/:/
or $ip =~ s/(:0){6}$/::/ or $ip =~ s/(:0){6}/:/
or $ip =~ s/(:0){5}$/::/ or $ip =~ s/(:0){5}/:/
or $ip =~ s/(:0){4}$/::/ or $ip =~ s/(:0){4}/:/
or $ip =~ s/(:0){3}$/::/ or $ip =~ s/(:0){3}/:/
or $ip =~ s/(:0){2}$/::/ or $ip =~ s/(:0){2}/:/
or $ip =~ s/(:0){1}$/::/ or $ip =~ s/(:0){1}/:/;
return $ip
}
} elsif ($af == AF_UNIX) {
return "unix/"
} else {
return undef
}
}
*format_ip = \&format_address;
=item inet_aton $name_or_address, $cb->(@addresses)
Works similarly to its Socket counterpart, except that it uses a
callback. Also, if a host has only an IPv6 address, this might be passed
to the callback instead (use the length to detect this - 4 for IPv4, 16
for IPv6).
Unlike the L<Socket> function of the same name, you can get multiple IPv4
and IPv6 addresses as result (and maybe even other adrdess types).
=cut
sub inet_aton {
my ($name, $cb) = @_;
if (my $ipn = &parse_ipv4) {
$cb->($ipn);
} elsif (my $ipn = &parse_ipv6) {
$cb->($ipn);
} elsif ($name eq "localhost") { # rfc2606 et al.
$cb->(v127.0.0.1, v0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1);
} else {
require AnyEvent::DNS;
# simple, bad suboptimal algorithm
AnyEvent::DNS::a ($name, sub {
if (@_) {
$cb->(map +(parse_ipv4 $_), @_);
} else {
$cb->();
#AnyEvent::DNS::aaaa ($name, $cb); need inet_pton
}
});
}
}
# check for broken platforms with extra field in sockaddr structure
# kind of a rfc vs. bsd issue, as usual (ok, normally it's a
# unix vs. bsd issue, a iso C vs. bsd issue or simply a
# correctness vs. bsd issue.
my $pack_family = (0x55 == Socket::sockaddr_family "\x55\x55")
? "xC" : "S";
=item $sa = AnyEvent::Socket::pack_sockaddr $service, $host
Pack the given port/host combination into a binary sockaddr
structure. Handles both IPv4 and IPv6 host addresses, as well as UNIX
domain sockets (C<$host> == C<unix/> and C<$service> == absolute
pathname).
=cut
sub pack_sockaddr($$) {
my $af = address_family $_[1];
if ($af == AF_INET) {
Socket::pack_sockaddr_in $_[0], $_[1]
} elsif ($af == AF_INET6) {
pack "$pack_family nL a16 L",
AF_INET6,
$_[0], # port
0, # flowinfo
$_[1], # addr
0 # scope id
=3= |