NAME

    Net::LibAsyncNS - a Perl wrapper around libasyncns

SYNOPSIS

       use Net::LibAsyncNS;
       use Socket qw( SOCK_RAW );
    
       my $asyncns = Net::LibAsyncNS->new( 1 );
    
       # By specifying this socktype hint, we only get one result per address family
       my %hints = ( socktype => SOCK_RAW );
    
       my $query = $asyncns->getaddrinfo( "localhost", undef, \%hints );
    
       while( $asyncns->getnqueries ) {
          $asyncns->wait( 1 );
    
          if( $query->isdone ) {
             my ( $err, @res ) = $asyncns->getaddrinfo_done( $query );
             die "getaddrinfo - $err" if $err;
    
             foreach my $res ( @res ) {
                printf "family=%d, addr=%v02x\n", $res->{family}, $res->{addr};
             }
          }
       }

DESCRIPTION

    The name resolver functions getaddrinfo and getnameinfo as provided by
    most C libraries are blocking functions; they will perform their work
    and return an answer when it is ready. This makes it hard to use these
    name resolvers in asynchronous or non-blocking code.

    The libasyncns library provides a way to invoke these library functions
    from within an asynchronous or non-blocking program. Individual
    resolver queries are made by calling a function which returns an object
    representing an outstanding query (a kind of future). A filehandle is
    provided by the resolver to watch for readability; when it is readable,
    a function should be called to collect completed queries. The example
    in the SYNOPSIS above does not demonstrate this; see the EXAMPLES
    section below for one that does.

CONSTRUCTOR

 new

       $asyncns = Net::LibAsyncNS->new( $n_proc )

    Construct a new Net::LibAsyncNS object. It will be initialised with
    $n_proc processes or threads to handle nameserver lookups.

METHODS

 fd

       $fd = $asyncns->fd

    Returns a file descriptor number to poll for readability on.

 new_handle_for_fd

       $handle = $asyncns->new_handle_for_fd

    Returns a new IO::Handle object wrapping the underlying file
    descriptor. Note that the handle is not cached; a new object is created
    each time this method is called. For well-behaved results, this should
    only be called once.

 wait

       $success = $asyncns->wait( $block )

    Wait for more queries to be ready. If $block is true, this method will
    block until at least one query is ready, if false it will process any
    pending IO without blocking. It returns true if the operation was
    successful or false if an IO error happened; $! will be set in this
    case.

 getnqueries

       $n = $asyncns->getnqueries

    Return the number of outstanding queries.

 getaddrinfo

       $q = $asyncns->getaddrinfo( $host, $service, $hints )

    Starts an asynchronous getaddrinfo resolution on the given $host and
    $service names. If provided, $hints should be a HASH reference where
    the following keys are recognised:

    flags => INT

    family => INT

    socktype => INT

    protocol => INT

 getaddrinfo_done

       ( $err, @res ) = $asyncns->getaddrinfo_done( $q )

    Finishes a getaddrinfo resolution, returning an error code, and a list
    of results. Each result will be a HASH reference containing the
    following keys:

    family => INT

    socktype => INT

    protocol => INT

      Socket type values to pass to socket

    addr => STRING

      Address to pass to connect

    canonname => STRING

      If requested, the canonical hostname for this address

 getnameinfo

       $q = $asyncns->getnameinfo( $addr, $flags, $wanthost, $wantserv )

    Starts an asynchronous getnameinfo resolution on the given address. The
    $wanthost and $wantserv booleans indicate if the hostname or service
    name are required.

 getnameinfo_done

       ( $err, $host, $service ) = $asyncns->getnameinfo_done( $q )

    Finishes a getnameinfo resolution, returning an error code, the
    hostname and service name, if requested.

 res_query

 res_search

       $q = $asyncns->res_query( $dname, $class, $type )
    
       $q = $asyncns->res_search( $dname, $class, $type )

    Starts an asynchronous res_query or res_search resolution on the given
    domain name, class and type.

 res_done

       $answer = $asyncns->res_done( $q )

    Finishes a res_query or res_search resolution, returning the answer in
    a packed string, or undef if it fails. If it fails $! will contain the
    error details.

 isdone

       $done = $asyncns->isdone( $q )

    Returns true if the given query is ready.

 getnext

       $q = $asyncns->getnext

    Returns the next query object that is completed, or undef if none are
    ready yet. This will only yet be valid after calling the wait method at
    least once.

 cancel

       $asyncns->cancel( $q )

    Cancels a currently outstanding query. After this is called, the query
    in $q should not be further accessed, as memory associated with it will
    have been reclaimed.

 setuserdata

       $asyncns->setuserdata( $q, $data )

    Stores an arbitrary Perl scalar with the query. It can later be
    retrieved using getuserdata.

 getuserdata

       $data = $asyncns->getuserdata( $q )

    Returns the Perl scalar previously stored with the query, or undef if
    no value has yet been set.

CONSTANTS

    The following constants are provided by Net::LibAsyncNS::Constants.

    Flags for getaddrinfo:

       AI_PASSIVE
       AI_CANONNAME
       AI_NUMERICHOST
       AI_NUMERICSERV

    Error values:

       EAI_BADFLAGS
       EAI_NONAME
       EAI_AGAIN
       EAI_FAIL
       EAI_NODATA
       EAI_FAMILY
       EAI_SERVICE
       EAI_SOCKTYPE
       EAI_ADDRFAMILY
       EAI_MEMORY

    Flags for getnameinfo:

       NI_NUMERICHOST
       NI_NUMERICSERV
       NI_NAMEREQD
       NI_DGRAM

QUERY OBJECTS

    The following methods are available on query objects, returned by
    getaddrinfo and getnameinfo.

 asyncns

       $asyncns = $query->asyncns

    Returns the underlying Net::LibAsyncNS object backing the query

 isdone

       $done = $query->isdone

 setuserdata

       $query->setuserdata( $data )

 getuserdata

       $data = $query->getuserdata

    Shortcuts to the equivalent method on the underlying Net::LibAsyncNS
    object

EXAMPLES

 Multiple Queries

    The SYNOPSIS example only has one outstanding query. To wait for
    multiple queries to complete, the getnext method can be used. Per-query
    context data can be stored in the query itself by using the setuserdata
    and getuserdata accessors.

       use Net::LibAsyncNS;
       use Socket qw( SOCK_RAW );
    
       my $asyncns = Net::LibAsyncNS->new( 1 );
    
       my %hints = ( socktype => SOCK_RAW );
       my @hosts = qw( some hostnames here );
    
       foreach my $host ( @hosts ) {
          my $query = $asyncns->getaddrinfo( $host, undef, \%hints );
          $query->setuserdata( $host );
       }
    
       while( $asyncns->getnqueries ) {
          $asyncns->wait( 1 ) or die "asyncns_wait: $!";
    
          while( my $query = $asyncns->getnext ) {
             my ( $err, @res ) = $asyncns->getaddrinfo_done( $query );
             my $host = $query->getuserdata;
    
             print "$host - $err\n" and next if $err;
    
             foreach my $res ( @res ) {
                printf "%s is: family=%d, addr=%v02x\n", 
                   $host, $res->{family}, $res->{addr};
             }
          }
       }

    In this example, the per-query data stored by setuserdata is just the
    hostname, but any Perl scalar may be stored, such as a HASH ref
    containing many keys, or CODE ref to a callback function of some kind.

 Non-blocking IO

    The examples above wait synchronously for the query/queries to
    complete, in the wait method. However, most of the point of this
    library is to allow asynchronous resolver calls to mix with other
    asynchronous and non-blocking code. This is achieved by the containing
    program waiting for a filehandle to become readable, and to call
    $asyncns->wait( 0 ) when it is.

    The following example shows integration with a simple IO::Poll-based
    program.

       use IO::Poll;
       use Net::LibAsyncNS;
       use Socket qw( SOCK_RAW );
    
       my $asyncns = Net::LibAsyncNS->new( 1 );
       my %hints = ( socktype => SOCK_RAW );
    
       my @hosts = qw( some hostnames here );
    
       foreach my $host ( @hosts ) {
          my $query = $asyncns->getaddrinfo( $host, undef, \%hints );
          $query->setuserdata( $host );
       }
    
       my $asyncns_handle = $asyncns->new_handle_for_fd;
    
       my $poll = IO::Poll->new;
       $poll->mask( $asyncns_handle => POLLIN );
    
       while( $asyncns->getnqueries ) {
          defined $poll->poll or die "poll() - $!";
    
          if( $poll->events( $asyncns_handle ) ) {
             while( my $query = $asyncns->getnext ) {
                my ( $err, @res ) = $asyncns->getaddrinfo_done( $query );
                my $host = $query->getuserdata;
    
                print "$host - $err\n" and next if $err;
    
                foreach my $res ( @res ) {
                   printf "%s is: family=%d, addr=%v02x\n", 
                      $host, $res->{family}, $res->{addr};
                }
             }
          }
       }

SEE ALSO

      * http://0pointer.de/lennart/projects/libasyncns is a C library for
      Linux/Unix for executing name service queries asynchronously. It is
      an asynchronous wrapper around getaddrinfo(3), getnameinfo(3),
      res_query(3) and res_search(3) from libc and libresolv.

AUTHOR

    Paul Evans <leonerd@leonerd.org.uk>

