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