EV-ADNS

 view release on metacpan or  search on metacpan

ADNS.xs  view on Meta::CPAN

#include "XSUB.h"

#include <poll.h>

#define ADNS_FEATURE_MANYAF
#include <adns.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "EVAPI.h"

#define DEFAULT_INIT_FLAGS \
   adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn \
   | adns_if_noautosys | adns_if_permit_ipv4 | adns_if_permit_ipv6

static struct pollfd *fds;
static int nfd, mfd;
static ev_io *iow;
static ev_timer tw;
static ev_idle iw;
static ev_prepare pw;
static struct timeval tv_now;
static int outstanding;

static void
outstanding_inc (adns_state ads)
{
  if (!outstanding++)
    ev_prepare_start (EV_DEFAULT, &pw);
}

static void
outstanding_dec (adns_state ads)
{
  --outstanding;
}

struct ctx
{
  SV *self;
  adns_state ads;
  adns_query query;
  SV *cb;
};

static SV *
ip_to_sv (int family, void *addr)
{
  char buf[128];

  return newSVpv (inet_ntop (family, addr, buf, sizeof buf), 0);
}

static SV *
addr_to_sv (adns_rr_addr *addr)
{
  return ip_to_sv (addr->addr.sa.sa_family,
                   addr->addr.sa.sa_family == AF_INET6
                   ? (void *)&addr->addr.inet6.sin6_addr
                   : (void *)&addr->addr.inet.sin_addr);
}

static SV *
ha2sv (adns_rr_hostaddr *rr)
{
  int i;
  AV *av = newAV ();
  av_push (av, newSVpv (rr->host, 0));
  av_push (av, newSViv (rr->astatus));

  for (i = 0; i < rr->naddrs; ++i)
    av_push (av, addr_to_sv (rr->addrs + i));

  return newRV_noinc ((SV *)av);
}

static void
process (adns_state ads)
{
  dSP;

  ENTER;
  SAVETMPS;

  for (;;)
    {
      int i;
      adns_query q = 0;
      adns_answer *a;
      void *ctx;
      SV *cb;
      struct ctx *c;
      int r = adns_check (ads, &q, &a, &ctx);
      
      if (r)
        break;

      c = (struct ctx *)ctx;
      cb = c->cb;
      c->cb = 0; outstanding_dec (ads);
      SvREFCNT_dec (c->self);

      assert (cb);

      PUSHMARK (SP);

      EXTEND (SP, a->nrrs + 2);
      PUSHs (sv_2mortal (newSViv (a->status)));
      PUSHs (sv_2mortal (newSViv (a->expires)));

      for (i = 0; i < a->nrrs; ++i)
        {
          SV *sv;

          switch (a->type & adns_r_unknown ? adns_r_unknown : a->type)
            {
              case adns_r_ns_raw:
              case adns_r_cname:
              case adns_r_ptr:



( run in 0.686 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )