=head1 NAME

UniEvent::Resolver - performs asynchronous DNS resolution.



=head1 SYNOPSIS

    my $loop = UniEvent::Loop->new;
    my $resolver = new UniEvent::Resolver($loop);

    # simplified form and cancellation
    my $req = $resolver->resolve('crazypanda.ru', sub {
        my ($addr, $err, $req) = @_;
        say "cancelled" if $err == UE::SystemError::operation_canceled;
    });
    $req->cancel;

    # advanced form
    my $req = $resolver->resolve({
        node       => 'crazypanda.ru',
        service    => 'https',
        use_cache  => 1,
        on_resolve => sub {
            my ($addr, $err, $req) = @_;
            return if $err;
            say "resolved as ", $addr->[0]->ip, ":", $addr->[0]->port;
        },
    });
    
    # using loop's resolver
    $loop->resolver->resolve('crazypanda.ru', sub { ... });


=head1 DESCRIPTION

Resolver performs asynchronous DNS resolution, i.e. it maps symbolic names like "crazypanda.ru" into IP addresses like 91.234.119.79.

Under the hood it uses L<c-ares|https://c-ares.haxx.se/> library for performing resolution.

Normally, you don't need to call resolver methods directly, as methods like C<connect($host, $port)> in L<UniEvent::Tcp> implicitly uses this resolver.
However if you need to resolve something by yourself, it is recommended to use per-loop resolver instance accessible via loop's C<resolver()> method.
Such usage shares resolver's cache and worker connections across all loop's consumers.

    $loop->resolver->resolve(...);

Per-loop resolver is autocreated with default config on first use.
If you need your own custom-configured resolver, you need to create resolver instance and use it instead of per-loop resolver. Alternatively, you can change some
settings in per-loop resolver.



=head1 METHODS

=head2 new([$loop = default], [$config = default])

Constructs new resolver instance, binding the supplied C<$loop> to it and using
the provided config. The config is a hashref with the following properties:

=over

=item cache_expiration_time

If a cache entry is older (in seconds) than C<cache_expiration_time>, it will be deleted from cache and the actual resolving will be made,
adding a fresh entry into cache.

Default value: 1200 seconds.

=item cache_limit

Maximum size of cached addresses in the resolver cache.
All entries in cache will be cleared upon hitting the limit.

If set to zero, requests will not be cached at all.

Default value: 10000 records.

=item query_timeout

Timeout value for single request resolution, in seconds.

Default value: 5 seconds.

=item workers

Maximum number of concurrently resolved requests.

Default value: 5.

=back


=head2 resolve($hostname, $callback, [$timeout = 5.0])

=head2 resolve(\%params)

Initiates asynchronous DNS resolution. In the simple form, just hostname (node) to be resolved, callback and request timeout is expected.
In more advanced form, hashref with the following options is expected:

=over

=item node [required]

The host name to be resolved

=item timeout

Max time for address resolution, in seconds

=item service

string with port number or name of the service (see C</etc/services>) for port mapping.

=item port

Port number

=item hints

Address info hints. Use C<hints> function for costruction.

=item use_cache

If set to C<false>, cache is not used and actual resolving will be made (after which cache will not be updated).

=item on_resolve

The callback.

=back

The L<UniEvent::Resolver::Request> is returned. It can be used for tracking address
resolution or for the request cancellation.

Callback signature is:

    my ($addresses, $error, $request) = @_;

Where C<$addresses> is the array of L<Net::SockAddr>.


=head2 cache_expiration_time([$value]) {

Get/set cache expiration time in seconds.


=head2 cache_limit ([$value])

Get/set cache limit.


=head2 cache_size ()

Returns current size of the cache (number of entries).


=head2 queue_size ()

Returns the amount of requests, which are waiting to be resolved by workers.


=head2 clear_cache ()

Clears cache by force.


=head2 reset()

Cancels all resolving and pending requests.
Their callbacks will be called with C<UE::SystemError::operation_canceled> error.


=head1 FUNCTIONS

=head2 hints($family, $socktype, [$protocol = 0], [$flags = 0])

Constructs address info hints for address resolution.

    use UniEvent;
    use UniEvent::Resolver;

    my $hints = UniEvent::Resolver::hints(AF_INET, SOCK_STREAM, PF_INET)


The address info hints is opaque structure without any user visible operations
on it. Its sole purpose is to construct hints for the address resolution.

Flags can be:

=over

=item NUMERICSERV

If this option is set service field will be treated as a numeric value, i.e.
instead of "https" it will assume the number "443" (as a string).

=item CANONNAME

Resolves L<CNAME records|https://en.wikipedia.org/wiki/CNAME_record>

Check type constant

=back

=cut
