AnyEvent-DNS-EtcHosts
view release on metacpan or search on metacpan
lib/AnyEvent/DNS/EtcHosts.pm view on Meta::CPAN
=for markdown ```perl
use AnyEvent::DNS::EtcHosts server => '8.8.8.8';
$ perl -MAnyEvent::DNS::EtcHosts script.pl
=for markdown ```
Enables this module globally. Additional arguments will be passed to
L<AnyEvent::DNS> constructor.
=cut
sub import {
my ($class, %args) = @_;
$GUARD = $class->register(%args);
}
=head2 no AnyEvent::DNS::EtcHosts
Disables this module globally.
=cut
sub unimport {
my ($class) = @_;
undef $GUARD;
}
=head1 METHODS
=head2 register
=for markdown ```perl
require AnyEvent::DNS::EtcHosts;
$guard = AnyEvent::DNS::EtcHosts->register(%args);
undef $guard;
=for markdown ```
Enables this module in lexical scope. The module will be disabled out of
scope. Additional arguments will be passed to L<AnyEvent::DNS> constructor.
If you want to use AnyEvent::DNS::EtcHosts in lexical scope only, you should
use C<require> rather than C<use> keyword, because C<import> method enables
AnyEvent::DNS::EtcHosts globally.
=cut
sub register {
my ($class, %args) = @_;
my $old_resolver = $AnyEvent::DNS::RESOLVER;
$AnyEvent::DNS::RESOLVER = do {
my $resolver = AnyEvent::DNS::EtcHosts->new(
untaint => 1,
max_outstanding => $ENV{PERL_ANYEVENT_MAX_OUTSTANDING_DNS} || 1,
%args
);
if (not $args{server}) {
$ENV{PERL_ANYEVENT_RESOLV_CONF}
? $resolver->_load_resolv_conf_file($ENV{PERL_ANYEVENT_RESOLV_CONF})
: $resolver->os_config;
}
$resolver;
};
# Overwrite original helper function only if exists
my $old_helper = do {
\&AnyEvent::Socket::_load_hosts_unless
if ((prototype 'AnyEvent::Socket::_load_hosts_unless') || '') eq '&$@';
};
if ($old_helper) {
no warnings 'redefine';
*AnyEvent::Socket::_load_hosts_unless = sub (&$@) {
my ($cont, $cv, @dns) = @_;
$cv->end;
};
}
return AnyEvent::Util::guard {
$AnyEvent::DNS::RESOLVER = $old_resolver;
no warnings 'redefine';
*AnyEvent::Socket::_load_hosts_unless = $old_helper if $old_helper;
};
}
# Helper functions taken from AnyEvent::Socket 7.05
our %HOSTS; # $HOSTS{$nodename}[$ipv6] = [@aliases...]
our @HOSTS_CHECKING; # callbacks to call when hosts have been loaded
our $HOSTS_MTIME;
sub _parse_hosts($) {
%HOSTS = ();
for (split /\n/, $_[0]) {
s/#.*$//;
s/^[ \t]+//;
y/A-Z/a-z/;
my ($addr, @aliases) = split /[ \t]+/;
next unless @aliases;
if (my $ipv4 = AnyEvent::Socket::parse_ipv4 $addr) {
($ipv4) = $ipv4 =~ /^(.*)$/s if AnyEvent::TAINT;
push @{ $HOSTS{$_}[0] }, $ipv4 for @aliases;
} elsif (my $ipv6 = AnyEvent::Socket::parse_ipv6 $addr) {
($ipv6) = $ipv6 =~ /^(.*)$/s if AnyEvent::TAINT;
push @{ $HOSTS{$_}[1] }, $ipv6 for @aliases;
}
}
}
# helper function - unless dns delivered results, check and parse hosts, then call continuation code
( run in 1.309 second using v1.01-cache-2.11-cpan-97f6503c9c8 )