package POEDaemon::DNS; use strict; use warnings FATAL => 'all'; no warnings 'redefine'; use POE qw(Component::Client::DNS); use POEDaemon; sub states { return $_[0], [qw( dns_start dns_stop dns_query dns_response )]; } sub dns_start { my ($kernel, $heap) = @_[KERNEL, HEAP]; $heap->{dns} = POE::Component::Client::DNS->spawn ( Alias => 'dns', Timeout => 10, #Nameservers => [], HostsFile => '', ); $kernel->delay(tcpclient_find_target => connretry_rand); } sub dns_stop { my $heap = $_[HEAP]; $heap->{dns}->shutdown if $heap->{dns}; } sub dns_query { my ($heap, $args) = @_[HEAP, ARG0]; return if $heap->{shutdown}; return unless $heap->{dns}; my $host = $args->{host} || return; my $searchlist_0 = ($heap->{dns}->get_resolver->searchlist)[0]; if ($searchlist_0 && $host !~ /\./) { $host = sprintf "%s.%s", $host, $searchlist_0; } $heap->{dns}->resolve ( class => 'IN', type => 'ANY', host => $host, context => {}, event => 'dns_response', ); } sub dns_response { my ($kernel, $heap, $response) = @_[KERNEL, HEAP, ARG0]; return if $heap->{shutdown}; unless ($response->{response}) { log_enabled && logline "error '%s', retry", $response->{error}; unless ($heap->{shutdown}) { $kernel->delay(tcpclient_find_target => connretry_rand); } return; } my @answers = $response->{response}->answer; unless (@answers) { log_enabled && logline 'no answer, retry'; unless ($heap->{shutdown}) { $kernel->delay(tcpclient_find_target => connretry_rand); } return; } my @results; foreach my $answer (@answers) { my $type = uc $answer->type; my $rdatastr = $answer->rdatastr; if ($type =~ /^A(?:AAA)?$/i) { log_enabled && logline "'%s' '%s' '%s' = '%s'", $response->{host}, $response->{class}, $type, $rdatastr; next if $type eq 'A' && $heap->{tcpclient_connretry_count} <= 10; push @results, { type => $type, addr => $rdatastr, }; } } unless (@results) { log_enabled && logline 'no valid answers, retry'; unless ($heap->{shutdown}) { $kernel->delay(tcpclient_find_target => connretry_rand); } return; } my $random_result = $results[int rand $#results + 1]; log_enabled && logline "random result: type = '%s', addr = '%s'", $random_result->{type}, $random_result->{addr}; my $socketdomain; if ($random_result->{type} eq 'A') { $socketdomain = 'inet'; } elsif ($random_result->{type} eq 'AAAA') { $socketdomain = 'inet6'; } unless ($socketdomain) { log_enabled && logline 'invalid answer, retry'; unless ($heap->{shutdown}) { $kernel->delay(tcpclient_find_target => connretry_rand); } return; } $kernel->yield(tcpclient_init => { socketdomain => $socketdomain, remoteaddress => $random_result->{addr}, }); } 1;