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