--- cvsroot/EV-ADNS/ADNS.xs 2007/12/01 15:54:40 1.5 +++ cvsroot/EV-ADNS/ADNS.xs 2007/12/01 21:01:32 1.7 @@ -17,6 +17,16 @@ SV *cb; }; +static SV * +ha2sv (adns_rr_hostaddr *rr) +{ + AV *av = newAV (); + av_push (av, newSVpv (rr->host, 0)); + // TODO: add addresses + + return newRV_noinc ((SV *)av); +} + static void process () { @@ -24,6 +34,7 @@ for (;;) { + int i; adns_query q = 0; adns_answer *a; void *ctx; @@ -31,7 +42,6 @@ struct ctx *c; int r = adns_check (ads, &q, &a, &ctx); - printf ("check %d\n", r);//D if (r) break; @@ -39,10 +49,142 @@ cb = c->cb; c->cb = 0; ev_unref (); + SvREFCNT_dec (c->self); PUSHMARK (SP); - XPUSHs (sv_2mortal (newSViv (a->status))); + 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: + case adns_r_ptr_raw: + sv = newSVpv (a->rrs.str [i], 0); + break; + + case adns_r_txt: + sv = newSVpvn (a->rrs.manyistr [i]->str, a->rrs.manyistr [i]->i); + break; + + case adns_r_a: + sv = newSVpv (inet_ntoa (a->rrs.inaddr [i]), 0); + break; + + case adns_r_ns: + sv = ha2sv (a->rrs.hostaddr + i); + break; + + case adns_r_hinfo: + { + /* untested */ + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_intstrpair *rr = a->rrs.intstrpair + i; + + av_push (av, newSVpvn (rr->array [0].str, rr->array [0].i)); + av_push (av, newSVpvn (rr->array [1].str, rr->array [1].i)); + } + break; + + case adns_r_rp: + case adns_r_rp_raw: + { + /* untested */ + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_strpair *rr = a->rrs.strpair + i; + + av_push (av, newSVpv (rr->array [0], 0)); + av_push (av, newSVpv (rr->array [1], 0)); + } + break; + + case adns_r_mx: + { + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_inthostaddr *rr = a->rrs.inthostaddr + i; + + av_push (av, newSViv (rr->i)); + av_push (av, ha2sv (&rr->ha)); + } + break; + + case adns_r_mx_raw: + { + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_intstr *rr = a->rrs.intstr + i; + + av_push (av, newSViv (rr->i)); + av_push (av, newSVpv (rr->str, 0)); + } + break; + + case adns_r_soa: + case adns_r_soa_raw: + { + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_soa *rr = a->rrs.soa + i; + + av_push (av, newSVpv (rr->mname, 0)); + av_push (av, newSVpv (rr->rname, 0)); + av_push (av, newSVuv (rr->serial)); + av_push (av, newSVuv (rr->refresh)); + av_push (av, newSVuv (rr->retry)); + av_push (av, newSVuv (rr->expire)); + av_push (av, newSVuv (rr->minimum)); + } + break; + + case adns_r_srv_raw: + { + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_srvraw *rr = a->rrs.srvraw + i; + + av_push (av, newSViv (rr->priority)); + av_push (av, newSViv (rr->weight)); + av_push (av, newSViv (rr->port)); + av_push (av, newSVpv (rr->host, 0)); + } + break; + + case adns_r_srv: + { + AV *av = newAV (); + sv = newRV_noinc ((SV *)av); + adns_rr_srvha *rr = a->rrs.srvha + i; + + av_push (av, newSViv (rr->priority)); + av_push (av, newSViv (rr->weight)); + av_push (av, newSViv (rr->port)); + av_push (av, ha2sv (&rr->ha)); + } + break; + + case adns_r_unknown: + sv = newSVpvn (a->rrs.byteblock [i].data, a->rrs.byteblock [i].len); + break; + + default: + case adns_r_addr: + sv = &PL_sv_undef; /* not supported */ + break; + } + + PUSHs (sv_2mortal (sv)); + } + free (a); PUTBACK; @@ -50,7 +192,6 @@ SPAGAIN; SvREFCNT_dec (cb); - SvREFCNT_dec (c->self); } } @@ -91,10 +232,17 @@ int i; int timeout = 3600000; - ev_timer_stop (EV_A_ &tw); + if (ev_is_active (&tw)) + { + ev_ref (); + ev_timer_stop (EV_A_ &tw); + } for (i = 0; i < nfd; ++i) - ev_io_stop (EV_A_ iow + i); + { + ev_ref (); + ev_io_stop (EV_A_ iow + i); + } process (); @@ -106,14 +254,13 @@ { mfd = nfd; - free (iow); iow = malloc (mfd * sizeof (struct pollfd)); - free (fds); fds = malloc (mfd * sizeof (ev_io)); + free (iow); iow = malloc (mfd * sizeof (ev_io)); + free (fds); fds = malloc (mfd * sizeof (struct pollfd)); } - printf ("to %d\n", timeout);//d - ev_timer_set (&tw, timeout * 1e-3, 0.); ev_timer_start (EV_A_ &tw); + ev_unref (); // create one ev_io per pollfd for (i = 0; i < nfd; ++i) @@ -123,6 +270,7 @@ | (fds [i].events & POLLOUT ? EV_WRITE : 0))); ev_io_start (EV_A_ iow + i); + ev_unref (); } } @@ -240,6 +388,7 @@ if (r) { SvREFCNT_dec (csv); + errno = r; XSRETURN_EMPTY; } else @@ -247,6 +396,7 @@ ev_ref (); SvPOK_only (csv); SvCUR_set (csv, sizeof (struct ctx)); + c->self = csv; c->cb = newSVsv (cb); @@ -260,6 +410,8 @@ } void DESTROY (SV *req) + ALIAS: + cancel = 1 CODE: { struct ctx *c; @@ -273,8 +425,10 @@ if (c->cb) { ev_unref (); - adns_cancel (c->query); SvREFCNT_dec (c->cb); + c->cb = 0; + adns_cancel (c->query); + SvREFCNT_dec (c->self); } }