Mercurial > repo
comparison perl-5.22.2/win32/win32sck.c @ 8045:a16537d2fe07
<xfix> tar xf perl-5.22.2.tar.gz # Ah, whatever, I\'m doing it anyway
author | HackBot |
---|---|
date | Sat, 14 May 2016 14:54:38 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
8044:711c038a7dce | 8045:a16537d2fe07 |
---|---|
1 /* win32sck.c | |
2 * | |
3 * (c) 1995 Microsoft Corporation. All rights reserved. | |
4 * Developed by hip communications inc. | |
5 * Portions (c) 1993 Intergraph Corporation. All rights reserved. | |
6 * | |
7 * You may distribute under the terms of either the GNU General Public | |
8 * License or the Artistic License, as specified in the README file. | |
9 */ | |
10 | |
11 #define WIN32IO_IS_STDIO | |
12 #define WIN32SCK_IS_STDSCK | |
13 #define WIN32_LEAN_AND_MEAN | |
14 #define PERLIO_NOT_STDIO 0 | |
15 #ifdef __GNUC__ | |
16 #define Win32_Winsock | |
17 #endif | |
18 #include <windows.h> | |
19 #include <ws2spi.h> | |
20 | |
21 #include "EXTERN.h" | |
22 #include "perl.h" | |
23 | |
24 #include "Win32iop.h" | |
25 #include <sys/socket.h> | |
26 #include <fcntl.h> | |
27 #include <sys/stat.h> | |
28 #include <assert.h> | |
29 #include <io.h> | |
30 | |
31 /* thanks to Beverly Brown (beverly@datacube.com) */ | |
32 #define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) | |
33 #define TO_SOCKET(x) _get_osfhandle(x) | |
34 | |
35 #define StartSockets() \ | |
36 STMT_START { \ | |
37 if (!wsock_started) \ | |
38 start_sockets(); \ | |
39 } STMT_END | |
40 | |
41 #define SOCKET_TEST(x, y) \ | |
42 STMT_START { \ | |
43 StartSockets(); \ | |
44 if((x) == (y)) \ | |
45 errno = get_last_socket_error(); \ | |
46 } STMT_END | |
47 | |
48 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) | |
49 | |
50 static int get_last_socket_error(void); | |
51 static struct servent* win32_savecopyservent(struct servent*d, | |
52 struct servent*s, | |
53 const char *proto); | |
54 | |
55 static int wsock_started = 0; | |
56 | |
57 #ifdef WIN32_DYN_IOINFO_SIZE | |
58 EXTERN_C Size_t w32_ioinfo_size; | |
59 #endif | |
60 | |
61 EXTERN_C void | |
62 EndSockets(void) | |
63 { | |
64 if (wsock_started) | |
65 WSACleanup(); | |
66 } | |
67 | |
68 /* Translate WSAExxx values to corresponding Exxx values where possible. Not all | |
69 * WSAExxx constants have corresponding Exxx constants in <errno.h> (even in | |
70 * VC++ 2010 and above, which have expanded <errno.h> with more values), but | |
71 * most missing constants are provided by win32/include/sys/errno2.h. The few | |
72 * that are not are returned unchanged. | |
73 * | |
74 * The list of possible WSAExxx values used here comes from the MSDN page | |
75 * titled "Windows Sockets Error Codes". | |
76 * | |
77 * (Note: Only the WSAExxx values are handled here; other WSAxxx values are | |
78 * returned unchanged. The return value normally ends up in errno/$! and at | |
79 * the Perl code level may be tested against the Exxx constants exported by | |
80 * the Errno and POSIX modules, which have never handled the other WSAxxx | |
81 * values themselves, apparently without any ill effect so far.) | |
82 */ | |
83 int | |
84 convert_wsa_error_to_errno(int wsaerr) | |
85 { | |
86 switch (wsaerr) { | |
87 case WSAEINTR: | |
88 return EINTR; | |
89 case WSAEBADF: | |
90 return EBADF; | |
91 case WSAEACCES: | |
92 return EACCES; | |
93 case WSAEFAULT: | |
94 return EFAULT; | |
95 case WSAEINVAL: | |
96 return EINVAL; | |
97 case WSAEMFILE: | |
98 return EMFILE; | |
99 case WSAEWOULDBLOCK: | |
100 return EWOULDBLOCK; | |
101 case WSAEINPROGRESS: | |
102 return EINPROGRESS; | |
103 case WSAEALREADY: | |
104 return EALREADY; | |
105 case WSAENOTSOCK: | |
106 return ENOTSOCK; | |
107 case WSAEDESTADDRREQ: | |
108 return EDESTADDRREQ; | |
109 case WSAEMSGSIZE: | |
110 return EMSGSIZE; | |
111 case WSAEPROTOTYPE: | |
112 return EPROTOTYPE; | |
113 case WSAENOPROTOOPT: | |
114 return ENOPROTOOPT; | |
115 case WSAEPROTONOSUPPORT: | |
116 return EPROTONOSUPPORT; | |
117 case WSAESOCKTNOSUPPORT: | |
118 return ESOCKTNOSUPPORT; | |
119 case WSAEOPNOTSUPP: | |
120 return EOPNOTSUPP; | |
121 case WSAEPFNOSUPPORT: | |
122 return EPFNOSUPPORT; | |
123 case WSAEAFNOSUPPORT: | |
124 return EAFNOSUPPORT; | |
125 case WSAEADDRINUSE: | |
126 return EADDRINUSE; | |
127 case WSAEADDRNOTAVAIL: | |
128 return EADDRNOTAVAIL; | |
129 case WSAENETDOWN: | |
130 return ENETDOWN; | |
131 case WSAENETUNREACH: | |
132 return ENETUNREACH; | |
133 case WSAENETRESET: | |
134 return ENETRESET; | |
135 case WSAECONNABORTED: | |
136 return ECONNABORTED; | |
137 case WSAECONNRESET: | |
138 return ECONNRESET; | |
139 case WSAENOBUFS: | |
140 return ENOBUFS; | |
141 case WSAEISCONN: | |
142 return EISCONN; | |
143 case WSAENOTCONN: | |
144 return ENOTCONN; | |
145 case WSAESHUTDOWN: | |
146 return ESHUTDOWN; | |
147 case WSAETOOMANYREFS: | |
148 return ETOOMANYREFS; | |
149 case WSAETIMEDOUT: | |
150 return ETIMEDOUT; | |
151 case WSAECONNREFUSED: | |
152 return ECONNREFUSED; | |
153 case WSAELOOP: | |
154 return ELOOP; | |
155 case WSAENAMETOOLONG: | |
156 return ENAMETOOLONG; | |
157 case WSAEHOSTDOWN: | |
158 return WSAEHOSTDOWN; /* EHOSTDOWN is not defined */ | |
159 case WSAEHOSTUNREACH: | |
160 return EHOSTUNREACH; | |
161 case WSAENOTEMPTY: | |
162 return ENOTEMPTY; | |
163 case WSAEPROCLIM: | |
164 return EPROCLIM; | |
165 case WSAEUSERS: | |
166 return EUSERS; | |
167 case WSAEDQUOT: | |
168 return EDQUOT; | |
169 case WSAESTALE: | |
170 return ESTALE; | |
171 case WSAEREMOTE: | |
172 return EREMOTE; | |
173 case WSAEDISCON: | |
174 return WSAEDISCON; /* EDISCON is not defined */ | |
175 case WSAENOMORE: | |
176 return WSAENOMORE; /* ENOMORE is not defined */ | |
177 #ifdef WSAECANCELLED | |
178 case WSAECANCELLED: /* New in WinSock2 */ | |
179 return ECANCELED; | |
180 #endif | |
181 case WSAEINVALIDPROCTABLE: | |
182 return WSAEINVALIDPROCTABLE; /* EINVALIDPROCTABLE is not defined */ | |
183 case WSAEINVALIDPROVIDER: | |
184 return WSAEINVALIDPROVIDER; /* EINVALIDPROVIDER is not defined */ | |
185 case WSAEPROVIDERFAILEDINIT: | |
186 return WSAEPROVIDERFAILEDINIT; /* EPROVIDERFAILEDINIT is not defined */ | |
187 case WSAEREFUSED: | |
188 return WSAEREFUSED; /* EREFUSED is not defined */ | |
189 } | |
190 | |
191 return wsaerr; | |
192 } | |
193 | |
194 #ifdef ERRNO_HAS_POSIX_SUPPLEMENT | |
195 /* Translate Exxx values in the POSIX supplement range defined in VC++ 2010 and | |
196 * above (EADDRINUSE <= err <= EWOULDBLOCK) to corresponding WSAExxx values. Not | |
197 * all such Exxx constants have corresponding WSAExxx constants in <winsock*.h>; | |
198 * we just use ERROR_INVALID_FUNCTION for those that are missing but do not | |
199 * really expect to encounter them anyway in the context in which this function | |
200 * is called. | |
201 * Some versions of MinGW/gcc-4.8 and above also define most, but not all, of | |
202 * these extra Exxx values. The missing ones are all cases for which there is no | |
203 * corresponding WSAExxx constant anyway, so we simply omit the cases for them | |
204 * here. | |
205 * Other Exxx values (err < sys_nerr) are returned unchanged. | |
206 */ | |
207 int | |
208 convert_errno_to_wsa_error(int err) | |
209 { | |
210 switch (err) { | |
211 case EADDRINUSE: | |
212 return WSAEADDRINUSE; | |
213 case EADDRNOTAVAIL: | |
214 return WSAEADDRNOTAVAIL; | |
215 case EAFNOSUPPORT: | |
216 return WSAEAFNOSUPPORT; | |
217 case EALREADY: | |
218 return WSAEALREADY; | |
219 #ifdef EBADMSG | |
220 case EBADMSG: /* Not defined in gcc-4.8.0 */ | |
221 return ERROR_INVALID_FUNCTION; | |
222 #endif | |
223 case ECANCELED: | |
224 #ifdef WSAECANCELLED | |
225 return WSAECANCELLED; /* New in WinSock2 */ | |
226 #else | |
227 return ERROR_INVALID_FUNCTION; | |
228 #endif | |
229 case ECONNABORTED: | |
230 return WSAECONNABORTED; | |
231 case ECONNREFUSED: | |
232 return WSAECONNREFUSED; | |
233 case ECONNRESET: | |
234 return WSAECONNRESET; | |
235 case EDESTADDRREQ: | |
236 return WSAEDESTADDRREQ; | |
237 case EHOSTUNREACH: | |
238 return WSAEHOSTUNREACH; | |
239 #ifdef EIDRM | |
240 case EIDRM: /* Not defined in gcc-4.8.0 */ | |
241 return ERROR_INVALID_FUNCTION; | |
242 #endif | |
243 case EINPROGRESS: | |
244 return WSAEINPROGRESS; | |
245 case EISCONN: | |
246 return WSAEISCONN; | |
247 case ELOOP: | |
248 return WSAELOOP; | |
249 case EMSGSIZE: | |
250 return WSAEMSGSIZE; | |
251 case ENETDOWN: | |
252 return WSAENETDOWN; | |
253 case ENETRESET: | |
254 return WSAENETRESET; | |
255 case ENETUNREACH: | |
256 return WSAENETUNREACH; | |
257 case ENOBUFS: | |
258 return WSAENOBUFS; | |
259 #ifdef ENODATA | |
260 case ENODATA: /* Not defined in gcc-4.8.0 */ | |
261 return ERROR_INVALID_FUNCTION; | |
262 #endif | |
263 #ifdef ENOLINK | |
264 case ENOLINK: /* Not defined in gcc-4.8.0 */ | |
265 return ERROR_INVALID_FUNCTION; | |
266 #endif | |
267 #ifdef ENOMSG | |
268 case ENOMSG: /* Not defined in gcc-4.8.0 */ | |
269 return ERROR_INVALID_FUNCTION; | |
270 #endif | |
271 case ENOPROTOOPT: | |
272 return WSAENOPROTOOPT; | |
273 #ifdef ENOSR | |
274 case ENOSR: /* Not defined in gcc-4.8.0 */ | |
275 return ERROR_INVALID_FUNCTION; | |
276 #endif | |
277 #ifdef ENOSTR | |
278 case ENOSTR: /* Not defined in gcc-4.8.0 */ | |
279 return ERROR_INVALID_FUNCTION; | |
280 #endif | |
281 case ENOTCONN: | |
282 return WSAENOTCONN; | |
283 #ifdef ENOTRECOVERABLE | |
284 case ENOTRECOVERABLE: /* Not defined in gcc-4.8.0 */ | |
285 return ERROR_INVALID_FUNCTION; | |
286 #endif | |
287 case ENOTSOCK: | |
288 return WSAENOTSOCK; | |
289 case ENOTSUP: | |
290 return ERROR_INVALID_FUNCTION; | |
291 case EOPNOTSUPP: | |
292 return WSAEOPNOTSUPP; | |
293 #ifdef EOTHER | |
294 case EOTHER: /* Not defined in gcc-4.8.0 */ | |
295 return ERROR_INVALID_FUNCTION; | |
296 #endif | |
297 case EOVERFLOW: | |
298 return ERROR_INVALID_FUNCTION; | |
299 case EOWNERDEAD: | |
300 return ERROR_INVALID_FUNCTION; | |
301 case EPROTO: | |
302 return ERROR_INVALID_FUNCTION; | |
303 case EPROTONOSUPPORT: | |
304 return WSAEPROTONOSUPPORT; | |
305 case EPROTOTYPE: | |
306 return WSAEPROTOTYPE; | |
307 #ifdef ETIME | |
308 case ETIME: /* Not defined in gcc-4.8.0 */ | |
309 return ERROR_INVALID_FUNCTION; | |
310 #endif | |
311 case ETIMEDOUT: | |
312 return WSAETIMEDOUT; | |
313 #ifdef ETXTBSY | |
314 case ETXTBSY: /* Not defined in gcc-4.8.0 */ | |
315 return ERROR_INVALID_FUNCTION; | |
316 #endif | |
317 case EWOULDBLOCK: | |
318 return WSAEWOULDBLOCK; | |
319 } | |
320 | |
321 return err; | |
322 } | |
323 #endif /* ERRNO_HAS_POSIX_SUPPLEMENT */ | |
324 | |
325 static int | |
326 get_last_socket_error(void) | |
327 { | |
328 return convert_wsa_error_to_errno(WSAGetLastError()); | |
329 } | |
330 | |
331 void | |
332 start_sockets(void) | |
333 { | |
334 unsigned short version; | |
335 WSADATA retdata; | |
336 int ret; | |
337 | |
338 /* | |
339 * initalize the winsock interface and insure that it is | |
340 * cleaned up at exit. | |
341 */ | |
342 version = 0x2; | |
343 if(ret = WSAStartup(version, &retdata)) | |
344 Perl_croak_nocontext("Unable to locate winsock library!\n"); | |
345 if(retdata.wVersion != version) | |
346 Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); | |
347 | |
348 /* atexit((void (*)(void)) EndSockets); */ | |
349 wsock_started = 1; | |
350 } | |
351 | |
352 /* in no sockets Win32 builds, these use the inline functions defined in | |
353 * perl.h | |
354 */ | |
355 u_long | |
356 win32_htonl(u_long hostlong) | |
357 { | |
358 #ifndef WIN32_NO_SOCKETS | |
359 StartSockets(); | |
360 #endif | |
361 return htonl(hostlong); | |
362 } | |
363 | |
364 u_short | |
365 win32_htons(u_short hostshort) | |
366 { | |
367 #ifndef WIN32_NO_SOCKETS | |
368 StartSockets(); | |
369 #endif | |
370 return htons(hostshort); | |
371 } | |
372 | |
373 u_long | |
374 win32_ntohl(u_long netlong) | |
375 { | |
376 #ifndef WIN32_NO_SOCKETS | |
377 StartSockets(); | |
378 #endif | |
379 return ntohl(netlong); | |
380 } | |
381 | |
382 u_short | |
383 win32_ntohs(u_short netshort) | |
384 { | |
385 #ifndef WIN32_NO_SOCKETS | |
386 StartSockets(); | |
387 #endif | |
388 return ntohs(netshort); | |
389 } | |
390 | |
391 | |
392 | |
393 SOCKET | |
394 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) | |
395 { | |
396 SOCKET r; | |
397 | |
398 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); | |
399 return OPEN_SOCKET(r); | |
400 } | |
401 | |
402 int | |
403 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) | |
404 { | |
405 int r; | |
406 | |
407 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); | |
408 return r; | |
409 } | |
410 | |
411 int | |
412 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) | |
413 { | |
414 int r; | |
415 | |
416 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); | |
417 return r; | |
418 } | |
419 | |
420 | |
421 int | |
422 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) | |
423 { | |
424 int r; | |
425 | |
426 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); | |
427 return r; | |
428 } | |
429 | |
430 int | |
431 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) | |
432 { | |
433 int r; | |
434 | |
435 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); | |
436 return r; | |
437 } | |
438 | |
439 int | |
440 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) | |
441 { | |
442 int r; | |
443 | |
444 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); | |
445 return r; | |
446 } | |
447 | |
448 int | |
449 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) | |
450 { | |
451 int r; | |
452 | |
453 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); | |
454 return r; | |
455 } | |
456 | |
457 int | |
458 win32_listen(SOCKET s, int backlog) | |
459 { | |
460 int r; | |
461 | |
462 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); | |
463 return r; | |
464 } | |
465 | |
466 int | |
467 win32_recv(SOCKET s, char *buf, int len, int flags) | |
468 { | |
469 int r; | |
470 | |
471 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); | |
472 return r; | |
473 } | |
474 | |
475 int | |
476 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) | |
477 { | |
478 int r; | |
479 int frombufsize = *fromlen; | |
480 | |
481 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); | |
482 /* Winsock's recvfrom() only returns a valid 'from' when the socket | |
483 * is connectionless. Perl expects a valid 'from' for all types | |
484 * of sockets, so go the extra mile. | |
485 */ | |
486 if (r != SOCKET_ERROR && frombufsize == *fromlen) | |
487 (void)win32_getpeername(s, from, fromlen); | |
488 return r; | |
489 } | |
490 | |
491 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ | |
492 int | |
493 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) | |
494 { | |
495 int r; | |
496 int i, fd, save_errno = errno; | |
497 FD_SET nrd, nwr, nex; | |
498 bool just_sleep = TRUE; | |
499 | |
500 StartSockets(); | |
501 | |
502 FD_ZERO(&nrd); | |
503 FD_ZERO(&nwr); | |
504 FD_ZERO(&nex); | |
505 for (i = 0; i < nfds; i++) { | |
506 if (rd && PERL_FD_ISSET(i,rd)) { | |
507 fd = TO_SOCKET(i); | |
508 FD_SET((unsigned)fd, &nrd); | |
509 just_sleep = FALSE; | |
510 } | |
511 if (wr && PERL_FD_ISSET(i,wr)) { | |
512 fd = TO_SOCKET(i); | |
513 FD_SET((unsigned)fd, &nwr); | |
514 just_sleep = FALSE; | |
515 } | |
516 if (ex && PERL_FD_ISSET(i,ex)) { | |
517 fd = TO_SOCKET(i); | |
518 FD_SET((unsigned)fd, &nex); | |
519 just_sleep = FALSE; | |
520 } | |
521 } | |
522 | |
523 /* winsock seems incapable of dealing with all three fd_sets being empty, | |
524 * so do the (millisecond) sleep as a special case | |
525 */ | |
526 if (just_sleep) { | |
527 if (timeout) | |
528 Sleep(timeout->tv_sec * 1000 + | |
529 timeout->tv_usec / 1000); /* do the best we can */ | |
530 else | |
531 Sleep(UINT_MAX); | |
532 return 0; | |
533 } | |
534 | |
535 errno = save_errno; | |
536 SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, (PTIMEVAL)timeout)); | |
537 save_errno = errno; | |
538 | |
539 for (i = 0; i < nfds; i++) { | |
540 if (rd && PERL_FD_ISSET(i,rd)) { | |
541 fd = TO_SOCKET(i); | |
542 if (!FD_ISSET(fd, &nrd)) | |
543 PERL_FD_CLR(i,rd); | |
544 } | |
545 if (wr && PERL_FD_ISSET(i,wr)) { | |
546 fd = TO_SOCKET(i); | |
547 if (!FD_ISSET(fd, &nwr)) | |
548 PERL_FD_CLR(i,wr); | |
549 } | |
550 if (ex && PERL_FD_ISSET(i,ex)) { | |
551 fd = TO_SOCKET(i); | |
552 if (!FD_ISSET(fd, &nex)) | |
553 PERL_FD_CLR(i,ex); | |
554 } | |
555 } | |
556 errno = save_errno; | |
557 return r; | |
558 } | |
559 | |
560 int | |
561 win32_send(SOCKET s, const char *buf, int len, int flags) | |
562 { | |
563 int r; | |
564 | |
565 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); | |
566 return r; | |
567 } | |
568 | |
569 int | |
570 win32_sendto(SOCKET s, const char *buf, int len, int flags, | |
571 const struct sockaddr *to, int tolen) | |
572 { | |
573 int r; | |
574 | |
575 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); | |
576 return r; | |
577 } | |
578 | |
579 int | |
580 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) | |
581 { | |
582 int r; | |
583 | |
584 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); | |
585 return r; | |
586 } | |
587 | |
588 int | |
589 win32_shutdown(SOCKET s, int how) | |
590 { | |
591 int r; | |
592 | |
593 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); | |
594 return r; | |
595 } | |
596 | |
597 int | |
598 win32_closesocket(SOCKET s) | |
599 { | |
600 int r; | |
601 | |
602 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); | |
603 return r; | |
604 } | |
605 | |
606 void | |
607 convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) | |
608 { | |
609 Copy(in, out, 1, WSAPROTOCOL_INFOA); | |
610 wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol)); | |
611 } | |
612 | |
613 SOCKET | |
614 open_ifs_socket(int af, int type, int protocol) | |
615 { | |
616 dTHX; | |
617 char *s; | |
618 unsigned long proto_buffers_len = 0; | |
619 int error_code; | |
620 SOCKET out = INVALID_SOCKET; | |
621 | |
622 if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s)) | |
623 return WSASocket(af, type, protocol, NULL, 0, 0); | |
624 | |
625 if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR | |
626 && error_code == WSAENOBUFS) | |
627 { | |
628 WSAPROTOCOL_INFOW *proto_buffers; | |
629 int protocols_available = 0; | |
630 | |
631 Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW), | |
632 WSAPROTOCOL_INFOW); | |
633 | |
634 if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, | |
635 &proto_buffers_len, &error_code)) != SOCKET_ERROR) | |
636 { | |
637 int i; | |
638 for (i = 0; i < protocols_available; i++) | |
639 { | |
640 WSAPROTOCOL_INFOA proto_info; | |
641 | |
642 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily) | |
643 || (type != proto_buffers[i].iSocketType) | |
644 || (protocol != 0 && proto_buffers[i].iProtocol != 0 && | |
645 protocol != proto_buffers[i].iProtocol)) | |
646 continue; | |
647 | |
648 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0) | |
649 continue; | |
650 | |
651 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info); | |
652 | |
653 out = WSASocket(af, type, protocol, &proto_info, 0, 0); | |
654 break; | |
655 } | |
656 } | |
657 | |
658 Safefree(proto_buffers); | |
659 } | |
660 | |
661 return out; | |
662 } | |
663 | |
664 SOCKET | |
665 win32_socket(int af, int type, int protocol) | |
666 { | |
667 SOCKET s; | |
668 | |
669 StartSockets(); | |
670 | |
671 if((s = open_ifs_socket(af, type, protocol)) == INVALID_SOCKET) | |
672 errno = get_last_socket_error(); | |
673 else | |
674 s = OPEN_SOCKET(s); | |
675 | |
676 return s; | |
677 } | |
678 | |
679 /* | |
680 * close RTL fd while respecting sockets | |
681 * added as temporary measure until PerlIO has real | |
682 * Win32 native layer | |
683 * -- BKS, 11-11-2000 | |
684 */ | |
685 | |
686 int my_close(int fd) | |
687 { | |
688 int osf; | |
689 if (!wsock_started) /* No WinSock? */ | |
690 return(close(fd)); /* Then not a socket. */ | |
691 osf = TO_SOCKET(fd);/* Get it now before it's gone! */ | |
692 if (osf != -1) { | |
693 int err; | |
694 err = closesocket(osf); | |
695 if (err == 0) { | |
696 assert(_osfhnd(fd) == osf); /* catch a bad ioinfo struct def */ | |
697 /* don't close freed handle */ | |
698 _set_osfhnd(fd, INVALID_HANDLE_VALUE); | |
699 return close(fd); | |
700 } | |
701 else if (err == SOCKET_ERROR) { | |
702 err = get_last_socket_error(); | |
703 if (err != ENOTSOCK) { | |
704 (void)close(fd); | |
705 errno = err; | |
706 return EOF; | |
707 } | |
708 } | |
709 } | |
710 return close(fd); | |
711 } | |
712 | |
713 #undef fclose | |
714 int | |
715 my_fclose (FILE *pf) | |
716 { | |
717 int osf; | |
718 if (!wsock_started) /* No WinSock? */ | |
719 return(fclose(pf)); /* Then not a socket. */ | |
720 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ | |
721 if (osf != -1) { | |
722 int err; | |
723 win32_fflush(pf); | |
724 err = closesocket(osf); | |
725 if (err == 0) { | |
726 assert(_osfhnd(win32_fileno(pf)) == osf); /* catch a bad ioinfo struct def */ | |
727 /* don't close freed handle */ | |
728 _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE); | |
729 return fclose(pf); | |
730 } | |
731 else if (err == SOCKET_ERROR) { | |
732 err = get_last_socket_error(); | |
733 if (err != ENOTSOCK) { | |
734 (void)fclose(pf); | |
735 errno = err; | |
736 return EOF; | |
737 } | |
738 } | |
739 } | |
740 return fclose(pf); | |
741 } | |
742 | |
743 struct hostent * | |
744 win32_gethostbyaddr(const char *addr, int len, int type) | |
745 { | |
746 struct hostent *r; | |
747 | |
748 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); | |
749 return r; | |
750 } | |
751 | |
752 struct hostent * | |
753 win32_gethostbyname(const char *name) | |
754 { | |
755 struct hostent *r; | |
756 | |
757 SOCKET_TEST(r = gethostbyname(name), NULL); | |
758 return r; | |
759 } | |
760 | |
761 int | |
762 win32_gethostname(char *name, int len) | |
763 { | |
764 int r; | |
765 | |
766 SOCKET_TEST_ERROR(r = gethostname(name, len)); | |
767 return r; | |
768 } | |
769 | |
770 struct protoent * | |
771 win32_getprotobyname(const char *name) | |
772 { | |
773 struct protoent *r; | |
774 | |
775 SOCKET_TEST(r = getprotobyname(name), NULL); | |
776 return r; | |
777 } | |
778 | |
779 struct protoent * | |
780 win32_getprotobynumber(int num) | |
781 { | |
782 struct protoent *r; | |
783 | |
784 SOCKET_TEST(r = getprotobynumber(num), NULL); | |
785 return r; | |
786 } | |
787 | |
788 struct servent * | |
789 win32_getservbyname(const char *name, const char *proto) | |
790 { | |
791 dTHXa(NULL); | |
792 struct servent *r; | |
793 | |
794 SOCKET_TEST(r = getservbyname(name, proto), NULL); | |
795 if (r) { | |
796 aTHXa(PERL_GET_THX); | |
797 r = win32_savecopyservent(&w32_servent, r, proto); | |
798 } | |
799 return r; | |
800 } | |
801 | |
802 struct servent * | |
803 win32_getservbyport(int port, const char *proto) | |
804 { | |
805 dTHXa(NULL); | |
806 struct servent *r; | |
807 | |
808 SOCKET_TEST(r = getservbyport(port, proto), NULL); | |
809 if (r) { | |
810 aTHXa(PERL_GET_THX); | |
811 r = win32_savecopyservent(&w32_servent, r, proto); | |
812 } | |
813 return r; | |
814 } | |
815 | |
816 int | |
817 win32_ioctl(int i, unsigned int u, char *data) | |
818 { | |
819 u_long u_long_arg; | |
820 int retval; | |
821 | |
822 if (!wsock_started) { | |
823 Perl_croak_nocontext("ioctl implemented only on sockets"); | |
824 /* NOTREACHED */ | |
825 } | |
826 | |
827 /* mauke says using memcpy avoids alignment issues */ | |
828 memcpy(&u_long_arg, data, sizeof u_long_arg); | |
829 retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); | |
830 memcpy(data, &u_long_arg, sizeof u_long_arg); | |
831 | |
832 if (retval == SOCKET_ERROR) { | |
833 int err = get_last_socket_error(); | |
834 if (err == ENOTSOCK) { | |
835 Perl_croak_nocontext("ioctl implemented only on sockets"); | |
836 /* NOTREACHED */ | |
837 } | |
838 errno = err; | |
839 } | |
840 return retval; | |
841 } | |
842 | |
843 char FAR * | |
844 win32_inet_ntoa(struct in_addr in) | |
845 { | |
846 StartSockets(); | |
847 return inet_ntoa(in); | |
848 } | |
849 | |
850 unsigned long | |
851 win32_inet_addr(const char FAR *cp) | |
852 { | |
853 StartSockets(); | |
854 return inet_addr(cp); | |
855 } | |
856 | |
857 /* | |
858 * Networking stubs | |
859 */ | |
860 | |
861 void | |
862 win32_endhostent() | |
863 { | |
864 win32_croak_not_implemented("endhostent"); | |
865 } | |
866 | |
867 void | |
868 win32_endnetent() | |
869 { | |
870 win32_croak_not_implemented("endnetent"); | |
871 } | |
872 | |
873 void | |
874 win32_endprotoent() | |
875 { | |
876 win32_croak_not_implemented("endprotoent"); | |
877 } | |
878 | |
879 void | |
880 win32_endservent() | |
881 { | |
882 win32_croak_not_implemented("endservent"); | |
883 } | |
884 | |
885 | |
886 struct netent * | |
887 win32_getnetent(void) | |
888 { | |
889 win32_croak_not_implemented("getnetent"); | |
890 return (struct netent *) NULL; | |
891 } | |
892 | |
893 struct netent * | |
894 win32_getnetbyname(char *name) | |
895 { | |
896 win32_croak_not_implemented("getnetbyname"); | |
897 return (struct netent *)NULL; | |
898 } | |
899 | |
900 struct netent * | |
901 win32_getnetbyaddr(long net, int type) | |
902 { | |
903 win32_croak_not_implemented("getnetbyaddr"); | |
904 return (struct netent *)NULL; | |
905 } | |
906 | |
907 struct protoent * | |
908 win32_getprotoent(void) | |
909 { | |
910 win32_croak_not_implemented("getprotoent"); | |
911 return (struct protoent *) NULL; | |
912 } | |
913 | |
914 struct servent * | |
915 win32_getservent(void) | |
916 { | |
917 win32_croak_not_implemented("getservent"); | |
918 return (struct servent *) NULL; | |
919 } | |
920 | |
921 void | |
922 win32_sethostent(int stayopen) | |
923 { | |
924 win32_croak_not_implemented("sethostent"); | |
925 } | |
926 | |
927 | |
928 void | |
929 win32_setnetent(int stayopen) | |
930 { | |
931 win32_croak_not_implemented("setnetent"); | |
932 } | |
933 | |
934 | |
935 void | |
936 win32_setprotoent(int stayopen) | |
937 { | |
938 win32_croak_not_implemented("setprotoent"); | |
939 } | |
940 | |
941 | |
942 void | |
943 win32_setservent(int stayopen) | |
944 { | |
945 win32_croak_not_implemented("setservent"); | |
946 } | |
947 | |
948 static struct servent* | |
949 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) | |
950 { | |
951 d->s_name = s->s_name; | |
952 d->s_aliases = s->s_aliases; | |
953 d->s_port = s->s_port; | |
954 if (s->s_proto && strlen(s->s_proto)) | |
955 d->s_proto = s->s_proto; | |
956 else | |
957 if (proto && strlen(proto)) | |
958 d->s_proto = (char *)proto; | |
959 else | |
960 d->s_proto = "tcp"; | |
961 | |
962 return d; | |
963 } | |
964 | |
965 |