ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/EV.xs
Revision: 1.3
Committed: Fri Oct 26 17:24:18 2007 UTC (16 years, 6 months ago) by root
Branch: MAIN
Changes since 1.2: +17 -16 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <math.h>
6 #include <netinet/in.h>
7
8 #include <sys/time.h>
9 #include <time.h>
10 #include <event.h>
11 #include <evdns.h>
12 /*include <evhttp.h>*/ /* does not compile */
13
14 #define EV_NONE 0
15 #define EV_UNDEF -1
16
17 #define TIMEOUT_NONE HUGE_VAL
18
19 typedef struct event_base *Base;
20
21 static HV *stash_base, *stash_event;
22
23 static double tv_get (struct timeval *tv)
24 {
25 return tv->tv_sec + tv->tv_usec * 1e-6;
26 }
27
28 static void tv_set (struct timeval *tv, double val)
29 {
30 tv->tv_sec = (long)val;
31 tv->tv_usec = (long)((val - (double)tv->tv_sec) * 1e6);
32
33 }
34
35 /////////////////////////////////////////////////////////////////////////////
36 // Event
37
38 typedef struct ev {
39 struct event ev;
40 SV *cb, *fh;
41 SV *self; /* contains this struct */
42 double timeout;
43 double interval;
44 unsigned char active;
45 unsigned char abstime;
46 } *Event;
47
48 static double
49 e_now ()
50 {
51 struct timeval tv;
52 gettimeofday (&tv, 0);
53
54 return tv_get (&tv);
55 }
56
57 static void e_cb (int fd, short events, void *arg);
58
59 static int sv_fileno (SV *fh)
60 {
61 SvGETMAGIC (fh);
62
63 if (SvROK (fh))
64 fh = SvRV (fh);
65
66 if (SvTYPE (fh) == SVt_PVGV)
67 return PerlIO_fileno (IoIFP (sv_2io (fh)));
68
69 if (SvIOK (fh))
70 return SvIV (fh);
71
72 return -1;
73 }
74
75 static Event
76 e_new (SV *fh, short events, SV *cb)
77 {
78 int fd = sv_fileno (fh);
79 Event ev;
80 SV *self = NEWSV (0, sizeof (struct ev));
81 SvPOK_only (self);
82 SvCUR_set (self, sizeof (struct ev));
83
84 ev = (Event)SvPVX (self);
85
86 ev->fh = newSVsv (fh);
87 ev->cb = newSVsv (cb);
88 ev->self = self;
89 ev->timeout = TIMEOUT_NONE;
90 ev->interval = 0.;
91 ev->abstime = 0;
92 ev->active = 0;
93
94 event_set (&ev->ev, fd, events, e_cb, (void *)ev);
95
96 return ev;
97 }
98
99 static struct timeval *
100 e_tv (Event ev)
101 {
102 static struct timeval tv;
103 double to = ev->timeout;
104
105 if (to == TIMEOUT_NONE)
106 return 0;
107
108 if (ev->abstime)
109 {
110 double now = e_now ();
111
112 if (now > to && ev->interval)
113 ev->timeout = (to += ceil ((now - to) / ev->interval) * ev->interval);
114
115 to -= now;
116 }
117 else if (to < 0.)
118 to = 0.;
119
120 tv_set (&tv, to);
121
122 return &tv;
123 }
124
125 static SV *e_self (Event ev)
126 {
127 SV *rv;
128
129 if (SvOBJECT (ev->self))
130 rv = newRV_inc (ev->self);
131 else
132 {
133 rv = newRV_noinc (ev->self);
134 sv_bless (rv, stash_event);
135 SvREADONLY_on (ev->self);
136 }
137
138 return rv;
139 }
140
141 static int
142 e_start (Event ev)
143 {
144 if (ev->active) event_del (&ev->ev);
145 ev->active = 1;
146 return event_add (&ev->ev, e_tv (ev));
147 }
148
149 static int e_stop (Event ev)
150 {
151 return ev->active
152 ? (ev->active = 0), event_del (&ev->ev)
153 : 0;
154 }
155
156 static void
157 e_cb (int fd, short events, void *arg)
158 {
159 struct ev *ev = (struct ev*)arg;
160 dSP;
161
162 ENTER;
163 SAVETMPS;
164
165 if (!(ev->ev.ev_events & EV_PERSIST))
166 ev->active = 0;
167
168 PUSHMARK (SP);
169 EXTEND (SP, 2);
170 PUSHs (sv_2mortal (e_self (ev)));
171 PUSHs (sv_2mortal (newSViv (events)));
172 PUTBACK;
173 call_sv (ev->cb, G_DISCARD | G_VOID | G_EVAL);
174 /*TODO: if err, call some logging function */
175
176 if (ev->interval && !ev->active)
177 e_start (ev);
178
179 FREETMPS;
180 LEAVE;
181 }
182
183 /////////////////////////////////////////////////////////////////////////////
184 // DNS
185
186 static void
187 dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg)
188 {
189 dSP;
190 SV *cb = (SV *)arg;
191
192 ENTER;
193 SAVETMPS;
194 PUSHMARK (SP);
195 EXTEND (SP, count + 3);
196 PUSHs (sv_2mortal (newSViv (result)));
197
198 if (result == DNS_ERR_NONE && ttl >= 0)
199 {
200 int i;
201
202 PUSHs (sv_2mortal (newSViv (type)));
203 PUSHs (sv_2mortal (newSViv (ttl)));
204
205 for (i = 0; i < count; ++i)
206 switch (type)
207 {
208 case DNS_IPv6_AAAA:
209 PUSHs (sv_2mortal (newSVpvn (i * 16 + (char *)addresses, 16)));
210 break;
211 case DNS_IPv4_A:
212 PUSHs (sv_2mortal (newSVpvn (i * 4 + (char *)addresses, 4)));
213 break;
214 case DNS_PTR:
215 PUSHs (sv_2mortal (newSVpv (*(char **)addresses, 0)));
216 break;
217 }
218 }
219
220 PUTBACK;
221 call_sv (sv_2mortal (cb), G_DISCARD | G_VOID | G_EVAL);
222
223 FREETMPS;
224 LEAVE;
225 }
226
227 /////////////////////////////////////////////////////////////////////////////
228 // XS interface functions
229
230 MODULE = EV PACKAGE = EV PREFIX = event_
231
232 BOOT:
233 {
234 HV *stash = gv_stashpv ("EV", 1);
235
236 static const struct {
237 const char *name;
238 IV iv;
239 } *civ, const_iv[] = {
240 # define const_iv(pfx, name) { # name, (IV) pfx ## name },
241 const_iv (EV_, NONE)
242 const_iv (EV_, TIMEOUT)
243 const_iv (EV_, READ)
244 const_iv (EV_, WRITE)
245 const_iv (EV_, SIGNAL)
246 const_iv (EV_, PERSIST)
247 const_iv (EV, LOOP_ONCE)
248 const_iv (EV, LOOP_NONBLOCK)
249 const_iv (EV, BUFFER_READ)
250 const_iv (EV, BUFFER_WRITE)
251 const_iv (EV, BUFFER_EOF)
252 const_iv (EV, BUFFER_ERROR)
253 const_iv (EV, BUFFER_TIMEOUT)
254 };
255
256 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
257 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
258
259 stash_base = gv_stashpv ("EV::Base" , 1);
260 stash_event = gv_stashpv ("EV::Event", 1);
261 }
262
263 double now ()
264 CODE:
265 RETVAL = e_now ();
266 OUTPUT:
267 RETVAL
268
269 const char *version ()
270 ALIAS:
271 method = 1
272 CODE:
273 RETVAL = ix ? event_get_method () : event_get_version ();
274 OUTPUT:
275 RETVAL
276
277 Base event_init ()
278
279 int event_priority_init (int npri)
280
281 int event_dispatch ()
282
283 int event_loop (int flags = 0)
284
285 int event_loopexit (double after = 0)
286 CODE:
287 {
288 struct timeval tv;
289 tv_set (&tv, after);
290 event_loopexit (&tv);
291 }
292
293 Event event (SV *cb)
294 CODE:
295 RETVAL = e_new (NEWSV (0, 0), 0, cb);
296 OUTPUT:
297 RETVAL
298
299 Event io (SV *fh, short events, SV *cb)
300 ALIAS:
301 io_ns = 1
302 CODE:
303 RETVAL = e_new (fh, events, cb);
304 if (!ix) e_start (RETVAL);
305 OUTPUT:
306 RETVAL
307
308 Event timer (double after, int repeat, SV *cb)
309 ALIAS:
310 timer_ns = 1
311 CODE:
312 RETVAL = e_new (NEWSV (0, 0), 0, cb);
313 RETVAL->timeout = after;
314 RETVAL->interval = repeat;
315 if (!ix) e_start (RETVAL);
316 OUTPUT:
317 RETVAL
318
319 Event timer_abs (double at, double interval, SV *cb)
320 ALIAS:
321 timer_abs_ns = 1
322 CODE:
323 RETVAL = e_new (NEWSV (0, 0), 0, cb);
324 RETVAL->timeout = at;
325 RETVAL->interval = interval;
326 RETVAL->abstime = 1;
327 if (!ix) e_start (RETVAL);
328 OUTPUT:
329 RETVAL
330
331 Event signal (SV *signal, SV *cb)
332 ALIAS:
333 signal_ns = 1
334 CODE:
335 RETVAL = e_new (signal, EV_SIGNAL | EV_PERSIST, cb);
336 if (!ix) e_start (RETVAL);
337 OUTPUT:
338 RETVAL
339
340 PROTOTYPES: DISABLE
341
342
343 MODULE = EV PACKAGE = EV::Base PREFIX = event_base_
344
345 Base new ()
346 CODE:
347 RETVAL = event_init ();
348 OUTPUT:
349 RETVAL
350
351 int event_base_dispatch (Base base)
352
353 int event_base_loop (Base base, int flags = 0)
354
355 int event_base_loopexit (Base base, double after)
356 CODE:
357 {
358 struct timeval tv;
359 tv.tv_sec = (long)after;
360 tv.tv_usec = (long)(after - tv.tv_sec) * 1e6;
361 event_base_loopexit (base, &tv);
362 }
363
364 int event_base_priority_init (Base base, int npri)
365
366 void event_base_set (Base base, Event ev)
367 C_ARGS: base, &ev->ev
368
369 void DESTROY (Base base)
370 CODE:
371 /*event_base_free (base);*/ /* causes too many problems */
372
373
374 MODULE = EV PACKAGE = EV::Event PREFIX = event_
375
376 int event_priority_set (Event ev, int pri)
377 C_ARGS: &ev->ev, pri
378
379 int event_add (Event ev, double timeout = TIMEOUT_NONE)
380 CODE:
381 ev->timeout = timeout;
382 ev->abstime = 0;
383 RETVAL = e_start (ev);
384 OUTPUT:
385 RETVAL
386
387 int event_start (Event ev)
388 CODE:
389 RETVAL = e_start (ev);
390 OUTPUT:
391 RETVAL
392
393 int event_del (Event ev)
394 ALIAS:
395 stop = 0
396 CODE:
397 RETVAL = e_stop (ev);
398 OUTPUT:
399 RETVAL
400
401 void DESTROY (Event ev)
402 CODE:
403 e_stop (ev);
404 SvREFCNT_dec (ev->cb);
405 SvREFCNT_dec (ev->fh);
406
407 SV *cb (Event ev, SV *new_cb = 0)
408 CODE:
409 RETVAL = newSVsv (ev->cb);
410 if (items > 1)
411 sv_setsv (ev->cb, new_cb);
412 OUTPUT:
413 RETVAL
414
415 SV *fh (Event ev, SV *new_fh = 0)
416 ALIAS:
417 signal = 0
418 CODE:
419 RETVAL = newSVsv (ev->fh);
420 if (items > 1)
421 {
422 if (ev->active) event_del (&ev->ev);
423 sv_setsv (ev->fh, new_fh);
424 ev->ev.ev_fd = sv_fileno (ev->fh);
425 if (ev->active) event_add (&ev->ev, e_tv (ev));
426 }
427 OUTPUT:
428 RETVAL
429
430 short events (Event ev, short new_events = EV_UNDEF)
431 CODE:
432 RETVAL = ev->ev.ev_events;
433 if (items > 1)
434 {
435 if (ev->active) event_del (&ev->ev);
436 ev->ev.ev_events = new_events;
437 if (ev->active) event_add (&ev->ev, e_tv (ev));
438 }
439 OUTPUT:
440 RETVAL
441
442 double timeout (Event ev, double new_timeout = 0., int repeat = 0)
443 CODE:
444 RETVAL = ev->timeout;
445 if (items > 1)
446 {
447 if (ev->active) event_del (&ev->ev);
448 ev->timeout = new_timeout;
449 ev->interval = repeat;
450 ev->abstime = 0;
451 if (ev->active) event_add (&ev->ev, e_tv (ev));
452 }
453 OUTPUT:
454 RETVAL
455
456 void timeout_abs (Event ev, double at, double interval = 0.)
457 CODE:
458 if (ev->active) event_del (&ev->ev);
459 ev->timeout = at;
460 ev->interval = interval;
461 ev->abstime = 1;
462 if (ev->active) event_add (&ev->ev, e_tv (ev));
463
464
465 MODULE = EV PACKAGE = EV::DNS PREFIX = evdns_
466
467 BOOT:
468 {
469 HV *stash = gv_stashpv ("EV::DNS", 1);
470
471 static const struct {
472 const char *name;
473 IV iv;
474 } *civ, const_iv[] = {
475 # define const_iv(pfx, name) { # name, (IV) pfx ## name },
476
477 const_iv (DNS_, ERR_NONE)
478 const_iv (DNS_, ERR_FORMAT)
479 const_iv (DNS_, ERR_SERVERFAILED)
480 const_iv (DNS_, ERR_NOTEXIST)
481 const_iv (DNS_, ERR_NOTIMPL)
482 const_iv (DNS_, ERR_REFUSED)
483 const_iv (DNS_, ERR_TRUNCATED)
484 const_iv (DNS_, ERR_UNKNOWN)
485 const_iv (DNS_, ERR_TIMEOUT)
486 const_iv (DNS_, ERR_SHUTDOWN)
487 const_iv (DNS_, IPv4_A)
488 const_iv (DNS_, PTR)
489 const_iv (DNS_, IPv6_AAAA)
490 const_iv (DNS_, QUERY_NO_SEARCH)
491 const_iv (DNS_, OPTION_SEARCH)
492 const_iv (DNS_, OPTION_NAMESERVERS)
493 const_iv (DNS_, OPTION_MISC)
494 const_iv (DNS_, OPTIONS_ALL)
495 const_iv (DNS_, NO_SEARCH)
496 };
497
498 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
499 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
500 }
501
502 int evdns_init ()
503
504 void evdns_shutdown (int fail_requests = 1)
505
506 const char *evdns_err_to_string (int err)
507
508 int evdns_nameserver_add (U32 address)
509
510 int evdns_count_nameservers ()
511
512 int evdns_clear_nameservers_and_suspend ()
513
514 int evdns_resume ()
515
516 int evdns_nameserver_ip_add (char *ip_as_string)
517
518 int evdns_resolve_ipv4 (const char *name, int flags, SV *cb)
519 C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
520
521 int evdns_resolve_ipv6 (const char *name, int flags, SV *cb)
522 C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
523
524 int evdns_resolve_reverse (SV *addr, int flags, SV *cb)
525 ALIAS:
526 evdns_resolve_reverse_ipv6 = 1
527 CODE:
528 {
529 STRLEN len;
530 char *data = SvPVbyte (addr, len);
531 if (len != (ix ? 16 : 4))
532 croak ("ipv4/ipv6 address to resolve must be given as 4/16 byte octet string");
533
534 RETVAL = ix
535 ? evdns_resolve_reverse_ipv6 ((struct in6_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb))
536 : evdns_resolve_reverse ((struct in_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb));
537 }
538 OUTPUT:
539 RETVAL
540
541 int evdns_set_option (char *option, char *val, int flags)
542
543 int evdns_resolv_conf_parse (int flags, const char *filename)
544
545 #ifdef MS_WINDOWS
546
547 int evdns_config_windows_nameservers ()
548
549 #endif
550
551 void evdns_search_clear ()
552
553 void evdns_search_add (char *domain)
554
555 void evdns_search_ndots_set (int ndots)
556