ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-ADNS/ADNS.xs
Revision: 1.8
Committed: Sat Dec 1 21:29:08 2007 UTC (16 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-0_1
Changes since 1.7: +26 -8 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #include "EXTERN.h"
2     #include "perl.h"
3     #include "XSUB.h"
4    
5     #include <poll.h>
6     #include <adns.h>
7    
8     #include "EVAPI.h"
9    
10 root 1.2 static HV *stash;
11 root 1.1 static adns_state ads;
12    
13     struct ctx
14     {
15 root 1.2 SV *self;
16     adns_query query;
17 root 1.1 SV *cb;
18     };
19    
20 root 1.6 static SV *
21     ha2sv (adns_rr_hostaddr *rr)
22     {
23     AV *av = newAV ();
24     av_push (av, newSVpv (rr->host, 0));
25     // TODO: add addresses
26    
27     return newRV_noinc ((SV *)av);
28     }
29    
30 root 1.1 static void
31     process ()
32     {
33 root 1.3 dSP;
34    
35 root 1.1 for (;;)
36     {
37 root 1.6 int i;
38 root 1.4 adns_query q = 0;
39 root 1.1 adns_answer *a;
40 root 1.3 void *ctx;
41     SV *cb;
42     struct ctx *c;
43     int r = adns_check (ads, &q, &a, &ctx);
44 root 1.1
45     if (r)
46     break;
47 root 1.3
48     c = (struct ctx *)ctx;
49     cb = c->cb;
50     c->cb = 0;
51     ev_unref ();
52 root 1.6 SvREFCNT_dec (c->self);
53 root 1.3
54 root 1.5 PUSHMARK (SP);
55    
56 root 1.6 EXTEND (SP, a->nrrs + 2);
57     PUSHs (sv_2mortal (newSViv (a->status)));
58     PUSHs (sv_2mortal (newSViv (a->expires)));
59    
60     for (i = 0; i < a->nrrs; ++i)
61     {
62     SV *sv;
63    
64     switch (a->type & adns_r_unknown ? adns_r_unknown : a->type)
65     {
66     case adns_r_ns_raw:
67     case adns_r_cname:
68     case adns_r_ptr:
69     case adns_r_ptr_raw:
70     sv = newSVpv (a->rrs.str [i], 0);
71     break;
72    
73     case adns_r_txt:
74 root 1.8 {
75     AV *av = newAV ();
76     adns_rr_intstr *rr = a->rrs.manyistr [i];
77    
78     while (rr->str)
79     {
80     av_push (av, newSVpvn (rr->str, rr->i));
81     ++rr;
82     }
83    
84     sv = newRV_noinc ((SV *)av);
85     }
86 root 1.6 break;
87    
88     case adns_r_a:
89     sv = newSVpv (inet_ntoa (a->rrs.inaddr [i]), 0);
90     break;
91    
92     case adns_r_ns:
93     sv = ha2sv (a->rrs.hostaddr + i);
94     break;
95    
96     case adns_r_hinfo:
97     {
98     /* untested */
99     AV *av = newAV ();
100     adns_rr_intstrpair *rr = a->rrs.intstrpair + i;
101    
102     av_push (av, newSVpvn (rr->array [0].str, rr->array [0].i));
103     av_push (av, newSVpvn (rr->array [1].str, rr->array [1].i));
104 root 1.8
105     sv = newRV_noinc ((SV *)av);
106 root 1.6 }
107     break;
108    
109     case adns_r_rp:
110     case adns_r_rp_raw:
111     {
112     /* untested */
113     AV *av = newAV ();
114     adns_rr_strpair *rr = a->rrs.strpair + i;
115    
116     av_push (av, newSVpv (rr->array [0], 0));
117     av_push (av, newSVpv (rr->array [1], 0));
118 root 1.8
119     sv = newRV_noinc ((SV *)av);
120 root 1.6 }
121     break;
122    
123     case adns_r_mx:
124     {
125     AV *av = newAV ();
126     adns_rr_inthostaddr *rr = a->rrs.inthostaddr + i;
127    
128     av_push (av, newSViv (rr->i));
129     av_push (av, ha2sv (&rr->ha));
130 root 1.8
131     sv = newRV_noinc ((SV *)av);
132 root 1.6 }
133     break;
134    
135     case adns_r_mx_raw:
136     {
137     AV *av = newAV ();
138     adns_rr_intstr *rr = a->rrs.intstr + i;
139    
140     av_push (av, newSViv (rr->i));
141     av_push (av, newSVpv (rr->str, 0));
142 root 1.8
143     sv = newRV_noinc ((SV *)av);
144 root 1.6 }
145     break;
146    
147     case adns_r_soa:
148     case adns_r_soa_raw:
149     {
150     AV *av = newAV ();
151     adns_rr_soa *rr = a->rrs.soa + i;
152    
153     av_push (av, newSVpv (rr->mname, 0));
154     av_push (av, newSVpv (rr->rname, 0));
155     av_push (av, newSVuv (rr->serial));
156     av_push (av, newSVuv (rr->refresh));
157     av_push (av, newSVuv (rr->retry));
158     av_push (av, newSVuv (rr->expire));
159     av_push (av, newSVuv (rr->minimum));
160 root 1.8
161     sv = newRV_noinc ((SV *)av);
162 root 1.6 }
163     break;
164    
165     case adns_r_srv_raw:
166     {
167     AV *av = newAV ();
168     adns_rr_srvraw *rr = a->rrs.srvraw + i;
169    
170     av_push (av, newSViv (rr->priority));
171     av_push (av, newSViv (rr->weight));
172     av_push (av, newSViv (rr->port));
173     av_push (av, newSVpv (rr->host, 0));
174 root 1.8
175     sv = newRV_noinc ((SV *)av);
176 root 1.6 }
177     break;
178    
179     case adns_r_srv:
180     {
181     AV *av = newAV ();
182     adns_rr_srvha *rr = a->rrs.srvha + i;
183    
184     av_push (av, newSViv (rr->priority));
185     av_push (av, newSViv (rr->weight));
186     av_push (av, newSViv (rr->port));
187     av_push (av, ha2sv (&rr->ha));
188 root 1.8
189     sv = newRV_noinc ((SV *)av);
190 root 1.6 }
191     break;
192    
193     case adns_r_unknown:
194     sv = newSVpvn (a->rrs.byteblock [i].data, a->rrs.byteblock [i].len);
195     break;
196    
197     default:
198     case adns_r_addr:
199     sv = &PL_sv_undef; /* not supported */
200     break;
201     }
202    
203     PUSHs (sv_2mortal (sv));
204     }
205    
206 root 1.4 free (a);
207    
208     PUTBACK;
209 root 1.5 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
210 root 1.4 SPAGAIN;
211 root 1.3
212     SvREFCNT_dec (cb);
213 root 1.1 }
214     }
215    
216     static struct pollfd *fds;
217 root 1.4 static int nfd, mfd;
218 root 1.1 static ev_io *iow;
219     static ev_timer tw;
220     static ev_prepare prepare_ev;
221 root 1.2 static struct timeval tv_now;
222 root 1.1
223     static void
224     update_now (EV_P)
225     {
226 root 1.2 ev_tstamp t = ev_now ();
227 root 1.1
228 root 1.2 tv_now.tv_sec = (long)t;
229     tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e-6);
230 root 1.1 }
231    
232     static void
233     timer_cb (EV_P_ ev_timer *w, int revents)
234     {
235     }
236    
237     static void
238     io_cb (EV_P_ ev_io *w, int revents)
239     {
240     update_now (EV_A);
241    
242     if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
243     if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
244     }
245    
246     // create io watchers for each fd and a timer before blocking
247     static void
248     prepare_cb (EV_P_ ev_prepare *w, int revents)
249     {
250     int i;
251     int timeout = 3600000;
252    
253 root 1.6 if (ev_is_active (&tw))
254     {
255     ev_ref ();
256     ev_timer_stop (EV_A_ &tw);
257     }
258 root 1.1
259     for (i = 0; i < nfd; ++i)
260 root 1.6 {
261     ev_ref ();
262     ev_io_stop (EV_A_ iow + i);
263     }
264 root 1.1
265     process ();
266    
267     update_now (EV_A);
268    
269 root 1.4 nfd = mfd;
270    
271 root 1.1 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
272     {
273 root 1.4 mfd = nfd;
274    
275 root 1.7 free (iow); iow = malloc (mfd * sizeof (ev_io));
276     free (fds); fds = malloc (mfd * sizeof (struct pollfd));
277 root 1.1 }
278    
279     ev_timer_set (&tw, timeout * 1e-3, 0.);
280     ev_timer_start (EV_A_ &tw);
281 root 1.6 ev_unref ();
282 root 1.1
283 root 1.4 // create one ev_io per pollfd
284 root 1.1 for (i = 0; i < nfd; ++i)
285     {
286     ev_io_init (iow + i, io_cb, fds [i].fd,
287     ((fds [i].events & POLLIN ? EV_READ : 0)
288     | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
289    
290     ev_io_start (EV_A_ iow + i);
291 root 1.6 ev_unref ();
292 root 1.1 }
293     }
294    
295     MODULE = EV::ADNS PACKAGE = EV::ADNS
296    
297     PROTOTYPES: ENABLE
298    
299     BOOT:
300     {
301 root 1.2 stash = gv_stashpv ("EV::ADNS", 1);
302 root 1.1
303     static const struct {
304     const char *name;
305     IV iv;
306     } *civ, const_iv[] = {
307 root 1.3 # define const_iv(name) { # name, (IV) adns_ ## name },
308 root 1.1 const_iv (if_none)
309     const_iv (if_noenv)
310     const_iv (if_noerrprint)
311     const_iv (if_noserverwarn)
312     const_iv (if_debug)
313     const_iv (if_logpid)
314     const_iv (if_noautosys)
315     const_iv (if_eintr)
316     const_iv (if_nosigpipe)
317     const_iv (if_checkc_entex)
318     const_iv (if_checkc_freq)
319    
320     const_iv (qf_none)
321     const_iv (qf_search)
322     const_iv (qf_usevc)
323     const_iv (qf_owner)
324     const_iv (qf_quoteok_query)
325     const_iv (qf_quoteok_cname)
326     const_iv (qf_quoteok_anshost)
327     const_iv (qf_quotefail_cname)
328     const_iv (qf_cname_loose)
329     const_iv (qf_cname_forbid)
330    
331     const_iv (rrt_typemask)
332     const_iv (_qtf_deref)
333     const_iv (_qtf_mail822)
334     const_iv (r_unknown)
335     const_iv (r_none)
336     const_iv (r_a)
337     const_iv (r_ns_raw)
338     const_iv (r_ns)
339     const_iv (r_cname)
340     const_iv (r_soa_raw)
341     const_iv (r_soa)
342     const_iv (r_ptr_raw)
343     const_iv (r_ptr)
344     const_iv (r_hinfo)
345     const_iv (r_mx_raw)
346     const_iv (r_mx)
347     const_iv (r_txt)
348     const_iv (r_rp_raw)
349     const_iv (r_rp)
350     const_iv (r_srv_raw)
351     const_iv (r_srv)
352     const_iv (r_addr)
353    
354     const_iv (s_ok)
355     const_iv (s_nomemory)
356     const_iv (s_unknownrrtype)
357     const_iv (s_systemfail)
358     const_iv (s_max_localfail)
359     const_iv (s_timeout)
360     const_iv (s_allservfail)
361     const_iv (s_norecurse)
362     const_iv (s_invalidresponse)
363     const_iv (s_unknownformat)
364     const_iv (s_max_remotefail)
365     const_iv (s_rcodeservfail)
366     const_iv (s_rcodeformaterror)
367     const_iv (s_rcodenotimplemented)
368     const_iv (s_rcoderefused)
369     const_iv (s_rcodeunknown)
370     const_iv (s_max_tempfail)
371     const_iv (s_inconsistent)
372     const_iv (s_prohibitedcname)
373     const_iv (s_answerdomaininvalid)
374     const_iv (s_answerdomaintoolong)
375     const_iv (s_invaliddata)
376     const_iv (s_max_misconfig)
377     const_iv (s_querydomainwrong)
378     const_iv (s_querydomaininvalid)
379     const_iv (s_querydomaintoolong)
380     const_iv (s_max_misquery)
381     const_iv (s_nxdomain)
382     const_iv (s_nodata)
383     const_iv (s_max_permfail)
384     };
385    
386     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
387     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
388    
389     I_EV_API ("EV::ADNS");
390    
391     ev_prepare_init (&prepare_ev, prepare_cb); ev_prepare_start (EV_DEFAULT_ &prepare_ev);
392     ev_unref ();
393    
394     ev_init (&tw, timer_cb);
395    
396     adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
397     }
398    
399 root 1.3 void submit (char *owner, int type, int flags, SV *cb)
400 root 1.2 PPCODE:
401 root 1.1 {
402 root 1.2 SV *csv = NEWSV (0, sizeof (struct ctx));
403     struct ctx *c = (struct ctx *)SvPVX (csv);
404     int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query);
405 root 1.1
406     if (r)
407     {
408 root 1.2 SvREFCNT_dec (csv);
409 root 1.6 errno = r;
410 root 1.1 XSRETURN_EMPTY;
411     }
412 root 1.2 else
413     {
414 root 1.3 ev_ref ();
415 root 1.2 SvPOK_only (csv);
416     SvCUR_set (csv, sizeof (struct ctx));
417 root 1.6
418 root 1.2 c->self = csv;
419     c->cb = newSVsv (cb);
420    
421     if (GIMME_V != G_VOID)
422     {
423 root 1.5 csv = sv_2mortal (newRV_inc (csv));
424 root 1.2 sv_bless (csv, stash);
425     XPUSHs (csv);
426     }
427     }
428 root 1.1 }
429    
430 root 1.2 void DESTROY (SV *req)
431 root 1.6 ALIAS:
432     cancel = 1
433 root 1.2 CODE:
434     {
435     struct ctx *c;
436    
437     if (!(SvROK (req) && SvOBJECT (SvRV (req))
438     && (SvSTASH (SvRV (req)) == stash)))
439     croak ("object is not of type EV::ADNS");
440    
441     c = (struct ctx *)SvPVX (SvRV (req));
442    
443     if (c->cb)
444     {
445 root 1.3 ev_unref ();
446 root 1.6 SvREFCNT_dec (c->cb);
447     c->cb = 0;
448 root 1.2 adns_cancel (c->query);
449 root 1.6 SvREFCNT_dec (c->self);
450 root 1.2 }
451     }
452    
453    
454 root 1.1
455