NAME

POE::Component::Client::DNS - a DNS client component

SYNOPSIS

use POE qw(Component::Client::DNS);

POE::Component::Client::DNS->spawn(
  Alias       => 'named',       # defaults to 'resolver'
  Timeout     => 120,           # defaults to 90 seconds
  Nameservers => [ localhost ], # defaults per Net::DNS
);

$kernel->post('named',     # posts to the 'named' alias
              'resolve',   # post to named's 'resolve' state
              'postback',  # which of our states will receive responses
              $address,    # the address to resolve
              'A', 'IN'    # the record type and class to return
             );

# Or

$kernel->post(named => resolve => [postback => $param], $address,'MX');

# When the specified postback state is an array reference, it will
# handle the first element as the name of the postback state, and
# any following parameters will be passed back in the $_[ARG0]
# array.

# This is the sub which is called when the session receives a
# 'postback' event.
sub postback_handler {
  my (@original_request_parameters) = @{$_[ARG0]}[0..2];
  my (@postback_parameters) = @{$_[ARG0]}[3..$#_[ARG0]];
  my ($net_dns_packet, $net_dns_errorstring) = @{$_[ARG1]};

  my $request_address = $original_request_parameters[0];

  unless (defined $net_dns_packet) {
    print "$request_address: error ($net_dns_errorstring)\n";
    return;
  }

  my @net_dns_answers = $net_dns_packet->answer;

  unless (@net_dns_answers) {
    print "$request_address: no answer\n";
    return;
  }

  foreach my $net_dns_answer (@net_dns_answers) {
    printf( "%25s (%-10.10s) %s\n",
            $request_address,
            $net_dns_answer->type,
            $net_dns_answer->rdatastr
          );
  }
}

DESCRIPTION

POE::Component::Client::DNS is a wrapper for non-blocking Net::DNS. It lets other tasks to run while something is waiting for a nameserver to respond, and it lets several DNS queries run in parallel.

DNS client components are not proper objects. Instead of being created, as most objects are, they are "spawned" as separate sessions. To avoid confusion (and hopefully not cause other confusion), they must be spawned with a spawn method, not created anew with a new one.

PoCo::Client::DNS's spawn method takes a few named parameters:

Alias => $session_alias

Alias sets the name by which the session will be known. If no alias is given, the component defaults to "resolver". The alias lets several sessions interact with resolver components without keeping (or even knowing) hard references to them. It's possible to spawn several DNS components with different names.

Timeout => $resolve_timeout

Timeout specifies the amount of time a DNS client component will wait for a response. $resolve_timeout holds a real number indicating how many seconds to wait. It's possible to wait for fractional seconds with it whether or not Time::HiRes is installed, but installing Time::HiRes will make the actual timeouts more accurate. The default timeout period is 90 seconds.

Nameservers => \@name_servers

Nameservers holds a reference to a list of nameservers to try. The nameservers are passed directly to Net::DNS::Resolver's nameservers method. Net::DNS::Resolver's default nameservers are the ones that occur in /etc/resolv.conf or its local equivalent.

Sessions communicate asynchronously with PoCo::Client::DNS. They post requests to it, and it posts responses back.

Requests are posted to the component's "resolve" state. They include the name of a state to post responses back to, an address to look up, and a reference to a list of record types to return. For example:

$kernel->post(resolver => resolve => # resolver session alias & state
         [ got_response => $param ], # my state to receive responses
            'poe.perl.org',          # look up poe.perl.org
            'ANY'                    # return any IN records found
          );

Requests include the state to which responses will be posted. In the previous example, the handler for a 'got_response' state will be called with each resolver response. If the passed through parameter for 'got_response' is an array reference then the first element will be treated as the name of the state, and any further elements will be passed back to the state as arguments.

Resolver responses come with two list references:

my ($request_packet, $response_packet) = @_[ARG0, ARG1];

$request_packet contains the address and record types from the original request, and any user specified parameters for postback:

my ($request_address, $request_type, $request_class, @params) = 
    @$request_packet;

$response_packet contains two things: a reference to a Net::DNS::Packet object (or undef on error), and the last Net::DNS::Resolver error string (which describes why the packet reference might be undef).

my ($response_packet, $response_error) = @$response_packet;

Please see the Net::DNS::Packet manpage for more information about DNS packets and their contents. The PoCo::Client::DNS test program is also a good example for using Net::DNS::Packet objects.

SEE ALSO

This component is built upon Net::DNS and POE. Please see its source code and the documentation for its foundation modules to learn more.

Also see the test program, t/01_resolve.t, in the PoCo::Client::DNS distribution.

BUGS

This component does not yet expose the full power of Net::DNS.

AUTHOR & COPYRIGHTS

POE::Component::Client::DNS is Copyright 1999-2002 by Rocco Caputo. All rights are reserved. POE::Component::Client::DNS is free software; you may redistribute it and/or modify it under the same terms as Perl itself.

Postback arguments were contributed by tag.

Rocco may be contacted by e-mail via rcaputo@cpan.org.