ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV/EV.xs
Revision: 1.20
Committed: Wed Oct 31 13:57:34 2007 UTC (16 years, 6 months ago) by root
Branch: MAIN
Changes since 1.19: +5 -22 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 /*#include <netinet/in.h>*/
6
7 #define TIMEOUT_NONE HUGE_VAL
8
9 #define EV_PROTOTYPES 1
10 #include "EV/EVAPI.h"
11
12 #include "libev/ev.c"
13
14 typedef int Signal;
15
16 static struct EVAPI evapi;
17
18 static HV
19 *stash_watcher,
20 *stash_io,
21 *stash_time,
22 *stash_timer,
23 *stash_periodic,
24 *stash_signal,
25 *stash_idle,
26 *stash_check;
27
28 static int
29 sv_signum (SV *sig)
30 {
31 int signum;
32
33 if (SvIV (sig) > 0)
34 return SvIV (sig);
35
36 for (signum = 1; signum < SIG_SIZE; ++signum)
37 if (strEQ (SvPV_nolen (sig), PL_sig_name [signum]))
38 return signum;
39
40 return -1;
41 }
42
43 /////////////////////////////////////////////////////////////////////////////
44 // Event
45
46 static void e_cb (struct ev_watcher *w, int revents);
47
48 static int
49 sv_fileno (SV *fh)
50 {
51 SvGETMAGIC (fh);
52
53 if (SvROK (fh))
54 fh = SvRV (fh);
55
56 if (SvTYPE (fh) == SVt_PVGV)
57 return PerlIO_fileno (IoIFP (sv_2io (fh)));
58
59 if (SvIOK (fh))
60 return SvIV (fh);
61
62 return -1;
63 }
64
65 static void *
66 e_new (int size, SV *cb_sv)
67 {
68 struct ev_watcher *w;
69 SV *self = NEWSV (0, size);
70 SvPOK_only (self);
71 SvCUR_set (self, size);
72
73 w = (struct ev_watcher *)SvPVX (self);
74
75 evw_init (w, e_cb);
76
77 w->fh = 0;
78 w->cb_sv = newSVsv (cb_sv);
79 w->self = self;
80
81 return (void *)w;
82 }
83
84 static SV *
85 e_bless (struct ev_watcher *w, HV *stash)
86 {
87 SV *rv;
88
89 if (SvOBJECT (w->self))
90 rv = newRV_inc (w->self);
91 else
92 {
93 rv = newRV_noinc (w->self);
94 sv_bless (rv, stash);
95 SvREADONLY_on (w->self);
96 }
97
98 return rv;
99 }
100
101 static void
102 e_cb (struct ev_watcher *w, int revents)
103 {
104 dSP;
105 I32 mark = SP - PL_stack_base;
106 SV *sv_self, *sv_events;
107 static SV *sv_events_cache;
108
109 sv_self = newRV_inc (w->self); /* w->self MUST be blessed by now */
110
111 if (sv_events_cache)
112 {
113 sv_events = sv_events_cache; sv_events_cache = 0;
114 SvIV_set (sv_events, revents);
115 }
116 else
117 sv_events = newSViv (revents);
118
119 PUSHMARK (SP);
120 EXTEND (SP, 2);
121 PUSHs (sv_self);
122 PUSHs (sv_events);
123 PUTBACK;
124 call_sv (w->cb_sv, G_DISCARD | G_VOID | G_EVAL);
125 SP = PL_stack_base + mark; PUTBACK;
126
127 SvREFCNT_dec (sv_self);
128
129 if (sv_events_cache)
130 SvREFCNT_dec (sv_events);
131 else
132 sv_events_cache = sv_events;
133
134 if (SvTRUE (ERRSV))
135 {
136 PUSHMARK (SP);
137 PUTBACK;
138 call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
139 SP = PL_stack_base + mark; PUTBACK;
140 }
141 }
142
143 #if 0
144 /////////////////////////////////////////////////////////////////////////////
145 // DNS
146
147 static void
148 dns_cb (int result, char type, int count, int ttl, void *addresses, void *arg)
149 {
150 dSP;
151 SV *cb = (SV *)arg;
152
153 ENTER;
154 SAVETMPS;
155 PUSHMARK (SP);
156 EXTEND (SP, count + 3);
157 PUSHs (sv_2mortal (newSViv (result)));
158
159 if (result == DNS_ERR_NONE && ttl >= 0)
160 {
161 int i;
162
163 PUSHs (sv_2mortal (newSViv (type)));
164 PUSHs (sv_2mortal (newSViv (ttl)));
165
166 for (i = 0; i < count; ++i)
167 switch (type)
168 {
169 case DNS_IPv6_AAAA:
170 PUSHs (sv_2mortal (newSVpvn (i * 16 + (char *)addresses, 16)));
171 break;
172 case DNS_IPv4_A:
173 PUSHs (sv_2mortal (newSVpvn (i * 4 + (char *)addresses, 4)));
174 break;
175 case DNS_PTR:
176 PUSHs (sv_2mortal (newSVpv (*(char **)addresses, 0)));
177 break;
178 }
179 }
180
181 PUTBACK;
182 call_sv (sv_2mortal (cb), G_DISCARD | G_VOID | G_EVAL);
183
184 FREETMPS;
185
186 if (SvTRUE (ERRSV))
187 {
188 PUSHMARK (SP);
189 PUTBACK;
190 call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR);
191 }
192
193 LEAVE;
194 }
195 #endif
196
197 #define CHECK_REPEAT(repeat) if (repeat < 0.) \
198 croak (# repeat " value must be >= 0");
199
200 /////////////////////////////////////////////////////////////////////////////
201 // XS interface functions
202
203 MODULE = EV PACKAGE = EV PREFIX = ev_
204
205 BOOT:
206 {
207 int i;
208 HV *stash = gv_stashpv ("EV", 1);
209
210 static const struct {
211 const char *name;
212 IV iv;
213 } *civ, const_iv[] = {
214 # define const_iv(pfx, name) { # name, (IV) pfx ## name },
215 const_iv (EV_, UNDEF)
216 const_iv (EV_, NONE)
217 const_iv (EV_, TIMEOUT)
218 const_iv (EV_, READ)
219 const_iv (EV_, WRITE)
220 const_iv (EV_, SIGNAL)
221 const_iv (EV_, IDLE)
222 const_iv (EV_, CHECK)
223 const_iv (EV_, ERROR)
224
225 const_iv (EV, LOOP_ONESHOT)
226 const_iv (EV, LOOP_NONBLOCK)
227
228 const_iv (EV, METHOD_NONE)
229 const_iv (EV, METHOD_SELECT)
230 const_iv (EV, METHOD_EPOLL)
231 };
232
233 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
234 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
235
236 stash_watcher = gv_stashpv ("EV::Watcher" , 1);
237 stash_io = gv_stashpv ("EV::IO" , 1);
238 stash_time = gv_stashpv ("EV::Time" , 1);
239 stash_timer = gv_stashpv ("EV::Timer" , 1);
240 stash_periodic = gv_stashpv ("EV::Periodic", 1);
241 stash_signal = gv_stashpv ("EV::Signal" , 1);
242 stash_idle = gv_stashpv ("EV::Idle" , 1);
243 stash_check = gv_stashpv ("EV::Check" , 1);
244
245 {
246 SV *sv = perl_get_sv ("EV::API", TRUE);
247 perl_get_sv ("EV::API", TRUE); /* silence 5.10 warning */
248
249 /* the poor man's shared library emulator */
250 evapi.ver = EV_API_VERSION;
251 evapi.rev = EV_API_REVISION;
252 evapi.sv_fileno = sv_fileno;
253 evapi.sv_signum = sv_signum;
254 evapi.now = &ev_now;
255 evapi.method = &ev_method;
256 evapi.loop_done = &ev_loop_done;
257 evapi.time = ev_time;
258 evapi.loop = ev_loop;
259 evapi.once = ev_once;
260 evapi.io_start = evio_start;
261 evapi.io_stop = evio_stop;
262 evapi.timer_start = evtimer_start;
263 evapi.timer_stop = evtimer_stop;
264 evapi.timer_again = evtimer_again;
265 evapi.periodic_start = evperiodic_start;
266 evapi.periodic_stop = evperiodic_stop;
267 evapi.signal_start = evsignal_start;
268 evapi.signal_stop = evsignal_stop;
269 evapi.idle_start = evidle_start;
270 evapi.idle_stop = evidle_stop;
271 evapi.check_start = evcheck_start;
272 evapi.check_stop = evcheck_stop;
273
274 sv_setiv (sv, (IV)&evapi);
275 SvREADONLY_on (sv);
276 }
277 }
278
279 NV ev_now ()
280 CODE:
281 RETVAL = ev_now;
282 OUTPUT:
283 RETVAL
284
285 int ev_method ()
286 CODE:
287 RETVAL = ev_method;
288 OUTPUT:
289 RETVAL
290
291 NV ev_time ()
292
293 void ev_init (int flags = 0)
294
295 void ev_loop (int flags = 0)
296
297 void ev_loop_done (int value = 1)
298 CODE:
299 ev_loop_done = value;
300
301 struct ev_io *io (SV *fh, int events, SV *cb)
302 PROTOTYPE: $$&
303 ALIAS:
304 io_ns = 1
305 CODE:
306 RETVAL = e_new (sizeof (struct ev_io), cb);
307 RETVAL->fh = newSVsv (fh);
308 evio_set (RETVAL, sv_fileno (RETVAL->fh), events);
309 if (!ix) evio_start (RETVAL);
310 OUTPUT:
311 RETVAL
312
313 struct ev_timer *timer (NV after, NV repeat, SV *cb)
314 PROTOTYPE: $$&
315 ALIAS:
316 timer_ns = 1
317 INIT:
318 CHECK_REPEAT (repeat);
319 CODE:
320 RETVAL = e_new (sizeof (struct ev_timer), cb);
321 evtimer_set (RETVAL, after, repeat);
322 if (!ix) evtimer_start (RETVAL);
323 OUTPUT:
324 RETVAL
325
326 struct ev_periodic *periodic (NV at, NV interval, SV *cb)
327 PROTOTYPE: $$&
328 ALIAS:
329 periodic_ns = 1
330 INIT:
331 CHECK_REPEAT (interval);
332 CODE:
333 RETVAL = e_new (sizeof (struct ev_periodic), cb);
334 evperiodic_set (RETVAL, at, interval);
335 if (!ix) evperiodic_start (RETVAL);
336 OUTPUT:
337 RETVAL
338
339 struct ev_signal *signal (Signal signum, SV *cb)
340 PROTOTYPE: $&
341 ALIAS:
342 signal_ns = 1
343 CODE:
344 RETVAL = e_new (sizeof (struct ev_signal), cb);
345 evsignal_set (RETVAL, signum);
346 if (!ix) evsignal_start (RETVAL);
347 OUTPUT:
348 RETVAL
349
350 struct ev_idle *idle (SV *cb)
351 PROTOTYPE: &
352 ALIAS:
353 idle_ns = 1
354 CODE:
355 RETVAL = e_new (sizeof (struct ev_idle), cb);
356 evidle_set (RETVAL);
357 if (!ix) evidle_start (RETVAL);
358 OUTPUT:
359 RETVAL
360
361 struct ev_check *check (SV *cb)
362 PROTOTYPE: &
363 ALIAS:
364 check_ns = 1
365 CODE:
366 RETVAL = e_new (sizeof (struct ev_check), cb);
367 evcheck_set (RETVAL);
368 if (!ix) evcheck_start (RETVAL);
369 OUTPUT:
370 RETVAL
371
372
373 PROTOTYPES: DISABLE
374
375 MODULE = EV PACKAGE = EV::Watcher PREFIX = ev_
376
377 int ev_is_active (struct ev_watcher *w)
378
379 SV *cb (struct ev_watcher *w, SV *new_cb = 0)
380 CODE:
381 {
382 RETVAL = newSVsv (w->cb_sv);
383
384 if (items > 1)
385 sv_setsv (w->cb_sv, new_cb);
386 }
387 OUTPUT:
388 RETVAL
389
390 MODULE = EV PACKAGE = EV::IO PREFIX = evio_
391
392 void evio_start (struct ev_io *w)
393
394 void evio_stop (struct ev_io *w)
395
396 void set (struct ev_io *w, SV *fh, int events)
397 CODE:
398 {
399 int active = w->active;
400 if (active) evio_stop (w);
401
402 sv_setsv (w->fh, fh);
403 evio_set (w, sv_fileno (w->fh), events);
404
405 if (active) evio_start (w);
406 }
407
408 SV *fh (struct ev_io *w, SV *new_fh = 0)
409 CODE:
410 {
411 RETVAL = newSVsv (w->fh);
412
413 if (items > 1)
414 {
415 int active = w->active;
416 if (active) evio_stop (w);
417
418 sv_setsv (w->fh, new_fh);
419 evio_set (w, sv_fileno (w->fh), w->events);
420
421 if (active) evio_start (w);
422 }
423 }
424 OUTPUT:
425 RETVAL
426
427 short events (struct ev_io *w, short new_events = EV_UNDEF)
428 CODE:
429 {
430 RETVAL = w->events;
431
432 if (items > 1)
433 {
434 int active = w->active;
435 if (active) evio_stop (w);
436
437 evio_set (w, w->fd, new_events);
438
439 if (active) evio_start (w);
440 }
441 }
442 OUTPUT:
443 RETVAL
444
445 MODULE = EV PACKAGE = EV::Signal PREFIX = evsignal_
446
447 void evsignal_start (struct ev_signal *w)
448
449 void evsignal_stop (struct ev_signal *w)
450
451 void set (struct ev_signal *w, SV *signal = 0)
452 CODE:
453 {
454 Signal signum = sv_signum (signal); /* may croak here */
455 int active = w->active;
456
457 if (active) evsignal_stop (w);
458 evsignal_set (w, signum);
459 if (active) evsignal_start (w);
460 }
461
462 MODULE = EV PACKAGE = EV::Time
463
464 MODULE = EV PACKAGE = EV::Timer PREFIX = evtimer_
465
466 void evtimer_start (struct ev_timer *w)
467 INIT:
468 CHECK_REPEAT (w->repeat);
469
470 void evtimer_stop (struct ev_timer *w)
471
472 void evtimer_again (struct ev_timer *w)
473 INIT:
474 CHECK_REPEAT (w->repeat);
475
476 void set (struct ev_timer *w, NV after, NV repeat = 0.)
477 INIT:
478 CHECK_REPEAT (repeat);
479 CODE:
480 {
481 int active = w->active;
482 if (active) evtimer_stop (w);
483 evtimer_set (w, after, repeat);
484 if (active) evtimer_start (w);
485 }
486
487 MODULE = EV PACKAGE = EV::Periodic PREFIX = evperiodic_
488
489 void evperiodic_start (struct ev_periodic *w)
490 INIT:
491 CHECK_REPEAT (w->interval);
492
493 void evperiodic_stop (struct ev_periodic *w)
494
495 void set (struct ev_periodic *w, NV at, NV interval = 0.)
496 INIT:
497 CHECK_REPEAT (interval);
498 CODE:
499 {
500 int active = w->active;
501 if (active) evperiodic_stop (w);
502 evperiodic_set (w, at, interval);
503 if (active) evperiodic_start (w);
504 }
505
506 MODULE = EV PACKAGE = EV::Idle PREFIX = evidle_
507
508 void evidle_start (struct ev_idle *w)
509
510 void evidle_stop (struct ev_idle *w)
511
512 MODULE = EV PACKAGE = EV::Check PREFIX = evcheck_
513
514 void evcheck_start (struct ev_check *w)
515
516 void evcheck_stop (struct ev_check *w)
517
518 #if 0
519
520 MODULE = EV PACKAGE = EV::DNS PREFIX = evdns_
521
522 BOOT:
523 {
524 HV *stash = gv_stashpv ("EV::DNS", 1);
525
526 static const struct {
527 const char *name;
528 IV iv;
529 } *civ, const_iv[] = {
530 # define const_iv(pfx, name) { # name, (IV) pfx ## name },
531 const_iv (DNS_, ERR_NONE)
532 const_iv (DNS_, ERR_FORMAT)
533 const_iv (DNS_, ERR_SERVERFAILED)
534 const_iv (DNS_, ERR_NOTEXIST)
535 const_iv (DNS_, ERR_NOTIMPL)
536 const_iv (DNS_, ERR_REFUSED)
537 const_iv (DNS_, ERR_TRUNCATED)
538 const_iv (DNS_, ERR_UNKNOWN)
539 const_iv (DNS_, ERR_TIMEOUT)
540 const_iv (DNS_, ERR_SHUTDOWN)
541 const_iv (DNS_, IPv4_A)
542 const_iv (DNS_, PTR)
543 const_iv (DNS_, IPv6_AAAA)
544 const_iv (DNS_, QUERY_NO_SEARCH)
545 const_iv (DNS_, OPTION_SEARCH)
546 const_iv (DNS_, OPTION_NAMESERVERS)
547 const_iv (DNS_, OPTION_MISC)
548 const_iv (DNS_, OPTIONS_ALL)
549 const_iv (DNS_, NO_SEARCH)
550 };
551
552 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
553 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
554 }
555
556 int evdns_init ()
557
558 void evdns_shutdown (int fail_requests = 1)
559
560 const char *evdns_err_to_string (int err)
561
562 int evdns_nameserver_add (U32 address)
563
564 int evdns_count_nameservers ()
565
566 int evdns_clear_nameservers_and_suspend ()
567
568 int evdns_resume ()
569
570 int evdns_nameserver_ip_add (char *ip_as_string)
571
572 int evdns_resolve_ipv4 (const char *name, int flags, SV *cb)
573 C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
574
575 int evdns_resolve_ipv6 (const char *name, int flags, SV *cb)
576 C_ARGS: name, flags, dns_cb, (void *)SvREFCNT_inc (cb)
577
578 int evdns_resolve_reverse (SV *addr, int flags, SV *cb)
579 ALIAS:
580 evdns_resolve_reverse_ipv6 = 1
581 CODE:
582 {
583 STRLEN len;
584 char *data = SvPVbyte (addr, len);
585 if (len != (ix ? 16 : 4))
586 croak ("ipv4/ipv6 address to be resolved must be given as 4/16 byte octet string");
587
588 RETVAL = ix
589 ? evdns_resolve_reverse_ipv6 ((struct in6_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb))
590 : evdns_resolve_reverse ((struct in_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb));
591 }
592 OUTPUT:
593 RETVAL
594
595 int evdns_set_option (char *option, char *val, int flags)
596
597 int evdns_resolv_conf_parse (int flags, const char *filename)
598
599 #ifdef MS_WINDOWS
600
601 int evdns_config_windows_nameservers ()
602
603 #endif
604
605 void evdns_search_clear ()
606
607 void evdns_search_add (char *domain)
608
609 void evdns_search_ndots_set (int ndots)
610
611
612 MODULE = EV PACKAGE = EV::HTTP PREFIX = evhttp_
613
614 BOOT:
615 {
616 HV *stash = gv_stashpv ("EV::HTTP", 1);
617
618 static const struct {
619 const char *name;
620 IV iv;
621 } *civ, const_iv[] = {
622 # define const_iv(pfx, name) { # name, (IV) pfx ## name },
623 const_iv (HTTP_, OK)
624 const_iv (HTTP_, NOCONTENT)
625 const_iv (HTTP_, MOVEPERM)
626 const_iv (HTTP_, MOVETEMP)
627 const_iv (HTTP_, NOTMODIFIED)
628 const_iv (HTTP_, BADREQUEST)
629 const_iv (HTTP_, NOTFOUND)
630 const_iv (HTTP_, SERVUNAVAIL)
631 const_iv (EVHTTP_, REQ_OWN_CONNECTION)
632 const_iv (EVHTTP_, PROXY_REQUEST)
633 const_iv (EVHTTP_, REQ_GET)
634 const_iv (EVHTTP_, REQ_POST)
635 const_iv (EVHTTP_, REQ_HEAD)
636 const_iv (EVHTTP_, REQUEST)
637 const_iv (EVHTTP_, RESPONSE)
638 };
639
640 for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; )
641 newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv));
642 }
643
644 MODULE = EV PACKAGE = EV::HTTP::Request PREFIX = evhttp_request_
645
646 #HttpRequest new (SV *klass, SV *cb)
647
648 #void DESTROY (struct evhttp_request *req);
649
650 #endif
651
652
653
654
655
656
657
658