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