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