EV-cares

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

eg/cli.pl
eg/dane.pl
eg/dns_compare.pl
eg/dns_proxy.pl
eg/dns_types.pl
eg/dnssec_chain.pl
eg/email_health.pl
eg/futures.pl
eg/healthcheck.pl
eg/healthmon.pl
eg/keep_alive.pl
eg/mta_probe.pl
eg/parallel.pl
eg/resolve.pl
eg/resolver_pool.pl
eg/reverse.pl
eg/spf.pl
eg/spf_chain.pl
eg/srv.pl
eg/svcb.pl
eg/timing.pl

cares.xs  view on Meta::CPAN


typedef struct {
    ev_io watcher;
    ares_socket_t fd;
} ev_cares_io_t;

struct ev_cares_s {
    U32 magic;
    ares_channel channel;
    struct ev_loop *loop;
    SV *loop_sv;       /* keeps a custom EV::Loop alive; NULL for default loop */
    ev_timer timer;
    ev_cares_io_t ios[MAX_IO];
    int active_queries;
    int destroyed;
    int in_callback;    /* prevent Safefree while callbacks run */
    int free_pending;   /* deferred Safefree after last callback */
    int cleanup_pending; /* deferred channel teardown after last callback */
    int last_timeouts;  /* timeouts count from the most recent callback */
};

cares.xs  view on Meta::CPAN

        }
 #endif
        else {
            warn("EV::cares::new: unknown option '%s'", key);
        }
    }

    Newxz(self, 1, ev_cares_t);
    self->magic = EV_CARES_MAGIC;
    self->loop = loop_ptr;
    /* Keep the EV::Loop's blessed object alive — its DESTROY calls
       ev_loop_destroy().  Holding the outer RV is not enough; inc the
       underlying SV (the IV that stores the loop pointer). */
    if (loop_sv) self->loop_sv = SvREFCNT_inc_simple_NN(SvRV(loop_sv));
    for (i = 0; i < MAX_IO; i++)
        self->ios[i].fd = ARES_SOCKET_BAD;

    opts.sock_state_cb = sock_state_cb;
    opts.sock_state_cb_data = self;
    optmask |= ARES_OPT_SOCK_STATE_CB;

eg/keep_alive.pl  view on Meta::CPAN

#!/usr/bin/env perl
# Long-running daemon pattern: a single EV::cares instance refreshes a
# fixed set of names every $interval seconds, handling transient upstream
# failures by calling reinit() (which re-reads /etc/resolv.conf) and
# logging fail-over behavior.  Intended as a copyable starting point for
# health-check daemons that need cached, periodically-refreshed records.
#
# Usage:
#   perl eg/keep_alive.pl                  # default 30s, defaults to a few hosts
#   perl eg/keep_alive.pl 5 cloudflare.com github.com
#   ^C to stop
use strict;
use warnings;
use EV;
use EV::cares qw(:all);

my $interval = (@ARGV && $ARGV[0] =~ /^\d+\z/) ? shift : 30;
my @names    = @ARGV ? @ARGV : qw(cloudflare.com github.com perl.org);

my %TRANSIENT = map { $_ => 1 }

eg/upstream_ad_check.pl  view on Meta::CPAN


# Need the EDNS flag so the upstream actually sets DO and reports AD;
# without it many resolvers strip the AD bit out of paranoia.
my $flags = ARES_FLAG_EDNS;

printf "Querying %s for an A record on %d resolver(s)\n\n", $name, scalar @servers;
printf "%-20s %-7s %-7s %-7s %s\n", 'server', 'rcode', 'ad', 'ra', 'note';
printf "%s\n", '-' x 60;

my $pending = scalar @servers;
my @resolvers;   # keep resolvers alive across the for loop iterations;
                 # otherwise each $r drops to refcount 0 at end-of-iter,
                 # DESTROY runs ares_destroy, and every callback fires
                 # with ARES_EDESTRUCTION before we ever pump EV::run.
for my $srv (@servers) {
    my $r = EV::cares->new(servers => [$srv], flags => $flags, timeout => 5);
    push @resolvers, $r;
    $r->query($name, C_IN, T_A, sub {
        my ($status, $buf) = @_;
        my $note = '';
        my ($rcode, $ad, $ra) = ('-', '-', '-');

t/06_loop.t  view on Meta::CPAN


# resolver retains the loop SV: dropping the user's last ref must not
# free the loop until the resolver itself is gone
{
    my $loop = EV::Loop->new;
    my $weak = $loop;
    weaken($weak);

    my $r = EV::cares->new(loop => $loop, lookups => 'f');
    undef $loop;
    ok(defined $weak, 'loop SV retained while resolver is alive');

    undef $r;
    ok(!defined $weak, 'loop SV released after resolver destroyed');
}

done_testing;

t/14_concurrent.t  view on Meta::CPAN

    my $count = 0;
    for my $r (@resolvers) {
        $r->resolve('localhost', sub { $count++ });
    }
    my $t2 = EV::timer 5, 0, sub { EV::break };
    EV::run until $count >= 5;
    is($count, 5, '5 concurrent resolvers each got their callback');
    is($_->active_queries, 0, 'each instance settles to 0') for @resolvers;
}

# Independent destroy: destroying one resolver leaves others alive
{
    my $live = EV::cares->new(lookups => 'f');
    my $doomed = EV::cares->new(lookups => 'f');
    $doomed->destroy;
    is($doomed->is_destroyed, 1, 'doomed is destroyed');
    is($live->is_destroyed,   0, 'live is unaffected');

    my $done;
    $live->resolve('localhost', sub { $done = 1 });
    my $t3 = EV::timer 5, 0, sub { $done = 1 };



( run in 0.830 second using v1.01-cache-2.11-cpan-483215c6ad5 )