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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines