ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/EV.xs
Revision: 1.2
Committed: Fri Oct 26 16:51:27 2007 UTC (16 years, 6 months ago) by root
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
looks better

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