[Vm-dev] [commit] r2406 - Merging support files from cogvm branch.

commits at squeakvm.org commits at squeakvm.org
Thu Jun 9 08:14:49 UTC 2011


Author: andreas
Date: 2011-06-09 01:14:49 -0700 (Thu, 09 Jun 2011)
New Revision: 2406

Modified:
   trunk/platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c
Log:
Merging support files from cogvm branch.

Modified: trunk/platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c
===================================================================
--- trunk/platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c	2011-06-09 07:33:56 UTC (rev 2405)
+++ trunk/platforms/win32/plugins/SocketPlugin/sqWin32NewNet.c	2011-06-09 08:14:49 UTC (rev 2406)
@@ -34,12 +34,16 @@
 
 #ifndef NO_NETWORK
 
+#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
+#  define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
+#endif
+
 #ifndef NO_RCSID
   static char RCSID[]="$Id$";
 #endif
 
 #ifndef NDEBUG
-#define DBG(s) debugCheckWatcherThreads(PSP(s))
+#define DBG(s,c) debugCheckWatcherThreads(PSP(s),c)
 #else
 #define DBG(s)
 #endif
@@ -47,6 +51,7 @@
 /*** Socket Type Constants ***/
 #define TCPSocketType 0
 #define UDPSocketType 1
+#define RAWSocketType 2
 
 /*** Resolver Status Constants ***/
 #define RESOLVER_UNINITIALIZED 0
@@ -84,6 +89,7 @@
 
 static int resolverSemaphoreIndex = 0;
 static int thisNetSession = 0;
+static int runningVista = 0;
 static u_long zero = 0;
 static u_long one = 1;
 
@@ -365,7 +371,7 @@
   }
 }
 
-static void debugCheckWatcherThreads(privateSocketStruct *pss) {
+static void debugCheckWatcherThreads(privateSocketStruct *pss, char* caller) {
   int state = pss->sockState;
   int printReason = 0;
 
@@ -405,7 +411,7 @@
       printReason |= 64; /* not watching for close */
   }
   if(printReason) {
-    printf("#### WARNING: Watcher threads are running wild on socket\n");
+    printf("#### WARNING: Watcher threads are running wild on socket (%s)\n", caller);
     if(printReason & 1)
       printf("\t* Watching for stuff while unconnected\n");
     if(printReason & 2)
@@ -649,10 +655,11 @@
   /* Create the read watcher */
   hThread =
     CreateThread(NULL,			   /* No security descriptor */
-		 pageSize,                 /* default stack size     */
+		 128*1024,                 /* max stack size     */
 		 (LPTHREAD_START_ROUTINE) readWatcherThread, /* what to do */
 		 (LPVOID) pss,      /* parameter for thread   */
-		 CREATE_SUSPENDED,  /* creation parameter -- create suspended so we can check the return value */
+		 CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,  
+		   /* creation parameter -- create suspended so we can check the return value */
 		 &id);              /* return value for thread id */
   pss->hReadThread = hThread;
   if(!hThread) {
@@ -671,10 +678,11 @@
   /* Create the write watcher */
   hThread =
     CreateThread(NULL,			   /* No security descriptor */
-		 pageSize,                 /* default stack size     */
+		 128*1024,                 /* max stack size     */
 		 (LPTHREAD_START_ROUTINE) writeWatcherThread,/* what to do */
 		 (LPVOID) pss,      /* parameter for thread   */
-		 CREATE_SUSPENDED,  /* creation parameter -- create suspended so we can check the return value */
+		 CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,  
+		   /* creation parameter -- create suspended so we can check the return value */
 		 &id);              /* return value for thread id */
   pss->hWriteThread = hThread;
   if(!hThread) {
@@ -703,9 +711,15 @@
 int sqNetworkInit(int semaIndex)
 {
   int err;
+  OSVERSIONINFOEX osInfo;
 
+  if (thisNetSession != 0) return 0; /* network is already initialized */
 
-  if (thisNetSession != 0) return 0;  /* noop if network is already initialized */
+  /* detect if we're running on Vista */
+  ZeroMemory(&osInfo, sizeof(osInfo));
+  osInfo.dwOSVersionInfoSize = sizeof(osInfo);
+  GetVersionEx((OSVERSIONINFO*)&osInfo);
+  runningVista = osInfo.dwMajorVersion >= 6;
 
   err = WSAStartup( MAKEWORD(2,0), &wsaData );
   if ( err != 0 )
@@ -839,7 +853,7 @@
   int status;
 
   if (!SocketValid(s)) return -1;
-  DBG(s);
+  DBG(s, "sqSocketConnectionStatus");
   status = SOCKETSTATE(s) & 0xFFFF;
   return status;
 }
@@ -860,7 +874,7 @@
   ADDRESS(s)->sin_port = htons((short)port);
   ADDRESS(s)->sin_addr.s_addr = htonl(addr);
 
-  if(UDPSocketType == s->socketType) { /* UDP */
+  if(TCPSocketType != s->socketType) { /* UDP/RAW */
     if(!pss->sockState & SOCK_BOUND_UDP) {
       /* The socket is locally unbound and we
 	 must 'magically' assign a local port so
@@ -914,7 +928,7 @@
   ZeroMemory(&addr,sizeof(struct sockaddr_in));
   addr.sin_family = AF_INET;
   addr.sin_port = htons((short)port);
-  addr.sin_addr.s_addr = localHostAddress;
+  addr.sin_addr.s_addr = INADDR_ANY;
 
   result = bind( SOCKET(s), (struct sockaddr*) &addr, sizeof(struct sockaddr_in));
   if(result == SOCKET_ERROR) {
@@ -922,7 +936,7 @@
     FAIL();
     return;
   }
-  if(UDPSocketType == s->socketType) { /* UDP */
+  if(TCPSocketType != s->socketType) { /* UDP/RAW */
     SOCKETSTATE(s) = Connected | SOCK_BOUND_UDP | SOCK_DATA_WRITABLE;
   } else { /* TCP */
     /* show our willingness to accept a single incoming connection */
@@ -982,7 +996,7 @@
 
   if (!SocketValid(s)) return;
 
-  if(UDPSocketType == s->socketType) {
+  if(TCPSocketType != s->socketType) { /* UDP/RAW */
     sqSocketListenOnPort(s, port);
     return;
   }
@@ -1056,7 +1070,7 @@
   int sockState;
 
   if(!SocketValid(s)) return 0;
-  DBG(s);
+  DBG(s,"sqSocketReceiveDataAvailable");
   sockState = SOCKETSTATE(s);
   return (sockState & SOCK_DATA_READABLE) /* e.g., do we have data? */
     && ((sockState & SOCK_PUBLIC_MASK) == Connected); /* and are we still connected? */
@@ -1077,7 +1091,7 @@
   if(bufSize <= 0) return bufSize;
 
   /* read incoming data */
-  if(UDPSocketType == pss->sockType) { /* UDP */
+  if(TCPSocketType != pss->sockType) { /* UDP/RAW */
     addrSize = sizeof(pss->peer);
     result = recvfrom(pss->s, buf, bufSize, 0,
 		      (struct sockaddr*) &pss->peer, &addrSize);
@@ -1093,8 +1107,8 @@
   /* Check if something went wrong */
   if(result <= 0) {
       if(result == 0) {
-	/* UDP doesn't know "other end closed" state */
-	if(pss->sockType != UDPSocketType)
+	/* UDP/RAW doesn't know "other end closed" state */
+	if(pss->sockType == TCPSocketType)
 	  pss->sockState = OtherEndClosed;
       } else if(result < 0) {
 	int err = WSAGetLastError();
@@ -1103,8 +1117,8 @@
 	  /* NOTE: We consider all other errors to be fatal, e.g.,
 	     report them as "other end closed". Looking at the
 	     WSock documentation this ought to be correct. */
-	  /* UDP doesn't know "other end closed" state */
-	  if(pss->sockType != UDPSocketType) {
+	  /* UDP/RAW doesn't know "other end closed" state */
+	  if(pss->sockType == TCPSocketType) {
 	    pss->sockState = OtherEndClosed;
 	    SIGNAL(pss->connSema);
 	  }
@@ -1133,7 +1147,7 @@
   int sockState;
 
   if (!SocketValid(s)) return 1;
-  DBG(s);
+  DBG(s, "sqSocketSendDone");
   sockState = SOCKETSTATE(s);
   return (sockState & SOCK_DATA_WRITABLE) /* e.g., everything has been written */
     && ((sockState & SOCK_PUBLIC_MASK) == Connected); /* and we are still connected */
@@ -1160,7 +1174,7 @@
   if(!bufSize) return 0;
 
   /* send actual data */
-  if(UDPSocketType == pss->sockType) { /* UDP */
+  if(TCPSocketType != pss->sockType) { /* UDP/RAW */
     addrSize = sizeof(pss->peer);
     result = sendto(pss->s, buf, bufSize, 0,
 		    (struct sockaddr*) &pss->peer, addrSize);
@@ -1175,8 +1189,8 @@
   /* Check if something went wrong */
   if(result <= 0) {
       if(result == 0) {
-	/* UDP doesn't know "other end closed" state */
-	if(pss->sockType != UDPSocketType)
+	/* UDP/RAW doesn't know "other end closed" state */
+	if(pss->sockType == TCPSocketType)
 	  pss->sockState = OtherEndClosed;
       } else {
 	int err = WSAGetLastError();
@@ -1185,8 +1199,8 @@
 	  /* NOTE: We consider all other errors to be fatal, e.g.,
 	     report them as "other end closed". Looking at the
 	     WSock documentation this ought to be correct. */
-	  /* UDP doesn't know "other end closed" state */
-	  if(pss->sockType != UDPSocketType) {
+	  /* UDP/RAW doesn't know "other end closed" state */
+	  if(pss->sockType == TCPSocketType) {
 	    pss->sockState = OtherEndClosed;
 	    SIGNAL(pss->connSema);
 	  }
@@ -1255,7 +1269,7 @@
   if (!SocketValid(s)) return -1;
   if(TCPSocketType == s->socketType) { /* TCP */
     if(getpeername(SOCKET(s), (struct sockaddr *)&sin, &sinSize)) return 0; /* failed */
-  } else { /* UDP */
+  } else { /* UDP/RAW */
     MoveMemory(&sin,&(PSP(s)->peer),sinSize);
   }
   if(sin.sin_family != AF_INET) return 0; /* can't handle other than internet addresses */
@@ -1318,13 +1332,23 @@
 
   SOCKET newSocket;
   privateSocketStruct *pss;
+  int domain;
 
+  switch (netType) {
+    case 0: domain= AF_INET;	break;	/* SQ_SOCKET_DOMAIN_UNSPECIFIED */
+    case 2:	domain= AF_INET;	break;	/* SQ_SOCKET_DOMAIN_INET4 */
+    case 3:	domain= AF_INET6;	break;	/* SQ_SOCKET_DOMAIN_INET6 */
+	default:
+		FAIL();
+		return;
+  }
+
   s->sessionID = 0;
   /* perform internal initialization */
   if(socketType == TCPSocketType)
-    newSocket = socket(AF_INET,SOCK_STREAM, 0);
+    newSocket = socket(domain,SOCK_STREAM, 0);
   else if(socketType == UDPSocketType)
-    newSocket = socket(AF_INET, SOCK_DGRAM, 0);
+    newSocket = socket(domain, SOCK_DGRAM, 0);
   else { FAIL(); return; }
   if(newSocket == INVALID_SOCKET) {
     FAIL();
@@ -1332,9 +1356,21 @@
   }
   /* Allow the re-use of the current port */
   setsockopt(newSocket, SOL_SOCKET, SO_REUSEADDR, (char*) &one, sizeof(one));
-  /* Disable TCP delays */
+  /* Make the socket non-blocking */
   ioctlsocket(newSocket,FIONBIO,&one);
 
+   /* XXXX: Work around a Windows Vista bug. Vista's TCP stack tries
+     to auto-tune the TCP window size and fails miserably with some
+     equipment in the middle. The effect is that after a little while
+     the network connection will simply stall and not receive any
+     more data. We work around this by specifying the window size
+     explicitly (only for Vista; one would hope that later versions
+     of windows get this done without failing. */
+  if(runningVista && socketType == TCPSocketType) {
+    unsigned int val = 65536;
+    setsockopt(newSocket, SOL_SOCKET, SO_RCVBUF, &val, sizeof(val));
+  }
+
   /* initialize private socket structure */
   pss = (privateSocketStruct*) calloc(1,sizeof(privateSocketStruct));
   pss->s = newSocket;
@@ -1382,7 +1418,78 @@
   }
 }
 
+/*************************************************************************/
 
+void sqSocketCreateRawProtoTypeRecvBytesSendBytesSemaIDReadSemaIDWriteSemaID(SocketPtr s, int netType, int protoType, int recvBufSize, int sendBufSize, int connSemaIndex, int readSemaIndex, int writeSemaIndex)
+{
+
+  SOCKET newSocket;
+  privateSocketStruct *pss;
+  int domain;
+
+  switch (netType) {
+    case 0: domain= AF_INET;	break;	/* SQ_SOCKET_DOMAIN_UNSPECIFIED */
+    case 2:	domain= AF_INET;	break;	/* SQ_SOCKET_DOMAIN_INET4 */
+    case 3:	domain= AF_INET6;	break;	/* SQ_SOCKET_DOMAIN_INET6 */
+	default:
+		FAIL();
+		return;
+  }
+
+  s->sessionID = 0;
+  /* perform internal initialization */
+  switch(protoType) {
+    case 1: newSocket = socket(domain, SOCK_RAW, IPPROTO_ICMP); break;
+    default: newSocket = INVALID_SOCKET;
+  }
+  if(newSocket == INVALID_SOCKET) {
+    FAIL();
+    return;
+  }
+
+  /* Make the socket non-blocking */
+  ioctlsocket(newSocket,FIONBIO,&one);
+
+  /* initialize private socket structure */
+  pss = (privateSocketStruct*) calloc(1,sizeof(privateSocketStruct));
+  pss->s = newSocket;
+  pss->sockType = RAWSocketType;
+  pss->connSema = connSemaIndex;
+  pss->readSema = readSemaIndex;
+  pss->writeSema = writeSemaIndex;
+
+  /* Raw sockets are born "connected" */
+  pss->sockState = Connected | SOCK_DATA_WRITABLE;
+  pss->sockError= 0;
+
+  /* initial peer := wildcard */
+  ZeroMemory(&pss->peer, sizeof(pss->peer));
+  pss->peer.sin_family= AF_INET;
+  pss->peer.sin_port= htons((short)0);;
+  pss->peer.sin_addr.s_addr= INADDR_ANY;
+
+  /* fill the SQSocket */
+  s->sessionID = thisNetSession;
+  s->socketType = RAWSocketType;
+  s->privateSocketPtr = pss;
+
+  /* Create a new mutex object for synchronized access */
+  pss->mutex = CreateMutex(NULL, 0,NULL);
+  if(!pss->mutex) { FAIL(); return; }
+
+  /* Install the socket into the socket list */
+  pss->next = firstSocket;
+  firstSocket = pss;
+
+  /* Setup the watchers */
+  pss->readWatcherOp = pss->writeWatcherOp = WatchData;
+  if(!createWatcherThreads(pss)) {
+    /* note: necessary cleanup is done from within createWatcherThreads */
+    s->privateSocketPtr = NULL; /* declare invalid */
+    FAIL();
+  }
+}
+
 /*****************************************************************************
   sqSocketAcceptFromRecvBytesSendBytesSemaID:
   Create a new socket by accepting an incoming connection from the source socket.
@@ -1468,9 +1575,9 @@
 sqInt sqSocketReceiveUDPDataBufCountaddressportmoreFlag(SocketPtr s, char *buf, sqInt bufSize,  sqInt *address,  sqInt *port, sqInt *moreFlag)
 {
   int nRead;
-  if(UDPSocketType != s->socketType)
+  if(TCPSocketType == s->socketType)
     return interpreterProxy->primitiveFail();
-  /* bind UDP socket*/
+  /* bind UDP/RAW socket*/
   sqSocketConnectToPort(s, *address, *port);
   if(interpreterProxy->failed()) return 0;
   /* receive data */
@@ -1484,9 +1591,9 @@
 
 sqInt	sqSockettoHostportSendDataBufCount(SocketPtr s, sqInt address, sqInt port, char *buf, sqInt bufSize)
 {
-  if(UDPSocketType != s->socketType)
+  if(TCPSocketType == s->socketType)
     return interpreterProxy->primitiveFail();
-  /* bind UDP socket */
+  /* bind UDP/RAW socket */
   sqSocketConnectToPort(s, address, port);
   if(interpreterProxy->failed()) return 0;
   /* send data */
@@ -1758,6 +1865,7 @@
   /* forget last name */
   lastName[0] = 0;
   /* indicate finished operation */
+  CloseHandle(asyncLookupHandle);
   asyncLookupHandle = 0;
 }
 
@@ -1810,10 +1918,11 @@
   if(asyncLookupHandle) return; /* lookup in progress */
   asyncLookupHandle =
     CreateThread(NULL,                    /* No security descriptor */
-                 0,                       /* default stack size     */
+                 128*1024,                /* max stack size     */
                  (LPTHREAD_START_ROUTINE) &sqGetHostByAddr, /* what to do */
                  (LPVOID) address,        /* parameter for thread   */
-                 CREATE_SUSPENDED,        /* creation parameter -- create suspended so we can check the return value */
+                 CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
+					/* creation parameter -- create suspended so we can check the return value */
                  &id);                    /* return value for thread id */
   if(!asyncLookupHandle)
     printLastError(TEXT("CreateThread() failed"));
@@ -1845,10 +1954,11 @@
   lastError = 0;
   asyncLookupHandle =
     CreateThread(NULL,                    /* No security descriptor */
-                 0,                       /* default stack size     */
+                 128*1024,                /* max stack size     */
                  (LPTHREAD_START_ROUTINE) &sqGetHostByName, /* what to do */
                  (LPVOID) lastName,       /* parameter for thread   */
-                 CREATE_SUSPENDED,        /* creation parameter -- create suspended so we can check the return value */
+                 CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION,
+					/* creation parameter -- create suspended so we can check the return value */
                  &id);                    /* return value for thread id */
   if(!asyncLookupHandle)
     printLastError(TEXT("CreateThread() failed"));
@@ -1895,6 +2005,7 @@
     }
   else
     lastError = WSAGetLastError();
+  CloseHandle(asyncLookupHandle);
   asyncLookupHandle = 0;
   SIGNAL(resolverSemaphoreIndex);
   ExitThread(0);
@@ -1917,6 +2028,7 @@
     }
   else
     lastError = WSAGetLastError();
+  CloseHandle(asyncLookupHandle);
   asyncLookupHandle = 0;
   SIGNAL(resolverSemaphoreIndex);
   ExitThread(0);



More information about the Vm-dev mailing list