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