remove bogus symbols from global.sym
[p5sagit/p5-mst-13.2.git] / win32 / win32sck.c
index 5c2b73f..2713605 100644 (file)
@@ -24,6 +24,7 @@ extern CPerlObj* pPerl;
 #include "XSUB.h"
 #endif
 
+#include "Win32iop.h"
 #include <sys/socket.h>
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -32,18 +33,29 @@ extern CPerlObj* pPerl;
 
 /* thanks to Beverly Brown     (beverly@datacube.com) */
 #ifdef USE_SOCKETS_AS_HANDLES
-#      define OPEN_SOCKET(x)   _open_osfhandle(x,O_RDWR|O_BINARY)
+#      define OPEN_SOCKET(x)   win32_open_osfhandle(x,O_RDWR|O_BINARY)
 #      define TO_SOCKET(x)     _get_osfhandle(x)
 #else
 #      define OPEN_SOCKET(x)   (x)
 #      define TO_SOCKET(x)     (x)
 #endif /* USE_SOCKETS_AS_HANDLES */
 
+#ifdef USE_THREADS
 #define StartSockets() \
     STMT_START {                                       \
        if (!wsock_started)                             \
            start_sockets();                            \
+       set_socktype();                         \
+    } STMT_END
+#else
+#define StartSockets() \
+    STMT_START {                                       \
+       if (!wsock_started) {                           \
+           start_sockets();                            \
+           set_socktype();                             \
+       }                                               \
     } STMT_END
+#endif
 
 #define EndSockets() \
     STMT_START {                                       \
@@ -67,8 +79,10 @@ static struct servent* win32_savecopyservent(struct servent*d,
 #ifdef USE_THREADS
 #ifdef USE_DECLSPEC_THREAD
 __declspec(thread) struct servent myservent;
+__declspec(thread) int init_socktype;
 #else
 #define myservent (thr->i.Wservent)
+#define init_socktype (thr->i.Winit_socktype)
 #endif
 #else
 static struct servent myservent;
@@ -82,7 +96,6 @@ start_sockets(void)
     unsigned short version;
     WSADATA retdata;
     int ret;
-    int iSockOpt = SO_SYNCHRONOUS_NONALERT;
 
     /*
      * initalize the winsock interface and insure that it is
@@ -95,15 +108,28 @@ start_sockets(void)
        croak("Could not find version 1.1 of winsock dll\n");
 
     /* atexit((void (*)(void)) EndSockets); */
+    wsock_started = 1;
+}
 
+void
+set_socktype(void)
+{
 #ifdef USE_SOCKETS_AS_HANDLES
+#ifdef USE_THREADS
+    dTHR;
+    if(!init_socktype) {
+#endif
+    int iSockOpt = SO_SYNCHRONOUS_NONALERT;
     /*
      * Enable the use of sockets as filehandles
      */
     setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
                (char *)&iSockOpt, sizeof(iSockOpt));
+#ifdef USE_THREADS
+    init_socktype = 1;
+    }
+#endif
 #endif /* USE_SOCKETS_AS_HANDLES */
-    wsock_started = 1;
 }
 
 
@@ -261,8 +287,15 @@ int
 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
 {
     int r;
+    int frombufsize = *fromlen;
 
     SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
+    /* Winsock's recvfrom() only returns a valid 'from' when the socket
+     * is connectionless.  Perl expects a valid 'from' for all types
+     * of sockets, so go the extra mile.
+     */
+    if (r != SOCKET_ERROR && frombufsize == *fromlen)
+       (void)win32_getpeername(s, from, fromlen);
     return r;
 }
 
@@ -280,8 +313,11 @@ win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const
      * so do the (millisecond) sleep as a special case
      */
     if (!(rd || wr || ex)) {
-       Sleep(timeout->tv_sec  * 1000 +
-             timeout->tv_usec / 1000);         /* do the best we can */
+       if (timeout)
+           Sleep(timeout->tv_sec  * 1000 +
+                 timeout->tv_usec / 1000);     /* do the best we can */
+       else
+           Sleep(UINT_MAX);
        return 0;
     }
     StartSockets();