applied suggested fix for xhv_array sizing, with portability tweaks
[p5sagit/p5-mst-13.2.git] / win32 / win32sck.c
CommitLineData
326b05e3 1/* win32sck.c
68dc0745 2 *
3 * (c) 1995 Microsoft Corporation. All rights reserved.
4 * Developed by hip communications inc., http://info.hip.com/info/
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 */
0a753a76 10
390b85e7 11#define WIN32IO_IS_STDIO
55d25626 12#define WIN32SCK_IS_STDSCK
0a753a76 13#define WIN32_LEAN_AND_MEAN
a835ef8a 14#ifdef __GNUC__
15#define Win32_Winsock
ac4c12e7 16# ifdef __cplusplus
17#undef __attribute__ /* seems broken in 2.8.0 */
18#define __attribute__(p)
19# endif
a835ef8a 20#endif
390b85e7 21#include <windows.h>
0a753a76 22#include "EXTERN.h"
23#include "perl.h"
c69f6586 24
25#if defined(PERL_OBJECT)
26#define NO_XSLOCKS
27extern CPerlObj* pPerl;
28#include "XSUB.h"
29#endif
30
58a50f62 31#include "Win32iop.h"
0a753a76 32#include <sys/socket.h>
33#include <fcntl.h>
34#include <sys/stat.h>
35#include <assert.h>
390b85e7 36#include <io.h>
0a753a76 37
68dc0745 38/* thanks to Beverly Brown (beverly@datacube.com) */
326b05e3 39#ifdef USE_SOCKETS_AS_HANDLES
58a50f62 40# define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY)
326b05e3 41# define TO_SOCKET(x) _get_osfhandle(x)
0a753a76 42#else
0a753a76 43# define OPEN_SOCKET(x) (x)
44# define TO_SOCKET(x) (x)
68dc0745 45#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 46
401ef382 47#ifdef USE_THREADS
326b05e3 48#define StartSockets() \
49 STMT_START { \
50 if (!wsock_started) \
51 start_sockets(); \
401ef382 52 set_socktype(); \
326b05e3 53 } STMT_END
401ef382 54#else
55#define StartSockets() \
56 STMT_START { \
57 if (!wsock_started) { \
58 start_sockets(); \
59 set_socktype(); \
60 } \
61 } STMT_END
62#endif
326b05e3 63
64#define EndSockets() \
65 STMT_START { \
66 if (wsock_started) \
67 WSACleanup(); \
68 } STMT_END
69
70#define SOCKET_TEST(x, y) \
71 STMT_START { \
72 StartSockets(); \
73 if((x) == (y)) \
74 errno = WSAGetLastError(); \
75 } STMT_END
76
77#define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
78
137443ea 79static struct servent* win32_savecopyservent(struct servent*d,
80 struct servent*s,
81 const char *proto);
0a753a76 82
c53bd28a 83#ifdef USE_THREADS
84#ifdef USE_DECLSPEC_THREAD
0a753a76 85__declspec(thread) struct servent myservent;
401ef382 86__declspec(thread) int init_socktype;
c53bd28a 87#else
88#define myservent (thr->i.Wservent)
401ef382 89#define init_socktype (thr->i.Winit_socktype)
c53bd28a 90#endif
91#else
92static struct servent myservent;
93#endif
94
326b05e3 95static int wsock_started = 0;
68dc0745 96
97void
326b05e3 98start_sockets(void)
68dc0745 99{
100 unsigned short version;
101 WSADATA retdata;
102 int ret;
68dc0745 103
68dc0745 104 /*
105 * initalize the winsock interface and insure that it is
106 * cleaned up at exit.
107 */
108 version = 0x101;
326b05e3 109 if(ret = WSAStartup(version, &retdata))
110 croak("Unable to locate winsock library!\n");
68dc0745 111 if(retdata.wVersion != version)
326b05e3 112 croak("Could not find version 1.1 of winsock dll\n");
68dc0745 113
114 /* atexit((void (*)(void)) EndSockets); */
401ef382 115 wsock_started = 1;
116}
0a753a76 117
401ef382 118void
119set_socktype(void)
120{
0a753a76 121#ifdef USE_SOCKETS_AS_HANDLES
401ef382 122#ifdef USE_THREADS
123 dTHR;
124 if(!init_socktype) {
125#endif
126 int iSockOpt = SO_SYNCHRONOUS_NONALERT;
68dc0745 127 /*
128 * Enable the use of sockets as filehandles
129 */
326b05e3 130 setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
68dc0745 131 (char *)&iSockOpt, sizeof(iSockOpt));
401ef382 132#ifdef USE_THREADS
133 init_socktype = 1;
134 }
135#endif
68dc0745 136#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 137}
138
139
140#ifndef USE_SOCKETS_AS_HANDLES
f3986ebb 141#undef fdopen
68dc0745 142FILE *
f3986ebb 143my_fdopen(int fd, char *mode)
0a753a76 144{
68dc0745 145 FILE *fp;
146 char sockbuf[256];
147 int optlen = sizeof(sockbuf);
148 int retval;
0a753a76 149
326b05e3 150 if (!wsock_started)
fb73857a 151 return(fdopen(fd, mode));
0a753a76 152
326b05e3 153 retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
154 if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) {
fb73857a 155 return(fdopen(fd, mode));
68dc0745 156 }
0a753a76 157
68dc0745 158 /*
159 * If we get here, then fd is actually a socket.
160 */
fc36a67e 161 Newz(1310, fp, 1, FILE);
68dc0745 162 if(fp == NULL) {
163 errno = ENOMEM;
164 return NULL;
165 }
0a753a76 166
68dc0745 167 fp->_file = fd;
168 if(*mode == 'r')
169 fp->_flag = _IOREAD;
170 else
171 fp->_flag = _IOWRT;
172
173 return fp;
0a753a76 174}
68dc0745 175#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 176
177
68dc0745 178u_long
179win32_htonl(u_long hostlong)
0a753a76 180{
326b05e3 181 StartSockets();
182 return htonl(hostlong);
0a753a76 183}
184
68dc0745 185u_short
186win32_htons(u_short hostshort)
0a753a76 187{
326b05e3 188 StartSockets();
189 return htons(hostshort);
0a753a76 190}
191
68dc0745 192u_long
193win32_ntohl(u_long netlong)
0a753a76 194{
326b05e3 195 StartSockets();
196 return ntohl(netlong);
0a753a76 197}
198
68dc0745 199u_short
200win32_ntohs(u_short netshort)
0a753a76 201{
326b05e3 202 StartSockets();
203 return ntohs(netshort);
0a753a76 204}
205
206
0a753a76 207
68dc0745 208SOCKET
209win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 210{
68dc0745 211 SOCKET r;
0a753a76 212
326b05e3 213 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
68dc0745 214 return OPEN_SOCKET(r);
0a753a76 215}
216
68dc0745 217int
218win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 219{
68dc0745 220 int r;
0a753a76 221
326b05e3 222 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
68dc0745 223 return r;
0a753a76 224}
225
68dc0745 226int
227win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
0a753a76 228{
68dc0745 229 int r;
0a753a76 230
326b05e3 231 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
68dc0745 232 return r;
0a753a76 233}
234
235
68dc0745 236int
237win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 238{
68dc0745 239 int r;
0a753a76 240
326b05e3 241 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
68dc0745 242 return r;
0a753a76 243}
244
68dc0745 245int
246win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
0a753a76 247{
68dc0745 248 int r;
0a753a76 249
326b05e3 250 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
68dc0745 251 return r;
0a753a76 252}
253
68dc0745 254int
255win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
0a753a76 256{
68dc0745 257 int r;
0a753a76 258
326b05e3 259 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 260 return r;
0a753a76 261}
262
2d7a9237 263int
68dc0745 264win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
0a753a76 265{
68dc0745 266 int r;
0a753a76 267
326b05e3 268 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
68dc0745 269 return r;
0a753a76 270}
271
68dc0745 272int
273win32_listen(SOCKET s, int backlog)
0a753a76 274{
68dc0745 275 int r;
0a753a76 276
326b05e3 277 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
68dc0745 278 return r;
0a753a76 279}
280
68dc0745 281int
282win32_recv(SOCKET s, char *buf, int len, int flags)
0a753a76 283{
68dc0745 284 int r;
0a753a76 285
326b05e3 286 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
68dc0745 287 return r;
0a753a76 288}
289
68dc0745 290int
291win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
0a753a76 292{
68dc0745 293 int r;
0a753a76 294
326b05e3 295 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
68dc0745 296 return r;
0a753a76 297}
298
68dc0745 299/* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
300int
55d25626 301win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
0a753a76 302{
55d25626 303 int r;
304#ifdef USE_SOCKETS_AS_HANDLES
305 Perl_fd_set dummy;
68dc0745 306 int i, fd, bit, offset;
55d25626 307 FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
0a753a76 308
7e3be867 309 /* winsock seems incapable of dealing with all three null fd_sets,
310 * so do the (millisecond) sleep as a special case
311 */
312 if (!(rd || wr || ex)) {
87c2f9c4 313 if (timeout)
314 Sleep(timeout->tv_sec * 1000 +
315 timeout->tv_usec / 1000); /* do the best we can */
316 else
317 Sleep(UINT_MAX);
7e3be867 318 return 0;
319 }
f2bb5751 320 StartSockets();
55d25626 321 PERL_FD_ZERO(&dummy);
68dc0745 322 if (!rd)
323 rd = &dummy, prd = NULL;
324 else
325 prd = &nrd;
326 if (!wr)
327 wr = &dummy, pwr = NULL;
328 else
329 pwr = &nwr;
330 if (!ex)
331 ex = &dummy, pex = NULL;
332 else
333 pex = &nex;
0a753a76 334
68dc0745 335 FD_ZERO(&nrd);
336 FD_ZERO(&nwr);
337 FD_ZERO(&nex);
338 for (i = 0; i < nfds; i++) {
339 fd = TO_SOCKET(i);
55d25626 340 if (PERL_FD_ISSET(i,rd))
68dc0745 341 FD_SET(fd, &nrd);
55d25626 342 if (PERL_FD_ISSET(i,wr))
68dc0745 343 FD_SET(fd, &nwr);
55d25626 344 if (PERL_FD_ISSET(i,ex))
68dc0745 345 FD_SET(fd, &nex);
346 }
347
326b05e3 348 SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout));
0a753a76 349
68dc0745 350 for (i = 0; i < nfds; i++) {
351 fd = TO_SOCKET(i);
55d25626 352 if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
353 PERL_FD_CLR(i,rd);
354 if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
355 PERL_FD_CLR(i,wr);
356 if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
357 PERL_FD_CLR(i,ex);
68dc0745 358 }
55d25626 359#else
360 SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
361#endif
68dc0745 362 return r;
0a753a76 363}
364
68dc0745 365int
366win32_send(SOCKET s, const char *buf, int len, int flags)
0a753a76 367{
68dc0745 368 int r;
0a753a76 369
326b05e3 370 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
68dc0745 371 return r;
0a753a76 372}
373
68dc0745 374int
375win32_sendto(SOCKET s, const char *buf, int len, int flags,
376 const struct sockaddr *to, int tolen)
0a753a76 377{
68dc0745 378 int r;
0a753a76 379
326b05e3 380 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
68dc0745 381 return r;
0a753a76 382}
383
68dc0745 384int
385win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
0a753a76 386{
68dc0745 387 int r;
0a753a76 388
326b05e3 389 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
68dc0745 390 return r;
0a753a76 391}
392
68dc0745 393int
394win32_shutdown(SOCKET s, int how)
0a753a76 395{
68dc0745 396 int r;
0a753a76 397
326b05e3 398 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
68dc0745 399 return r;
0a753a76 400}
401
3a25acb4 402int
403win32_closesocket(SOCKET s)
404{
405 int r;
406
407 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
408 return r;
409}
410
68dc0745 411SOCKET
412win32_socket(int af, int type, int protocol)
0a753a76 413{
68dc0745 414 SOCKET s;
0a753a76 415
416#ifndef USE_SOCKETS_AS_HANDLES
326b05e3 417 SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
0a753a76 418#else
3a25acb4 419 StartSockets();
326b05e3 420 if((s = socket(af, type, protocol)) == INVALID_SOCKET)
421 errno = WSAGetLastError();
68dc0745 422 else
423 s = OPEN_SOCKET(s);
424#endif /* USE_SOCKETS_AS_HANDLES */
0a753a76 425
68dc0745 426 return s;
0a753a76 427}
428
fb73857a 429#undef fclose
430int
431my_fclose (FILE *pf)
432{
326b05e3 433 int osf, retval;
434 if (!wsock_started) /* No WinSock? */
435 return(fclose(pf)); /* Then not a socket. */
436 osf = TO_SOCKET(fileno(pf));/* Get it now before it's gone! */
437 retval = fclose(pf); /* Must fclose() before closesocket() */
438 if (osf != -1
439 && closesocket(osf) == SOCKET_ERROR
440 && WSAGetLastError() != WSAENOTSOCK)
441 {
442 return EOF;
443 }
444 return retval;
fb73857a 445}
446
68dc0745 447struct hostent *
448win32_gethostbyaddr(const char *addr, int len, int type)
0a753a76 449{
68dc0745 450 struct hostent *r;
0a753a76 451
326b05e3 452 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
68dc0745 453 return r;
0a753a76 454}
455
68dc0745 456struct hostent *
457win32_gethostbyname(const char *name)
0a753a76 458{
68dc0745 459 struct hostent *r;
0a753a76 460
326b05e3 461 SOCKET_TEST(r = gethostbyname(name), NULL);
68dc0745 462 return r;
0a753a76 463}
464
68dc0745 465int
466win32_gethostname(char *name, int len)
0a753a76 467{
68dc0745 468 int r;
0a753a76 469
326b05e3 470 SOCKET_TEST_ERROR(r = gethostname(name, len));
68dc0745 471 return r;
0a753a76 472}
473
68dc0745 474struct protoent *
475win32_getprotobyname(const char *name)
0a753a76 476{
68dc0745 477 struct protoent *r;
0a753a76 478
326b05e3 479 SOCKET_TEST(r = getprotobyname(name), NULL);
68dc0745 480 return r;
0a753a76 481}
482
68dc0745 483struct protoent *
484win32_getprotobynumber(int num)
0a753a76 485{
68dc0745 486 struct protoent *r;
0a753a76 487
326b05e3 488 SOCKET_TEST(r = getprotobynumber(num), NULL);
68dc0745 489 return r;
0a753a76 490}
491
68dc0745 492struct servent *
493win32_getservbyname(const char *name, const char *proto)
0a753a76 494{
68dc0745 495 struct servent *r;
c53bd28a 496 dTHR;
497
326b05e3 498 SOCKET_TEST(r = getservbyname(name, proto), NULL);
68dc0745 499 if (r) {
500 r = win32_savecopyservent(&myservent, r, proto);
501 }
502 return r;
0a753a76 503}
504
68dc0745 505struct servent *
506win32_getservbyport(int port, const char *proto)
0a753a76 507{
68dc0745 508 struct servent *r;
c53bd28a 509 dTHR;
0a753a76 510
326b05e3 511 SOCKET_TEST(r = getservbyport(port, proto), NULL);
68dc0745 512 if (r) {
513 r = win32_savecopyservent(&myservent, r, proto);
514 }
515 return r;
0a753a76 516}
517
f998180f 518int
519win32_ioctl(int i, unsigned int u, char *data)
520{
521 u_long argp = (u_long)data;
522 int retval;
523
524 if (!wsock_started) {
525 croak("ioctl implemented only on sockets");
526 /* NOTREACHED */
527 }
528
529 retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
530 if (retval == SOCKET_ERROR) {
531 if (WSAGetLastError() == WSAENOTSOCK) {
532 croak("ioctl implemented only on sockets");
533 /* NOTREACHED */
534 }
535 errno = WSAGetLastError();
536 }
537 return retval;
538}
539
68dc0745 540char FAR *
541win32_inet_ntoa(struct in_addr in)
0a753a76 542{
326b05e3 543 StartSockets();
544 return inet_ntoa(in);
0a753a76 545}
546
68dc0745 547unsigned long
548win32_inet_addr(const char FAR *cp)
0a753a76 549{
326b05e3 550 StartSockets();
551 return inet_addr(cp);
0a753a76 552}
68dc0745 553
554/*
555 * Networking stubs
556 */
0a753a76 557
68dc0745 558void
559win32_endhostent()
0a753a76 560{
326b05e3 561 croak("endhostent not implemented!\n");
0a753a76 562}
563
68dc0745 564void
565win32_endnetent()
0a753a76 566{
326b05e3 567 croak("endnetent not implemented!\n");
0a753a76 568}
569
68dc0745 570void
571win32_endprotoent()
0a753a76 572{
326b05e3 573 croak("endprotoent not implemented!\n");
0a753a76 574}
575
68dc0745 576void
577win32_endservent()
0a753a76 578{
326b05e3 579 croak("endservent not implemented!\n");
0a753a76 580}
581
582
68dc0745 583struct netent *
584win32_getnetent(void)
0a753a76 585{
326b05e3 586 croak("getnetent not implemented!\n");
68dc0745 587 return (struct netent *) NULL;
0a753a76 588}
589
68dc0745 590struct netent *
591win32_getnetbyname(char *name)
0a753a76 592{
326b05e3 593 croak("getnetbyname not implemented!\n");
68dc0745 594 return (struct netent *)NULL;
0a753a76 595}
596
68dc0745 597struct netent *
598win32_getnetbyaddr(long net, int type)
0a753a76 599{
326b05e3 600 croak("getnetbyaddr not implemented!\n");
68dc0745 601 return (struct netent *)NULL;
0a753a76 602}
603
68dc0745 604struct protoent *
605win32_getprotoent(void)
0a753a76 606{
326b05e3 607 croak("getprotoent not implemented!\n");
68dc0745 608 return (struct protoent *) NULL;
0a753a76 609}
610
68dc0745 611struct servent *
612win32_getservent(void)
0a753a76 613{
326b05e3 614 croak("getservent not implemented!\n");
68dc0745 615 return (struct servent *) NULL;
0a753a76 616}
617
68dc0745 618void
619win32_sethostent(int stayopen)
0a753a76 620{
326b05e3 621 croak("sethostent not implemented!\n");
0a753a76 622}
623
624
68dc0745 625void
626win32_setnetent(int stayopen)
0a753a76 627{
326b05e3 628 croak("setnetent not implemented!\n");
0a753a76 629}
630
631
68dc0745 632void
633win32_setprotoent(int stayopen)
0a753a76 634{
326b05e3 635 croak("setprotoent not implemented!\n");
0a753a76 636}
637
638
68dc0745 639void
640win32_setservent(int stayopen)
0a753a76 641{
326b05e3 642 croak("setservent not implemented!\n");
0a753a76 643}
644
137443ea 645static struct servent*
646win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
647{
648 d->s_name = s->s_name;
649 d->s_aliases = s->s_aliases;
650 d->s_port = s->s_port;
0af56dfe 651#ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
137443ea 652 if (!IsWin95() && s->s_proto && strlen(s->s_proto))
653 d->s_proto = s->s_proto;
0af56dfe 654 else
655#endif
c69f6586 656 if (proto && strlen(proto))
137443ea 657 d->s_proto = (char *)proto;
658 else
659 d->s_proto = "tcp";
660
661 return d;
662}
663
0a753a76 664