File Coverage

lib/UV.xs
Criterion Covered Total %
statement 821 947 86.6
branch 263 626 42.0
condition n/a
subroutine n/a
pod n/a
total 1084 1573 68.9


line stmt bran cond sub pod time code
1             #define PERL_NO_GET_CONTEXT 1
2              
3             #include "EXTERN.h"
4             #include "perl.h"
5             #include "XSUB.h"
6              
7             #define NEED_newCONSTSUB
8             #include "ppport.h"
9              
10             #include
11             #include
12              
13             #include
14              
15             #if defined(DEBUG) && DEBUG > 0
16             #define DEBUG_PRINT(fmt, args...) fprintf(stderr, "C -- %s:%d:%s(): " fmt, \
17             __FILE__, __LINE__, __func__, ##args)
18             #else
19             #define DEBUG_PRINT(fmt, args...) /* Don't do anything in release builds */
20             #endif
21              
22             #include "perl-backcompat.h"
23             #include "uv-backcompat.h"
24              
25             #ifdef MULTIPLICITY
26             # define storeTHX(var) (var) = aTHX
27             # define dTHXfield(var) tTHX var;
28             #else
29             # define storeTHX(var) dNOOP
30             # define dTHXfield(var)
31             #endif
32              
33             #if defined(__MINGW32__) || defined(WIN32)
34             #include /* we need _get_osfhandle() on windows */
35             # define _MAKE_SOCK(f) (_get_osfhandle(f))
36             #else
37             # define _MAKE_SOCK(f) (f)
38             #endif
39              
40 0           static void loop_walk_cb(uv_handle_t* handle, void* arg)
41             {
42             SV *self;
43             SV *cb;
44              
45             dTHX;
46              
47 0 0         if (!handle || !arg) return;
    0          
48 0           cb = (SV *)arg;
49 0 0         if (!cb || !SvOK(cb)) return;
    0          
    0          
    0          
50              
51 0           self = (SV *)(handle->data);
52              
53             /* provide info to the caller: invocant, suggested_size */
54 0           dSP;
55 0           ENTER;
56 0           SAVETMPS;
57              
58 0 0         if (self && SvROK(self)) {
    0          
59 0 0         PUSHMARK(SP);
60 0 0         EXTEND(SP, 1);
61 0           PUSHs(SvREFCNT_inc(self)); /* invocant */
62 0           PUTBACK;
63             }
64              
65 0           call_sv(cb, G_DISCARD|G_VOID);
66              
67 0 0         FREETMPS;
68 0           LEAVE;
69             }
70              
71             #define do_callback_accessor(var, cb) MY_do_callback_accessor(aTHX_ var, cb)
72 85           static SV *MY_do_callback_accessor(pTHX_ SV **var, SV *cb)
73             {
74 85 50         if(cb && SvOK(cb)) {
    100          
    50          
    50          
75 75           SvREFCNT_dec(*var);
76              
77 75           *var = newSVsv(cb);
78             }
79              
80 85 100         if(*var && SvOK(*var))
    50          
    0          
    0          
81 75           return SvREFCNT_inc(*var);
82             else
83 10           return &PL_sv_undef;
84             }
85              
86             #define newSV_error(err) MY_newSV_error(aTHX_ err)
87 10           static SV *MY_newSV_error(pTHX_ int err)
88             {
89 10 100         SV *sv = newSVpv(err ? uv_strerror(err) : "", 0);
90 10           sv_upgrade(sv, SVt_PVIV);
91 10           SvIV_set(sv, err);
92 10           SvIOK_on(sv);
93              
94 10           return sv;
95             }
96              
97 2           static HV *make_errstash(pTHX_ int err)
98             {
99             /* Technically a memory leak within libuv if err is unknown; we should
100             * consider using uv_err_name_r()
101             */
102 2           SV *name = newSVpvf("UV::Exception::%s::", uv_err_name(err));
103 2           sv_2mortal(name);
104              
105 2           HV *stash = get_hv(SvPVX(name), 0);
106 2 50         if(stash) return stash;
107              
108 2           stash = get_hv(SvPVX(name), GV_ADD);
109              
110             /* push @ISA, "UV::Exception" */
111 2           sv_catpvs(name, "ISA");
112 2           av_push(get_av(SvPVX(name), GV_ADD), newSVpvs_share("UV::Exception"));
113              
114 2           return stash;
115             }
116              
117             #define THROWERRSV(sv, err) \
118             do { \
119             SV *msgsv = mess_sv(sv, TRUE); \
120             sv_upgrade(msgsv, SVt_PVIV); \
121             SvIV_set(msgsv, err); SvIOK_on(msgsv); \
122             croak_sv(sv_bless(newRV_noinc(msgsv), make_errstash(aTHX_ err))); \
123             } while(0)
124              
125             #define THROWERR(message, err) \
126             THROWERRSV(newSVpvf(message " (%d): %s", err, uv_strerror(err)), err)
127              
128             #define CHECKCALL(call) \
129             do { \
130             int err = call; \
131             if(err != 0) \
132             THROWERRSV(newSVpvf("Couldn't %" HEKf " (%d): %s", \
133             HEKfARG(GvNAME_HEK(CvGV(cv))), \
134             err, uv_strerror(err)), err); \
135             } while(0)
136              
137             /**************
138             * UV::Handle *
139             **************/
140              
141             #define FIELDS_UV__Handle \
142             SV *selfrv; \
143             dTHXfield(perl) \
144             SV *data; \
145             SV *on_close;
146              
147             typedef struct UV__Handle {
148             uv_handle_t *h;
149             FIELDS_UV__Handle
150             } *UV__Handle;
151              
152             #define NEW_UV__Handle(var, type) \
153             Newxc(var, sizeof(*var) + sizeof(type), char, void); \
154             var->h = (type *)((char *)var + sizeof(*var));
155              
156             #define INIT_UV__Handle(handle) { \
157             handle->h->data = handle; \
158             storeTHX(handle->perl); \
159             handle->data = NULL; \
160             handle->on_close = NULL; \
161             }
162              
163             static void destroy_handle(UV__Handle self);
164 58           static void destroy_handle_base(pTHX_ UV__Handle self)
165             {
166 58           SvREFCNT_dec(self->data);
167 58           SvREFCNT_dec(self->on_close);
168              
169             /* No need to destroy self->selfrv because Perl is already destroying
170             * it, being the reason we are invoked in the first place
171             */
172              
173 58           Safefree(self);
174 58           }
175              
176 5           static void on_alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
177             {
178 5           Newx(buf->base, suggested, char);
179 5           buf->len = suggested;
180 5           }
181              
182 58           static void on_close_cb(uv_handle_t *handle)
183             {
184             UV__Handle self;
185             SV *cb;
186              
187 58 50         if(!handle || !handle->data) return;
    50          
188              
189 58           self = handle->data;
190 58 100         if(!(cb = self->on_close) || !SvOK(cb)) return;
    50          
    0          
    0          
191              
192             dTHXa(self->perl);
193 17           dSP;
194 17           ENTER;
195 17           SAVETMPS;
196              
197 17 50         PUSHMARK(SP);
198 17 50         EXTEND(SP, 1);
199 17           mPUSHs(newRV_inc(self->selfrv));
200 17           PUTBACK;
201              
202 17           call_sv(cb, G_DISCARD|G_VOID);
203              
204 17 50         FREETMPS;
205 17           LEAVE;
206             }
207              
208 13           static void on_close_then_destroy(uv_handle_t *handle)
209             {
210 13           on_close_cb(handle);
211 13           destroy_handle(handle->data);
212 13           }
213              
214             /**************
215             * UV::Stream *
216             **************/
217              
218             #define FIELDS_UV__Stream \
219             SV *on_read; \
220             SV *on_connection;
221              
222             #define INIT_UV__Stream(stream) { \
223             stream->on_read = NULL; \
224             stream->on_connection = NULL; \
225             }
226              
227             typedef struct UV__Stream {
228             uv_stream_t *h;
229             FIELDS_UV__Handle
230             FIELDS_UV__Stream
231             } *UV__Stream;
232              
233 7           static void destroy_stream(pTHX_ UV__Stream self)
234             {
235 7           SvREFCNT_dec(self->on_read);
236 7           SvREFCNT_dec(self->on_connection);
237 7           }
238              
239 3           static void on_read_cb(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
240             {
241             UV__Stream self;
242             SV *cb;
243              
244 3 50         if(!stream || !stream->data) return;
    50          
245              
246 3           self = stream->data;
247 3 50         if((cb = self->on_read) && SvOK(cb)) {
    50          
    0          
    0          
248             dTHXa(self->perl);
249 3           dSP;
250 3           ENTER;
251 3           SAVETMPS;
252              
253 3 50         PUSHMARK(SP);
254 3 50         EXTEND(SP, 3);
255 3           mPUSHs(newRV_inc(self->selfrv));
256 3 50         mPUSHs(nread < 0 ? newSV_error(nread) : &PL_sv_undef);
257 3 50         if(nread >= 0)
258 3           mPUSHp(buf->base, nread);
259 3           PUTBACK;
260              
261 3           call_sv(cb, G_DISCARD|G_VOID);
262              
263 3 50         FREETMPS;
264 3           LEAVE;
265             }
266              
267 3 50         if(buf && buf->base)
    50          
268 3           Safefree(buf->base);
269             }
270              
271 2           static void on_connection_cb(uv_stream_t *stream, int status)
272             {
273             UV__Stream self;
274             SV *cb;
275              
276 2 50         if(!stream || !stream->data) return;
    50          
277              
278 2           self = stream->data;
279 2 50         if(!(cb = self->on_connection) || !SvOK(cb)) return;
    50          
    0          
    0          
280              
281             dTHXa(self->perl);
282 2           dSP;
283 2           ENTER;
284 2           SAVETMPS;
285              
286 2 50         PUSHMARK(SP);
287 2 50         EXTEND(SP, 2);
288 2           mPUSHs(newRV_inc(self->selfrv));
289 2           mPUSHi(status);
290 2           PUTBACK;
291              
292 2           call_sv(cb, G_DISCARD|G_VOID);
293              
294 2 50         FREETMPS;
295 2           LEAVE;
296             }
297              
298             /*************
299             * UV::Async *
300             *************/
301              
302             typedef struct UV__Async {
303             uv_async_t *h;
304             FIELDS_UV__Handle
305             SV *on_async;
306             } *UV__Async;
307              
308 1           static void destroy_async(pTHX_ UV__Async self)
309             {
310 1           SvREFCNT_dec(self->on_async);
311 1           }
312              
313 1           static void on_async_cb(uv_async_t *async)
314             {
315             UV__Async self;
316             SV *cb;
317              
318 1 50         if(!async || !async->data) return;
    50          
319              
320 1           self = async->data;
321 1 50         if(!(cb = self->on_async) || !SvOK(cb)) return;
    50          
    0          
    0          
322              
323             dTHXa(self->perl);
324 1           dSP;
325 1           ENTER;
326 1           SAVETMPS;
327              
328 1 50         PUSHMARK(SP);
329 1 50         EXTEND(SP, 1);
330 1           mPUSHs(newRV_inc(self->selfrv));
331 1           PUTBACK;
332              
333 1           call_sv(cb, G_DISCARD|G_VOID);
334              
335 1 50         FREETMPS;
336 1           LEAVE;
337             }
338              
339             /*************
340             * UV::Check *
341             *************/
342              
343             /* See also http://docs.libuv.org/en/v1.x/check.html */
344              
345             typedef struct UV__Check {
346             uv_check_t *h;
347             FIELDS_UV__Handle
348             SV *on_check;
349             } *UV__Check;
350              
351 3           static void destroy_check(pTHX_ UV__Check self)
352             {
353 3           SvREFCNT_dec(self->on_check);
354 3           }
355              
356 2           static void on_check_cb(uv_check_t *check)
357             {
358             UV__Check self;
359             SV *cb;
360              
361 2 50         if(!check || !check->data) return;
    50          
362              
363 2           self = check->data;
364 2 50         if(!(cb = self->on_check) || !SvOK(cb)) return;
    50          
    0          
    0          
365              
366             dTHXa(self->perl);
367 2           dSP;
368 2           ENTER;
369 2           SAVETMPS;
370              
371 2 50         PUSHMARK(SP);
372 2 50         EXTEND(SP, 1);
373 2           mPUSHs(newRV_inc(self->selfrv));
374 2           PUTBACK;
375              
376 2           call_sv(cb, G_DISCARD|G_VOID);
377              
378 2 50         FREETMPS;
379 2           LEAVE;
380             }
381              
382             /************
383             * UV::Idle *
384             ************/
385              
386             /* See also http://docs.libuv.org/en/v1.x/idle.html */
387              
388             typedef struct UV__Idle {
389             uv_idle_t *h;
390             FIELDS_UV__Handle
391             SV *on_idle;
392             } *UV__Idle;
393              
394 2           static void destroy_idle(pTHX_ UV__Idle self)
395             {
396 2           SvREFCNT_dec(self->on_idle);
397 2           }
398              
399 1           static void on_idle_cb(uv_idle_t *idle)
400             {
401             UV__Idle self;
402             SV *cb;
403              
404 1 50         if(!idle || !idle->data) return;
    50          
405              
406 1           self = idle->data;
407 1 50         if(!(cb = self->on_idle) || !SvOK(cb)) return;
    50          
    0          
    0          
408              
409             dTHXa(self->perl);
410 1           dSP;
411 1           ENTER;
412 1           SAVETMPS;
413              
414 1 50         PUSHMARK(SP);
415 1 50         EXTEND(SP, 1);
416 1           mPUSHs(newRV_inc(self->selfrv));
417 1           PUTBACK;
418              
419 1           call_sv(cb, G_DISCARD|G_VOID);
420              
421 1 50         FREETMPS;
422 1           LEAVE;
423             }
424              
425             /************
426             * UV::Pipe *
427             ************/
428              
429             /* See also http://docs.libuv.org/en/v1.x/pipe.html */
430              
431             typedef struct UV__Pipe {
432             uv_pipe_t *h;
433             FIELDS_UV__Handle
434             FIELDS_UV__Stream
435             } *UV__Pipe;
436              
437 4           static void destroy_pipe(pTHX_ UV__Pipe self)
438             {
439 4           destroy_stream(aTHX_ (UV__Stream)self);
440 4           }
441              
442             /************
443             * UV::Poll *
444             ************/
445              
446             /* See also http://docs.libuv.org/en/v1.x/poll.html */
447              
448             typedef struct UV__Poll {
449             uv_poll_t *h;
450             FIELDS_UV__Handle
451             SV *on_poll;
452             } *UV__Poll;
453              
454 3           static void destroy_poll(pTHX_ UV__Poll self)
455             {
456 3           SvREFCNT_dec(self->on_poll);
457 3           }
458              
459 2           static void on_poll_cb(uv_poll_t *poll, int status, int events)
460             {
461             UV__Poll self;
462             SV *cb;
463              
464 2 50         if(!poll || !poll->data) return;
    50          
465              
466 2           self = poll->data;
467 2 50         if(!(cb = self->on_poll) || !SvOK(cb)) return;
    50          
    0          
    0          
468              
469             dTHXa(self->perl);
470 2           dSP;
471 2           ENTER;
472 2           SAVETMPS;
473              
474 2 50         PUSHMARK(SP);
475 2 50         EXTEND(SP, 3);
476 2           mPUSHs(newRV_inc(self->selfrv));
477 2           mPUSHi(status);
478 2           mPUSHi(events);
479 2           PUTBACK;
480              
481 2           call_sv(cb, G_DISCARD|G_VOID);
482              
483 2 50         FREETMPS;
484 2           LEAVE;
485             }
486              
487             /***************
488             * UV::Prepare *
489             ***************/
490              
491             /* See also http://docs.libuv.org/en/v1.x/prepare.html */
492              
493             typedef struct UV__Prepare {
494             uv_prepare_t *h;
495             FIELDS_UV__Handle
496             SV *on_prepare;
497             } *UV__Prepare;
498              
499 3           static void destroy_prepare(pTHX_ UV__Prepare self)
500             {
501 3           SvREFCNT_dec(self->on_prepare);
502 3           }
503              
504 2           static void on_prepare_cb(uv_prepare_t *prepare)
505             {
506             UV__Prepare self;
507             SV *cb;
508              
509 2 50         if(!prepare || !prepare->data) return;
    50          
510              
511 2           self = prepare->data;
512 2 50         if(!(cb = self->on_prepare) || !SvOK(cb)) return;
    50          
    0          
    0          
513              
514             dTHXa(self->perl);
515 2           dSP;
516 2           ENTER;
517 2           SAVETMPS;
518              
519 2 50         PUSHMARK(SP);
520 2 50         EXTEND(SP, 1);
521 2           mPUSHs(newRV_inc(self->selfrv));
522 2           PUTBACK;
523              
524 2           call_sv(cb, G_DISCARD|G_VOID);
525              
526 2 50         FREETMPS;
527 2           LEAVE;
528             }
529              
530             /* See also http://docs.libuv.org/en/v1.x/process.html */
531              
532             typedef struct UV__Process {
533             uv_process_t *h;
534             FIELDS_UV__Handle
535             SV *on_exit;
536              
537             /* fields for spawn */
538             uv_loop_t *loop;
539             uv_process_options_t options;
540             } *UV__Process;
541              
542 7           static void on_exit_cb(uv_process_t *process, int64_t exit_status, int term_signal)
543             {
544             UV__Process self;
545             SV *cb;
546              
547 7 50         if(!process || !process->data) return;
    50          
548              
549 7           self = process->data;
550 7 50         if(!(cb = self->on_exit) || !SvOK(cb)) return;
    50          
    0          
    0          
551              
552             dTHXa(self->perl);
553 7           dSP;
554 7           ENTER;
555 7           SAVETMPS;
556              
557 7 50         PUSHMARK(SP);
558 7 50         EXTEND(SP, 3);
559 7           mPUSHs(newRV_inc(self->selfrv));
560 7           mPUSHi(exit_status);
561 7           mPUSHi(term_signal);
562 7           PUTBACK;
563              
564 7           call_sv(cb, G_DISCARD|G_VOID);
565              
566 7 50         FREETMPS;
567 7           LEAVE;
568             }
569              
570             /**************
571             * UV::Signal *
572             **************/
573              
574             /* See also http://docs.libuv.org/en/v1.x/signal.html */
575              
576             typedef struct UV__Signal {
577             uv_signal_t *h;
578             FIELDS_UV__Handle
579             int signum;
580             SV *on_signal;
581             } *UV__Signal;
582              
583 2           static void destroy_signal(pTHX_ UV__Signal self)
584             {
585 2           SvREFCNT_dec(self->on_signal);
586 2           }
587              
588 1           static void on_signal_cb(uv_signal_t *signal, int signum)
589             {
590             UV__Signal self;
591             SV *cb;
592              
593 1 50         if(!signal || !signal->data) return;
    50          
594              
595 1           self = signal->data;
596 1 50         if(!(cb = self->on_signal) || !SvOK(cb)) return;
    50          
    0          
    0          
597              
598             dTHXa(self->perl);
599 1           dSP;
600 1           ENTER;
601 1           SAVETMPS;
602              
603 1 50         PUSHMARK(SP);
604 1 50         EXTEND(SP, 2);
605 1           mPUSHs(newRV_inc(self->selfrv));
606 1           mPUSHi(signum);
607 1           PUTBACK;
608              
609 1           call_sv(cb, G_DISCARD|G_VOID);
610              
611 1 50         FREETMPS;
612 1           LEAVE;
613             }
614              
615             /*************
616             * UV::Timer *
617             *************/
618              
619             /* See also http://docs.libuv.org/en/v1.x/timer.html */
620              
621             typedef struct UV__Timer {
622             uv_timer_t *h;
623             FIELDS_UV__Handle
624             SV *on_timer;
625             } *UV__Timer;
626              
627 31           static void destroy_timer(pTHX_ UV__Timer self)
628             {
629 31           SvREFCNT_dec(self->on_timer);
630 31           }
631              
632 51           static void on_timer_cb(uv_timer_t *timer)
633             {
634             UV__Timer self;
635             SV *cb;
636              
637 51 50         if(!timer || !timer->data) return;
    50          
638              
639 51           self = timer->data;
640 51 50         if(!(cb = self->on_timer) || !SvOK(cb)) return;
    50          
    0          
    0          
641              
642             dTHXa(self->perl);
643 51           dSP;
644 51           ENTER;
645 51           SAVETMPS;
646              
647 51 50         PUSHMARK(SP);
648 51 50         EXTEND(SP, 1);
649 51           mPUSHs(newRV_inc(self->selfrv));
650 51           PUTBACK;
651              
652 51           call_sv(cb, G_DISCARD|G_VOID);
653              
654 51 50         FREETMPS;
655 51           LEAVE;
656             }
657              
658             /***********
659             * UV::TCP *
660             ***********/
661              
662             /* See also http://docs.libuv.org/en/v1.x/tcp.html */
663              
664             typedef struct UV__TCP {
665             uv_tcp_t *h;
666             FIELDS_UV__Handle;
667             FIELDS_UV__Stream;
668             } *UV__TCP;
669              
670 3           static void destroy_tcp(pTHX_ UV__TCP self)
671             {
672 3           destroy_stream(aTHX_ (UV__Stream)self);
673 3           }
674              
675             /***********
676             * UV::TTY *
677             ***********/
678              
679             /* See also http://docs.libuv.org/en/v1.x/tty.html */
680              
681             typedef struct UV__TTY {
682             uv_tty_t *h;
683             FIELDS_UV__Handle
684             FIELDS_UV__Stream
685             } *UV__TTY;
686              
687 0           static void destroy_tty(pTHX_ UV__TTY self)
688             {
689 0           destroy_stream(aTHX_ (UV__Stream)self);
690 0           }
691              
692             /***********
693             * UV::UDP *
694             ***********/
695              
696             /* See also http://docs.libuv.org/en/v1.x/udp.html */
697              
698             typedef struct UV__UDP {
699             uv_udp_t *h;
700             FIELDS_UV__Handle
701             SV *on_recv;
702             } *UV__UDP;
703              
704 2           static void destroy_udp(pTHX_ UV__UDP self)
705             {
706 2           SvREFCNT_dec(self->on_recv);
707 2           }
708              
709 2           static void on_recv_cb(uv_udp_t *udp, ssize_t nread, const uv_buf_t *buf, const struct sockaddr *addr, unsigned flags)
710             {
711             UV__UDP self;
712             SV *cb;
713              
714 2 50         if(!udp || !udp->data) return;
    50          
715              
716 2           self = udp->data;
717 2 50         if((cb = self->on_recv) && SvOK(cb)) {
    50          
    0          
    0          
718 2           size_t addrlen = 0;
719             dTHXa(self->perl);
720 2           dSP;
721              
722             /* libuv doesn't give us the length of addr; we'll have to guess */
723 2           switch(((struct sockaddr_storage *)addr)->ss_family) {
724 2           case AF_INET: addrlen = sizeof(struct sockaddr_in); break;
725 0           case AF_INET6: addrlen = sizeof(struct sockaddr_in6); break;
726             }
727              
728 2           ENTER;
729 2           SAVETMPS;
730              
731 2 50         PUSHMARK(SP);
732 2 50         EXTEND(SP, 5);
733 2           mPUSHs(newRV_inc(self->selfrv));
734 2 50         mPUSHs(nread < 0 ? newSV_error(nread) : &PL_sv_undef);
735 2 50         if(nread >= 0)
736 2           mPUSHp(buf->base, nread);
737             else
738 0           PUSHs(&PL_sv_undef);
739 2           mPUSHp((char *)addr, addrlen);
740 2           mPUSHi(flags);
741 2           PUTBACK;
742              
743 2           call_sv(cb, G_DISCARD|G_VOID);
744              
745 2 50         FREETMPS;
746 2           LEAVE;
747             }
748              
749 2 50         if(buf && buf->base)
    50          
750 2           Safefree(buf->base);
751             }
752              
753             /* Handle destructor has to be able to see the type-specific destroy_
754             * functions above, so must be last
755             */
756              
757 58           static void destroy_handle(UV__Handle self)
758             {
759             dTHXa(self->perl);
760              
761 58           uv_handle_t *handle = self->h;
762 58           switch(handle->type) {
763 1           case UV_ASYNC: destroy_async (aTHX_ (UV__Async) self); break;
764 3           case UV_CHECK: destroy_check (aTHX_ (UV__Check) self); break;
765 2           case UV_IDLE: destroy_idle (aTHX_ (UV__Idle) self); break;
766             case UV_NAMED_PIPE:
767 4           destroy_pipe (aTHX_ (UV__Pipe) self); break;
768 3           case UV_POLL: destroy_poll (aTHX_ (UV__Poll) self); break;
769 3           case UV_PREPARE: destroy_prepare(aTHX_ (UV__Prepare)self); break;
770 2           case UV_SIGNAL: destroy_signal (aTHX_ (UV__Signal) self); break;
771 3           case UV_TCP: destroy_tcp (aTHX_ (UV__TCP) self); break;
772 31           case UV_TIMER: destroy_timer (aTHX_ (UV__Timer) self); break;
773 0           case UV_TTY: destroy_tty (aTHX_ (UV__TTY) self); break;
774 2           case UV_UDP: destroy_udp (aTHX_ (UV__UDP) self); break;
775             }
776              
777 58           destroy_handle_base(aTHX_ self);
778 58           }
779              
780             /***********
781             * UV::Req *
782             ***********/
783              
784             #define FIELDS_UV__Req \
785             SV *selfrv; \
786             dTHXfield(perl) \
787             SV *cb;
788              
789             typedef struct UV__Req {
790             uv_req_t *r;
791             FIELDS_UV__Req
792             } *UV__Req;
793              
794             #define NEW_UV__Req(var, type) \
795             Newxc(var, sizeof(*var) + sizeof(type), char, void); \
796             var->r = (type *)((char *)var + sizeof(*var));
797              
798             #define INIT_UV__Req(req) { \
799             req->r->data = req; \
800             storeTHX(req->perl); \
801             }
802              
803 8           static void on_req_cb(uv_req_t *_req, int status)
804             {
805 8           UV__Req req = _req->data;
806             dTHXa(req->perl);
807              
808 8 100         if(req->cb) {
809 7           dSP;
810 7           ENTER;
811 7           SAVETMPS;
812              
813 7 50         PUSHMARK(SP);
814 7 50         EXTEND(SP, 1);
815 7           mPUSHs(newSV_error(status));
816 7           PUTBACK;
817              
818 7           call_sv(req->cb, G_DISCARD|G_VOID);
819              
820 7 50         FREETMPS;
821 7           LEAVE;
822             }
823              
824 8           SvREFCNT_dec(req->selfrv);
825 8           }
826              
827             /* Simple UV::Req subtypes that just invoke a callback with status */
828              
829             typedef struct UV__Req_connect {
830             uv_connect_t *r;
831             FIELDS_UV__Req
832             } *UV__Req_connect;
833              
834             typedef struct UV__Req_shutdown {
835             uv_shutdown_t *r;
836             FIELDS_UV__Req
837             } *UV__Req_shutdown;
838              
839             typedef struct UV__Req_udp_send {
840             uv_udp_send_t *r;
841             FIELDS_UV__Req
842             char *s;
843             } *UV__Req_udp_send;
844              
845             typedef struct UV__Req_write {
846             uv_write_t *r;
847             FIELDS_UV__Req
848             char *s;
849             } *UV__Req_write;
850              
851             /* See also http://docs.libuv.org/en/v1.x/dns.html#c.uv_getaddrinfo */
852              
853             typedef struct UV__Req_getaddrinfo {
854             uv_getaddrinfo_t *r;
855             FIELDS_UV__Req
856             } *UV__Req_getaddrinfo;
857              
858             typedef struct UV__getaddrinfo_result {
859             int family;
860             int socktype;
861             int protocol;
862             socklen_t addrlen;
863             struct sockaddr *addr;
864             char *canonname;
865             } *UV__getaddrinfo_result;
866              
867 2           static void on_getaddrinfo_cb(uv_getaddrinfo_t *_req, int status, struct addrinfo *res)
868             {
869 2           UV__Req_getaddrinfo req = _req->data;
870             dTHXa(req->perl);
871              
872             struct addrinfo *addrp;
873              
874 2           dSP;
875 2           ENTER;
876 2           SAVETMPS;
877              
878 2 50         PUSHMARK(SP);
879 2 50         EXTEND(SP, 1);
880 2           mPUSHs(newSV_error(status));
881 3 100         for(addrp = res; addrp; addrp = addrp->ai_next) {
882             UV__getaddrinfo_result result;
883 1 50         STRLEN canonnamelen = addrp->ai_canonname ? strlen(addrp->ai_canonname) + 1 : 0;
884 1           Newxc(result, sizeof(*result) + addrp->ai_addrlen + canonnamelen, char, struct UV__getaddrinfo_result);
885              
886 1           result->family = addrp->ai_family;
887 1           result->socktype = addrp->ai_socktype;
888 1           result->protocol = addrp->ai_protocol;
889 1           result->addrlen = addrp->ai_addrlen;
890 1           result->addr = (struct sockaddr *)((char *)result + sizeof(*result));
891 1           Copy(addrp->ai_addr, result->addr, addrp->ai_addrlen, char);
892 1 50         if(canonnamelen) {
893 0           result->canonname = (char *)result->addr + addrp->ai_addrlen;
894 0           Copy(addrp->ai_canonname, result->canonname, canonnamelen, char);
895             }
896             else {
897 1           result->canonname = NULL;
898             }
899              
900 1 50         EXTEND(SP, 1);
901 1           PUSHmortal;
902 1           sv_setref_pv(TOPs, "UV::getaddrinfo_result", result);
903             }
904 2           PUTBACK;
905              
906 2           call_sv(req->cb, G_DISCARD|G_VOID);
907              
908 2 50         FREETMPS;
909 2           LEAVE;
910              
911 2           uv_freeaddrinfo(res);
912 2           SvREFCNT_dec(req->selfrv);
913 2           }
914              
915             typedef struct UV__Req_getnameinfo {
916             uv_getnameinfo_t *r;
917             FIELDS_UV__Req
918             } *UV__Req_getnameinfo;
919              
920 1           static void on_getnameinfo_cb(uv_getnameinfo_t *_req, int status, const char *hostname, const char *service)
921             {
922 1           UV__Req_getnameinfo req = _req->data;
923             dTHXa(req->perl);
924              
925 1           dSP;
926 1           ENTER;
927 1           SAVETMPS;
928              
929 1 50         PUSHMARK(SP);
930 1 50         EXTEND(SP, 3);
931 1           mPUSHs(newSV_error(status));
932 1           mPUSHp(hostname, strlen(hostname));
933 1           mPUSHp(service, strlen(service));
934 1           PUTBACK;
935              
936 1           call_sv(req->cb, G_DISCARD|G_VOID);
937              
938 1 50         FREETMPS;
939 1           LEAVE;
940              
941 1           SvREFCNT_dec(req->selfrv);
942 1           }
943              
944             /************
945             * UV::Loop *
946             ************/
947              
948             typedef struct UV__Loop {
949             uv_loop_t *loop; /* may point to uv_default_loop() or past this struct */
950             SV *on_walk; /* TODO as yet unused and probably not correct */
951             } *UV__Loop;
952              
953 10           static void on_loop_walk(uv_handle_t* handle, void* arg)
954             {
955 10           fprintf(stderr, "TODO: on_loop_walk\n");
956 10           }
957              
958             MODULE = UV PACKAGE = UV PREFIX = uv_
959              
960             BOOT:
961             {
962             HV *stash;
963             AV *export;
964             #define DO_CONST_IV(c) \
965             newCONSTSUB_flags(stash, #c, strlen(#c), 0, newSViv(c)); \
966             av_push(export, newSVpvs(#c));
967             #define DO_CONST_PV(c) \
968             newCONSTSUB_flags(stash, #c, strlen(#c), 0, newSVpvn(c, strlen(c))); \
969             av_push(export, newSVpvs(#c));
970              
971             /* constants under UV */
972             {
973 43           stash = gv_stashpv("UV", GV_ADD);
974 43           export = get_av("UV::EXPORT_XS", TRUE);
975              
976 43           DO_CONST_IV(UV_VERSION_MAJOR);
977 43           DO_CONST_IV(UV_VERSION_MINOR);
978 43           DO_CONST_IV(UV_VERSION_PATCH);
979 43           DO_CONST_IV(UV_VERSION_IS_RELEASE);
980 43           DO_CONST_IV(UV_VERSION_HEX);
981 43           DO_CONST_PV(UV_VERSION_SUFFIX);
982              
983 43           DO_CONST_IV(UV_E2BIG);
984 43           DO_CONST_IV(UV_EACCES);
985 43           DO_CONST_IV(UV_EADDRINUSE);
986 43           DO_CONST_IV(UV_EADDRNOTAVAIL);
987 43           DO_CONST_IV(UV_EAFNOSUPPORT);
988 43           DO_CONST_IV(UV_EAGAIN);
989 43           DO_CONST_IV(UV_EAI_ADDRFAMILY);
990 43           DO_CONST_IV(UV_EAI_AGAIN);
991 43           DO_CONST_IV(UV_EAI_BADFLAGS);
992 43           DO_CONST_IV(UV_EAI_BADHINTS);
993 43           DO_CONST_IV(UV_EAI_CANCELED);
994 43           DO_CONST_IV(UV_EAI_FAIL);
995 43           DO_CONST_IV(UV_EAI_FAMILY);
996 43           DO_CONST_IV(UV_EAI_MEMORY);
997 43           DO_CONST_IV(UV_EAI_NODATA);
998 43           DO_CONST_IV(UV_EAI_NONAME);
999 43           DO_CONST_IV(UV_EAI_OVERFLOW);
1000 43           DO_CONST_IV(UV_EAI_PROTOCOL);
1001 43           DO_CONST_IV(UV_EAI_SERVICE);
1002 43           DO_CONST_IV(UV_EAI_SOCKTYPE);
1003 43           DO_CONST_IV(UV_EALREADY);
1004 43           DO_CONST_IV(UV_EBADF);
1005 43           DO_CONST_IV(UV_EBUSY);
1006 43           DO_CONST_IV(UV_ECANCELED);
1007 43           DO_CONST_IV(UV_ECHARSET);
1008 43           DO_CONST_IV(UV_ECONNABORTED);
1009 43           DO_CONST_IV(UV_ECONNREFUSED);
1010 43           DO_CONST_IV(UV_ECONNRESET);
1011 43           DO_CONST_IV(UV_EDESTADDRREQ);
1012 43           DO_CONST_IV(UV_EEXIST);
1013 43           DO_CONST_IV(UV_EFAULT);
1014 43           DO_CONST_IV(UV_EFBIG);
1015 43           DO_CONST_IV(UV_EHOSTUNREACH);
1016 43           DO_CONST_IV(UV_EINTR);
1017 43           DO_CONST_IV(UV_EINVAL);
1018 43           DO_CONST_IV(UV_EIO);
1019 43           DO_CONST_IV(UV_EISCONN);
1020 43           DO_CONST_IV(UV_EISDIR);
1021 43           DO_CONST_IV(UV_ELOOP);
1022 43           DO_CONST_IV(UV_EMFILE);
1023 43           DO_CONST_IV(UV_EMSGSIZE);
1024 43           DO_CONST_IV(UV_ENAMETOOLONG);
1025 43           DO_CONST_IV(UV_ENETDOWN);
1026 43           DO_CONST_IV(UV_ENETUNREACH);
1027 43           DO_CONST_IV(UV_ENFILE);
1028 43           DO_CONST_IV(UV_ENOBUFS);
1029 43           DO_CONST_IV(UV_ENODEV);
1030 43           DO_CONST_IV(UV_ENOENT);
1031 43           DO_CONST_IV(UV_ENOMEM);
1032 43           DO_CONST_IV(UV_ENONET);
1033 43           DO_CONST_IV(UV_ENOPROTOOPT);
1034 43           DO_CONST_IV(UV_ENOSPC);
1035 43           DO_CONST_IV(UV_ENOSYS);
1036 43           DO_CONST_IV(UV_ENOTCONN);
1037 43           DO_CONST_IV(UV_ENOTDIR);
1038 43           DO_CONST_IV(UV_ENOTEMPTY);
1039 43           DO_CONST_IV(UV_ENOTSOCK);
1040 43           DO_CONST_IV(UV_ENOTSUP);
1041 43           DO_CONST_IV(UV_EPERM);
1042 43           DO_CONST_IV(UV_EPIPE);
1043 43           DO_CONST_IV(UV_EPROTO);
1044 43           DO_CONST_IV(UV_EPROTONOSUPPORT);
1045 43           DO_CONST_IV(UV_EPROTOTYPE);
1046 43           DO_CONST_IV(UV_ERANGE);
1047 43           DO_CONST_IV(UV_EROFS);
1048 43           DO_CONST_IV(UV_ESHUTDOWN);
1049 43           DO_CONST_IV(UV_ESPIPE);
1050 43           DO_CONST_IV(UV_ESRCH);
1051 43           DO_CONST_IV(UV_ETIMEDOUT);
1052 43           DO_CONST_IV(UV_ETXTBSY);
1053 43           DO_CONST_IV(UV_EXDEV);
1054 43           DO_CONST_IV(UV_UNKNOWN);
1055 43           DO_CONST_IV(UV_EOF);
1056 43           DO_CONST_IV(UV_ENXIO);
1057 43           DO_CONST_IV(UV_EMLINK);
1058             }
1059              
1060             /* constants under UV::Handle */
1061             {
1062 43           stash = gv_stashpv("UV::Handle", GV_ADD);
1063 43           export = get_av("UV::Handle::EXPORT_XS", TRUE);
1064              
1065 43           DO_CONST_IV(UV_ASYNC);
1066 43           DO_CONST_IV(UV_CHECK);
1067 43           DO_CONST_IV(UV_FS_EVENT);
1068 43           DO_CONST_IV(UV_FS_POLL);
1069 43           DO_CONST_IV(UV_IDLE);
1070 43           DO_CONST_IV(UV_NAMED_PIPE);
1071 43           DO_CONST_IV(UV_POLL);
1072 43           DO_CONST_IV(UV_PREPARE);
1073 43           DO_CONST_IV(UV_PROCESS);
1074 43           DO_CONST_IV(UV_STREAM);
1075 43           DO_CONST_IV(UV_TCP);
1076 43           DO_CONST_IV(UV_TIMER);
1077 43           DO_CONST_IV(UV_TTY);
1078 43           DO_CONST_IV(UV_UDP);
1079 43           DO_CONST_IV(UV_SIGNAL);
1080 43           DO_CONST_IV(UV_FILE);
1081             }
1082              
1083             /* constants under UV::Loop */
1084             {
1085 43           stash = gv_stashpv("UV::Loop", GV_ADD);
1086 43           export = get_av("UV::Loop::EXPORT_XS", TRUE);
1087              
1088             /* Loop run constants */
1089 43           DO_CONST_IV(UV_RUN_DEFAULT);
1090 43           DO_CONST_IV(UV_RUN_ONCE);
1091 43           DO_CONST_IV(UV_RUN_NOWAIT);
1092              
1093             /* expose the Loop configure constants */
1094 43           DO_CONST_IV(UV_LOOP_BLOCK_SIGNAL);
1095 43           DO_CONST_IV(SIGPROF);
1096             }
1097              
1098             /* constants under UV::Poll */
1099             {
1100 43           stash = gv_stashpv("UV::Poll", GV_ADD);
1101 43           export = get_av("UV::Poll::EXPORT_XS", TRUE);
1102              
1103             /* Poll Event Types */
1104 43           DO_CONST_IV(UV_READABLE);
1105 43           DO_CONST_IV(UV_WRITABLE);
1106 43           DO_CONST_IV(UV_DISCONNECT);
1107 43           DO_CONST_IV(UV_PRIORITIZED);
1108             }
1109              
1110             /* constants under UV::TTY */
1111             {
1112 43           stash = gv_stashpv("UV::TTY", GV_ADD);
1113 43           export = get_av("UV::TTY::EXPORT_XS", TRUE);
1114              
1115             /* TTY mode types */
1116 43           DO_CONST_IV(UV_TTY_MODE_NORMAL);
1117 43           DO_CONST_IV(UV_TTY_MODE_RAW);
1118 43           DO_CONST_IV(UV_TTY_MODE_IO);
1119             }
1120              
1121             /* constants under UV::UDP */
1122             {
1123 43           stash = gv_stashpv("UV::UDP", GV_ADD);
1124 43           export = get_av("UV::UDP::EXPORT_XS", TRUE);
1125              
1126             /* TTY mode types */
1127 43           DO_CONST_IV(UV_JOIN_GROUP);
1128 43           DO_CONST_IV(UV_LEAVE_GROUP);
1129             }
1130             }
1131              
1132             const char* uv_err_name(int err)
1133              
1134             UV uv_hrtime()
1135             CODE:
1136 3           RETVAL = uv_hrtime();
1137             OUTPUT:
1138             RETVAL
1139              
1140             const char* uv_strerror(int err)
1141              
1142             unsigned int uv_version()
1143              
1144             const char* uv_version_string()
1145              
1146             MODULE = UV PACKAGE = UV::Exception
1147              
1148             SV *
1149             message(SV *self)
1150             CODE:
1151 1           RETVAL = newSV(0);
1152 1           sv_copypv(RETVAL, SvRV(self));
1153             OUTPUT:
1154             RETVAL
1155              
1156             int
1157             code(SV *self)
1158             CODE:
1159 1 50         RETVAL = SvIV(SvRV(self));
1160             OUTPUT:
1161             RETVAL
1162              
1163             MODULE = UV PACKAGE = UV::Handle
1164              
1165             void
1166             DESTROY(UV::Handle self)
1167             CODE:
1168             /* TODO:
1169             $self->stop() if ($self->can('stop') && !$self->closing() && !$self->closed());
1170             */
1171 70 100         if(!uv_is_closing(self->h))
1172 25           uv_close(self->h, on_close_then_destroy);
1173             else
1174 45           destroy_handle(self);
1175              
1176             bool
1177             closed(UV::Handle self)
1178             CODE:
1179 82           RETVAL = 0;
1180             OUTPUT:
1181             RETVAL
1182              
1183             bool
1184             closing(UV::Handle self)
1185             CODE:
1186 45           RETVAL = uv_is_closing(self->h);
1187             OUTPUT:
1188             RETVAL
1189              
1190             bool
1191             active(UV::Handle self)
1192             CODE:
1193 29           RETVAL = uv_is_active(self->h);
1194             OUTPUT:
1195             RETVAL
1196              
1197             SV *
1198             loop(UV::Handle self)
1199             INIT:
1200             UV__Loop loop;
1201             CODE:
1202 8           Newx(loop, 1, struct UV__Loop);
1203 8           loop->loop = self->h->loop;
1204 8           loop->on_walk = NULL; /* this is a mess */
1205              
1206 8           RETVAL = newSV(0);
1207 8           sv_setref_pv(RETVAL, "UV::Loop", loop);
1208             OUTPUT:
1209             RETVAL
1210              
1211             SV *
1212             data(UV::Handle self, SV *data = NULL)
1213             CODE:
1214 8 100         if(items > 1) {
1215 4           SvREFCNT_dec(self->data);
1216 4           self->data = newSVsv(data);
1217             }
1218 8 50         RETVAL = self->data ? newSVsv(self->data) : &PL_sv_undef;
1219             OUTPUT:
1220             RETVAL
1221              
1222             void
1223             _close(UV::Handle self)
1224             CODE:
1225 45           uv_close(self->h, on_close_cb);
1226              
1227             SV *
1228             _on_close(UV::Handle self, SV *cb = NULL)
1229             CODE:
1230 27           RETVAL = do_callback_accessor(&self->on_close, cb);
1231             OUTPUT:
1232             RETVAL
1233              
1234             MODULE = UV PACKAGE = UV::Async
1235              
1236             SV *
1237             _new(char *class, UV::Loop loop)
1238             INIT:
1239             UV__Async self;
1240             int err;
1241             CODE:
1242 1           NEW_UV__Handle(self, uv_async_t);
1243              
1244 1           err = uv_async_init(loop->loop, self->h, &on_async_cb);
1245 1 50         if (err != 0) {
1246 0           Safefree(self);
1247 0           THROWERR("Couldn't initialise async handle", err);
1248             }
1249              
1250 1           INIT_UV__Handle(self);
1251 1           self->on_async = NULL;
1252              
1253 1           RETVAL = newSV(0);
1254 1           sv_setref_pv(RETVAL, "UV::Async", self);
1255 1           self->selfrv = SvRV(RETVAL); /* no inc */
1256             OUTPUT:
1257             RETVAL
1258              
1259             SV *
1260             _on_async(UV::Async self, SV *cb = NULL)
1261             CODE:
1262 1           RETVAL = do_callback_accessor(&self->on_async, cb);
1263             OUTPUT:
1264             RETVAL
1265              
1266             void
1267             send(UV::Async self)
1268             CODE:
1269 1 50         CHECKCALL(uv_async_send(self->h));
1270              
1271             MODULE = UV PACKAGE = UV::Check
1272              
1273             SV *
1274             _new(char *class, UV::Loop loop)
1275             INIT:
1276             UV__Check self;
1277             int err;
1278             CODE:
1279 3           NEW_UV__Handle(self, uv_check_t);
1280              
1281 3           err = uv_check_init(loop->loop, self->h);
1282 3 50         if (err != 0) {
1283 0           Safefree(self);
1284 0           THROWERR("Couldn't initialise check handle", err);
1285             }
1286              
1287 3           INIT_UV__Handle(self);
1288 3           self->on_check = NULL;
1289              
1290 3           RETVAL = newSV(0);
1291 3           sv_setref_pv(RETVAL, "UV::Check", self);
1292 3           self->selfrv = SvRV(RETVAL); /* no inc */
1293             OUTPUT:
1294             RETVAL
1295              
1296             SV *
1297             _on_check(UV::Check self, SV *cb = NULL)
1298             CODE:
1299 2           RETVAL = do_callback_accessor(&self->on_check, cb);
1300             OUTPUT:
1301             RETVAL
1302              
1303             void
1304             _start(UV::Check self)
1305             CODE:
1306 2 50         CHECKCALL(uv_check_start(self->h, on_check_cb));
1307              
1308             void
1309             stop(UV::Check self)
1310             CODE:
1311 4 50         CHECKCALL(uv_check_stop(self->h));
1312              
1313             MODULE = UV PACKAGE = UV::Idle
1314              
1315             SV *
1316             _new(char *class, UV::Loop loop)
1317             INIT:
1318             UV__Idle self;
1319             int err;
1320             CODE:
1321 2           NEW_UV__Handle(self, uv_idle_t);
1322              
1323 2           err = uv_idle_init(loop->loop, self->h);
1324 2 50         if (err != 0) {
1325 0           Safefree(self);
1326 0           THROWERR("Couldn't initialise idle handle", err);
1327             }
1328              
1329 2           INIT_UV__Handle(self);
1330 2           self->on_idle = NULL;
1331              
1332 2           RETVAL = newSV(0);
1333 2           sv_setref_pv(RETVAL, "UV::Idle", self);
1334 2           self->selfrv = SvRV(RETVAL); /* no inc */
1335             OUTPUT:
1336             RETVAL
1337              
1338             SV *
1339             _on_idle(UV::Idle self, SV *cb = NULL)
1340             CODE:
1341 1           RETVAL = do_callback_accessor(&self->on_idle, cb);
1342             OUTPUT:
1343             RETVAL
1344              
1345             void
1346             _start(UV::Idle self)
1347             CODE:
1348 1 50         CHECKCALL(uv_idle_start(self->h, on_idle_cb));
1349              
1350             void
1351             stop(UV::Idle self)
1352             CODE:
1353 2 50         CHECKCALL(uv_idle_stop(self->h));
1354              
1355             MODULE = UV PACKAGE = UV::Pipe
1356              
1357             SV *
1358             _new(char *class, UV::Loop loop)
1359             INIT:
1360             UV__Pipe self;
1361             int err;
1362             CODE:
1363 6           NEW_UV__Handle(self, uv_pipe_t);
1364              
1365 6           err = uv_pipe_init(loop->loop, self->h, 0);
1366 6 50         if (err != 0) {
1367 0           Safefree(self);
1368 0           THROWERR("Couldn't initialse pipe handle", err);
1369             }
1370              
1371 6           INIT_UV__Handle(self);
1372 6           INIT_UV__Stream(self);
1373              
1374 6           RETVAL = newSV(0);
1375 6           sv_setref_pv(RETVAL, "UV::Pipe", self);
1376 6           self->selfrv = SvRV(RETVAL); /* no inc */
1377             OUTPUT:
1378             RETVAL
1379              
1380             void
1381             _open(UV::Pipe self, int fd)
1382             CODE:
1383 3 50         CHECKCALL(uv_pipe_open(self->h, fd));
1384              
1385             void
1386             bind(UV::Pipe self, char *name)
1387             CODE:
1388 1 50         CHECKCALL(uv_pipe_bind(self->h, name));
1389              
1390             SV *
1391             connect(UV::Pipe self, char *path, SV *cb)
1392             INIT:
1393             UV__Req_connect req;
1394             CODE:
1395 1           NEW_UV__Req(req, uv_connect_t);
1396 1           INIT_UV__Req(req);
1397              
1398 1           uv_pipe_connect(req->r, self->h, path, (uv_connect_cb)on_req_cb);
1399              
1400 1           req->cb = newSVsv(cb);
1401              
1402 1           RETVAL = newSV(0);
1403 1           sv_setref_pv(RETVAL, "UV::Req", req);
1404 1           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
1405             OUTPUT:
1406             RETVAL
1407              
1408             SV *
1409             getpeername(UV::Pipe self)
1410             ALIAS:
1411             getpeername = 0
1412             getsockname = 1
1413             INIT:
1414             size_t len;
1415             int err;
1416             CODE:
1417 2           RETVAL = newSV(256);
1418 2           len = SvLEN(RETVAL);
1419              
1420 2           err = (ix == 0) ?
1421 2 100         uv_pipe_getpeername(self->h, SvPVX(RETVAL), &len) :
1422 1           uv_pipe_getsockname(self->h, SvPVX(RETVAL), &len);
1423 2 50         if(err != 0) {
1424 0           SvREFCNT_dec(RETVAL);
1425 0 0         croak("Couldn't %s from pipe handle (%d): %s", (ix == 0) ? "getpeername" : "getsockname",
1426             err, uv_strerror(err));
1427             }
1428              
1429 2           SvCUR_set(RETVAL, len);
1430 2           SvPOK_on(RETVAL);
1431             OUTPUT:
1432             RETVAL
1433              
1434             void
1435             chmod(UV::Pipe self, int flags)
1436             CODE:
1437 0 0         CHECKCALL(uv_pipe_chmod(self->h, flags));
1438              
1439             MODULE = UV PACKAGE = UV::Poll
1440              
1441             SV *
1442             _new(char *class, UV::Loop loop, int fd, bool is_socket)
1443             INIT:
1444             UV__Poll self;
1445             int err;
1446             CODE:
1447 4           NEW_UV__Handle(self, uv_poll_t);
1448              
1449 4 100         if(is_socket)
1450 1           err = uv_poll_init_socket(loop->loop, self->h, _MAKE_SOCK(fd));
1451             else
1452 3           err = uv_poll_init(loop->loop, self->h, fd);
1453 4 100         if (err != 0) {
1454 1           Safefree(self);
1455 1           THROWERR("Couldn't initialise poll handle", err);
1456             }
1457              
1458 3           INIT_UV__Handle(self);
1459 3           self->on_poll = NULL;
1460              
1461 3           RETVAL = newSV(0);
1462 3           sv_setref_pv(RETVAL, "UV::Poll", self);
1463 3           self->selfrv = SvRV(RETVAL); /* no inc */
1464             OUTPUT:
1465             RETVAL
1466              
1467             SV *
1468             _on_poll(UV::Poll self, SV *cb = NULL)
1469             CODE:
1470 2           RETVAL = do_callback_accessor(&self->on_poll, cb);
1471             OUTPUT:
1472             RETVAL
1473              
1474             void
1475             _start(UV::Poll self, int events = UV_READABLE)
1476             CODE:
1477 2 50         CHECKCALL(uv_poll_start(self->h, events, on_poll_cb));
1478              
1479             void
1480             stop(UV::Poll self)
1481             CODE:
1482 4 50         CHECKCALL(uv_poll_stop(self->h));
1483              
1484             MODULE = UV PACKAGE = UV::Prepare
1485              
1486             SV *
1487             _new(char *class, UV::Loop loop)
1488             INIT:
1489             UV__Prepare self;
1490             int err;
1491             CODE:
1492 3           NEW_UV__Handle(self, uv_prepare_t);
1493              
1494 3           err = uv_prepare_init(loop->loop, self->h);
1495 3 50         if (err != 0) {
1496 0           Safefree(self);
1497 0           THROWERR("Couldn't initialise prepare handle", err);
1498             }
1499              
1500 3           INIT_UV__Handle(self);
1501 3           self->on_prepare = NULL;
1502              
1503 3           RETVAL = newSV(0);
1504 3           sv_setref_pv(RETVAL, "UV::Prepare", self);
1505 3           self->selfrv = SvRV(RETVAL); /* no inc */
1506             OUTPUT:
1507             RETVAL
1508              
1509             SV *
1510             _on_prepare(UV::Prepare self, SV *cb = NULL)
1511             CODE:
1512 2           RETVAL = do_callback_accessor(&self->on_prepare, cb);
1513             OUTPUT:
1514             RETVAL
1515              
1516             void
1517             _start(UV::Prepare self)
1518             CODE:
1519 2 50         CHECKCALL(uv_prepare_start(self->h, on_prepare_cb));
1520              
1521             void
1522             stop(UV::Prepare self)
1523             CODE:
1524 4 50         CHECKCALL(uv_prepare_stop(self->h));
1525              
1526             MODULE = UV PACKAGE = UV::Process
1527              
1528             SV *
1529             _new(char *class, UV::Loop loop)
1530             INIT:
1531             UV__Process self;
1532             int err;
1533             CODE:
1534 7           NEW_UV__Handle(self, uv_process_t);
1535 7           self->loop = loop->loop;
1536              
1537 7           INIT_UV__Handle(self);
1538 7           self->on_exit = NULL;
1539              
1540 7           Zero(&self->options, 1, uv_process_options_t);
1541              
1542 7           self->options.exit_cb = &on_exit_cb;
1543              
1544 7           RETVAL = newSV(0);
1545 7           sv_setref_pv(RETVAL, "UV::Process", self);
1546 7           self->selfrv = SvRV(RETVAL); /* no inc */
1547             OUTPUT:
1548             RETVAL
1549              
1550             SV *
1551             _on_exit(UV::Process self, SV *cb = NULL)
1552             CODE:
1553 7           RETVAL = do_callback_accessor(&self->on_exit, cb);
1554             OUTPUT:
1555             RETVAL
1556              
1557             void
1558             _set_file(UV::Process self, char *file)
1559             CODE:
1560 7           self->options.file = savepv(file);
1561              
1562             void
1563             _set_args(UV::Process self, SV *args)
1564             INIT:
1565             AV *argsav;
1566             U32 i;
1567             CODE:
1568 7 50         if(!SvROK(args) || SvTYPE(SvRV(args)) != SVt_PVAV)
    50          
1569 0           croak("Expected args as ARRAY reference");
1570              
1571 7           argsav = (AV *)SvRV(args);
1572              
1573 7 50         Newx(self->options.args, AvFILL(argsav) + 3, char *);
    50          
    50          
1574 7           self->options.args[0] = NULL;
1575 21 50         for(i = 0; i <= AvFILL(argsav); i++)
    100          
1576 14 50         self->options.args[i+1] = savepv(SvPVbyte_nolen(AvARRAY(argsav)[i]));
1577 7           self->options.args[i+1] = NULL;
1578              
1579             void
1580             _set_env(UV::Process self, SV *env)
1581             INIT:
1582             HV *envhv;
1583             I32 nkeys, i, dummy;
1584             HE *iter;
1585             SV *tmp;
1586             CODE:
1587 1 50         if(!SvROK(env) || SvTYPE(SvRV(env)) != SVt_PVHV)
    50          
1588 0           croak("Expected env as HASH reference");
1589              
1590 1           envhv = (HV *)SvRV(env);
1591 1           nkeys = hv_iterinit(envhv);
1592              
1593 1 50         Newx(self->options.env, nkeys + 1, char *);
1594 1           tmp = sv_newmortal();
1595              
1596 1           i = 0;
1597 2 100         while((iter = hv_iternext(envhv))) {
1598 1 50         sv_setpvf(tmp, "%s=%s",
1599 2           hv_iterkey(iter, &dummy), SvPVbyte_nolen(HeVAL(iter)));
1600              
1601 1           self->options.env[i++] = SvPVX(tmp);
1602 1           SvPVX(tmp) = NULL;
1603 1           SvLEN(tmp) = 0;
1604             }
1605 1           self->options.env[i] = NULL;
1606              
1607             void
1608             _set_stdio_h(UV::Process self, int fd, SV *arg)
1609             INIT:
1610             uv_stdio_container_t *cont;
1611 1           int flags = 0;
1612 1           SV *fdarg = arg;
1613             CODE:
1614 1 50         if(self->options.stdio_count < (fd+1)) {
1615 1           int n = self->options.stdio_count;
1616 1 50         if(n < (fd+1)) n = (fd+1);
1617 1 50         if(n < 3) n = 3;
1618              
1619 1 50         Renew(self->options.stdio, n, uv_stdio_container_t);
1620             int i;
1621 4 100         for(i = self->options.stdio_count; i < n; i++)
1622 3           self->options.stdio[i].flags = UV_IGNORE;
1623              
1624 1           self->options.stdio_count = n;
1625             }
1626              
1627 1           cont = self->options.stdio + fd;
1628              
1629 1 50         if(SvROK(arg) && SvTYPE(SvRV(arg)) == SVt_PVHV) {
    50          
1630 0           fprintf(stderr, "TODO: grab extra values from hash\n");
1631             }
1632              
1633 1 50         if(!SvROK(fdarg)) {
1634             /* FD by stream number */
1635 0 0         cont->data.fd = SvIV(arg);
1636 0           flags |= UV_INHERIT_FD;
1637             }
1638 1 50         else if(SvTYPE(SvRV(fdarg)) == SVt_PVGV) {
1639             /* FD by globref */
1640 1 50         cont->data.fd = PerlIO_fileno(IoOFP(GvIO(SvRV(fdarg))));
    50          
    0          
    50          
1641 1           flags |= UV_INHERIT_FD;
1642             }
1643             else {
1644 0           croak("Unsure what to do with _set_stdio_h fd argument %" SVf, SVfARG(arg));
1645             }
1646              
1647 1           cont->flags = flags;
1648              
1649             void
1650             _set_setuid(UV::Process self, int uid)
1651             CODE:
1652 1           self->options.flags |= UV_PROCESS_SETUID;
1653 1           self->options.uid = uid;
1654              
1655             void
1656             _set_setgid(UV::Process self, int gid)
1657             CODE:
1658 0           self->options.flags |= UV_PROCESS_SETGID;
1659 0           self->options.uid = gid;
1660              
1661              
1662             void
1663             _spawn(UV::Process self)
1664             INIT:
1665             int err;
1666             CODE:
1667 7 50         if(!self->options.file)
1668 0           croak("Require 'file' to spawn a UV::Process");
1669 7 50         if(!self->options.args)
1670 0           croak("Require 'args' to spawn a UV::Process");
1671              
1672 7 50         if(!self->options.args[0])
1673 7           self->options.args[0] = savepv(self->options.file);
1674              
1675 7           err = uv_spawn(self->loop, self->h, &self->options);
1676 7 50         if (err != 0) {
1677 0           THROWERR("Couldn't spawn process", err);
1678             }
1679              
1680             void
1681             kill(UV::Process self, int signum)
1682             CODE:
1683 1 50         CHECKCALL(uv_process_kill(self->h, signum));
1684              
1685             int
1686             pid(UV::Process self)
1687             CODE:
1688 1           RETVAL = self->h->pid;
1689             OUTPUT:
1690             RETVAL
1691              
1692             MODULE = UV PACKAGE = UV::Signal
1693              
1694             SV *
1695             _new(char *class, UV::Loop loop, int signum)
1696             INIT:
1697             UV__Signal self;
1698             int err;
1699             CODE:
1700 2           NEW_UV__Handle(self, uv_signal_t);
1701              
1702 2           err = uv_signal_init(loop->loop, self->h);
1703 2 50         if (err != 0) {
1704 0           Safefree(self);
1705 0           THROWERR("Couldn't initialise signal handle", err);
1706             }
1707              
1708 2           INIT_UV__Handle(self);
1709 2           self->signum = signum; /* need to remember this until start() time */
1710 2           self->on_signal = NULL;
1711              
1712 2           RETVAL = newSV(0);
1713 2           sv_setref_pv(RETVAL, "UV::Signal", self);
1714 2           self->selfrv = SvRV(RETVAL); /* no inc */
1715             OUTPUT:
1716             RETVAL
1717              
1718             SV *
1719             _on_signal(UV::Signal self, SV *cb = NULL)
1720             CODE:
1721 1           RETVAL = do_callback_accessor(&self->on_signal, cb);
1722             OUTPUT:
1723             RETVAL
1724              
1725             void
1726             _start(UV::Signal self)
1727             CODE:
1728 1 50         CHECKCALL(uv_signal_start(self->h, on_signal_cb, self->signum));
1729              
1730             void
1731             stop(UV::Signal self)
1732             CODE:
1733 2 50         CHECKCALL(uv_signal_stop(self->h));
1734              
1735             MODULE = UV PACKAGE = UV::Stream
1736              
1737             SV *
1738             _on_read(UV::Stream self, SV *cb = NULL)
1739             CODE:
1740 3           RETVAL = do_callback_accessor(&self->on_read, cb);
1741             OUTPUT:
1742             RETVAL
1743              
1744             SV *
1745             _on_connection(UV::Stream self, SV *cb = NULL)
1746             CODE:
1747 2           RETVAL = do_callback_accessor(&self->on_connection, cb);
1748             OUTPUT:
1749             RETVAL
1750              
1751             void
1752             _listen(UV::Stream self, int backlog)
1753             CODE:
1754 2 50         CHECKCALL(uv_listen(self->h, backlog, on_connection_cb));
1755              
1756             void
1757             _accept(UV::Stream self, UV::Stream client)
1758             CODE:
1759 2 50         CHECKCALL(uv_accept(self->h, client->h));
1760              
1761             SV *
1762             shutdown(UV::Stream self, SV *cb)
1763             INIT:
1764             UV__Req_shutdown req;
1765             int err;
1766             CODE:
1767 2           NEW_UV__Req(req, uv_shutdown_t);
1768 2           INIT_UV__Req(req);
1769              
1770 2           err = uv_shutdown(req->r, self->h, (uv_shutdown_cb)on_req_cb);
1771              
1772 2 50         if(err != 0) {
1773 0           Safefree(req);
1774 0           THROWERR("Couldn't shutdown", err);
1775             }
1776              
1777 2           req->cb = newSVsv(cb);
1778              
1779 2           RETVAL = newSV(0);
1780 2           sv_setref_pv(RETVAL, "UV::Req", req);
1781 2           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
1782             OUTPUT:
1783             RETVAL
1784              
1785             void
1786             read_start(UV::Stream self)
1787             CODE:
1788 3 50         CHECKCALL(uv_read_start(self->h, on_alloc_cb, on_read_cb));
1789              
1790             void
1791             read_stop(UV::Stream self)
1792             CODE:
1793 0 0         CHECKCALL(uv_read_stop(self->h));
1794              
1795             SV *
1796             write(UV::Stream self, SV *s, SV *cb)
1797             INIT:
1798             UV__Req_write req;
1799             uv_buf_t buf[1];
1800             int err;
1801             CODE:
1802 2           NEW_UV__Req(req, uv_write_t);
1803 2           INIT_UV__Req(req);
1804              
1805 2           buf[0].len = SvCUR(s);
1806 2           buf[0].base = savepvn(SvPVX(s), buf[0].len);
1807              
1808 2           req->s = buf[0].base;
1809              
1810 2           err = uv_write(req->r, self->h, buf, 1, (uv_write_cb)on_req_cb);
1811              
1812 2 50         if(err != 0) {
1813 0           Safefree(req->s);
1814 0           Safefree(req);
1815 0           THROWERR("Couldn't write", err);
1816             }
1817              
1818 2           req->cb = newSVsv(cb);
1819              
1820 2           RETVAL = newSV(0);
1821 2           sv_setref_pv(RETVAL, "UV::Req", req);
1822 2           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
1823             OUTPUT:
1824             RETVAL
1825              
1826             MODULE = UV PACKAGE = UV::Timer
1827              
1828             SV *
1829             _new(char *class, UV::Loop loop)
1830             INIT:
1831             UV__Timer self;
1832             int err;
1833             CODE:
1834 33           NEW_UV__Handle(self, uv_timer_t);
1835              
1836 33           err = uv_timer_init(loop->loop, self->h);
1837 33 50         if (err != 0) {
1838 0           Safefree(self);
1839 0           THROWERR("Couldn't initialise timer handle", err);
1840             }
1841              
1842 33           INIT_UV__Handle(self);
1843 33           self->on_timer = NULL;
1844              
1845 33           RETVAL = newSV(0);
1846 33           sv_setref_pv(RETVAL, "UV::Timer", self);
1847 33           self->selfrv = SvRV(RETVAL); /* no inc */
1848             OUTPUT:
1849             RETVAL
1850              
1851             SV *
1852             _on_timer(UV::Timer self, SV *cb = NULL)
1853             CODE:
1854 35           RETVAL = do_callback_accessor(&self->on_timer, cb);
1855             OUTPUT:
1856             RETVAL
1857              
1858             void
1859             _start(UV::Timer self, UV timeout, UV repeat)
1860             CODE:
1861 35 50         CHECKCALL(uv_timer_start(self->h, on_timer_cb, timeout, repeat));
1862              
1863             UV
1864             _get_repeat(UV::Timer self)
1865             CODE:
1866 17           RETVAL = uv_timer_get_repeat(self->h);
1867             OUTPUT:
1868             RETVAL
1869              
1870             void
1871             _set_repeat(UV::Timer self, UV repeat)
1872             CODE:
1873 2           uv_timer_set_repeat(self->h, repeat);
1874              
1875             void
1876             again(UV::Timer self)
1877             CODE:
1878 11 100         CHECKCALL(uv_timer_again(self->h));
1879              
1880             void
1881             stop(UV::Timer self)
1882             CODE:
1883 33 50         CHECKCALL(uv_timer_stop(self->h));
1884              
1885             MODULE = UV PACKAGE = UV::TCP
1886              
1887             SV *
1888             _new(char *class, UV::Loop loop)
1889             INIT:
1890             UV__TCP self;
1891             int err;
1892             CODE:
1893 5           NEW_UV__Handle(self, uv_tcp_t);
1894              
1895 5           err = uv_tcp_init(loop->loop, self->h);
1896 5 50         if (err != 0) {
1897 0           Safefree(self);
1898 0           THROWERR("Couldn't initialise tcp handle", err);
1899             }
1900              
1901 5           INIT_UV__Handle(self);
1902 5           INIT_UV__Stream(self);
1903              
1904 5           RETVAL = newSV(0);
1905 5           sv_setref_pv(RETVAL, "UV::TCP", self);
1906 5           self->selfrv = SvRV(RETVAL); /* no inc */
1907             OUTPUT:
1908             RETVAL
1909              
1910             void
1911             _open(UV::TCP self, int fd)
1912             CODE:
1913 2 50         CHECKCALL(uv_tcp_open(self->h, fd));
1914              
1915             void
1916             nodelay(UV::TCP self, bool enable)
1917             CODE:
1918 0 0         CHECKCALL(uv_tcp_nodelay(self->h, enable));
1919              
1920             void
1921             keepalive(UV::TCP self, bool enable, unsigned int delay = 0)
1922             CODE:
1923 0 0         if(enable && items < 3)
    0          
1924 0           croak_xs_usage(cv, "self, enable=true, delay");
1925              
1926 0 0         CHECKCALL(uv_tcp_keepalive(self->h, enable, delay));
1927              
1928             void
1929             simultaneous_accepts(UV::TCP self, bool enable)
1930             CODE:
1931 0 0         CHECKCALL(uv_tcp_simultaneous_accepts(self->h, enable));
1932              
1933             void
1934             bind(UV::TCP self, SV *addr, int flags = 0)
1935             CODE:
1936 1 50         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    50          
1937 0           croak("Expected a packed socket address for addr");
1938              
1939 1 50         CHECKCALL(uv_tcp_bind(self->h, (struct sockaddr *)SvPVX(addr), flags));
1940              
1941             SV *
1942             connect(UV::TCP self, SV *addr, SV *cb)
1943             INIT:
1944             UV__Req_connect req;
1945             CODE:
1946 1           NEW_UV__Req(req, uv_connect_t);
1947 1           INIT_UV__Req(req);
1948              
1949 1 50         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    50          
1950 0           croak("Expected a packed socket address for addr");
1951              
1952 1           uv_tcp_connect(req->r, self->h, (struct sockaddr *)SvPVX(addr), (uv_connect_cb)on_req_cb);
1953              
1954 1           req->cb = newSVsv(cb);
1955              
1956 1           RETVAL = newSV(0);
1957 1           sv_setref_pv(RETVAL, "UV::Req", req);
1958 1           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
1959             OUTPUT:
1960             RETVAL
1961              
1962             SV *
1963             getpeername(UV::TCP self)
1964             ALIAS:
1965             getpeername = 0
1966             getsockname = 1
1967             INIT:
1968             int len;
1969             int err;
1970             CODE:
1971 2           len = sizeof(struct sockaddr_storage);
1972 2           RETVAL = newSV(len);
1973              
1974 2           err = (ix == 0) ?
1975 2 100         uv_tcp_getpeername(self->h, (struct sockaddr *)SvPVX(RETVAL), &len) :
1976 1           uv_tcp_getsockname(self->h, (struct sockaddr *)SvPVX(RETVAL), &len);
1977 2 50         if(err != 0) {
1978 0           SvREFCNT_dec(RETVAL);
1979 0 0         croak("Couldn't %s from tcp handle (%d): %s", (ix == 0) ? "getpeername" : "getsockname",
1980             err, uv_strerror(err));
1981             }
1982              
1983 2           SvCUR_set(RETVAL, len);
1984 2           SvPOK_on(RETVAL);
1985             OUTPUT:
1986             RETVAL
1987              
1988             void
1989             _close_reset(UV::TCP self)
1990             CODE:
1991 0 0         CHECKCALL(uv_tcp_close_reset(self->h, on_close_cb));
1992              
1993             MODULE = UV PACKAGE = UV::TTY
1994              
1995             SV *
1996             _new(char *class, UV::Loop loop, int fd)
1997             INIT:
1998             UV__TTY self;
1999             int err;
2000             CODE:
2001 0           NEW_UV__Handle(self, uv_tty_t);
2002              
2003 0           err = uv_tty_init(loop->loop, self->h, fd, 0);
2004 0 0         if (err != 0) {
2005 0           Safefree(self);
2006 0           THROWERR("Couldn't initialise tty handle", err);
2007             }
2008              
2009 0           INIT_UV__Handle(self);
2010 0           INIT_UV__Stream(self);
2011              
2012 0           RETVAL = newSV(0);
2013 0           sv_setref_pv(RETVAL, "UV::TTY", self);
2014 0           self->selfrv = SvRV(RETVAL); /* no inc */
2015             OUTPUT:
2016             RETVAL
2017              
2018             void
2019             set_mode(UV::TTY self, int mode)
2020             CODE:
2021 0 0         CHECKCALL(uv_tty_set_mode(self->h, mode));
2022              
2023             void
2024             get_winsize(UV::TTY self)
2025             INIT:
2026             int width, height;
2027             PPCODE:
2028 0 0         CHECKCALL(uv_tty_get_winsize(self->h, &width, &height));
2029 0 0         EXTEND(SP, 2);
2030 0           mPUSHi(width);
2031 0           mPUSHi(height);
2032 0           XSRETURN(2);
2033              
2034             MODULE = UV PACKAGE = UV::UDP
2035              
2036             SV *
2037             _new(char *class, UV::Loop loop)
2038             INIT:
2039             UV__UDP self;
2040             int err;
2041             CODE:
2042 5           NEW_UV__Handle(self, uv_udp_t);
2043              
2044 5           err = uv_udp_init(loop->loop, self->h);
2045 5 50         if (err != 0) {
2046 0           Safefree(self);
2047 0           THROWERR("Couldn't initialse udp handle", err);
2048             }
2049              
2050 5           INIT_UV__Handle(self);
2051 5           self->on_recv = NULL;
2052              
2053 5           RETVAL = newSV(0);
2054 5           sv_setref_pv(RETVAL, "UV::UDP", self);
2055 5           self->selfrv = SvRV(RETVAL); /* no inc */
2056             OUTPUT:
2057             RETVAL
2058              
2059             SV *
2060             _on_recv(UV::UDP self, SV *cb = NULL)
2061             CODE:
2062 2           RETVAL = do_callback_accessor(&self->on_recv, cb);
2063             OUTPUT:
2064             RETVAL
2065              
2066             void
2067             _open(UV::UDP self, int fd)
2068             CODE:
2069 2 50         CHECKCALL(uv_udp_open(self->h, fd));
2070              
2071             void
2072             bind(UV::UDP self, SV *addr, int flags = 0)
2073             CODE:
2074 1 50         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    50          
2075 0           croak("Expected a packed socket address for addr");
2076              
2077 1 50         CHECKCALL(uv_udp_bind(self->h, (struct sockaddr *)SvPVX(addr), flags));
2078              
2079             SV *
2080             connect(UV::UDP self, SV *addr)
2081             CODE:
2082 1 50         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    50          
2083 0           croak("Expected a packed socket address for addr");
2084              
2085 1 50         CHECKCALL(uv_udp_connect(self->h, (struct sockaddr *)SvPVX(addr)));
2086              
2087             SV *
2088             getpeername(UV::UDP self)
2089             ALIAS:
2090             getpeername = 0
2091             getsockname = 1
2092             INIT:
2093             int len;
2094             int err;
2095             CODE:
2096 2           len = sizeof(struct sockaddr_storage);
2097 2           RETVAL = newSV(len);
2098              
2099 2           err = (ix == 0) ?
2100 2 100         uv_udp_getpeername(self->h, (struct sockaddr *)SvPVX(RETVAL), &len) :
2101 1           uv_udp_getsockname(self->h, (struct sockaddr *)SvPVX(RETVAL), &len);
2102 2 50         if(err != 0) {
2103 0           SvREFCNT_dec(RETVAL);
2104 0 0         croak("Couldn't %s from udp handle (%d): %s", (ix == 0) ? "getpeername" : "getsockname",
2105             err, uv_strerror(err));
2106             }
2107              
2108 2           SvCUR_set(RETVAL, len);
2109 2           SvPOK_on(RETVAL);
2110             OUTPUT:
2111             RETVAL
2112              
2113             void
2114             recv_start(UV::UDP self)
2115             CODE:
2116 2 50         CHECKCALL(uv_udp_recv_start(self->h, on_alloc_cb, on_recv_cb));
2117              
2118             void
2119             recv_stop(UV::UDP self)
2120             CODE:
2121 0 0         CHECKCALL(uv_udp_recv_stop(self->h));
2122              
2123             SV *
2124             send(UV::UDP self, SV *s, ...)
2125             INIT:
2126             UV__Req_udp_send req;
2127             uv_buf_t buf[1];
2128             int err;
2129             SV *addr;
2130 2           struct sockaddr *sockaddr = NULL;
2131             SV *cb;
2132             CODE:
2133 2 50         if(items > 4)
2134 0           croak_xs_usage(cv, "self, s, [from], cb");
2135 2 50         else if(items == 4) {
2136 0           addr = ST(2);
2137 0           cb = ST(3);
2138             }
2139 2 100         else if(SvTYPE(SvRV(ST(2))) == SVt_PVCV) {
2140 1           addr = NULL;
2141 1           cb = ST(2);
2142             }
2143             else {
2144 1           addr = ST(2);
2145 1           cb = NULL;
2146             }
2147              
2148 2 100         if(addr) {
2149 1 50         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    50          
2150 0           croak("Expected a packed socket address for addr");
2151 1           sockaddr = (struct sockaddr *)SvPVX(addr);
2152             }
2153              
2154 2           NEW_UV__Req(req, uv_udp_send_t);
2155 2           INIT_UV__Req(req);
2156              
2157 2           buf[0].len = SvCUR(s);
2158 2           buf[0].base = savepvn(SvPVX(s), buf[0].len);
2159              
2160 2           req->s = buf[0].base;
2161              
2162 2           err = uv_udp_send(req->r, self->h, buf, 1, sockaddr,
2163             (uv_udp_send_cb)on_req_cb);
2164              
2165 2 50         if(err != 0) {
2166 0           Safefree(req->s);
2167 0           Safefree(req);
2168 0           THROWERR("Couldn't send", err);
2169             }
2170              
2171 2 100         if(cb)
2172 1           req->cb = newSVsv(cb);
2173             else
2174 1           req->cb = NULL;
2175              
2176 2           RETVAL = newSV(0);
2177 2           sv_setref_pv(RETVAL, "UV::Req", req);
2178 2           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
2179             OUTPUT:
2180             RETVAL
2181              
2182             void
2183             set_broadcast(UV::UDP self, bool on)
2184             CODE:
2185 0 0         CHECKCALL(uv_udp_set_broadcast(self->h, on));
2186              
2187             void
2188             set_ttl(UV::UDP self, int ttl)
2189             CODE:
2190 0 0         CHECKCALL(uv_udp_set_ttl(self->h, ttl));
2191              
2192             void
2193             set_multicast_loop(UV::UDP self, bool on)
2194             CODE:
2195 0 0         CHECKCALL(uv_udp_set_multicast_loop(self->h, on));
2196              
2197             void
2198             set_multicast_ttl(UV::UDP self, int ttl)
2199             CODE:
2200 0 0         CHECKCALL(uv_udp_set_multicast_ttl(self->h, ttl));
2201              
2202             void
2203             set_multicast_interface(UV::UDP self, SV *ifaddr)
2204             CODE:
2205 0 0         CHECKCALL(uv_udp_set_multicast_interface(self->h, SvPVbyte_nolen(ifaddr)));
    0          
2206              
2207             void
2208             set_membership(UV::UDP self, SV *mcaddr, SV *ifaddr, int membership)
2209             CODE:
2210 0 0         CHECKCALL(uv_udp_set_membership(
    0          
    0          
2211             self->h, SvPVbyte_nolen(mcaddr), SvPVbyte_nolen(ifaddr), membership));
2212              
2213             void
2214             set_source_membership(UV::UDP self, SV *mcaddr, SV *ifaddr, SV *srcaddr, int membership)
2215             CODE:
2216 0 0         CHECKCALL(uv_udp_set_source_membership(
    0          
    0          
    0          
2217             self->h, SvPVbyte_nolen(mcaddr), SvPVbyte_nolen(ifaddr), SvPVbyte_nolen(srcaddr), membership));
2218              
2219             void
2220             try_send(UV::UDP self, SV *s, ...)
2221             INIT:
2222             uv_buf_t buf[1];
2223             int err;
2224             SV *addr;
2225 1           struct sockaddr *sockaddr = NULL;
2226             CODE:
2227 1 50         if(items > 3)
2228 0           croak_xs_usage(cv, "self, s, [from]");
2229 1 50         else if(items == 3) {
2230 0           addr = ST(2);
2231             }
2232             else {
2233 1           addr = NULL;
2234             }
2235              
2236 1 50         if(addr) {
2237 0 0         if(!SvPOK(addr) || SvCUR(addr) < sizeof(struct sockaddr))
    0          
2238 0           croak("Expected a packed socket address for addr");
2239 0           sockaddr = (struct sockaddr *)SvPVX(addr);
2240             }
2241              
2242 1           buf[0].len = SvCUR(s);
2243 1           buf[0].base = savepvn(SvPVX(s), buf[0].len);
2244              
2245 1           err = uv_udp_try_send(self->h, buf, 1, sockaddr);
2246              
2247 1 50         if(err < 0) {
2248 0           THROWERR("Couldn't send", err);
2249             }
2250              
2251             UV
2252             get_send_queue_size(UV::UDP self)
2253             ALIAS:
2254             get_send_queue_size = 0
2255             get_send_queue_count = 1
2256             CODE:
2257 0           switch(ix) {
2258 0           case 0: RETVAL = uv_udp_get_send_queue_size(self->h); break;
2259 0           case 1: RETVAL = uv_udp_get_send_queue_count(self->h); break;
2260             }
2261             OUTPUT:
2262             RETVAL
2263              
2264             MODULE = UV PACKAGE = UV::Loop
2265              
2266             SV *
2267             _new(char *class, int want_default)
2268             INIT:
2269             UV__Loop self;
2270             int err;
2271             CODE:
2272 30 100         Newxc(self, sizeof(struct UV__Loop) + (!want_default * sizeof(uv_loop_t)),
2273             char, struct UV__Loop);
2274 30           self->on_walk = NULL;
2275              
2276 30 100         if(want_default) {
2277 26           self->loop = uv_default_loop();
2278             }
2279             else {
2280 4           self->loop = (uv_loop_t *)((char *)self + sizeof(struct UV__Loop));
2281 4           err = uv_loop_init(self->loop);
2282 4 50         if(err != 0) {
2283 0           Safefree(self);
2284 0           THROWERR("Couldn't initialise loop", err);
2285             }
2286             }
2287              
2288 30           RETVAL = newSV(0);
2289 30           sv_setref_pv(RETVAL, "UV::Loop", self);
2290             OUTPUT:
2291             RETVAL
2292              
2293             SV *
2294             _on_walk(UV::Loop self, SV *cb = NULL)
2295             CODE:
2296 35 50         if(cb && SvOK(cb)) {
    100          
    50          
    50          
2297 5           SvREFCNT_dec(self->on_walk);
2298              
2299 5           self->on_walk = newSVsv(cb);
2300             }
2301              
2302 35           RETVAL = newSVsv(self->on_walk);
2303             OUTPUT:
2304             RETVAL
2305              
2306             void
2307             _walk(UV::Loop self)
2308             CODE:
2309 5           uv_walk(self->loop, on_loop_walk, self->on_walk);
2310              
2311             bool
2312             alive(UV::Loop self)
2313             CODE:
2314 16           RETVAL = uv_loop_alive(self->loop);
2315             OUTPUT:
2316             RETVAL
2317              
2318             int
2319             backend_fd(UV::Loop self)
2320             CODE:
2321 0           RETVAL = uv_backend_fd(self->loop);
2322             OUTPUT:
2323             RETVAL
2324              
2325             int
2326             backend_timeout(UV::Loop self)
2327             CODE:
2328 4           RETVAL = uv_backend_timeout(self->loop);
2329             OUTPUT:
2330             RETVAL
2331              
2332             void
2333             DESTROY(UV::Loop self)
2334             CODE:
2335             /* Don't allow closing the default loop */
2336 38 100         if(self->loop != uv_default_loop())
2337 4           uv_loop_close(self->loop);
2338              
2339             void
2340             configure(UV::Loop self, int option, int value)
2341             CODE:
2342 1 50         CHECKCALL(uv_loop_configure(self->loop, option, value));
2343              
2344             bool
2345             is_default(UV::Loop self)
2346             CODE:
2347 8           RETVAL = (self->loop == uv_default_loop());
2348             OUTPUT:
2349             RETVAL
2350              
2351             UV
2352             now(UV::Loop self)
2353             CODE:
2354 1583           RETVAL = uv_now(self->loop);
2355             OUTPUT:
2356             RETVAL
2357              
2358             int
2359             run(UV::Loop self, int mode = UV_RUN_DEFAULT)
2360             CODE:
2361 1621           RETVAL = uv_run(self->loop, mode);
2362             OUTPUT:
2363             RETVAL
2364              
2365             void
2366             stop(UV::Loop self)
2367             CODE:
2368 0           uv_stop(self->loop);
2369              
2370             void
2371             update_time(UV::Loop self)
2372             CODE:
2373 11           uv_update_time(self->loop);
2374              
2375             SV *
2376             _getaddrinfo(UV::Loop self, char *node, char *service, SV *flags, SV *family, SV *socktype, SV *protocol, SV *cb)
2377             INIT:
2378             UV__Req_getaddrinfo req;
2379 2           struct addrinfo hints = { 0 };
2380             int err;
2381             CODE:
2382 2           NEW_UV__Req(req, uv_getaddrinfo_t);
2383 2           INIT_UV__Req(req);
2384              
2385 2 50         hints.ai_flags = SvOK(flags) ? SvIV(flags) : (AI_V4MAPPED|AI_ADDRCONFIG);
    50          
    50          
    0          
2386 2 50         hints.ai_family = SvOK(family) ? SvIV(family) : AF_UNSPEC;
    50          
    50          
    0          
2387 2 100         hints.ai_socktype = SvOK(socktype) ? SvIV(socktype) : 0;
    50          
    50          
    50          
2388 2 50         hints.ai_protocol = SvOK(protocol) ? SvIV(protocol) : 0;
    50          
    50          
    0          
2389              
2390 2           err = uv_getaddrinfo(self->loop, req->r, on_getaddrinfo_cb,
2391             node, service, &hints);
2392 2 50         if (err != 0) {
2393 0           Safefree(req);
2394 0           THROWERR("Couldn't getaddrinfo", err);
2395             }
2396              
2397 2           req->cb = newSVsv(cb);
2398              
2399 2           RETVAL = newSV(0);
2400 2           sv_setref_pv(RETVAL, "UV::Req", req);
2401 2           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
2402             OUTPUT:
2403             RETVAL
2404              
2405             SV *
2406             getnameinfo(UV::Loop self, SV *addr, int flags, SV *cb)
2407             INIT:
2408             UV__Req_getnameinfo req;
2409             int err;
2410             CODE:
2411 1           NEW_UV__Req(req, uv_getnameinfo_t);
2412 1           INIT_UV__Req(req);
2413              
2414 1 50         err = uv_getnameinfo(self->loop, req->r, on_getnameinfo_cb,
2415 1           (struct sockaddr *)SvPV_nolen(addr), flags);
2416 1 50         if (err != 0) {
2417 0           Safefree(req);
2418 0           THROWERR("Couldn't getnameinfo", err);
2419             }
2420              
2421 1           req->cb = newSVsv(cb);
2422              
2423 1           RETVAL = newSV(0);
2424 1           sv_setref_pv(RETVAL, "UV::Req", req);
2425 1           req->selfrv = SvREFCNT_inc(SvRV(RETVAL));
2426             OUTPUT:
2427             RETVAL
2428              
2429             MODULE = UV PACKAGE = UV::Req
2430              
2431             void
2432             DESTROY(UV::Req req)
2433             CODE:
2434 11           switch(req->r->type) {
2435             case UV_CONNECT:
2436 2           SvREFCNT_dec(((UV__Req_connect)req)->cb);
2437 2           break;
2438              
2439             case UV_GETADDRINFO:
2440 2           SvREFCNT_dec(((UV__Req_getaddrinfo)req)->cb);
2441 2           break;
2442              
2443             case UV_GETNAMEINFO:
2444 1           SvREFCNT_dec(((UV__Req_getnameinfo)req)->cb);
2445 1           break;
2446              
2447             case UV_SHUTDOWN:
2448 2           SvREFCNT_dec(((UV__Req_shutdown)req)->cb);
2449 2           break;
2450              
2451             case UV_WRITE:
2452 2           Safefree(((UV__Req_write)req)->s);
2453 2           SvREFCNT_dec(((UV__Req_write)req)->cb);
2454 2           break;
2455             }
2456              
2457 11           Safefree(req);
2458              
2459             void
2460             cancel(UV::Req req)
2461             INIT:
2462             int err;
2463             CODE:
2464 1           err = uv_cancel(req->r);
2465             /* Cancellation is best-effort; don't consider it an error if we get
2466             * EBUSY */
2467 1 50         if((err != 0) && (err != UV_EBUSY))
    0          
2468 0           THROWERR("Couldn't cancel", err);
2469              
2470             MODULE = UV PACKAGE = UV::getaddrinfo_result
2471              
2472             void
2473             DESTROY(UV::getaddrinfo_result self)
2474             CODE:
2475 1           Safefree(self);
2476              
2477             int
2478             family(UV::getaddrinfo_result self)
2479             ALIAS:
2480             family = 0
2481             socktype = 1
2482             protocol = 2
2483             CODE:
2484 3           switch(ix) {
2485 1           case 0: RETVAL = self->family; break;
2486 1           case 1: RETVAL = self->socktype; break;
2487 1           case 2: RETVAL = self->protocol; break;
2488             }
2489             OUTPUT:
2490             RETVAL
2491              
2492             SV *
2493             addr(UV::getaddrinfo_result self)
2494             ALIAS:
2495             addr = 0
2496             canonname = 1
2497             CODE:
2498 1           switch(ix) {
2499 1           case 0: RETVAL = newSVpvn((char *)self->addr, self->addrlen); break;
2500 0 0         case 1: RETVAL = self->canonname ? newSVpv(self->canonname, 0) : &PL_sv_undef; break;
2501             }
2502             OUTPUT:
2503             RETVAL