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