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