File Coverage

lib/UV.xs
Criterion Covered Total %
statement 835 961 86.8
branch 291 656 44.3
condition n/a
subroutine n/a
pod n/a
total 1126 1617 69.6


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