ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-ADNS/ADNS.xs
Revision: 1.10
Committed: Mon Dec 3 19:04:54 2007 UTC (16 years, 7 months ago) by root
Branch: MAIN
CVS Tags: rel-0_3
Changes since 1.9: +4 -1 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 root 1.9 static ev_idle iw;
221 root 1.1 static ev_prepare prepare_ev;
222 root 1.2 static struct timeval tv_now;
223 root 1.1
224     static void
225     update_now (EV_P)
226     {
227 root 1.2 ev_tstamp t = ev_now ();
228 root 1.1
229 root 1.2 tv_now.tv_sec = (long)t;
230 root 1.10 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e6);
231 root 1.1 }
232    
233     static void
234 root 1.9 idle_cb (EV_P_ ev_idle *w, int revents)
235     {
236     ev_idle_stop (EV_A_ w);
237     }
238    
239     static void
240 root 1.1 timer_cb (EV_P_ ev_timer *w, int revents)
241     {
242 root 1.10 update_now ();
243    
244     adns_processtimeouts (ads, &tv_now);
245 root 1.1 }
246    
247     static void
248     io_cb (EV_P_ ev_io *w, int revents)
249     {
250     update_now (EV_A);
251    
252     if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
253     if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
254     }
255    
256     // create io watchers for each fd and a timer before blocking
257     static void
258     prepare_cb (EV_P_ ev_prepare *w, int revents)
259     {
260     int i;
261     int timeout = 3600000;
262    
263 root 1.6 if (ev_is_active (&tw))
264     {
265     ev_ref ();
266     ev_timer_stop (EV_A_ &tw);
267     }
268 root 1.1
269 root 1.9 if (ev_is_active (&iw))
270     ev_idle_stop (EV_A_ &iw);
271    
272 root 1.1 for (i = 0; i < nfd; ++i)
273 root 1.6 {
274     ev_ref ();
275     ev_io_stop (EV_A_ iow + i);
276     }
277 root 1.1
278     process ();
279    
280     update_now (EV_A);
281    
282 root 1.4 nfd = mfd;
283    
284 root 1.1 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
285     {
286 root 1.4 mfd = nfd;
287    
288 root 1.7 free (iow); iow = malloc (mfd * sizeof (ev_io));
289     free (fds); fds = malloc (mfd * sizeof (struct pollfd));
290 root 1.1 }
291    
292     ev_timer_set (&tw, timeout * 1e-3, 0.);
293     ev_timer_start (EV_A_ &tw);
294 root 1.6 ev_unref ();
295 root 1.1
296 root 1.4 // create one ev_io per pollfd
297 root 1.1 for (i = 0; i < nfd; ++i)
298     {
299     ev_io_init (iow + i, io_cb, fds [i].fd,
300     ((fds [i].events & POLLIN ? EV_READ : 0)
301     | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
302    
303     ev_io_start (EV_A_ iow + i);
304 root 1.6 ev_unref ();
305 root 1.1 }
306     }
307    
308     MODULE = EV::ADNS PACKAGE = EV::ADNS
309    
310     PROTOTYPES: ENABLE
311    
312     BOOT:
313     {
314 root 1.2 stash = gv_stashpv ("EV::ADNS", 1);
315 root 1.1
316     static const struct {
317     const char *name;
318     IV iv;
319     } *civ, const_iv[] = {
320 root 1.3 # define const_iv(name) { # name, (IV) adns_ ## name },
321 root 1.1 const_iv (if_none)
322     const_iv (if_noenv)
323     const_iv (if_noerrprint)
324     const_iv (if_noserverwarn)
325     const_iv (if_debug)
326     const_iv (if_logpid)
327     const_iv (if_noautosys)
328     const_iv (if_eintr)
329     const_iv (if_nosigpipe)
330     const_iv (if_checkc_entex)
331     const_iv (if_checkc_freq)
332    
333     const_iv (qf_none)
334     const_iv (qf_search)
335     const_iv (qf_usevc)
336     const_iv (qf_owner)
337     const_iv (qf_quoteok_query)
338     const_iv (qf_quoteok_cname)
339     const_iv (qf_quoteok_anshost)
340     const_iv (qf_quotefail_cname)
341     const_iv (qf_cname_loose)
342     const_iv (qf_cname_forbid)
343    
344     const_iv (rrt_typemask)
345     const_iv (_qtf_deref)
346     const_iv (_qtf_mail822)
347     const_iv (r_unknown)
348     const_iv (r_none)
349     const_iv (r_a)
350     const_iv (r_ns_raw)
351     const_iv (r_ns)
352     const_iv (r_cname)
353     const_iv (r_soa_raw)
354     const_iv (r_soa)
355     const_iv (r_ptr_raw)
356     const_iv (r_ptr)
357     const_iv (r_hinfo)
358     const_iv (r_mx_raw)
359     const_iv (r_mx)
360     const_iv (r_txt)
361     const_iv (r_rp_raw)
362     const_iv (r_rp)
363     const_iv (r_srv_raw)
364     const_iv (r_srv)
365     const_iv (r_addr)
366    
367     const_iv (s_ok)
368     const_iv (s_nomemory)
369     const_iv (s_unknownrrtype)
370     const_iv (s_systemfail)
371     const_iv (s_max_localfail)
372     const_iv (s_timeout)
373     const_iv (s_allservfail)
374     const_iv (s_norecurse)
375     const_iv (s_invalidresponse)
376     const_iv (s_unknownformat)
377     const_iv (s_max_remotefail)
378     const_iv (s_rcodeservfail)
379     const_iv (s_rcodeformaterror)
380     const_iv (s_rcodenotimplemented)
381     const_iv (s_rcoderefused)
382     const_iv (s_rcodeunknown)
383     const_iv (s_max_tempfail)
384     const_iv (s_inconsistent)
385     const_iv (s_prohibitedcname)
386     const_iv (s_answerdomaininvalid)
387     const_iv (s_answerdomaintoolong)
388     const_iv (s_invaliddata)
389     const_iv (s_max_misconfig)
390     const_iv (s_querydomainwrong)
391     const_iv (s_querydomaininvalid)
392     const_iv (s_querydomaintoolong)
393     const_iv (s_max_misquery)
394     const_iv (s_nxdomain)
395     const_iv (s_nodata)
396     const_iv (s_max_permfail)
397     };
398    
399     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
400     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
401    
402     I_EV_API ("EV::ADNS");
403    
404 root 1.9 ev_prepare_init (&prepare_ev, prepare_cb);
405     ev_prepare_start (EV_DEFAULT_ &prepare_ev);
406 root 1.1 ev_unref ();
407    
408 root 1.9 ev_init (&iw, idle_cb);
409 root 1.1 ev_init (&tw, timer_cb);
410    
411     adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
412     }
413    
414 root 1.3 void submit (char *owner, int type, int flags, SV *cb)
415 root 1.2 PPCODE:
416 root 1.1 {
417 root 1.2 SV *csv = NEWSV (0, sizeof (struct ctx));
418     struct ctx *c = (struct ctx *)SvPVX (csv);
419     int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query);
420 root 1.1
421     if (r)
422     {
423 root 1.2 SvREFCNT_dec (csv);
424 root 1.6 errno = r;
425 root 1.1 XSRETURN_EMPTY;
426     }
427 root 1.2 else
428     {
429 root 1.3 ev_ref ();
430 root 1.2 SvPOK_only (csv);
431     SvCUR_set (csv, sizeof (struct ctx));
432 root 1.6
433 root 1.2 c->self = csv;
434     c->cb = newSVsv (cb);
435    
436 root 1.9 if (!ev_is_active (&iw))
437     ev_idle_start (EV_A_ &iw);
438    
439 root 1.2 if (GIMME_V != G_VOID)
440     {
441 root 1.5 csv = sv_2mortal (newRV_inc (csv));
442 root 1.2 sv_bless (csv, stash);
443     XPUSHs (csv);
444     }
445     }
446 root 1.1 }
447    
448 root 1.2 void DESTROY (SV *req)
449 root 1.6 ALIAS:
450     cancel = 1
451 root 1.2 CODE:
452     {
453     struct ctx *c;
454    
455     if (!(SvROK (req) && SvOBJECT (SvRV (req))
456     && (SvSTASH (SvRV (req)) == stash)))
457     croak ("object is not of type EV::ADNS");
458    
459     c = (struct ctx *)SvPVX (SvRV (req));
460    
461     if (c->cb)
462     {
463 root 1.3 ev_unref ();
464 root 1.6 SvREFCNT_dec (c->cb);
465     c->cb = 0;
466 root 1.2 adns_cancel (c->query);
467 root 1.6 SvREFCNT_dec (c->self);
468 root 1.2 }
469     }
470    
471    
472 root 1.1
473