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

# User Rev Content
1 root 1.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 root 1.3 SvGETMAGIC (fh);
62 root 1.1
63 root 1.3 if (SvROK (fh))
64     fh = SvRV (fh);
65 root 1.1
66 root 1.3 if (SvTYPE (fh) == SVt_PVGV)
67     return PerlIO_fileno (IoIFP (sv_2io (fh)));
68 root 1.1
69 root 1.3 if (SvIOK (fh))
70     return SvIV (fh);
71 root 1.1
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 root 1.3 int event_loopexit (double after = 0)
286 root 1.1 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 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
296 root 1.1 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 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
313 root 1.1 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 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
324 root 1.1 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 root 1.3 SV *cb (Event ev, SV *new_cb = 0)
408 root 1.1 CODE:
409 root 1.3 RETVAL = newSVsv (ev->cb);
410     if (items > 1)
411     sv_setsv (ev->cb, new_cb);
412     OUTPUT:
413     RETVAL
414 root 1.1
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 root 1.2 ev->ev.ev_fd = sv_fileno (ev->fh);
425 root 1.1 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