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