ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/EV.xs
Revision: 1.13
Committed: Mon Oct 29 18:33:02 2007 UTC (16 years, 6 months ago) by root
Branch: MAIN
CVS Tags: rel-0_03
Changes since 1.12: +1 -0 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    
204     ENTER;
205     SAVETMPS;
206    
207 root 1.7 if (!(ev->ev.ev_events & EV_PERSIST) || (events & EV_TIMEOUT))
208 root 1.1 ev->active = 0;
209    
210     PUSHMARK (SP);
211     EXTEND (SP, 2);
212     PUSHs (sv_2mortal (e_self (ev)));
213     PUSHs (sv_2mortal (newSViv (events)));
214     PUTBACK;
215     call_sv (ev->cb, G_DISCARD | G_VOID | G_EVAL);
216    
217     if (ev->interval && !ev->active)
218     e_start (ev);
219    
220     FREETMPS;
221 root 1.8
222     if (SvTRUE (ERRSV))
223     {
224     PUSHMARK (SP);
225     PUTBACK;
226     call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
227     }
228    
229 root 1.1 LEAVE;
230     }
231    
232     /////////////////////////////////////////////////////////////////////////////
233     // DNS
234    
235     static void
236     dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg)
237     {
238     dSP;
239     SV *cb = (SV *)arg;
240    
241     ENTER;
242     SAVETMPS;
243     PUSHMARK (SP);
244     EXTEND (SP, count + 3);
245     PUSHs (sv_2mortal (newSViv (result)));
246    
247     if (result == DNS_ERR_NONE && ttl >= 0)
248     {
249     int i;
250    
251     PUSHs (sv_2mortal (newSViv (type)));
252     PUSHs (sv_2mortal (newSViv (ttl)));
253    
254     for (i = 0; i < count; ++i)
255     switch (type)
256     {
257     case DNS_IPv6_AAAA:
258     PUSHs (sv_2mortal (newSVpvn (i * 16 + (char *)addresses, 16)));
259     break;
260     case DNS_IPv4_A:
261     PUSHs (sv_2mortal (newSVpvn (i * 4 + (char *)addresses, 4)));
262     break;
263     case DNS_PTR:
264     PUSHs (sv_2mortal (newSVpv (*(char **)addresses, 0)));
265     break;
266     }
267     }
268    
269     PUTBACK;
270     call_sv (sv_2mortal (cb), G_DISCARD | G_VOID | G_EVAL);
271    
272     FREETMPS;
273 root 1.8
274     if (SvTRUE (ERRSV))
275     {
276     PUSHMARK (SP);
277     PUTBACK;
278     call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
279     }
280    
281 root 1.1 LEAVE;
282     }
283    
284     /////////////////////////////////////////////////////////////////////////////
285     // XS interface functions
286    
287     MODULE = EV PACKAGE = EV PREFIX = event_
288    
289     BOOT:
290     {
291 root 1.10 int i;
292 root 1.1 HV *stash = gv_stashpv ("EV", 1);
293    
294     static const struct {
295     const char *name;
296     IV iv;
297     } *civ, const_iv[] = {
298     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
299     const_iv (EV_, NONE)
300     const_iv (EV_, TIMEOUT)
301     const_iv (EV_, READ)
302     const_iv (EV_, WRITE)
303     const_iv (EV_, SIGNAL)
304     const_iv (EV_, PERSIST)
305     const_iv (EV, LOOP_ONCE)
306     const_iv (EV, LOOP_NONBLOCK)
307     const_iv (EV, BUFFER_READ)
308     const_iv (EV, BUFFER_WRITE)
309     const_iv (EV, BUFFER_EOF)
310     const_iv (EV, BUFFER_ERROR)
311     const_iv (EV, BUFFER_TIMEOUT)
312     };
313    
314     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
315     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
316    
317     stash_base = gv_stashpv ("EV::Base" , 1);
318     stash_event = gv_stashpv ("EV::Event", 1);
319 root 1.11
320     {
321     SV *sv = perl_get_sv ("EV::API", TRUE);
322     perl_get_sv ("EV::API", TRUE); /* silence 5.10 warning */
323    
324     evapi.ver = EV_API_VERSION;
325     evapi.rev = EV_API_REVISION;
326     evapi.now = e_now;
327     evapi.once = api_once;
328 root 1.13 evapi.loop = event_loop;
329 root 1.11
330     sv_setiv (sv, (IV)&evapi);
331     SvREADONLY_on (sv);
332     }
333 root 1.1 }
334    
335     double now ()
336     CODE:
337     RETVAL = e_now ();
338     OUTPUT:
339     RETVAL
340    
341     const char *version ()
342     ALIAS:
343     method = 1
344     CODE:
345     RETVAL = ix ? event_get_method () : event_get_version ();
346     OUTPUT:
347     RETVAL
348    
349     Base event_init ()
350    
351     int event_priority_init (int npri)
352    
353     int event_dispatch ()
354    
355     int event_loop (int flags = 0)
356    
357 root 1.3 int event_loopexit (double after = 0)
358 root 1.1 CODE:
359     {
360     struct timeval tv;
361     tv_set (&tv, after);
362     event_loopexit (&tv);
363     }
364    
365     Event event (SV *cb)
366     CODE:
367 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
368 root 1.1 OUTPUT:
369     RETVAL
370    
371     Event io (SV *fh, short events, SV *cb)
372     ALIAS:
373     io_ns = 1
374     CODE:
375     RETVAL = e_new (fh, events, cb);
376     if (!ix) e_start (RETVAL);
377     OUTPUT:
378     RETVAL
379    
380 root 1.9 Event timed_io (SV *fh, short events, double timeout, SV *cb)
381     ALIAS:
382     timed_io_ns = 1
383     CODE:
384     {
385     events = timeout ? events & ~EV_PERSIST : events | EV_PERSIST;
386    
387     RETVAL = e_new (fh, events, cb);
388    
389     if (timeout)
390     {
391     RETVAL->timeout = timeout;
392     RETVAL->interval = 1;
393     }
394    
395     if (!ix) e_start (RETVAL);
396     }
397     OUTPUT:
398     RETVAL
399    
400 root 1.1 Event timer (double after, int repeat, SV *cb)
401     ALIAS:
402     timer_ns = 1
403     CODE:
404 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
405 root 1.1 RETVAL->timeout = after;
406     RETVAL->interval = repeat;
407     if (!ix) e_start (RETVAL);
408     OUTPUT:
409     RETVAL
410    
411     Event timer_abs (double at, double interval, SV *cb)
412     ALIAS:
413     timer_abs_ns = 1
414     CODE:
415 root 1.3 RETVAL = e_new (NEWSV (0, 0), 0, cb);
416 root 1.1 RETVAL->timeout = at;
417     RETVAL->interval = interval;
418     RETVAL->abstime = 1;
419     if (!ix) e_start (RETVAL);
420     OUTPUT:
421     RETVAL
422    
423 root 1.10 Event signal (Signal signum, SV *cb)
424 root 1.1 ALIAS:
425     signal_ns = 1
426     CODE:
427 root 1.10 RETVAL = e_new (ST (0), EV_SIGNAL | EV_PERSIST, cb);
428     RETVAL->ev.ev_fd = signum;
429 root 1.1 if (!ix) e_start (RETVAL);
430     OUTPUT:
431     RETVAL
432    
433     PROTOTYPES: DISABLE
434    
435    
436     MODULE = EV PACKAGE = EV::Base PREFIX = event_base_
437    
438     Base new ()
439     CODE:
440     RETVAL = event_init ();
441     OUTPUT:
442     RETVAL
443    
444     int event_base_dispatch (Base base)
445    
446     int event_base_loop (Base base, int flags = 0)
447    
448     int event_base_loopexit (Base base, double after)
449     CODE:
450     {
451     struct timeval tv;
452     tv.tv_sec = (long)after;
453     tv.tv_usec = (long)(after - tv.tv_sec) * 1e6;
454     event_base_loopexit (base, &tv);
455     }
456    
457     int event_base_priority_init (Base base, int npri)
458    
459     void event_base_set (Base base, Event ev)
460     C_ARGS: base, &ev->ev
461    
462     void DESTROY (Base base)
463     CODE:
464     /*event_base_free (base);*/ /* causes too many problems */
465    
466    
467     MODULE = EV PACKAGE = EV::Event PREFIX = event_
468    
469     int event_priority_set (Event ev, int pri)
470     C_ARGS: &ev->ev, pri
471    
472     int event_add (Event ev, double timeout = TIMEOUT_NONE)
473     CODE:
474     ev->timeout = timeout;
475     ev->abstime = 0;
476     RETVAL = e_start (ev);
477     OUTPUT:
478     RETVAL
479    
480     int event_start (Event ev)
481     CODE:
482     RETVAL = e_start (ev);
483     OUTPUT:
484     RETVAL
485    
486     int event_del (Event ev)
487     ALIAS:
488     stop = 0
489     CODE:
490     RETVAL = e_stop (ev);
491     OUTPUT:
492     RETVAL
493    
494     void DESTROY (Event ev)
495     CODE:
496     e_stop (ev);
497     SvREFCNT_dec (ev->cb);
498     SvREFCNT_dec (ev->fh);
499    
500 root 1.3 SV *cb (Event ev, SV *new_cb = 0)
501 root 1.1 CODE:
502 root 1.3 RETVAL = newSVsv (ev->cb);
503     if (items > 1)
504     sv_setsv (ev->cb, new_cb);
505     OUTPUT:
506     RETVAL
507 root 1.1
508     SV *fh (Event ev, SV *new_fh = 0)
509     CODE:
510     RETVAL = newSVsv (ev->fh);
511     if (items > 1)
512     {
513     if (ev->active) event_del (&ev->ev);
514     sv_setsv (ev->fh, new_fh);
515 root 1.9 ev->ev.ev_fd = sv_fileno (ev->fh);
516 root 1.10 ev->ev.ev_events &= ev->ev.ev_events & ~EV_SIGNAL;
517 root 1.1 if (ev->active) event_add (&ev->ev, e_tv (ev));
518     }
519     OUTPUT:
520     RETVAL
521    
522 root 1.10 SV *signal (Event ev, SV *new_signal = 0)
523     CODE:
524     {
525     Signal signum;
526    
527     if (items > 1)
528     signum = sv_signum (new_signal); /* may croak here */
529    
530     RETVAL = newSVsv (ev->fh);
531    
532     if (items > 1)
533     {
534     if (ev->active) event_del (&ev->ev);
535     sv_setsv (ev->fh, new_signal);
536     ev->ev.ev_fd = signum;
537     ev->ev.ev_events |= EV_SIGNAL;
538     if (ev->active) event_add (&ev->ev, e_tv (ev));
539     }
540     }
541     OUTPUT:
542     RETVAL
543    
544 root 1.1 short events (Event ev, short new_events = EV_UNDEF)
545     CODE:
546     RETVAL = ev->ev.ev_events;
547     if (items > 1)
548     {
549     if (ev->active) event_del (&ev->ev);
550     ev->ev.ev_events = new_events;
551     if (ev->active) event_add (&ev->ev, e_tv (ev));
552     }
553     OUTPUT:
554     RETVAL
555    
556     double timeout (Event ev, double new_timeout = 0., int repeat = 0)
557     CODE:
558     RETVAL = ev->timeout;
559     if (items > 1)
560     {
561     if (ev->active) event_del (&ev->ev);
562     ev->timeout = new_timeout;
563     ev->interval = repeat;
564     ev->abstime = 0;
565     if (ev->active) event_add (&ev->ev, e_tv (ev));
566     }
567     OUTPUT:
568     RETVAL
569    
570     void timeout_abs (Event ev, double at, double interval = 0.)
571     CODE:
572     if (ev->active) event_del (&ev->ev);
573     ev->timeout = at;
574     ev->interval = interval;
575     ev->abstime = 1;
576     if (ev->active) event_add (&ev->ev, e_tv (ev));
577    
578    
579     MODULE = EV PACKAGE = EV::DNS PREFIX = evdns_
580    
581     BOOT:
582     {
583     HV *stash = gv_stashpv ("EV::DNS", 1);
584    
585     static const struct {
586     const char *name;
587     IV iv;
588     } *civ, const_iv[] = {
589     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
590     const_iv (DNS_, ERR_NONE)
591     const_iv (DNS_, ERR_FORMAT)
592     const_iv (DNS_, ERR_SERVERFAILED)
593     const_iv (DNS_, ERR_NOTEXIST)
594     const_iv (DNS_, ERR_NOTIMPL)
595     const_iv (DNS_, ERR_REFUSED)
596     const_iv (DNS_, ERR_TRUNCATED)
597     const_iv (DNS_, ERR_UNKNOWN)
598     const_iv (DNS_, ERR_TIMEOUT)
599     const_iv (DNS_, ERR_SHUTDOWN)
600     const_iv (DNS_, IPv4_A)
601     const_iv (DNS_, PTR)
602     const_iv (DNS_, IPv6_AAAA)
603     const_iv (DNS_, QUERY_NO_SEARCH)
604     const_iv (DNS_, OPTION_SEARCH)
605     const_iv (DNS_, OPTION_NAMESERVERS)
606     const_iv (DNS_, OPTION_MISC)
607     const_iv (DNS_, OPTIONS_ALL)
608     const_iv (DNS_, NO_SEARCH)
609     };
610    
611     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
612     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
613     }
614    
615     int evdns_init ()
616    
617     void evdns_shutdown (int fail_requests = 1)
618    
619     const char *evdns_err_to_string (int err)
620    
621     int evdns_nameserver_add (U32 address)
622    
623     int evdns_count_nameservers ()
624    
625     int evdns_clear_nameservers_and_suspend ()
626    
627     int evdns_resume ()
628    
629     int evdns_nameserver_ip_add (char *ip_as_string)
630    
631     int evdns_resolve_ipv4 (const char *name, int flags, SV *cb)
632     C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
633    
634     int evdns_resolve_ipv6 (const char *name, int flags, SV *cb)
635     C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
636    
637     int evdns_resolve_reverse (SV *addr, int flags, SV *cb)
638     ALIAS:
639     evdns_resolve_reverse_ipv6 = 1
640     CODE:
641     {
642     STRLEN len;
643     char *data = SvPVbyte (addr, len);
644     if (len != (ix ? 16 : 4))
645 root 1.8 croak ("ipv4/ipv6 address to be resolved must be given as 4/16 byte octet string");
646 root 1.1
647     RETVAL = ix
648     ? evdns_resolve_reverse_ipv6 ((struct in6_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb))
649     : evdns_resolve_reverse ((struct in_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb));
650     }
651     OUTPUT:
652     RETVAL
653    
654     int evdns_set_option (char *option, char *val, int flags)
655    
656     int evdns_resolv_conf_parse (int flags, const char *filename)
657    
658     #ifdef MS_WINDOWS
659    
660     int evdns_config_windows_nameservers ()
661    
662     #endif
663    
664     void evdns_search_clear ()
665    
666     void evdns_search_add (char *domain)
667    
668     void evdns_search_ndots_set (int ndots)
669    
670 root 1.5
671     MODULE = EV PACKAGE = EV::HTTP PREFIX = evhttp_
672    
673     BOOT:
674     {
675     HV *stash = gv_stashpv ("EV::HTTP", 1);
676    
677     static const struct {
678     const char *name;
679     IV iv;
680     } *civ, const_iv[] = {
681     # define const_iv(pfx, name) { # name, (IV) pfx ## name },
682     const_iv (HTTP_, OK)
683     const_iv (HTTP_, NOCONTENT)
684     const_iv (HTTP_, MOVEPERM)
685     const_iv (HTTP_, MOVETEMP)
686     const_iv (HTTP_, NOTMODIFIED)
687     const_iv (HTTP_, BADREQUEST)
688     const_iv (HTTP_, NOTFOUND)
689     const_iv (HTTP_, SERVUNAVAIL)
690     const_iv (EVHTTP_, REQ_OWN_CONNECTION)
691     const_iv (EVHTTP_, PROXY_REQUEST)
692     const_iv (EVHTTP_, REQ_GET)
693     const_iv (EVHTTP_, REQ_POST)
694     const_iv (EVHTTP_, REQ_HEAD)
695     const_iv (EVHTTP_, REQUEST)
696     const_iv (EVHTTP_, RESPONSE)
697     };
698    
699     for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
700     newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
701     }
702    
703     MODULE = EV PACKAGE = EV::HTTP::Request PREFIX = evhttp_request_
704    
705     #HttpRequest new (SV *klass, SV *cb)
706    
707     #void DESTROY (struct evhttp_request *req);
708    
709    
710    
711    
712    
713    
714    
715