1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4 
5 #include <fcntl.h>
6 #include <sys/types.h>
7 #include <sys/socket.h>
8 #include <errno.h>
9 
10 #ifndef EWOULDBLOCK
11 #define EWOULDBLOCK EAGAIN
12 #endif
13 
14 MODULE = POSIX::Socket    PACKAGE = POSIX::Socket   PREFIX = smh
15 
16 IV
17 smh_close(fd)
18     IV fd
19 
20     PROTOTYPE: DISABLE
21 
22     CODE:
23     RETVAL = close(fd);
24     OUTPUT:
25     RETVAL
26 
27 IV
28 smh_socket(socket_family, socket_type, protocol)
29     IV socket_family;
30     IV socket_type;
31     IV protocol;
32 
33     PROTOTYPE: DISABLE
34 
35     CODE:
36     RETVAL = socket(socket_family, socket_type, protocol);
37     OUTPUT:
38     RETVAL
39 
40 #ifndef WIN32
41 
42 IV
43 smh_fcntl(fildes, cmd, arg)
44     IV fildes;
45     IV cmd;
46     IV arg;
47 
48     PROTOTYPE: DISABLE
49 
50     CODE:
51     RETVAL = fcntl(fildes, cmd, arg);
52     OUTPUT:
53     RETVAL
54 
55 #endif
56 
57 IV
58 smh_bind(fd, addr)
59     IV fd;
60     SV * addr;
61 
62     PROTOTYPE: DISABLE
63     PREINIT:
64     STRLEN addrlen;
65     char *sockaddr_pv = SvPVbyte(addr, addrlen);
66 
67     CODE:
68     RETVAL = bind(fd, (struct sockaddr*)sockaddr_pv, addrlen);
69     OUTPUT:
70     RETVAL
71 
72 IV
73 smh_connect(fd, addr)
74     IV fd;
75     SV * addr;
76 
77     PROTOTYPE: DISABLE
78     PREINIT:
79     STRLEN addrlen;
80     char *sockaddr_pv = SvPVbyte(addr, addrlen);
81 
82     CODE:
83     RETVAL = connect(fd, (struct sockaddr*)sockaddr_pv, addrlen);
84     OUTPUT:
85     RETVAL
86 
87 IV
88 smh_recv(fd, sv_buffer, len, flags)
89     IV fd;
90     SV * sv_buffer;
91     IV len;
92     IV flags;
93 
94     PREINIT:
95     int count;
96 
97     PROTOTYPE: DISABLE
98 
99     CODE:
100     if (!SvOK(sv_buffer)) {
101          sv_setpvn(sv_buffer, "", 0);
102     }
103     SvUPGRADE((SV*)ST(1), SVt_PV);
104     sv_buffer = (SV*)SvGROW((SV*)ST(1), len);
105     count = recv(fd, (void*)sv_buffer, len, flags);
106     if (count >= 0)
107     {
108         SvCUR_set((SV*)ST(1), count);
109         SvTAINT(ST(1));
110         SvSETMAGIC(ST(1));
111     }
112     RETVAL = count;
113 
114     OUTPUT:
115     RETVAL
116 
117 IV
118 smh_recvfrom(fd, sv_buffer, len, flags, sv_sock_addr)
119     IV fd;
120     SV * sv_buffer;
121     IV len;
122     IV flags;
123 	SV * sv_sock_addr;
124 
125     PREINIT:
126     int count;
127 	int fromSockSize = sizeof(struct sockaddr);
128 
129     PROTOTYPE: DISABLE
130 
131     CODE:
132     if (!SvOK(sv_buffer)) {
133          sv_setpvn(sv_buffer, "", 0);
134     }
135     SvUPGRADE((SV*)ST(1), SVt_PV);
136     sv_buffer = (SV*)SvGROW((SV*)ST(1), len);
137 
138 	if (!SvOK(sv_sock_addr)) {
139          sv_setpvn(sv_sock_addr, "", 0);
140     }
141     SvUPGRADE((SV*)ST(4), SVt_PV);
142     sv_sock_addr = (SV*)SvGROW((SV*)ST(4), fromSockSize);
143 
144     count = recvfrom( fd, (void*)sv_buffer, len, flags, (struct sockaddr*)sv_sock_addr, &fromSockSize );
145     if (count >= 0)
146     {
147         SvCUR_set((SV*)ST(1), count);
148         SvTAINT(ST(1));
149         SvSETMAGIC(ST(1));
150 
151 		SvCUR_set((SV*)ST(4), fromSockSize);
152         SvTAINT(ST(4));
153         SvSETMAGIC(ST(4));
154     }
155     RETVAL = count;
156 
157     OUTPUT:
158 	sv_sock_addr
159     RETVAL
160 
161 IV
162 smh_recvn(fd, sv_buffer, len, flags)
163     IV fd;
164     SV * sv_buffer;
165     IV len;
166     IV flags;
167 
168     PREINIT:
169     int nrecv;
170     int nleft = len;
171     void * ptr;
172 
173     PROTOTYPE: DISABLE
174 
175     CODE:
176     if (!SvOK(sv_buffer)) {
177          sv_setpvn(sv_buffer, "", 0);
178     }
179     SvUPGRADE((SV*)ST(1), SVt_PV);
180     sv_buffer = (SV*)SvGROW((SV*)ST(1), len);
181     ptr = (void *) sv_buffer;
182     RETVAL = len;
183     while (nleft > 0)
184     {
185         nrecv = recv(fd, ptr, nleft, flags);
186         if (nrecv == -1)
187         {
188             if ((errno == EAGAIN) || (errno == EINTR) || (errno == EWOULDBLOCK))
189             {
190                 continue;
191             } else {
192                 RETVAL = -1;
193                 break;
194             }
195         }
196         else if (nrecv == 0)
197         {
198             RETVAL = 0;
199             break;
200         }
201         else
202         {
203             nleft -= nrecv;
204             ptr += nrecv;
205         }
206 
207     }
208     SvCUR_set((SV*)ST(1), len-nleft);
209     SvTAINT(ST(1));
210     SvSETMAGIC(ST(1));
211 
212     OUTPUT:
213     RETVAL
214 
215 
216 IV
217 smh_getsockname(fd, sv_sock_addr)
218     IV fd;
219     SV * sv_sock_addr;
220 
221     PREINIT:
222     int count = sizeof(struct sockaddr);
223     char * sock_addr;
224 
225     PROTOTYPE: DISABLE
226 
227     CODE:
228     if (!SvOK(sv_sock_addr)) {
229          sv_setpvn(sv_sock_addr, "", 0);
230     }
231     SvUPGRADE((SV*)ST(1), SVt_PV);
232     sv_sock_addr = (SV*)SvGROW((SV*)ST(1), count);
233     RETVAL = getsockname(fd, (struct sockaddr*)sv_sock_addr, &count);
234     if (count >= 0)
235     {
236         SvCUR_set((SV*)ST(1), count);
237         SvTAINT(ST(1));
238         SvSETMAGIC(ST(1));
239     }
240 
241     OUTPUT:
242     RETVAL
243 
244 
245 IV
smh_getsockopt(fd,level,optname,optval,optlen)246 smh_getsockopt(fd, level, optname, optval, optlen)
247     IV fd;
248     IV level;
249     IV optname;
250     SV * optval;
251     int optlen;
252 
253     PREINIT:
254 
255     PROTOTYPE: DISABLE
256 
257     CODE:
258     if (!SvOK(optval)) {
259          sv_setpvn(optval, "", 0);
260     }
261     SvUPGRADE((SV*)ST(3), SVt_PV);
262     optval = (SV*)SvGROW((SV*)ST(3), optlen);
263     if (RETVAL = getsockopt(fd, level, optname, (void*)optval, (socklen_t*)&optlen) != -1)
264     {
265         SvCUR_set((SV*)ST(3), optlen);
266         SvTAINT(ST(3));
267         SvSETMAGIC(ST(3));
268     }
269 
270     OUTPUT:
271     RETVAL
272 
273 
274 IV
275 smh_setsockopt(fd, level, optname, optval)
276     IV fd;
277     IV level;
278     IV optname;
279     SV * optval;
280 
281     PREINIT:
282     STRLEN len;
283     char *msg = SvPVbyte(optval,len);
284 
285     PROTOTYPE: DISABLE
286 
287     CODE:
288     RETVAL = setsockopt(fd, level, optname, (void*)msg, len);
289 
290     OUTPUT:
291     RETVAL
292 
293 
294 IV
295 smh_send(fd, buf, flags)
296     IV fd;
297     SV * buf;
298     IV flags;
299 
300     PROTOTYPE: DISABLE
301     PREINIT:
302     STRLEN len;
303     char *msg = SvPVbyte(buf, len);
304 
305 
306     CODE:
307     RETVAL = send(fd, msg, len, flags);
308     OUTPUT:
309 
310 IV
311 smh_sendn(fd, buf, flags)
312     IV fd;
313     SV * buf;
314     IV flags;
315 
316     PROTOTYPE: DISABLE
317 
318     PREINIT:
319     STRLEN len;
320     char *msg = SvPVbyte(buf, len);
321     int nwritten;
322     int nleft = len;
323 
324     CODE:
325     RETVAL = len;
326     while (nleft > 0)
327     {
328         nwritten = send(fd, msg, nleft, flags);
329         if (nwritten == -1)
330         {
331             if ((errno == EAGAIN) || (errno == EINTR) || (errno == EWOULDBLOCK))
332             {
333                 continue;
334             } else {
335                 RETVAL = -1;
336                 break;
337             }
338         }
339         else
340         {
341             nleft -= nwritten;
342             msg += nwritten;
343         }
344     }
345 
346     OUTPUT:
347     RETVAL
348 
349 
350 IV
351 smh_sendto(fd, buf, flags, dest_addr)
352     IV fd;
353     SV * buf;
354     IV flags;
355     SV * dest_addr;
356 
357     PROTOTYPE: DISABLE
358     PREINIT:
359     STRLEN addrlen;
360     STRLEN len;
361     char *msg = SvPVbyte(buf,len);
362     char *sockaddr_pv = SvPVbyte(dest_addr, addrlen);
363 
364 
365     CODE:
366     RETVAL = sendto(fd, msg, len, flags, (struct sockaddr*)sockaddr_pv, addrlen);
367     OUTPUT:
368     RETVAL
369 
370 IV
371 smh_accept(fd)
372     IV fd;
373 
374     PROTOTYPE: DISABLE
375 
376     CODE:
377     RETVAL = accept(fd, NULL, NULL);
378     OUTPUT:
379     RETVAL
380 
381 IV
382 smh_listen(fd, backlog)
383     IV fd;
384     IV backlog;
385 
386     PROTOTYPE: DISABLE
387 
388     CODE:
389     RETVAL = listen(fd, backlog);
390     OUTPUT:
391     RETVAL
392 
393