ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/EV-ADNS/ADNS.xs
(Generate patch)

Comparing cvsroot/EV-ADNS/ADNS.xs (file contents):
Revision 1.1 by root, Sat Dec 1 13:53:11 2007 UTC vs.
Revision 1.16 by root, Thu Dec 20 07:13:36 2007 UTC

5#include <poll.h> 5#include <poll.h>
6#include <adns.h> 6#include <adns.h>
7 7
8#include "EVAPI.h" 8#include "EVAPI.h"
9 9
10static adns_state ads; 10static struct pollfd *fds;
11static int nfd, mfd;
12static ev_io *iow;
13static ev_timer tw;
14static ev_idle iw;
15static ev_prepare pw;
16static struct timeval tv_now;
17static int outstanding;
18
19static void
20outstanding_inc (adns_state ads)
21{
22 if (!outstanding++)
23 ev_prepare_start (EV_DEFAULT, &pw);
24}
25
26static void
27outstanding_dec (adns_state ads)
28{
29 --outstanding;
30}
11 31
12struct ctx 32struct ctx
13{ 33{
14 SV *req; 34 SV *self;
35 adns_state ads;
36 adns_query query;
15 SV *cb; 37 SV *cb;
16}; 38};
17 39
18static void 40static SV *
19process () 41ha2sv (adns_rr_hostaddr *rr)
20{ 42{
43 AV *av = newAV ();
44 av_push (av, newSVpv (rr->host, 0));
45 // TODO: add addresses
46
47 return newRV_noinc ((SV *)av);
48}
49
50static void
51process (adns_state ads)
52{
53 dSP;
54
21 for (;;) 55 for (;;)
22 { 56 {
57 int i;
23 adns_query q; 58 adns_query q = 0;
24 adns_answer *a; 59 adns_answer *a;
25 void *c; 60 void *ctx;
61 SV *cb;
62 struct ctx *c;
26 int r = adns_check (ads, &q, &a, &c); 63 int r = adns_check (ads, &q, &a, &ctx);
27 64
28 if (r) 65 if (r)
29 break; 66 break;
67
68 c = (struct ctx *)ctx;
69 cb = c->cb;
70 c->cb = 0; outstanding_dec (ads);
71 SvREFCNT_dec (c->self);
72
73 assert (cb);
74
75 PUSHMARK (SP);
76
77 EXTEND (SP, a->nrrs + 2);
78 PUSHs (sv_2mortal (newSViv (a->status)));
79 PUSHs (sv_2mortal (newSViv (a->expires)));
80
81 for (i = 0; i < a->nrrs; ++i)
82 {
83 SV *sv;
84
85 switch (a->type & adns_r_unknown ? adns_r_unknown : a->type)
86 {
87 case adns_r_ns_raw:
88 case adns_r_cname:
89 case adns_r_ptr:
90 case adns_r_ptr_raw:
91 sv = newSVpv (a->rrs.str [i], 0);
92 break;
93
94 case adns_r_txt:
95 {
96 AV *av = newAV ();
97 adns_rr_intstr *rr = a->rrs.manyistr [i];
98
99 while (rr->str)
100 {
101 av_push (av, newSVpvn (rr->str, rr->i));
102 ++rr;
103 }
104
105 sv = newRV_noinc ((SV *)av);
106 }
107 break;
108
109 case adns_r_a:
110 sv = newSVpv (inet_ntoa (a->rrs.inaddr [i]), 0);
111 break;
112
113 case adns_r_ns:
114 sv = ha2sv (a->rrs.hostaddr + i);
115 break;
116
117 case adns_r_hinfo:
118 {
119 /* untested */
120 AV *av = newAV ();
121 adns_rr_intstrpair *rr = a->rrs.intstrpair + i;
122
123 av_push (av, newSVpvn (rr->array [0].str, rr->array [0].i));
124 av_push (av, newSVpvn (rr->array [1].str, rr->array [1].i));
125
126 sv = newRV_noinc ((SV *)av);
127 }
128 break;
129
130 case adns_r_rp:
131 case adns_r_rp_raw:
132 {
133 /* untested */
134 AV *av = newAV ();
135 adns_rr_strpair *rr = a->rrs.strpair + i;
136
137 av_push (av, newSVpv (rr->array [0], 0));
138 av_push (av, newSVpv (rr->array [1], 0));
139
140 sv = newRV_noinc ((SV *)av);
141 }
142 break;
143
144 case adns_r_mx:
145 {
146 AV *av = newAV ();
147 adns_rr_inthostaddr *rr = a->rrs.inthostaddr + i;
148
149 av_push (av, newSViv (rr->i));
150 av_push (av, ha2sv (&rr->ha));
151
152 sv = newRV_noinc ((SV *)av);
153 }
154 break;
155
156 case adns_r_mx_raw:
157 {
158 AV *av = newAV ();
159 adns_rr_intstr *rr = a->rrs.intstr + i;
160
161 av_push (av, newSViv (rr->i));
162 av_push (av, newSVpv (rr->str, 0));
163
164 sv = newRV_noinc ((SV *)av);
165 }
166 break;
167
168 case adns_r_soa:
169 case adns_r_soa_raw:
170 {
171 AV *av = newAV ();
172 adns_rr_soa *rr = a->rrs.soa + i;
173
174 av_push (av, newSVpv (rr->mname, 0));
175 av_push (av, newSVpv (rr->rname, 0));
176 av_push (av, newSVuv (rr->serial));
177 av_push (av, newSVuv (rr->refresh));
178 av_push (av, newSVuv (rr->retry));
179 av_push (av, newSVuv (rr->expire));
180 av_push (av, newSVuv (rr->minimum));
181
182 sv = newRV_noinc ((SV *)av);
183 }
184 break;
185
186 case adns_r_srv_raw:
187 {
188 AV *av = newAV ();
189 adns_rr_srvraw *rr = a->rrs.srvraw + i;
190
191 av_push (av, newSViv (rr->priority));
192 av_push (av, newSViv (rr->weight));
193 av_push (av, newSViv (rr->port));
194 av_push (av, newSVpv (rr->host, 0));
195
196 sv = newRV_noinc ((SV *)av);
197 }
198 break;
199
200 case adns_r_srv:
201 {
202 AV *av = newAV ();
203 adns_rr_srvha *rr = a->rrs.srvha + i;
204
205 av_push (av, newSViv (rr->priority));
206 av_push (av, newSViv (rr->weight));
207 av_push (av, newSViv (rr->port));
208 av_push (av, ha2sv (&rr->ha));
209
210 sv = newRV_noinc ((SV *)av);
211 }
212 break;
213
214 case adns_r_unknown:
215 sv = newSVpvn (a->rrs.byteblock [i].data, a->rrs.byteblock [i].len);
216 break;
217
218 default:
219 case adns_r_addr:
220 sv = &PL_sv_undef; /* not supported */
221 break;
222 }
223
224 PUSHs (sv_2mortal (sv));
225 }
226
227 free (a);
228
229 PUTBACK;
230 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
231 SPAGAIN;
232
233 if (SvTRUE (ERRSV))
234 warn ("%s", SvPV_nolen (ERRSV));
235
236 SvREFCNT_dec (cb);
30 } 237 }
31} 238}
32 239
33static struct pollfd *fds;
34static int nfd;
35static ev_io *iow;
36static ev_timer tw;
37static ev_prepare prepare_ev;
38static struct timeval *tv_now;
39
40static void 240static void
41update_now (EV_P) 241update_now (EV_P)
42{ 242{
43 ev_tstamp t = ev_now (EV_P); 243 ev_tstamp t = ev_now (EV_A);
44 244
45 tv.tv_sec = (long)t; 245 tv_now.tv_sec = (long)t;
46 tv.tv_usec = (long)((t - (ev_tstamp)tv.tv_sec) * 1e-6); 246 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.tv_sec) * 1e6);
247}
248
249static void
250idle_cb (EV_P_ ev_idle *w, int revents)
251{
252 ev_idle_stop (EV_A, w);
47} 253}
48 254
49static void 255static void
50timer_cb (EV_P_ ev_timer *w, int revents) 256timer_cb (EV_P_ ev_timer *w, int revents)
51{ 257{
258 adns_state ads = (adns_state)w->data;
259 update_now (EV_A);
260
261 adns_processtimeouts (ads, &tv_now);
52} 262}
53 263
54static void 264static void
55io_cb (EV_P_ ev_io *w, int revents) 265io_cb (EV_P_ ev_io *w, int revents)
56{ 266{
267 adns_state ads = (adns_state)w->data;
57 update_now (EV_A); 268 update_now (EV_A);
58 269
59 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now); 270 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
60 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now); 271 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
61} 272}
64static void 275static void
65prepare_cb (EV_P_ ev_prepare *w, int revents) 276prepare_cb (EV_P_ ev_prepare *w, int revents)
66{ 277{
67 int i; 278 int i;
68 int timeout = 3600000; 279 int timeout = 3600000;
280 adns_state ads = (adns_state)w->data;
69 281
282 if (ev_is_active (&tw))
70 ev_timer_stop (EV_A_ &tw); 283 ev_timer_stop (EV_A, &tw);
284
285 if (ev_is_active (&iw))
286 ev_idle_stop (EV_A, &iw);
71 287
72 for (i = 0; i < nfd; ++i) 288 for (i = 0; i < nfd; ++i)
73 ev_io_stop (EV_A_ iow + i); 289 ev_io_stop (EV_A, iow + i);
74 290
75 process (); 291 process (ads);
292
293 if (!outstanding)
294 {
295 ev_prepare_stop (EV_A, w);
296 return;
297 }
76 298
77 update_now (EV_A); 299 update_now (EV_A);
300
301 nfd = mfd;
78 302
79 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now)) 303 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
80 { 304 {
305 mfd = nfd;
306
307 free (iow); iow = malloc (mfd * sizeof (ev_io));
81 free (iow); iow = malloc (nfd * sizeof (struct pollfd)); 308 free (fds); fds = malloc (mfd * sizeof (struct pollfd));
82 free (fds); fds = malloc (nfd * sizeof (ev_io));
83 } 309 }
84 310
85 ev_timer_set (&tw, timeout * 1e-3, 0.); 311 ev_timer_set (&tw, timeout * 1e-3, 0.);
86 ev_timer_start (EV_A_ &tw); 312 ev_timer_start (EV_A, &tw);
87 313
88 // create on ev_io per pollfd 314 // create one ev_io per pollfd
89 for (i = 0; i < nfd; ++i) 315 for (i = 0; i < nfd; ++i)
90 { 316 {
317 ev_io *w = iow + i;
318
91 ev_io_init (iow + i, io_cb, fds [i].fd, 319 ev_io_init (w, io_cb, fds [i].fd,
92 ((fds [i].events & POLLIN ? EV_READ : 0) 320 ((fds [i].events & POLLIN ? EV_READ : 0)
93 | (fds [i].events & POLLOUT ? EV_WRITE : 0))); 321 | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
94 322
323 w->data = (void *)ads;
95 ev_io_start (EV_A_ iow + i); 324 ev_io_start (EV_A, w);
96 } 325 }
97} 326}
98 327
328static HV *stash;
329static adns_state ads;
330
99MODULE = EV::ADNS PACKAGE = EV::ADNS 331MODULE = EV::ADNS PACKAGE = EV::ADNS
100 332
101PROTOTYPES: ENABLE 333PROTOTYPES: ENABLE
102 334
103BOOT: 335BOOT:
104{ 336{
105#if 0
106 HV *stash = gv_stashpv ("EV::ADNS", 1); 337 stash = gv_stashpv ("EV::ADNS", 1);
107 338
108 static const struct { 339 static const struct {
109 const char *name; 340 const char *name;
110 IV iv; 341 IV iv;
111 } *civ, const_iv[] = { 342 } *civ, const_iv[] = {
112# define const_iv(pfx, name) { # name, (IV) adns_ ## name }, 343# define const_iv(name) { # name, (IV) adns_ ## name },
113 const_iv (if_none) 344 const_iv (if_none)
114 const_iv (if_noenv) 345 const_iv (if_noenv)
115 const_iv (if_noerrprint) 346 const_iv (if_noerrprint)
116 const_iv (if_noserverwarn) 347 const_iv (if_noserverwarn)
117 const_iv (if_debug) 348 const_iv (if_debug)
188 const_iv (s_max_permfail) 419 const_iv (s_max_permfail)
189 }; 420 };
190 421
191 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) 422 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
192 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 423 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
193#endif
194 424
195 I_EV_API ("EV::ADNS"); 425 I_EV_API ("EV::ADNS");
196 426
197 ev_prepare_init (&prepare_ev, prepare_cb); ev_prepare_start (EV_DEFAULT_ &prepare_ev); 427 adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
198 ev_unref ();
199 428
429 ev_prepare_init (&pw, prepare_cb);
430 pw.data = (void *)ads;
431
432 ev_init (&iw, idle_cb); ev_set_priority (&iw, EV_MINPRI);
433 iw.data = (void *)ads;
200 ev_init (&tw, timer_cb); 434 ev_init (&tw, timer_cb);
201 435 tw.data = (void *)ads;
202 adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
203} 436}
204 437
205int adns_submit (char *owner, int type, int flags, SV *cb) 438void submit (char *owner, int type, int flags, SV *cb)
206 CODE: 439 PPCODE:
207{ 440{
441 SV *csv = NEWSV (0, sizeof (struct ctx));
208 struct ctx *c = (struct ctx *)malloc (sizeof (ctx)); 442 struct ctx *c = (struct ctx *)SvPVX (csv);
209 adns_query q;
210 int r = adns_submit (owner, type, flags, (void *)c, &q); 443 int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query);
444
445 outstanding_inc (ads);
211 446
212 if (r) 447 if (r)
213 { 448 {
214 free (c); 449 SvREFCNT_dec (csv);
450 errno = r;
215 XSRETURN_EMPTY; 451 XSRETURN_EMPTY;
216 } 452 }
217} 453 else
454 {
455 SvPOK_only (csv);
456 SvCUR_set (csv, sizeof (struct ctx));
218 457
458 c->self = csv;
459 c->cb = newSVsv (cb);
460 c->ads = ads;
219 461
462 if (!ev_is_active (&iw))
463 ev_idle_start (EV_DEFAULT, &iw);
220 464
465 if (GIMME_V != G_VOID)
466 {
467 csv = sv_2mortal (newRV_inc (csv));
468 sv_bless (csv, stash);
469 XPUSHs (csv);
470 }
471 }
472}
473
474void DESTROY (SV *req)
475 ALIAS:
476 cancel = 1
477 CODE:
478{
479 struct ctx *c;
480
481 if (!(SvROK (req) && SvOBJECT (SvRV (req))
482 && (SvSTASH (SvRV (req)) == stash)))
483 croak ("object is not of type EV::ADNS");
484
485 c = (struct ctx *)SvPVX (SvRV (req));
486
487 if (c->cb)
488 {
489 SvREFCNT_dec (c->cb);
490 c->cb = 0; outstanding_dec (c->ads);
491 adns_cancel (c->query);
492 SvREFCNT_dec (c->self);
493 }
494}
495
496
497
498

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines