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

# Content
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 static HV *stash;
11 static adns_state ads;
12
13 struct ctx
14 {
15 SV *self;
16 adns_query query;
17 SV *cb;
18 };
19
20 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 static void
31 process ()
32 {
33 dSP;
34
35 for (;;)
36 {
37 int i;
38 adns_query q = 0;
39 adns_answer *a;
40 void *ctx;
41 SV *cb;
42 struct ctx *c;
43 int r = adns_check (ads, &q, &a, &ctx);
44
45 if (r)
46 break;
47
48 c = (struct ctx *)ctx;
49 cb = c->cb;
50 c->cb = 0;
51 ev_unref ();
52 SvREFCNT_dec (c->self);
53 printf ("refrefclr\n");
54
55 PUSHMARK (SP);
56
57 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 free (a);
190
191 PUTBACK;
192 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
193 SPAGAIN;
194
195 SvREFCNT_dec (cb);
196 }
197 }
198
199 static struct pollfd *fds;
200 static int nfd, mfd;
201 static ev_io *iow;
202 static ev_timer tw;
203 static ev_prepare prepare_ev;
204 static struct timeval tv_now;
205
206 static void
207 update_now (EV_P)
208 {
209 ev_tstamp t = ev_now ();
210
211 tv_now.tv_sec = (long)t;
212 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e-6);
213 }
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 if (ev_is_active (&tw))
237 {
238 ev_ref ();
239 ev_timer_stop (EV_A_ &tw);
240 }
241
242 for (i = 0; i < nfd; ++i)
243 {
244 ev_ref ();
245 ev_io_stop (EV_A_ iow + i);
246 }
247
248 process ();
249
250 update_now (EV_A);
251
252 nfd = mfd;
253
254 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
255 {
256 mfd = nfd;
257
258 free (iow); iow = malloc (mfd * sizeof (struct pollfd));
259 free (fds); fds = malloc (mfd * sizeof (ev_io));
260 }
261
262 ev_timer_set (&tw, timeout * 1e-3, 0.);
263 ev_timer_start (EV_A_ &tw);
264 ev_unref ();
265
266 // create one ev_io per pollfd
267 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 ev_unref ();
275 }
276 }
277
278 MODULE = EV::ADNS PACKAGE = EV::ADNS
279
280 PROTOTYPES: ENABLE
281
282 BOOT:
283 {
284 stash = gv_stashpv ("EV::ADNS", 1);
285
286 static const struct {
287 const char *name;
288 IV iv;
289 } *civ, const_iv[] = {
290 # define const_iv(name) { # name, (IV) adns_ ## name },
291 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 void submit (char *owner, int type, int flags, SV *cb)
383 PPCODE:
384 {
385 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
389 if (r)
390 {
391 SvREFCNT_dec (csv);
392 errno = r;
393 XSRETURN_EMPTY;
394 }
395 else
396 {
397 ev_ref ();
398 SvPOK_only (csv);
399 SvCUR_set (csv, sizeof (struct ctx));
400
401 c->self = csv;
402 c->cb = newSVsv (cb);
403
404 if (GIMME_V != G_VOID)
405 {
406 csv = sv_2mortal (newRV_inc (csv));
407 sv_bless (csv, stash);
408 XPUSHs (csv);
409 }
410 }
411 }
412
413 void DESTROY (SV *req)
414 ALIAS:
415 cancel = 1
416 CODE:
417 {
418 struct ctx *c;
419
420 printf ("destroy\n");
421 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 ev_unref ();
430 SvREFCNT_dec (c->cb);
431 c->cb = 0;
432 adns_cancel (c->query);
433 SvREFCNT_dec (c->self);
434 printf ("refrefcl2\n");
435 }
436 }
437
438
439
440