ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/EV.xs
Revision: 1.14
Committed: Tue Oct 30 12:48:29 2007 UTC (16 years, 6 months ago) by root
Branch: MAIN
Changes since 1.13: +24 -9 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 root 1.4
13     /* workaround for evhttp.h requiring obscure bsd headers */
14     #ifndef TAILQ_ENTRY
15     #define TAILQ_ENTRY(type) \
16     struct { \
17     struct type *tqe_next; /* next element */ \
18     struct type **tqe_prev; /* address of previous next element */ \
19     }
20     #endif /* !TAILQ_ENTRY */
21     #include <evhttp.h>
22 root 1.1
23     #define EV_NONE 0
24     #define EV_UNDEF -1
25    
26     #define TIMEOUT_NONE HUGE_VAL
27    
28 root 1.11 #include "EV/EVAPI.h"
29    
30 root 1.1 typedef struct event_base *Base;
31 root 1.10 typedef int Signal;
32 root 1.1
33 root 1.11 static struct EVAPI evapi;
34    
35 root 1.1 static HV *stash_base, *stash_event;
36    
37     static double tv_get (struct timeval *tv)
38     {
39     return tv->tv_sec + tv->tv_usec * 1e-6;
40     }
41    
42     static void tv_set (struct timeval *tv, double val)
43     {
44     tv->tv_sec = (long)val;
45     tv->tv_usec = (long)((val - (double)tv->tv_sec) * 1e6);
46    
47     }
48    
49 root 1.10 static int
50     sv_signum (SV *sig)
51     {
52     int signum;
53    
54     if (SvIV (sig) > 0)
55     return SvIV (sig);
56    
57     for (signum = 1; signum < SIG_SIZE; ++signum)
58     if (strEQ (SvPV_nolen (sig), PL_sig_name [signum]))
59     return signum;
60    
61     return -1;
62     }
63    
64 root 1.11 static void
65     api_once (int fd, short events, double timeout, void (*cb)(int, short, void *), void *arg)
66     {
67 root 1.12 if (timeout >= 0.)
68 root 1.11 {
69     struct timeval tv;
70     tv_set (&tv, timeout);
71     event_once (fd, events, cb, arg, &tv);
72     }
73     else
74     event_once (fd, events, cb, arg, 0);
75     }
76    
77 root 1.1 /////////////////////////////////////////////////////////////////////////////
78     // Event
79    
80     typedef struct ev {
81     struct event ev;
82     SV *cb, *fh;
83     SV *self; /* contains this struct */
84     double timeout;
85     double interval;
86     unsigned char active;
87     unsigned char abstime;
88     } *Event;
89    
90     static double
91 root 1.11 e_now (void)
92 root 1.1 {
93     struct timeval tv;
94     gettimeofday (&tv, 0);
95    
96     return tv_get (&tv);
97     }
98    
99     static void e_cb (int fd, short events, void *arg);
100    
101     static int sv_fileno (SV *fh)
102     {
103 root 1.3 SvGETMAGIC (fh);
104 root 1.1
105 root 1.3 if (SvROK (fh))
106     fh = SvRV (fh);
107 root 1.1
108 root 1.3 if (SvTYPE (fh) == SVt_PVGV)
109     return PerlIO_fileno (IoIFP (sv_2io (fh)));
110 root 1.1
111 root 1.3 if (SvIOK (fh))
112     return SvIV (fh);
113 root 1.1
114     return -1;
115     }
116    
117     static Event
118     e_new (SV *fh, short events, SV *cb)
119     {
120     int fd = sv_fileno (fh);
121     Event ev;
122     SV *self = NEWSV (0, sizeof (struct ev));
123     SvPOK_only (self);
124     SvCUR_set (self, sizeof (struct ev));
125    
126     ev = (Event)SvPVX (self);
127    
128     ev->fh = newSVsv (fh);
129     ev->cb = newSVsv (cb);
130     ev->self = self;
131     ev->timeout = TIMEOUT_NONE;
132     ev->interval = 0.;
133     ev->abstime = 0;
134     ev->active = 0;
135    
136     event_set (&ev->ev, fd, events, e_cb, (void *)ev);
137    
138     return ev;
139     }
140    
141     static struct timeval *
142     e_tv (Event ev)
143     {
144     static struct timeval tv;
145     double to = ev->timeout;
146    
147     if (to == TIMEOUT_NONE)
148     return 0;
149    
150     if (ev->abstime)
151     {
152     double now = e_now ();
153    
154 root 1.6 if (ev->interval)
155 root 1.1 ev->timeout = (to += ceil ((now - to) / ev->interval) * ev->interval);
156    
157     to -= now;
158     }
159     else if (to < 0.)
160     to = 0.;
161    
162     tv_set (&tv, to);
163    
164     return &tv;
165     }
166    
167     static SV *e_self (Event ev)
168     {
169     SV *rv;
170    
171     if (SvOBJECT (ev->self))
172     rv = newRV_inc (ev->self);
173     else
174     {
175     rv = newRV_noinc (ev->self);
176     sv_bless (rv, stash_event);
177     SvREADONLY_on (ev->self);
178     }
179    
180     return rv;
181     }
182    
183     static int
184     e_start (Event ev)
185     {
186     if (ev->active) event_del (&ev->ev);
187     ev->active = 1;
188     return event_add (&ev->ev, e_tv (ev));
189     }
190    
191     static int e_stop (Event ev)
192     {
193     return ev->active
194     ? (ev->active = 0), event_del (&ev->ev)
195     : 0;
196     }
197    
198     static void
199     e_cb (int fd, short events, void *arg)
200     {
201     struct ev *ev = (struct ev*)arg;
202     dSP;
203 root 1.14 I32 mark = SP - PL_stack_base;
204     SV *sv_self, *sv_events;
205     static SV *sv_events_cache;
206 root 1.1
207 root 1.7 if (!(ev->ev.ev_events & EV_PERSIST) || (events & EV_TIMEOUT))
208 root 1.1 ev->active = 0;
209    
210 root 1.14 sv_self = e_self (ev);
211    
212     if (sv_events_cache)
213     {
214     sv_events = sv_events_cache; sv_events_cache = 0;
215     SvIV_set (sv_events, events);
216     }
217     else
218     sv_events = newSViv (events);
219    
220 root 1.1 PUSHMARK (SP);
221     EXTEND (SP, 2);
222 root 1.14 PUSHs (sv_self);
223     PUSHs (sv_events);
224 root 1.1 PUTBACK;
225     call_sv (ev->cb, G_DISCARD | G_VOID | G_EVAL);
226 root 1.14 SP = PL_stack_base + mark; PUTBACK;
227    
228     SvREFCNT_dec (sv_self);
229    
230     if (sv_events_cache)
231     SvREFCNT_dec (sv_events);
232     else
233     sv_events_cache = sv_events;
234 root 1.1
235     if (ev->interval && !ev->active)
236     e_start (ev);
237    
238 root 1.8 if (SvTRUE (ERRSV))
239     {
240     PUSHMARK (SP);
241     PUTBACK;
242     call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
243 root 1.14 SP = PL_stack_base + mark; PUTBACK;
244 root 1.8 }
245 root 1.1 }
246    
247     /////////////////////////////////////////////////////////////////////////////
248     // DNS
249    
250     static void
251     dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg)
252     {
253     dSP;
254     SV *cb = (SV *)arg;
255    
256     ENTER;
257     SAVETMPS;
258     PUSHMARK (SP);
259     EXTEND (SP, count + 3);
260     PUSHs (sv_2mortal (newSViv (result)));
261    
262     if (result == DNS_ERR_NONE && ttl >= 0)
263     {
264     int i;
265    
266     PUSHs (sv_2mortal (newSViv (type)));
267     PUSHs (sv_2mortal (newSViv (ttl)));
268    
269     for (i = 0; i < count; ++i)
270     switch (type)
271     {
272     case DNS_IPv6_AAAA:
273     PUSHs (sv_2mortal (newSVpvn (i * 16 + (char *)addresses, 16)));
274     break;
275     case DNS_IPv4_A:
276     PUSHs (sv_2mortal (newSVpvn (i * 4 + (char *)addresses, 4)));
277     break;
278     case DNS_PTR:
279     PUSHs (sv_2mortal (newSVpv (*(char **)addresses, 0)));
280     break;
281     }
282     }
283    
284     PUTBACK;
285     call_sv (sv_2mortal (cb), G_DISCARD | G_VOID | G_EVAL);
286    
287     FREETMPS;
288 root 1.8
289     if (SvTRUE (ERRSV))
290     {
291     PUSHMARK (SP);
292     PUTBACK;
293     call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
294     }
295    
296 root 1.1 LEAVE;
297     }
298    
299     /////////////////////////////////////////////////////////////////////////////
300     // XS interface functions
301    
302     MODULE = EV PACKAGE = EV PREFIX = event_
303    
304     BOOT:
305     {
306 root 1.10 int i;
307 root 1.1 HV *stash = gv_stashpv ("EV", 1);
308    
309     static const struct {
310     const char *name;
311     IV iv;
312     } *civ, const_iv[] = {
313     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
314     const_iv (EV_, NONE)
315     const_iv (EV_, TIMEOUT)
316     const_iv (EV_, READ)
317     const_iv (EV_, WRITE)
318     const_iv (EV_, SIGNAL)
319     const_iv (EV_, PERSIST)
320     const_iv (EV, LOOP_ONCE)
321     const_iv (EV, LOOP_NONBLOCK)
322     const_iv (EV, BUFFER_READ)
323     const_iv (EV, BUFFER_WRITE)
324     const_iv (EV, BUFFER_EOF)
325     const_iv (EV, BUFFER_ERROR)
326     const_iv (EV, BUFFER_TIMEOUT)
327     };
328    
329     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
330     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
331    
332     stash_base = gv_stashpv ("EV::Base" , 1);
333     stash_event = gv_stashpv ("EV::Event", 1);
334 root 1.11
335     {
336     SV *sv = perl_get_sv ("EV::API", TRUE);
337     perl_get_sv ("EV::API", TRUE); /* silence 5.10 warning */
338    
339     evapi.ver = EV_API_VERSION;
340     evapi.rev = EV_API_REVISION;
341     evapi.now = e_now;
342     evapi.once = api_once;
343 root 1.13 evapi.loop = event_loop;
344 root 1.11
345     sv_setiv (sv, (IV)&evapi);
346     SvREADONLY_on (sv);
347     }
348 root 1.1 }
349    
350     double now ()
351     CODE:
352     RETVAL = e_now ();
353     OUTPUT:
354     RETVAL
355    
356     const char *version ()
357     ALIAS:
358     method = 1
359     CODE:
360     RETVAL = ix ? event_get_method () : event_get_version ();
361     OUTPUT:
362     RETVAL
363    
364     Base event_init ()
365    
366     int event_priority_init (int npri)
367    
368     int event_dispatch ()
369    
370     int event_loop (int flags = 0)
371    
372 root 1.3 int event_loopexit (double after = 0)
373 root 1.1 CODE:
374     {
375     struct timeval tv;
376     tv_set (&tv, after);
377     event_loopexit (&tv);
378     }
379    
380     Event event (SV *cb)
381     CODE:
382 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
383 root 1.1 OUTPUT:
384     RETVAL
385    
386     Event io (SV *fh, short events, SV *cb)
387     ALIAS:
388     io_ns = 1
389     CODE:
390     RETVAL = e_new (fh, events, cb);
391     if (!ix) e_start (RETVAL);
392     OUTPUT:
393     RETVAL
394    
395 root 1.9 Event timed_io (SV *fh, short events, double timeout, SV *cb)
396     ALIAS:
397     timed_io_ns = 1
398     CODE:
399     {
400     events = timeout ? events & ~EV_PERSIST : events | EV_PERSIST;
401    
402     RETVAL = e_new (fh, events, cb);
403    
404     if (timeout)
405     {
406     RETVAL->timeout = timeout;
407     RETVAL->interval = 1;
408     }
409    
410     if (!ix) e_start (RETVAL);
411     }
412     OUTPUT:
413     RETVAL
414    
415 root 1.1 Event timer (double after, int repeat, SV *cb)
416     ALIAS:
417     timer_ns = 1
418     CODE:
419 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
420 root 1.1 RETVAL->timeout = after;
421     RETVAL->interval = repeat;
422     if (!ix) e_start (RETVAL);
423     OUTPUT:
424     RETVAL
425    
426     Event timer_abs (double at, double interval, SV *cb)
427     ALIAS:
428     timer_abs_ns = 1
429     CODE:
430 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
431 root 1.1 RETVAL->timeout = at;
432     RETVAL->interval = interval;
433     RETVAL->abstime = 1;
434     if (!ix) e_start (RETVAL);
435     OUTPUT:
436     RETVAL
437    
438 root 1.10 Event signal (Signal signum, SV *cb)
439 root 1.1 ALIAS:
440     signal_ns = 1
441     CODE:
442 root 1.10 RETVAL = e_new (ST (0), EV_SIGNAL | EV_PERSIST, cb);
443     RETVAL->ev.ev_fd = signum;
444 root 1.1 if (!ix) e_start (RETVAL);
445     OUTPUT:
446     RETVAL
447    
448     PROTOTYPES: DISABLE
449    
450    
451     MODULE = EV PACKAGE = EV::Base PREFIX = event_base_
452    
453     Base new ()
454     CODE:
455     RETVAL = event_init ();
456     OUTPUT:
457     RETVAL
458    
459     int event_base_dispatch (Base base)
460    
461     int event_base_loop (Base base, int flags = 0)
462    
463     int event_base_loopexit (Base base, double after)
464     CODE:
465     {
466     struct timeval tv;
467     tv.tv_sec = (long)after;
468     tv.tv_usec = (long)(after - tv.tv_sec) * 1e6;
469     event_base_loopexit (base, &tv);
470     }
471    
472     int event_base_priority_init (Base base, int npri)
473    
474     void event_base_set (Base base, Event ev)
475     C_ARGS: base, &ev->ev
476    
477     void DESTROY (Base base)
478     CODE:
479     /*event_base_free (base);*/ /* causes too many problems */
480    
481    
482     MODULE = EV PACKAGE = EV::Event PREFIX = event_
483    
484     int event_priority_set (Event ev, int pri)
485     C_ARGS: &ev->ev, pri
486    
487     int event_add (Event ev, double timeout = TIMEOUT_NONE)
488     CODE:
489     ev->timeout = timeout;
490     ev->abstime = 0;
491     RETVAL = e_start (ev);
492     OUTPUT:
493     RETVAL
494    
495     int event_start (Event ev)
496     CODE:
497     RETVAL = e_start (ev);
498     OUTPUT:
499     RETVAL
500    
501     int event_del (Event ev)
502     ALIAS:
503     stop = 0
504     CODE:
505     RETVAL = e_stop (ev);
506     OUTPUT:
507     RETVAL
508    
509     void DESTROY (Event ev)
510     CODE:
511     e_stop (ev);
512     SvREFCNT_dec (ev->cb);
513     SvREFCNT_dec (ev->fh);
514    
515 root 1.3 SV *cb (Event ev, SV *new_cb = 0)
516 root 1.1 CODE:
517 root 1.3 RETVAL = newSVsv (ev->cb);
518     if (items > 1)
519     sv_setsv (ev->cb, new_cb);
520     OUTPUT:
521     RETVAL
522 root 1.1
523     SV *fh (Event ev, SV *new_fh = 0)
524     CODE:
525     RETVAL = newSVsv (ev->fh);
526     if (items > 1)
527     {
528     if (ev->active) event_del (&ev->ev);
529     sv_setsv (ev->fh, new_fh);
530 root 1.9 ev->ev.ev_fd = sv_fileno (ev->fh);
531 root 1.10 ev->ev.ev_events &= ev->ev.ev_events & ~EV_SIGNAL;
532 root 1.1 if (ev->active) event_add (&ev->ev, e_tv (ev));
533     }
534     OUTPUT:
535     RETVAL
536    
537 root 1.10 SV *signal (Event ev, SV *new_signal = 0)
538     CODE:
539     {
540     Signal signum;
541    
542     if (items > 1)
543     signum = sv_signum (new_signal); /* may croak here */
544    
545     RETVAL = newSVsv (ev->fh);
546    
547     if (items > 1)
548     {
549     if (ev->active) event_del (&ev->ev);
550     sv_setsv (ev->fh, new_signal);
551     ev->ev.ev_fd = signum;
552     ev->ev.ev_events |= EV_SIGNAL;
553     if (ev->active) event_add (&ev->ev, e_tv (ev));
554     }
555     }
556     OUTPUT:
557     RETVAL
558    
559 root 1.1 short events (Event ev, short new_events = EV_UNDEF)
560     CODE:
561     RETVAL = ev->ev.ev_events;
562     if (items > 1)
563     {
564     if (ev->active) event_del (&ev->ev);
565     ev->ev.ev_events = new_events;
566     if (ev->active) event_add (&ev->ev, e_tv (ev));
567     }
568     OUTPUT:
569     RETVAL
570    
571     double timeout (Event ev, double new_timeout = 0., int repeat = 0)
572     CODE:
573     RETVAL = ev->timeout;
574     if (items > 1)
575     {
576     if (ev->active) event_del (&ev->ev);
577     ev->timeout = new_timeout;
578     ev->interval = repeat;
579     ev->abstime = 0;
580     if (ev->active) event_add (&ev->ev, e_tv (ev));
581     }
582     OUTPUT:
583     RETVAL
584    
585     void timeout_abs (Event ev, double at, double interval = 0.)
586     CODE:
587     if (ev->active) event_del (&ev->ev);
588     ev->timeout = at;
589     ev->interval = interval;
590     ev->abstime = 1;
591     if (ev->active) event_add (&ev->ev, e_tv (ev));
592    
593    
594     MODULE = EV PACKAGE = EV::DNS PREFIX = evdns_
595    
596     BOOT:
597     {
598     HV *stash = gv_stashpv ("EV::DNS", 1);
599    
600     static const struct {
601     const char *name;
602     IV iv;
603     } *civ, const_iv[] = {
604     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
605     const_iv (DNS_, ERR_NONE)
606     const_iv (DNS_, ERR_FORMAT)
607     const_iv (DNS_, ERR_SERVERFAILED)
608     const_iv (DNS_, ERR_NOTEXIST)
609     const_iv (DNS_, ERR_NOTIMPL)
610     const_iv (DNS_, ERR_REFUSED)
611     const_iv (DNS_, ERR_TRUNCATED)
612     const_iv (DNS_, ERR_UNKNOWN)
613     const_iv (DNS_, ERR_TIMEOUT)
614     const_iv (DNS_, ERR_SHUTDOWN)
615     const_iv (DNS_, IPv4_A)
616     const_iv (DNS_, PTR)
617     const_iv (DNS_, IPv6_AAAA)
618     const_iv (DNS_, QUERY_NO_SEARCH)
619     const_iv (DNS_, OPTION_SEARCH)
620     const_iv (DNS_, OPTION_NAMESERVERS)
621     const_iv (DNS_, OPTION_MISC)
622     const_iv (DNS_, OPTIONS_ALL)
623     const_iv (DNS_, NO_SEARCH)
624     };
625    
626     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
627     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
628     }
629    
630     int evdns_init ()
631    
632     void evdns_shutdown (int fail_requests = 1)
633    
634     const char *evdns_err_to_string (int err)
635    
636     int evdns_nameserver_add (U32 address)
637    
638     int evdns_count_nameservers ()
639    
640     int evdns_clear_nameservers_and_suspend ()
641    
642     int evdns_resume ()
643    
644     int evdns_nameserver_ip_add (char *ip_as_string)
645    
646     int evdns_resolve_ipv4 (const char *name, int flags, SV *cb)
647     C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
648    
649     int evdns_resolve_ipv6 (const char *name, int flags, SV *cb)
650     C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
651    
652     int evdns_resolve_reverse (SV *addr, int flags, SV *cb)
653     ALIAS:
654     evdns_resolve_reverse_ipv6 = 1
655     CODE:
656     {
657     STRLEN len;
658     char *data = SvPVbyte (addr, len);
659     if (len != (ix ? 16 : 4))
660 root 1.8 croak ("ipv4/ipv6 address to be resolved must be given as 4/16 byte octet string");
661 root 1.1
662     RETVAL = ix
663     ? evdns_resolve_reverse_ipv6 ((struct in6_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb))
664     : evdns_resolve_reverse ((struct in_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb));
665     }
666     OUTPUT:
667     RETVAL
668    
669     int evdns_set_option (char *option, char *val, int flags)
670    
671     int evdns_resolv_conf_parse (int flags, const char *filename)
672    
673     #ifdef MS_WINDOWS
674    
675     int evdns_config_windows_nameservers ()
676    
677     #endif
678    
679     void evdns_search_clear ()
680    
681     void evdns_search_add (char *domain)
682    
683     void evdns_search_ndots_set (int ndots)
684    
685 root 1.5
686     MODULE = EV PACKAGE = EV::HTTP PREFIX = evhttp_
687    
688     BOOT:
689     {
690     HV *stash = gv_stashpv ("EV::HTTP", 1);
691    
692     static const struct {
693     const char *name;
694     IV iv;
695     } *civ, const_iv[] = {
696     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
697     const_iv (HTTP_, OK)
698     const_iv (HTTP_, NOCONTENT)
699     const_iv (HTTP_, MOVEPERM)
700     const_iv (HTTP_, MOVETEMP)
701     const_iv (HTTP_, NOTMODIFIED)
702     const_iv (HTTP_, BADREQUEST)
703     const_iv (HTTP_, NOTFOUND)
704     const_iv (HTTP_, SERVUNAVAIL)
705     const_iv (EVHTTP_, REQ_OWN_CONNECTION)
706     const_iv (EVHTTP_, PROXY_REQUEST)
707     const_iv (EVHTTP_, REQ_GET)
708     const_iv (EVHTTP_, REQ_POST)
709     const_iv (EVHTTP_, REQ_HEAD)
710     const_iv (EVHTTP_, REQUEST)
711     const_iv (EVHTTP_, RESPONSE)
712     };
713    
714     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
715     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
716     }
717    
718     MODULE = EV PACKAGE = EV::HTTP::Request PREFIX = evhttp_request_
719    
720     #HttpRequest new (SV *klass, SV *cb)
721    
722     #void DESTROY (struct evhttp_request *req);
723    
724    
725    
726    
727    
728    
729    
730