--- cvsroot/EV/EV.xs 2007/10/26 16:51:27 1.2 +++ cvsroot/EV/EV.xs 2007/10/29 18:33:02 1.13 @@ -9,14 +9,28 @@ #include #include #include -/*include */ /* does not compile */ + +/* workaround for evhttp.h requiring obscure bsd headers */ +#ifndef TAILQ_ENTRY +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ +} +#endif /* !TAILQ_ENTRY */ +#include #define EV_NONE 0 #define EV_UNDEF -1 #define TIMEOUT_NONE HUGE_VAL +#include "EV/EVAPI.h" + typedef struct event_base *Base; +typedef int Signal; + +static struct EVAPI evapi; static HV *stash_base, *stash_event; @@ -32,6 +46,34 @@ } +static int +sv_signum (SV *sig) +{ + int signum; + + if (SvIV (sig) > 0) + return SvIV (sig); + + for (signum = 1; signum < SIG_SIZE; ++signum) + if (strEQ (SvPV_nolen (sig), PL_sig_name [signum])) + return signum; + + return -1; +} + +static void +api_once (int fd, short events, double timeout, void (*cb)(int, short, void *), void *arg) +{ + if (timeout >= 0.) + { + struct timeval tv; + tv_set (&tv, timeout); + event_once (fd, events, cb, arg, &tv); + } + else + event_once (fd, events, cb, arg, 0); +} + ///////////////////////////////////////////////////////////////////////////// // Event @@ -46,7 +88,7 @@ } *Event; static double -e_now () +e_now (void) { struct timeval tv; gettimeofday (&tv, 0); @@ -58,19 +100,16 @@ static int sv_fileno (SV *fh) { - if (fh) - { - SvGETMAGIC (fh); + SvGETMAGIC (fh); - if (SvROK (fh)) - fh = SvRV (fh); + if (SvROK (fh)) + fh = SvRV (fh); - if (SvTYPE (fh) == SVt_PVGV) - return PerlIO_fileno (IoIFP (sv_2io (fh))); + if (SvTYPE (fh) == SVt_PVGV) + return PerlIO_fileno (IoIFP (sv_2io (fh))); - if (SvIOK (fh)) - return SvIV (fh); - } + if (SvIOK (fh)) + return SvIV (fh); return -1; } @@ -112,7 +151,7 @@ { double now = e_now (); - if (now > to && ev->interval) + if (ev->interval) ev->timeout = (to += ceil ((now - to) / ev->interval) * ev->interval); to -= now; @@ -165,7 +204,7 @@ ENTER; SAVETMPS; - if (!(ev->ev.ev_events & EV_PERSIST)) + if (!(ev->ev.ev_events & EV_PERSIST) || (events & EV_TIMEOUT)) ev->active = 0; PUSHMARK (SP); @@ -174,12 +213,19 @@ PUSHs (sv_2mortal (newSViv (events))); PUTBACK; call_sv (ev->cb, G_DISCARD | G_VOID | G_EVAL); - /*TODO: if err, call some logging function */ if (ev->interval && !ev->active) e_start (ev); FREETMPS; + + if (SvTRUE (ERRSV)) + { + PUSHMARK (SP); + PUTBACK; + call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR); + } + LEAVE; } @@ -224,6 +270,14 @@ call_sv (sv_2mortal (cb), G_DISCARD | G_VOID | G_EVAL); FREETMPS; + + if (SvTRUE (ERRSV)) + { + PUSHMARK (SP); + PUTBACK; + call_sv (get_sv ("EV::DIED", 1), G_DISCARD | G_VOID | G_EVAL | G_KEEPERR); + } + LEAVE; } @@ -234,6 +288,7 @@ BOOT: { + int i; HV *stash = gv_stashpv ("EV", 1); static const struct { @@ -261,6 +316,20 @@ stash_base = gv_stashpv ("EV::Base" , 1); stash_event = gv_stashpv ("EV::Event", 1); + + { + SV *sv = perl_get_sv ("EV::API", TRUE); + perl_get_sv ("EV::API", TRUE); /* silence 5.10 warning */ + + evapi.ver = EV_API_VERSION; + evapi.rev = EV_API_REVISION; + evapi.now = e_now; + evapi.once = api_once; + evapi.loop = event_loop; + + sv_setiv (sv, (IV)&evapi); + SvREADONLY_on (sv); + } } double now () @@ -285,7 +354,7 @@ int event_loop (int flags = 0) -int event_loopexit (double after) +int event_loopexit (double after = 0) CODE: { struct timeval tv; @@ -295,7 +364,7 @@ Event event (SV *cb) CODE: - RETVAL = e_new (0, 0, cb); + RETVAL = e_new (NEWSV (0, 0), 0, cb); OUTPUT: RETVAL @@ -308,11 +377,31 @@ OUTPUT: RETVAL +Event timed_io (SV *fh, short events, double timeout, SV *cb) + ALIAS: + timed_io_ns = 1 + CODE: +{ + events = timeout ? events & ~EV_PERSIST : events | EV_PERSIST; + + RETVAL = e_new (fh, events, cb); + + if (timeout) + { + RETVAL->timeout = timeout; + RETVAL->interval = 1; + } + + if (!ix) e_start (RETVAL); +} + OUTPUT: + RETVAL + Event timer (double after, int repeat, SV *cb) ALIAS: timer_ns = 1 CODE: - RETVAL = e_new (0, 0, cb); + RETVAL = e_new (NEWSV (0, 0), 0, cb); RETVAL->timeout = after; RETVAL->interval = repeat; if (!ix) e_start (RETVAL); @@ -323,7 +412,7 @@ ALIAS: timer_abs_ns = 1 CODE: - RETVAL = e_new (0, 0, cb); + RETVAL = e_new (NEWSV (0, 0), 0, cb); RETVAL->timeout = at; RETVAL->interval = interval; RETVAL->abstime = 1; @@ -331,11 +420,12 @@ OUTPUT: RETVAL -Event signal (SV *signal, SV *cb) +Event signal (Signal signum, SV *cb) ALIAS: signal_ns = 1 CODE: - RETVAL = e_new (signal, EV_SIGNAL | EV_PERSIST, cb); + RETVAL = e_new (ST (0), EV_SIGNAL | EV_PERSIST, cb); + RETVAL->ev.ev_fd = signum; if (!ix) e_start (RETVAL); OUTPUT: RETVAL @@ -407,25 +497,50 @@ SvREFCNT_dec (ev->cb); SvREFCNT_dec (ev->fh); -void cb (Event ev, SV *new_cb) +SV *cb (Event ev, SV *new_cb = 0) CODE: - sv_setsv (ev->cb, new_cb); + RETVAL = newSVsv (ev->cb); + if (items > 1) + sv_setsv (ev->cb, new_cb); + OUTPUT: + RETVAL SV *fh (Event ev, SV *new_fh = 0) - ALIAS: - signal = 0 CODE: RETVAL = newSVsv (ev->fh); if (items > 1) { if (ev->active) event_del (&ev->ev); sv_setsv (ev->fh, new_fh); - ev->ev.ev_fd = sv_fileno (ev->fh); + ev->ev.ev_fd = sv_fileno (ev->fh); + ev->ev.ev_events &= ev->ev.ev_events & ~EV_SIGNAL; if (ev->active) event_add (&ev->ev, e_tv (ev)); } OUTPUT: RETVAL +SV *signal (Event ev, SV *new_signal = 0) + CODE: +{ + Signal signum; + + if (items > 1) + signum = sv_signum (new_signal); /* may croak here */ + + RETVAL = newSVsv (ev->fh); + + if (items > 1) + { + if (ev->active) event_del (&ev->ev); + sv_setsv (ev->fh, new_signal); + ev->ev.ev_fd = signum; + ev->ev.ev_events |= EV_SIGNAL; + if (ev->active) event_add (&ev->ev, e_tv (ev)); + } +} + OUTPUT: + RETVAL + short events (Event ev, short new_events = EV_UNDEF) CODE: RETVAL = ev->ev.ev_events; @@ -472,7 +587,6 @@ IV iv; } *civ, const_iv[] = { # define const_iv(pfx, name) { # name, (IV) pfx ## name }, - const_iv (DNS_, ERR_NONE) const_iv (DNS_, ERR_FORMAT) const_iv (DNS_, ERR_SERVERFAILED) @@ -528,7 +642,7 @@ STRLEN len; char *data = SvPVbyte (addr, len); if (len != (ix ? 16 : 4)) - croak ("ipv4/ipv6 address to resolve must be given as 4/16 byte octet string"); + croak ("ipv4/ipv6 address to be resolved must be given as 4/16 byte octet string"); RETVAL = ix ? evdns_resolve_reverse_ipv6 ((struct in6_addr *)data, flags, dns_cb, (void *)SvREFCNT_inc (cb)) @@ -553,3 +667,49 @@ void evdns_search_ndots_set (int ndots) + +MODULE = EV PACKAGE = EV::HTTP PREFIX = evhttp_ + +BOOT: +{ + HV *stash = gv_stashpv ("EV::HTTP", 1); + + static const struct { + const char *name; + IV iv; + } *civ, const_iv[] = { +# define const_iv(pfx, name) { # name, (IV) pfx ## name }, + const_iv (HTTP_, OK) + const_iv (HTTP_, NOCONTENT) + const_iv (HTTP_, MOVEPERM) + const_iv (HTTP_, MOVETEMP) + const_iv (HTTP_, NOTMODIFIED) + const_iv (HTTP_, BADREQUEST) + const_iv (HTTP_, NOTFOUND) + const_iv (HTTP_, SERVUNAVAIL) + const_iv (EVHTTP_, REQ_OWN_CONNECTION) + const_iv (EVHTTP_, PROXY_REQUEST) + const_iv (EVHTTP_, REQ_GET) + const_iv (EVHTTP_, REQ_POST) + const_iv (EVHTTP_, REQ_HEAD) + const_iv (EVHTTP_, REQUEST) + const_iv (EVHTTP_, RESPONSE) + }; + + for (civ = const_iv + sizeof (const_iv) / sizeof (const_iv [0]); civ-- > const_iv; ) + newCONSTSUB (stash, (char *)civ->name, newSViv (civ->iv)); +} + +MODULE = EV PACKAGE = EV::HTTP::Request PREFIX = evhttp_request_ + +#HttpRequest new (SV *klass, SV *cb) + +#void DESTROY (struct evhttp_request *req); + + + + + + + +