File Coverage

FDpassData.xs
Criterion Covered Total %
statement 62 69 89.8
branch 40 60 66.6
condition n/a
subroutine n/a
pod n/a
total 102 129 79.0


line stmt bran cond sub pod time code
1             #ifdef __sun
2             #define _XOPEN_SOURCE 1
3             #define _XOPEN_SOURCE_EXTENDED 1
4             #define __EXTENSIONS__ 1
5             #endif
6              
7             #include "EXTERN.h"
8             #include "perl.h"
9             #include "XSUB.h"
10              
11             #include // needed by broken bsds for NULL used in sys/uio.h
12             #include
13             #include
14             #include
15             #include
16             #include
17              
18             #ifndef CMSG_SPACE
19             # define CMSG_SPACE(len) (sizeof (struct cmsghdr) + len)
20             #endif
21              
22             #ifndef CMSG_LEN
23             # define CMSG_LEN(len) (sizeof (struct cmsghdr) + len)
24             #endif
25              
26             int
27 5           _fd_sendata (int socket, void * buf, int len, int fd)
28             {
29              
30             int size;
31             struct msghdr msg;
32             struct iovec iov;
33             struct cmsghdr *cmsg;
34             union {
35             struct cmsghdr cmsghdr;
36             char control[CMSG_SPACE(sizeof (int))];
37             } cmsgu;
38              
39 5           iov.iov_base = buf;
40 5           iov.iov_len = len;
41              
42 5           msg.msg_name = NULL;
43 5           msg.msg_namelen = 0;
44 5           msg.msg_iov = &iov;
45 5           msg.msg_iovlen = 1;
46              
47 5 100         if (fd >= 0) {
48 3           msg.msg_control = cmsgu.control;
49 3           msg.msg_controllen = sizeof(cmsgu.control);
50              
51 3 50         cmsg = CMSG_FIRSTHDR(&msg);
52 3           cmsg->cmsg_len = CMSG_LEN(sizeof (int));
53 3           cmsg->cmsg_level = SOL_SOCKET;
54 3           cmsg->cmsg_type = SCM_RIGHTS;
55              
56             //printf ("passing fd %d\n", fd);
57 3           *((int *) CMSG_DATA(cmsg)) = fd;
58             } else {
59 2           msg.msg_control = NULL;
60 2           msg.msg_controllen = 0;
61             //printf ("not passing fd\n");
62             }
63              
64 5           size = sendmsg(socket, &msg, 0);
65              
66 5           return size;
67             }
68              
69             int
70 5           _fd_recvdata (int socket, void * buf, int len, int * fd)
71             {
72              
73             int size;
74              
75 5 50         if (fd) {
76             struct msghdr msg;
77             struct iovec iov;
78             struct cmsghdr *cmsg;
79              
80             union {
81             struct cmsghdr cmsghdr;
82             char control[CMSG_SPACE(sizeof (int))];
83             } cmsgu;
84              
85 5           iov.iov_base = buf;
86 5           iov.iov_len = len;
87              
88 5           msg.msg_name = NULL;
89 5           msg.msg_namelen = 0;
90 5           msg.msg_iov = &iov;
91 5           msg.msg_iovlen = 1;
92 5           msg.msg_control = cmsgu.control;
93 5           msg.msg_controllen = sizeof(cmsgu.control);
94              
95 5           size = recvmsg (socket, &msg, 0);
96              
97 5 50         if (size < 0) {
98             //fprintf(stderr, "sock %d , size to small\n",socket);
99             //perror(strerror(errno));
100 0           return -1;
101             }
102              
103 5 100         cmsg = CMSG_FIRSTHDR(&msg);
104 5 100         if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int))) {
    50          
105 3 50         if (cmsg->cmsg_level != SOL_SOCKET) {
106             //fprintf (stderr, "invalid cmsg_level %d\n", cmsg->cmsg_level);
107 0           return -1;
108             }
109 3 50         else if (cmsg->cmsg_type != SCM_RIGHTS) {
110             //fprintf (stderr, "invalid cmsg_type %d\n", cmsg->cmsg_type);
111 0           return -1;
112             }
113 3           *fd = *((int *) CMSG_DATA(cmsg));
114             //printf ("received fd %d\n", *fd);
115             } else {
116 5           *fd = -1;
117             }
118             } else {
119 0           size = read (socket, buf, len);
120 0           *fd = -1;
121             }
122 5           return size;
123             }
124              
125             MODULE = IO::FDpassData PACKAGE = IO::FDpassData
126              
127             PROTOTYPES: ENABLED
128              
129             int
130             fd_sendata (socket, b, ...)
131             int socket
132             SV * b
133             INIT:
134 5           STRLEN len = 1;
135 5           unsigned char * buf = "\0"; // preset to empty string if message buffer is 'undef'
136             int fd;
137             CODE:
138 5 100         if (SvOK(b) && SvPOK(b)) {
    50          
    50          
    50          
139 4 50         buf = (unsigned char *) SvPV(b,len);
140 4 100         if (len == 0) // zero length string "\0"
141 1           len = 1;
142             }
143 5 100         if (items == 3 && SvOK(ST(2)) && SvIOK(ST(2))) {
    100          
    50          
    50          
    50          
144 3 50         fd = (int)SvIV(ST(2));
145             } else {
146 2           fd = -1;
147             }
148 5           RETVAL = _fd_sendata(socket, buf, len, fd);
149             OUTPUT:
150             RETVAL
151              
152              
153             void
154             fd_recvdata (sock, len)
155             int sock
156             int len
157             PREINIT:
158             int fd, size;
159 5           unsigned char * buf = malloc(len);
160             PPCODE:
161 5           size = _fd_recvdata(sock, buf, len, &fd);
162 5 50         if (size < 0) { // ERROR
163 0           free(buf);
164 0           XSRETURN_EMPTY;
165             }
166 5 100         if (size == 1 && buf[0] == 0x0) {
    50          
167 2           size = 0;
168             }
169 5 50         XPUSHs(sv_2mortal(newSViv(size)));
170 5 100         if (size == 0) {
171 2 50         XPUSHs(sv_2mortal(newSVpvn(buf,0)));
172             } else {
173 3 50         XPUSHs(sv_2mortal(newSVpvn(buf,size)));
174             }
175 5           free(buf);
176 5 100         if (fd < 0) {
177 2           XSRETURN(2);
178             }
179 3 50         XPUSHs(sv_2mortal(newSViv(fd)));
180 5           XSRETURN(3);