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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines