Net-LibAsyncNS

 view release on metacpan or  search on metacpan

lib/Net/LibAsyncNS.xs  view on Meta::CPAN


  PREINIT:
    char *hostname = NULL;
    char *servicename = NULL;
    STRLEN len;
    struct addrinfo hints_s = { 0 };
    asyncns_query_t *query;

  CODE:
    SvGETMAGIC(host);
    if(SvOK(host)) {
      hostname = SvPV_nomg(host, len);
      if (!len)
        hostname = NULL;
    }

    SvGETMAGIC(service);
    if(SvOK(service)) {
      servicename = SvPV_nomg(service, len);
      if (!len)
        servicename = NULL;
    }

    if(hints && SvOK(hints)) {
      HV *hintshash;
      SV **valp;

      if(!SvROK(hints) || SvTYPE(SvRV(hints)) != SVt_PVHV)
        croak("hints is not a HASH reference");

      hintshash = (HV*)SvRV(hints);

      if((valp = hv_fetch(hintshash, "flags", 5, 0)) != NULL)
        hints_s.ai_flags = SvIV(*valp);
      if((valp = hv_fetch(hintshash, "family", 6, 0)) != NULL)
        hints_s.ai_family = SvIV(*valp);
      if((valp = hv_fetch(hintshash, "socktype", 8, 0)) != NULL)
        hints_s.ai_socktype = SvIV(*valp);
      if((valp = hv_fetch(hintshash, "protocol", 8, 0)) != NULL)
        hints_s.ai_protocol = SvIV(*valp);
    }

    query = asyncns_getaddrinfo(self, hostname, servicename, &hints_s);

    RETVAL = newSVsv(query_new(ST(0), self, query)->sv);

  OUTPUT:
    RETVAL

void
getaddrinfo_done(self, q)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q

  INIT:
    int err;
    struct addrinfo *res;
    struct addrinfo *res_iter;
    int n_res;

  PPCODE:
    err = asyncns_getaddrinfo_done(self, q->query, &res);

    XPUSHs(gai_err_to_SV(err));

    if(err) {
      if(err != EAI_AGAIN)
        SvREFCNT_dec(q->sv);

      XSRETURN(1);
    }

    n_res = 0;
    for(res_iter = res; res_iter; res_iter = res_iter->ai_next) {
      HV *res_hv = newHV();

      hv_store(res_hv, "family",   6, newSViv(res_iter->ai_family),   0);
      hv_store(res_hv, "socktype", 8, newSViv(res_iter->ai_socktype), 0);
      hv_store(res_hv, "protocol", 8, newSViv(res_iter->ai_protocol), 0);

      hv_store(res_hv, "addr",     4, newSVpvn((char*)res_iter->ai_addr, res_iter->ai_addrlen), 0);

      if(res_iter->ai_canonname)
        hv_store(res_hv, "canonname", 9, newSVpv(res_iter->ai_canonname, 0), 0);
      else
        hv_store(res_hv, "canonname", 9, newSV(0), 0);

      XPUSHs(sv_2mortal(newRV_noinc((SV*)res_hv)));
      n_res++;
    }

    asyncns_freeaddrinfo(res);
    SvREFCNT_dec(q->sv);

    XSRETURN(1 + n_res);

SV *
getnameinfo(self, addr, flags, wanthost, wantserv)
  Net::LibAsyncNS self
  SV *addr
  int flags
  int wanthost
  int wantserv

  PREINIT:
    char *sa;
    STRLEN addr_len;
    asyncns_query_t *query;

  CODE:
    if(!SvPOK(addr))
      croak("addr is not a string");

    addr_len = SvCUR(addr);

    /* We need to ensure the sockaddr is aligned, because a random SvPV might
     * not be due to SvOOK */
    Newx(sa, addr_len, char);
    Copy(SvPV_nolen(addr), sa, addr_len, char);
#ifdef HAVE_SOCKADDR_SA_LEN
    ((struct sockaddr *)sa)->sa_len = addr_len;
#endif

    query = asyncns_getnameinfo(self, (struct sockaddr *)sa, addr_len, flags, wanthost, wantserv);

    RETVAL = newSVsv(query_new(ST(0), self, query)->sv);

  OUTPUT:
    RETVAL

void
getnameinfo_done(self, q)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q

  PREINIT:
    int err;
    char host[1024];
    char serv[256];

  PPCODE:
    err = asyncns_getnameinfo_done(self, q->query, host, sizeof(host), serv, sizeof(serv));

    XPUSHs(gai_err_to_SV(err));

    if(err) {
      if(err != EAI_AGAIN)
        SvREFCNT_dec(q->sv);

      XSRETURN(1);
    }

    XPUSHs(sv_2mortal(newSVpv(host, 0)));
    XPUSHs(sv_2mortal(newSVpv(serv, 0)));

    SvREFCNT_dec(q->sv);

    XSRETURN(3);

SV *
res_query(self, dname, class, type)
  Net::LibAsyncNS self
  char *dname
  int class
  int type

  PREINIT:
    asyncns_query_t *query;

  CODE:
    query = asyncns_res_query(self, dname, class, type);

    RETVAL = newSVsv(query_new(ST(0), self, query)->sv);

  OUTPUT:
    RETVAL

SV *
res_search(self, dname, class, type)
  Net::LibAsyncNS self
  char *dname
  int class
  int type

  PREINIT:
    asyncns_query_t *query;

  CODE:
    query = asyncns_res_search(self, dname, class, type);

    RETVAL = newSVsv(query_new(ST(0), self, query)->sv);

  OUTPUT:
    RETVAL

SV *
res_done(self, q)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q

  INIT:
    int len;
    unsigned char *answer;

  PPCODE:
    len = asyncns_res_done(self, q->query, &answer);
    if(len < 0) {
      if(-len != EAGAIN)
        SvREFCNT_dec(q->sv);

      errno = -len;
      XSRETURN_UNDEF;
    }

    mXPUSHp(answer, len);
    asyncns_freeanswer(answer);

    SvREFCNT_dec(q->sv);

    XSRETURN(1);

int
isdone(self, q)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q

  CODE:
    RETVAL = asyncns_isdone(self, q->query);
  OUTPUT:
    RETVAL

SV *
getnext(self)
  Net::LibAsyncNS self

  PREINIT:
    asyncns_query_t *query;

  CODE:
    query = asyncns_getnext(self);

    if(!query)
      XSRETURN_UNDEF;

    RETVAL = newSVsv(asyncns_getuserdata(self, query));
  OUTPUT:
    RETVAL

void
cancel(self, q)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q

  CODE:
    asyncns_cancel(self, q->query);
    SvREFCNT_dec(q->sv);

void
setuserdata(self, q, data)
  Net::LibAsyncNS self
  Net::LibAsyncNS::Query q
  SV *data

  CODE:
    if(q->userdata)



( run in 1.205 second using v1.01-cache-2.11-cpan-71847e10f99 )