AnyEvent-DNS-EtcHosts

 view release on metacpan or  search on metacpan

lib/AnyEvent/DNS/EtcHosts.pm  view on Meta::CPAN

            $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
sub _load_hosts_unless(&$@) {
    my ($cont, $cv, @dns) = @_;

    if (@dns) {
        $cv->end;
    } else {
        my $etc_hosts
            = length $ENV{PERL_ANYEVENT_HOSTS} ? $ENV{PERL_ANYEVENT_HOSTS}
            : AnyEvent::WIN32                  ? "$ENV{SystemRoot}/system32/drivers/etc/hosts"
            :                                    "/etc/hosts";

        push @HOSTS_CHECKING, sub {
            $cont->();
            $cv->end;
        };

        unless ($#HOSTS_CHECKING) {

            # we are not the first, so we actually have to do the work
            require AnyEvent::IO;

            AnyEvent::IO::aio_stat(
                $etc_hosts,
                sub {
                    if ((stat _)[9] ne ($HOSTS_MTIME || 0)) {
                        AE::log 8 => "(re)loading $etc_hosts.";
                        $HOSTS_MTIME = (stat _)[9];

                        # we might load a newer version of hosts,but that's a harmless race,
                        # as the next call will just load it again.
                        AnyEvent::IO::aio_load(
                            $etc_hosts,
                            sub {
                                _parse_hosts $_[0];
                                (shift @HOSTS_CHECKING)->() while @HOSTS_CHECKING;
                            }
                        );
                    } else {
                        (shift @HOSTS_CHECKING)->() while @HOSTS_CHECKING;
                    }
                }
            );
        }
    }
}

=head2 request

=for markdown ```perl

    $resolver->request($req, $cb->($res))

=for markdown ```

This is a wrapper for L<AnyEvent::DNS>->request method.

=cut

sub request {
    my ($self, $req, $cb) = @_;
    warn "req = " . Dumper $req if DEBUG;

    my $node = my $domain = $req->{qd}[0][0];
    $node =~ s/^_[a-z0-9-]*\._[a-z0-9-]*\.// if ($req->{qd}[0][1] eq 'srv');

    my $type = $req->{qd}[0][1];

    my (@ipv4, @ipv6, @srv);

    my $cv = AE::cv;

    $cv->begin;
    _load_hosts_unless {
        if (exists $HOSTS{$node}) {
            if ($type =~ /^([*]|srv)$/) {
                push @srv, $node;
            }
            if (ref $HOSTS{$node} eq 'ARRAY') {
                if ($type =~ /^([*]|a)$/ and exists $HOSTS{$node}[0]) {
                    push @ipv4, @{ $HOSTS{$node}[0] };
                }
                if ($type =~ /^([*]|aaaa)$/ and exists $HOSTS{$node}[1]) {



( run in 1.065 second using v1.01-cache-2.11-cpan-5511b514fd6 )