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.5 by root, Sat Dec 1 15:54:40 2007 UTC vs.
Revision 1.15 by root, Sat Dec 8 23:13:26 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 HV *stash; 10static struct pollfd *fds;
11static adns_state ads; 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}
12 31
13struct ctx 32struct ctx
14{ 33{
15 SV *self; 34 SV *self;
35 adns_state ads;
16 adns_query query; 36 adns_query query;
17 SV *cb; 37 SV *cb;
18}; 38};
19 39
40static SV *
41ha2sv (adns_rr_hostaddr *rr)
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
20static void 50static void
21process () 51process (adns_state ads)
22{ 52{
23 dSP; 53 dSP;
24 54
25 for (;;) 55 for (;;)
26 { 56 {
57 int i;
27 adns_query q = 0; 58 adns_query q = 0;
28 adns_answer *a; 59 adns_answer *a;
29 void *ctx; 60 void *ctx;
30 SV *cb; 61 SV *cb;
31 struct ctx *c; 62 struct ctx *c;
32 int r = adns_check (ads, &q, &a, &ctx); 63 int r = adns_check (ads, &q, &a, &ctx);
33 64
34 printf ("check %d\n", r);//D
35 if (r) 65 if (r)
36 break; 66 break;
37 67
38 c = (struct ctx *)ctx; 68 c = (struct ctx *)ctx;
39 cb = c->cb; 69 cb = c->cb;
40 c->cb = 0; 70 c->cb = 0; outstanding_dec (ads);
41 ev_unref (); 71 SvREFCNT_dec (c->self);
72
73 assert (cb);
42 74
43 PUSHMARK (SP); 75 PUSHMARK (SP);
44 76
77 EXTEND (SP, a->nrrs + 2);
45 XPUSHs (sv_2mortal (newSViv (a->status))); 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
46 free (a); 227 free (a);
47 228
48 PUTBACK; 229 PUTBACK;
49 call_sv (cb, G_VOID | G_DISCARD | G_EVAL); 230 call_sv (cb, G_VOID | G_DISCARD | G_EVAL);
50 SPAGAIN; 231 SPAGAIN;
51 232
233 if (SvTRUE (ERRSV))
234 warn ("%s", SvPV_nolen (ERRSV));
235
52 SvREFCNT_dec (cb); 236 SvREFCNT_dec (cb);
53 SvREFCNT_dec (c->self);
54 } 237 }
55} 238}
56 239
57static struct pollfd *fds;
58static int nfd, mfd;
59static ev_io *iow;
60static ev_timer tw;
61static ev_prepare prepare_ev;
62static struct timeval tv_now;
63
64static void 240static void
65update_now (EV_P) 241update_now (EV_P)
66{ 242{
67 ev_tstamp t = ev_now (); 243 ev_tstamp t = ev_now (EV_A);
68 244
69 tv_now.tv_sec = (long)t; 245 tv_now.tv_sec = (long)t;
70 tv_now.tv_usec = (long)((t - (ev_tstamp)tv_now.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);
71} 253}
72 254
73static void 255static void
74timer_cb (EV_P_ ev_timer *w, int revents) 256timer_cb (EV_P_ ev_timer *w, int revents)
75{ 257{
258 adns_state ads = (adns_state)w->data;
259 update_now (EV_A);
260
261 adns_processtimeouts (ads, &tv_now);
76} 262}
77 263
78static void 264static void
79io_cb (EV_P_ ev_io *w, int revents) 265io_cb (EV_P_ ev_io *w, int revents)
80{ 266{
267 adns_state ads = (adns_state)w->data;
81 update_now (EV_A); 268 update_now (EV_A);
82 269
83 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now); 270 if (revents & EV_READ ) adns_processreadable (ads, w->fd, &tv_now);
84 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now); 271 if (revents & EV_WRITE) adns_processwriteable (ads, w->fd, &tv_now);
85} 272}
88static void 275static void
89prepare_cb (EV_P_ ev_prepare *w, int revents) 276prepare_cb (EV_P_ ev_prepare *w, int revents)
90{ 277{
91 int i; 278 int i;
92 int timeout = 3600000; 279 int timeout = 3600000;
280 adns_state ads = (adns_state)w->data;
93 281
282 if (ev_is_active (&tw))
94 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);
95 287
96 for (i = 0; i < nfd; ++i) 288 for (i = 0; i < nfd; ++i)
97 ev_io_stop (EV_A_ iow + i); 289 ev_io_stop (EV_A_ iow + i);
98 290
99 process (); 291 process (ads);
292
293 if (!outstanding)
294 {
295 ev_prepare_stop (w);
296 return;
297 }
100 298
101 update_now (EV_A); 299 update_now (EV_A);
102 300
103 nfd = mfd; 301 nfd = mfd;
104 302
105 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now)) 303 while (adns_beforepoll (ads, fds, &nfd, &timeout, &tv_now))
106 { 304 {
107 mfd = nfd; 305 mfd = nfd;
108 306
307 free (iow); iow = malloc (mfd * sizeof (ev_io));
109 free (iow); iow = malloc (mfd * sizeof (struct pollfd)); 308 free (fds); fds = malloc (mfd * sizeof (struct pollfd));
110 free (fds); fds = malloc (mfd * sizeof (ev_io));
111 } 309 }
112
113 printf ("to %d\n", timeout);//d
114 310
115 ev_timer_set (&tw, timeout * 1e-3, 0.); 311 ev_timer_set (&tw, timeout * 1e-3, 0.);
116 ev_timer_start (EV_A_ &tw); 312 ev_timer_start (EV_A_ &tw);
117 313
118 // create one ev_io per pollfd 314 // create one ev_io per pollfd
119 for (i = 0; i < nfd; ++i) 315 for (i = 0; i < nfd; ++i)
120 { 316 {
317 ev_io *w = iow + i;
318
121 ev_io_init (iow + i, io_cb, fds [i].fd, 319 ev_io_init (w, io_cb, fds [i].fd,
122 ((fds [i].events & POLLIN ? EV_READ : 0) 320 ((fds [i].events & POLLIN ? EV_READ : 0)
123 | (fds [i].events & POLLOUT ? EV_WRITE : 0))); 321 | (fds [i].events & POLLOUT ? EV_WRITE : 0)));
124 322
323 w->data = (void *)ads;
125 ev_io_start (EV_A_ iow + i); 324 ev_io_start (EV_A_ w);
126 } 325 }
127} 326}
327
328static HV *stash;
329static adns_state ads;
128 330
129MODULE = EV::ADNS PACKAGE = EV::ADNS 331MODULE = EV::ADNS PACKAGE = EV::ADNS
130 332
131PROTOTYPES: ENABLE 333PROTOTYPES: ENABLE
132 334
220 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; )
221 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); 423 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
222 424
223 I_EV_API ("EV::ADNS"); 425 I_EV_API ("EV::ADNS");
224 426
225 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);
226 ev_unref ();
227 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;
228 ev_init (&tw, timer_cb); 434 ev_init (&tw, timer_cb);
229 435 tw.data = (void *)ads;
230 adns_init (&ads, adns_if_noenv | adns_if_noerrprint | adns_if_noserverwarn | adns_if_noautosys, 0);
231} 436}
232 437
233void submit (char *owner, int type, int flags, SV *cb) 438void submit (char *owner, int type, int flags, SV *cb)
234 PPCODE: 439 PPCODE:
235{ 440{
236 SV *csv = NEWSV (0, sizeof (struct ctx)); 441 SV *csv = NEWSV (0, sizeof (struct ctx));
237 struct ctx *c = (struct ctx *)SvPVX (csv); 442 struct ctx *c = (struct ctx *)SvPVX (csv);
238 int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query); 443 int r = adns_submit (ads, owner, type, flags, (void *)c, &c->query);
239 444
445 outstanding_inc (ads);
446
240 if (r) 447 if (r)
241 { 448 {
242 SvREFCNT_dec (csv); 449 SvREFCNT_dec (csv);
450 errno = r;
243 XSRETURN_EMPTY; 451 XSRETURN_EMPTY;
244 } 452 }
245 else 453 else
246 { 454 {
247 ev_ref ();
248 SvPOK_only (csv); 455 SvPOK_only (csv);
249 SvCUR_set (csv, sizeof (struct ctx)); 456 SvCUR_set (csv, sizeof (struct ctx));
457
250 c->self = csv; 458 c->self = csv;
251 c->cb = newSVsv (cb); 459 c->cb = newSVsv (cb);
460 c->ads = ads;
461
462 if (!ev_is_active (&iw))
463 ev_idle_start (EV_A_ &iw);
252 464
253 if (GIMME_V != G_VOID) 465 if (GIMME_V != G_VOID)
254 { 466 {
255 csv = sv_2mortal (newRV_inc (csv)); 467 csv = sv_2mortal (newRV_inc (csv));
256 sv_bless (csv, stash); 468 sv_bless (csv, stash);
258 } 470 }
259 } 471 }
260} 472}
261 473
262void DESTROY (SV *req) 474void DESTROY (SV *req)
475 ALIAS:
476 cancel = 1
263 CODE: 477 CODE:
264{ 478{
265 struct ctx *c; 479 struct ctx *c;
266 480
267 if (!(SvROK (req) && SvOBJECT (SvRV (req)) 481 if (!(SvROK (req) && SvOBJECT (SvRV (req))
270 484
271 c = (struct ctx *)SvPVX (SvRV (req)); 485 c = (struct ctx *)SvPVX (SvRV (req));
272 486
273 if (c->cb) 487 if (c->cb)
274 { 488 {
275 ev_unref (); 489 SvREFCNT_dec (c->cb);
490 c->cb = 0; outstanding_dec (c->ads);
276 adns_cancel (c->query); 491 adns_cancel (c->query);
277 SvREFCNT_dec (c->cb); 492 SvREFCNT_dec (c->self);
278 } 493 }
279} 494}
280 495
281 496
282 497

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines