fixed moving-object-when-interrupted-with-scavenge bugs;
authorClaus Gittinger <cg@exept.de>
Mon, 20 Dec 2004 20:57:03 +0100
changeset 1504 92005eec5c9d
parent 1503 4d97e4191d04
child 1505 5f65beb4aedd
fixed moving-object-when-interrupted-with-scavenge bugs; preps to re-merge with win32_socket
Make.proto
Socket.st
--- a/Make.proto	Mon Dec 20 12:13:54 2004 +0100
+++ b/Make.proto	Mon Dec 20 20:57:03 2004 +0100
@@ -1,4 +1,4 @@
-# $Header: /cvs/stx/stx/libbasic2/Make.proto,v 1.124 2004-03-23 09:40:13 cg Exp $
+# $Header: /cvs/stx/stx/libbasic2/Make.proto,v 1.125 2004-12-20 19:57:03 cg Exp $
 #
 
 TOP=..
@@ -16,10 +16,10 @@
 
 objs::  $(OBJS)
 
-zlib:  
+zlib:
 	cd ../support/zlib; $(MAKE)
 
-bz2lib: 
+bz2lib:
 	cd ../support/bz2lib; $(MAKE) libbz2.a
 
 #
@@ -28,10 +28,10 @@
 #
 # PSPRSTR:
 #       @$(MAKE) PSPrStr.$(O) STCFLAGS="$(STCFLAGS) $(LIMITSUPERINCLUDE) +optspace2"
-# 
+#
 # HPIIPRSTR:
 #       @$(MAKE) HPIIPrStr.$(O) STCFLAGS="$(STCFLAGS) $(LIMITSUPERINCLUDE) +optspace2"
-# 
+#
 # FX1PRSTR:
 #       @$(MAKE) FX1PrStr.$(O) STCFLAGS="$(STCFLAGS) $(LIMITSUPERINCLUDE) +optspace2"
 
@@ -44,5 +44,7 @@
 clobber::
 	@-rm -f *.c *.H classList.stc abbrev.stc
 
+Socket.$(O):   $(INCLUDE)/stxOSDefs.h
+
 # BEGINMAKEDEPEND --- do not remove this line; make depend needs it
 # ENDMAKEDEPEND --- do not remove this line; make depend needs it
--- a/Socket.st	Mon Dec 20 12:13:54 2004 +0100
+++ b/Socket.st	Mon Dec 20 20:57:03 2004 +0100
@@ -33,7 +33,80 @@
 # define __BEGIN_INTERRUPTABLE__ ..
 # define __END_INTERRUPTABLE__ ..
 
-#endif
+# define WRAP_STDIO
+# define DO_WRAP_CALLS
+
+# ifndef DO_WRAP_CALLS
+#  define STX_C_CALL0(__nm__, __f__)                                                    __f__()
+#  define STX_C_CALL1(__nm__, __f__, __a1__)                                            __f__((__a1__))
+#  define STX_C_CALL2(__nm__, __f__, __a1__, __a2__)                                    __f__((__a1__), (__a2__))
+#  define STX_C_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                            __f__((__a1__), (__a2__), (__a3__))
+#  define STX_API_CALL0(__nm__, __f__)                                                  __f__((__a1__))
+#  define STX_API_CALL1(__nm__, __f__, __a1__)                                          __f__((__a1__))
+#  define STX_API_CALL2(__nm__, __f__, __a1__, __a2__)                                  __f__((__a1__), (__a2__))
+#  define STX_API_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                          __f__((__a1__), (__a2__), (__a3__))
+#  define STX_API_CALL4(__nm__, __f__, __a1__, __a2__, __a3__, __a4__)                  __f__((__a1__), (__a2__), (__a3__), (__a4__))
+#  define STX_API_CALL5(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__)          __f__((__a1__), (__a2__), (__a3__), (__a4__), (__a5__))
+#  define STX_API_CALL6(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__, __a6__)  __f__((__a1__), (__a2__), (__a3__), (__a4__), (__a5__), (__a6__))
+# else
+#  define STX_C_CALL0(__nm__, __f__)                                                    __STX_C_CALL0(__nm__,(void*)__f__)
+#  define STX_C_CALL1(__nm__, __f__, __a1__)                                            __STX_C_CALL1(__nm__,(void*)__f__, (void*)(__a1__))
+#  define STX_C_CALL2(__nm__, __f__, __a1__, __a2__)                                    __STX_C_CALL2(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__))
+#  define STX_C_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                            __STX_C_CALL3(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__), (void*)(__a3__))
+#  define STX_API_CALL0(__nm__, __f__)                                                  __STX_API_CALL0(__nm__,(void*)__f__)
+#  define STX_API_CALL1(__nm__, __f__, __a1__)                                          __STX_API_CALL1(__nm__,(void*)__f__, (void*)(__a1__))
+#  define STX_API_CALL2(__nm__, __f__, __a1__, __a2__)                                  __STX_API_CALL2(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__))
+#  define STX_API_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                          __STX_API_CALL3(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__), (void*)(__a3__))
+#  define STX_API_CALL4(__nm__, __f__, __a1__, __a2__, __a3__, __a4__)                  __STX_API_CALL4(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__), (void*)(__a3__), (void*)(__a4__))
+#  define STX_API_CALL5(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__)          __STX_API_CALL5(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__), (void*)(__a3__), (void*)(__a4__), (void*)(__a5__))
+#  define STX_API_CALL6(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__, __a6__)  __STX_API_CALL6(__nm__,(void*)__f__, (void*)(__a1__), (void*)(__a2__), (void*)(__a3__), (void*)(__a4__), (void*)(__a5__), (void*)(__a6__))
+# endif
+
+# ifdef DO_WRAP_CALLS
+#  define GETHOSTBYNAME(hp, name)                    \
+      {                                              \
+	char __hostNm[512];                          \
+						     \
+	strncpy(__hostNm, name, sizeof(__hostNm)-1); \
+	__hostNm[sizeof(__hostNm)-1] = '\0';         \
+	do {                                         \
+	  __threadErrno = 0;                         \
+	  hp = STX_API_CALL1("gethostbyname", gethostbyname, __hostNm); \
+	} while ((hp < 0) && (__threadErrno == EINTR));      \
+      }
+
+#  define GETHOSTBYADDR(hp, addr, alen, af) \
+      do {                                 \
+	__threadErrno = 0;                 \
+	hp = STX_API_CALL3("gethostbyaddr", gethostbyaddr, addr, alen, af);    \
+      } while ((hp < 0) && (__threadErrno == EINTR));
+# else
+#  define GETHOSTBYNAME(hp, name) \
+	__BEGIN_INTERRUPTABLE__  \
+	hp = gethostbyname((char *) name); \
+	__END_INTERRUPTABLE__
+
+#  define GETHOSTBYADDR(hp, addr, alen, af) \
+	__BEGIN_INTERRUPTABLE__ \
+	hp = gethostbyaddr(addr, alen, af); \
+	__END_INTERRUPTABLE__
+# endif /* DO_WRAP_CALLS */
+
+#else /* not WIN32 */
+
+# define STX_C_CALL0(__nm__, __f__)                                                    __f__()
+# define STX_C_CALL1(__nm__, __f__, __a1__)                                            __f__((__a1__))
+# define STX_C_CALL2(__nm__, __f__, __a1__, __a2__)                                    __f__((__a1__), (__a2__))
+# define STX_C_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                            __f__((__a1__), (__a2__), (__a3__))
+# define STX_API_CALL0(__nm__, __f__)                                                  __f__((__a1__))
+# define STX_API_CALL1(__nm__, __f__, __a1__)                                          __f__((__a1__))
+# define STX_API_CALL2(__nm__, __f__, __a1__, __a2__)                                  __f__((__a1__), (__a2__))
+# define STX_API_CALL3(__nm__, __f__, __a1__, __a2__, __a3__)                          __f__((__a1__), (__a2__), (__a3__))
+# define STX_API_CALL4(__nm__, __f__, __a1__, __a2__, __a3__, __a4__)                  __f__((__a1__), (__a2__), (__a3__), (__a4__))
+# define STX_API_CALL5(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__)          __f__((__a1__), (__a2__), (__a3__), (__a4__), (__a5__))
+# define STX_API_CALL6(__nm__, __f__, __a1__, __a2__, __a3__, __a4__, __a5__, __a6__)  __f__((__a1__), (__a2__), (__a3__), (__a4__), (__a5__), (__a6__))
+
+#endif /* WIN32 */
 
 #include <stdio.h>
 #include <errno.h>
@@ -70,6 +143,11 @@
 # define DBGPRINTF(x)    /* as nothing */
 # define DBGFPRINTF(x)   /* as nothing */
 #endif
+#ifdef SRWDEBUG
+# define SRWPRINTF(x)    { if (__debugging__) printf x; }
+#else
+# define SRWPRINTF(x)    /* as nothing */
+#endif
 
 %}
 ! !
@@ -80,6 +158,85 @@
 %}
 ! !
 
+!Socket primitiveFunctions!
+%{
+
+static
+setupBufferParameters(aDataBuffer, startIndex, p_extPtr, p_offs, p_objSize)
+    OBJ aDataBuffer, startIndex;
+    char **p_extPtr;
+    int *p_offs;
+    int *p_objSize;
+{
+	char *extPtr = 0;
+	int sIdx = 0, objSize = 0, offs = 0;
+
+	sIdx = 0;
+	if (__isSmallInteger(startIndex)) {
+	    sIdx = __intVal(startIndex) - 1;
+	}
+
+	if (__isExternalBytesLike(aDataBuffer)) {
+	    OBJ sz;
+
+	    extPtr = (char *)(__externalBytesAddress(aDataBuffer));
+	    sz = __externalBytesSize(aDataBuffer);
+	    if (__isSmallInteger(sz)) {
+		objSize = __intVal(sz);
+	    } else {
+		objSize = 0; /* unknown */
+	    }
+	    offs = sIdx;
+	} else {
+	    OBJ oClass;
+	    int nInstVars, nInstBytes;
+
+	    oClass = __Class(aDataBuffer);
+	    switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+		case BYTEARRAY:
+		    offs = sIdx;
+		    break;
+		case WORDARRAY:
+		case SWORDARRAY:
+		    offs = sIdx * 2;
+		    break;
+		case LONGARRAY:
+		case SLONGARRAY:
+		    offs = sIdx * 4;
+		    break;
+		case LONGLONGARRAY:
+		case SLONGLONGARRAY:
+		    offs = sIdx * 8;
+# ifdef __NEED_LONGLONG_ALIGN
+		    offs += 4;
+# endif
+		    break;
+		case FLOATARRAY:
+		    offs = sIdx * sizeof(float);
+		    break;
+		case DOUBLEARRAY:
+		    offs = sIdx * sizeof(double);
+# ifdef __NEED_DOUBLE_ALIGN
+		    offs += 4;
+# endif
+		    break;
+		default:
+		    objSize = -1;
+		    break;
+	    }
+	    extPtr = (char *)0;
+	    nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+	    nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
+	    offs = offs + nInstBytes;
+	    objSize = _Size(aDataBuffer) - offs;
+	}
+	*p_extPtr = extPtr;
+	*p_objSize = objSize;
+	*p_offs = offs;
+}
+%}
+! !
+
 !Socket class methodsFor:'documentation'!
 
 copyright
@@ -586,9 +743,7 @@
 
     newSock := self newTCP.
     (newSock notNil and:[aServiceOrNil notNil]) ifTrue:[
-	(newSock bindTo:(self portOfService:aServiceOrNil) address:nil) ifFalse:[
-	    ^ nil
-	]
+	^ newSock tryToBindTo:(self portOfService:aServiceOrNil)
     ].
     ^ newSock
 
@@ -678,9 +833,7 @@
 
     newSock := self newTCP.
     newSock notNil ifTrue:[
-	(newSock bindTo:(self portOfService:aService) address:nil) ifFalse:[
-	    ^ nil
-	]
+	^ newSock tryToBindTo:(self portOfService:aService)
     ].
     ^ newSock
 !
@@ -702,9 +855,7 @@
 
     newSock := self newUDP.
     (newSock notNil and:[aServiceOrNil notNil]) ifTrue:[
-	(newSock bindTo:(self portOfService:aServiceOrNil) address:nil) ifFalse:[
-	    ^ nil
-	]
+	^ newSock tryToBindTo:(self portOfService:aServiceOrNil)
     ].
     ^ newSock
 
@@ -718,9 +869,7 @@
 
     newSock := self newUDP.
     newSock notNil ifTrue:[
-	(newSock bindTo:(self portOfService:aService) address:nil) ifFalse:[
-	    ^ nil
-	]
+	^ newSock tryToBindTo:(self portOfService:aService)
     ].
     ^ newSock
 "
@@ -790,9 +939,7 @@
 
     newSock := self newUNIX.
     newSock notNil ifTrue:[
-	(newSock bindTo:pathName address:nil) ifFalse:[
-	    ^ nil
-	]
+	^ newSock tryToBindTo:pathName
     ].
     ^ newSock
 
@@ -809,10 +956,8 @@
 
 family:domainSymbol type:typeSymbol
     "create a socket for domain and type - ST80 simply uses a different name.
-     Domain must be one of the symbols: #inet, #unix, #ns, #appletalk or #ns;
-     Type must be #stream, #datagram or #raw
-
-     XXX: currently only the #inet and #unix domains is supported"
+     Domain must be one of the symbols: #inet, #unix, #appletalk or #ns;
+     Type must be #stream, #datagram or #raw."
 
     ^ self domain:domainSymbol type:typeSymbol
 
@@ -1034,7 +1179,7 @@
     "standard & easy client setup:
 	create new client tcp socket, bind and connect;
 	return the socket.
-     The thread block (interruptable), until the connection is established."
+     The thread blocks (interruptable), until the connection is established."
 
     ^ self newTCPclientToHost:host port:(self portOfService:service).
 
@@ -1217,7 +1362,8 @@
 protocolOfService:aNameOrNumber
     "returns the protocol (as string) for a given IP-service
      or nil if no such service exists."
-%{  /* UNLIMITEDSTACK */
+
+%{  /* UNLIMITEDSTACK(noWIN32) */
 #ifndef NO_SOCKET
     struct servent *servent = NULL;
     short portNo;
@@ -1245,7 +1391,7 @@
     if (servent) {
 	RETURN ( __MKSTRING(servent->s_proto) );
     }
-#endif
+#endif /* !NO_SOCKET */
     RETURN ( nil );
 %}
     "
@@ -1427,56 +1573,63 @@
      The thread blocks until data arrives - you may want to wait before
      receiving, using #readWait or #readWaitWithTimeout:."
 
-
     |nReceived|
 
 %{
 #ifndef NO_SOCKET
-    OBJ oClass, myDomain;
     OBJ fp = __INST(filePointer);
-    int nInstVars, nInstBytes, objSize;
+    int objSize, offs;
     int sock;
     int n;
-    char *cp;
+    char *extPtr;
+    unsigned char *buffer;
+    unsigned char *allocatedBuffer;
     int flags = 0;
 
     if (fp != nil) {
 	sock = fileno(__FILEVal(fp));
 
-	oClass = __Class(aDataBuffer);
-	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-	    case BYTEARRAY:
-	    case WORDARRAY:
-	    case SWORDARRAY:
-	    case LONGARRAY:
-	    case SLONGARRAY:
-	    case FLOATARRAY:
-	    case DOUBLEARRAY:
-		break;
-	    default:
-		goto bad;
-	}
-
-	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
-	objSize = _Size(aDataBuffer) - nInstBytes;
-	cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
-	if (__isSmallInteger(startIndex)) {
-	    cp += __intVal(startIndex);
-	    objSize -= __intVal(startIndex);
-	}
+	setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize);
+	if (objSize < 0) goto bad;
 	if (__isSmallInteger(nBytes)) {
 	    if (__intVal(nBytes) < objSize) {
 		objSize = __intVal(nBytes);
 	    }
 	}
 
+#ifdef WIN32
+	if (extPtr) {
+	    buffer = extPtr + offs;
+	} else {
+	    allocatedBuffer = buffer = (char *)malloc(objSize);
+	}
+#endif
 	__BEGIN_INTERRUPTABLE__
+#ifdef WIN32
+	do {
+	    __threadErrno = 0;
+	    n = STX_API_CALL4("recv", recv, sock, buffer, objSize, flags);
+	} while ((n < 0) && (__threadErrno == EINTR));
+#else
 	do {
-	    n = recv(sock, cp, objSize, flags);
+	    if (extPtr) {
+		n = recv(sock, extPtr + offs, objSize, flags);
+	    } else {
+		n = recv(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags);
+	    }
 	} while ((n < 0) && (errno == EINTR));
+#endif
 	__END_INTERRUPTABLE__
 
+#ifdef WIN32
+	if (allocatedBuffer) {
+	    if (n > 0) {
+		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
+	    }
+	    free(allocatedBuffer);
+	}
+#endif
+
 	if (n < 0) {
 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
 	}
@@ -1541,91 +1694,82 @@
 
 %{
 #ifndef NO_SOCKET
-    OBJ oClass, myDomain;
     OBJ fp = __INST(filePointer);
-    int nInstVars, nInstBytes, objSize;
+    int objSize;
     int sock;
     union sockaddr_u sa;
     int alen = 0;
-    int n, offs, sIdx;
-    char *cp;
+    int n, offs;
     int flags = 0;
+    char *extPtr;
+    unsigned char *allocatedBuffer = NULL;
+    unsigned char *buffer = NULL;
 
     if (fp != nil) {
 	sock = fileno(__FILEVal(fp));
 
-	oClass = __Class(aDataBuffer);
-	offs = 0;
-	sIdx = 0;
-	if (__isSmallInteger(startIndex)) {
-	    sIdx = __intVal(startIndex) - 1;
-	}
-	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-	    case BYTEARRAY:
-		offs = sIdx;
-		break;
-	    case WORDARRAY:
-	    case SWORDARRAY:
-		offs = sIdx * 2;
-		break;
-	    case LONGARRAY:
-	    case SLONGARRAY:
-		offs = sIdx * 4;
-		break;
-	    case LONGLONGARRAY:
-	    case SLONGLONGARRAY:
-		offs = sIdx * 8;
-# ifdef __NEED_LONGLONG_ALIGN
-		offs += 4;
-# endif
-		break;
-	    case FLOATARRAY:
-		offs = sIdx * sizeof(float);
-		break;
-	    case DOUBLEARRAY:
-		offs = sIdx * sizeof(double);
-# ifdef __NEED_DOUBLE_ALIGN
-		offs += 4;
-# endif
-		break;
-	    default:
-		goto bad;
-	}
-
-	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
-	objSize = _Size(aDataBuffer) - nInstBytes;
-	objSize -= offs;
+	setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize);
+	if (objSize < 0) goto bad;
 	if (__isSmallInteger(nBytes)) {
 	    if (__intVal(nBytes) < objSize) {
 		objSize = __intVal(nBytes);
 	    }
 	}
-
+#ifdef WIN32
+	if (extPtr) {
+	    buffer = extPtr + offs;
+	} else {
+	    allocatedBuffer = buffer = (char *)malloc(objSize);
+	}
+#endif
 	__BEGIN_INTERRUPTABLE__
+#ifdef WIN32
+	do {
+	    __threadErrno = 0;
+	    alen = sizeof(sa);
+	    n = STX_API_CALL6("recvfrom", recvfrom, sock, buffer, objSize, flags, (struct sockaddr *)&sa, &alen);
+	} while ((n < 0) && (__threadErrno == EINTR));
+#else
 	do {
-	    cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
 	    alen = sizeof(sa);
-	    n = recvfrom(sock, cp, objSize, flags, (struct sockaddr *) &sa, &alen);
+	    if (extPtr) {
+		n = recvfrom(sock, extPtr + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
+	    } else {
+		n = recvfrom(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags, (struct sockaddr *) &sa, &alen);
+	    }
 	} while ((n < 0) && (errno == EINTR));
+#endif
 	__END_INTERRUPTABLE__
 
+#ifdef WIN32
+	if (allocatedBuffer) {
+	    if (n > 0) {
+		bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n);
+	    }
+	    free(allocatedBuffer);
+	}
+#endif
+
 	if (n >= 0) {
 	    if (__isNonNilObject(addr)) {
+		char *addrPtr;
+		OBJ oClass;
+		int nInstVars, nInstBytes, objSize;
+
 		oClass = __qClass(addr);
 		if (! __isBytes(addr) )
 		    goto bad;
 		nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
 		nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ));
 		objSize = __qSize(addr) - nInstBytes;
-		cp = (char *)__InstPtr(addr) + nInstBytes;
+		addrPtr = (char *)__InstPtr(addr) + nInstBytes;
 		if (objSize < alen)
 		    goto bad;
 
 		/*
 		 * extract the datagrams address
 		 */
-		bcopy((char *)&sa, cp, alen);
+		bcopy((char *)&sa, addrPtr, alen);
 		addrLen = __MKSMALLINT(alen);
 	    }
 	}
@@ -1661,7 +1805,7 @@
     self primitiveFailed
 !
 
-sendBuffer:aDataBuffer start:startIndex for:count flags:flags
+sendBuffer:aDataBuffer start:startIndex for:nBytes flags:flags
     "send data.
      Both must be ByteArray-like. The bytes in the addressBuffer must
      be a valid address for my domain (i.e. for inet, a 4-byte byteArray).
@@ -1675,78 +1819,67 @@
 #ifndef NO_SOCKET
     OBJ oClass;
     OBJ fp = __INST(filePointer);
-    int nInstVars, nInstBytes, objSize;
+    int objSize;
     int sock;
     int n;
-    char *cp;
+    char *extPtr;
     int _flags = 0;
-    int offs, nBytes, sIdx;
+    int offs;
     unsigned long norder;
+    unsigned char *buffer;
+    unsigned char *allocatedBuffer;
 
     _flags = __longIntVal(flags);
 
     if ((fp != nil)
      && __isSmallInteger(startIndex)
-     && __isSmallInteger(count)) {
+     && __isSmallInteger(nBytes)) {
 	sock = fileno(__FILEVal(fp));
 
-	oClass = __Class(aDataBuffer);
-	sIdx = __intVal(startIndex) - 1;
-	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-	    case BYTEARRAY:
-		offs = sIdx;
-		break;
-	    case WORDARRAY:
-	    case SWORDARRAY:
-		offs = sIdx * 2;
-		break;
-	    case LONGARRAY:
-	    case SLONGARRAY:
-		offs = sIdx * 4;
-		break;
-	    case LONGLONGARRAY:
-	    case SLONGLONGARRAY:
-		offs = sIdx * 8;
-# ifdef __NEED_LONGLONG_ALIGN
-		offs += 4;
-# endif
-		break;
-	    case FLOATARRAY:
-		offs = sIdx * sizeof(float);
-		break;
-	    case DOUBLEARRAY:
-		offs = sIdx * sizeof(double);
-# ifdef __NEED_DOUBLE_ALIGN
-		offs += 4;
-# endif
-		break;
-	    default:
-		goto bad;
-	}
-	nBytes = __intVal(count);
-
-	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
-	objSize = __qSize(aDataBuffer) - nInstBytes;
-	cp = (char *)__InstPtr(aDataBuffer) + nInstBytes;
-	cp += offs;
-	if ((offs + nBytes) > objSize) {
-# ifdef DGRAM_DEBUG
-	    printf("cut off ...\n");
-# endif
-	    nBytes = objSize - offs;
+	setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize);
+	if (objSize < 0) goto bad;
+	if (__isSmallInteger(nBytes)) {
+	    if (__intVal(nBytes) < objSize) {
+		objSize = __intVal(nBytes);
+	    }
 	}
 
 # ifdef DGRAM_DEBUG
 	printf("sending %d bytes ...\n", nBytes);
 # endif
 
+#ifdef WIN32
+	if (extPtr) {
+	    buffer = extPtr + offs;
+	} else {
+	    allocatedBuffer = buffer = (char *)malloc(objSize);
+	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
+	}
+#endif
+
 	__BEGIN_INTERRUPTABLE__
+#ifdef WIN32
 	do {
-	    n = send(sock, cp, nBytes, _flags);
+	    __threadErrno = 0;
+	    n = STX_API_CALL4("send", send, sock, buffer, objSize, _flags);
+	} while ((n < 0) && (__threadErrno == EINTR));
+#else
+	do {
+	    if (extPtr) {
+		n = send(sock, extPtr + offs, objSize, _flags);
+	    } else {
+		n = send(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags);
+	    }
 	} while ((n < 0) && (errno == EINTR));
+#endif
 	__END_INTERRUPTABLE__
 
+#ifdef WIN32
+	if (allocatedBuffer) {
+	    free(allocatedBuffer);
+	}
+#endif
+
 	if (n < 0) {
 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
 	}
@@ -1787,7 +1920,7 @@
     ^ self sendTo:anAddressBuffer buffer:buffer start:startIndex for:count flags:0
 !
 
-sendTo:anAddressBuffer buffer:aDataBuffer start:startIndex for:count flags:flags
+sendTo:anAddressBuffer buffer:aDataBuffer start:startIndex for:nBytes flags:flags
     "send datagramm data - fetch address of destination host from
      anAddressBuffer, data from aDataBuffer starting at startIndex,
      sending count bytes.
@@ -1816,21 +1949,25 @@
 #ifndef NO_SOCKET
     OBJ oClass;
     OBJ fp = __INST(filePointer);
-    int nInstVars, nInstBytes, objSize;
+    int objSize;
     struct sockaddr *sockaddr_ptr;
+    union sockaddr_u sa;
+    int alen = 0;
     int sockAddrOffs, sockaddr_size;
     int sock;
     int n;
-    char *cp;
+    char *extPtr;
     int _flags = 0;
-    int offs, nBytes;
+    int offs;
     unsigned long norder;
+    unsigned char *buffer;
+    unsigned char *allocatedBuffer;
 
     _flags = __longIntVal(flags);
 
     if ((fp != nil)
      && __isSmallInteger(startIndex)
-     && __isSmallInteger(count)) {
+     && __isSmallInteger(nBytes)) {
 	sock = fileno(__FILEVal(fp));
 
 	if (! __isBytes(addr)) {
@@ -1845,60 +1982,52 @@
 		sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
 	    nIndex = __qSize(addr) - OHDR_SIZE;
 	    sockaddr_size = nIndex - sockAddrOffs;
-	    sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
+	    if (sockaddr_size > sizeof(sa)) {
+		fprintf(stderr, "bad socketAddr\n");
+		goto bad;
+	    }
+	    bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
+	    sockaddr_ptr = (struct sockaddr *)(&sa);
+	}
+
+	setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize);
+	if (objSize < 0) goto bad;
+	if (__isSmallInteger(nBytes)) {
+	    if (__intVal(nBytes) < objSize) {
+		objSize = __intVal(nBytes);
+	    }
+	}
+
+#ifdef WIN32
+	if (extPtr) {
+	    buffer = extPtr + offs;
+	} else {
+	    allocatedBuffer = buffer = (char *)malloc(objSize);
+	    bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize);
 	}
-
-	oClass = __Class(aDataBuffer);
-	switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
-	    case BYTEARRAY:
-		offs = __intVal(startIndex) - 1;
-		break;
-	    case WORDARRAY:
-	    case SWORDARRAY:
-		offs = (__intVal(startIndex) - 1) * 2;
-		break;
-	    case LONGARRAY:
-	    case SLONGARRAY:
-		offs = (__intVal(startIndex) - 1) * 4;
-		break;
-	    case LONGLONGARRAY:
-	    case SLONGLONGARRAY:
-		offs = (__intVal(startIndex) - 1) * 8;
-# ifdef __NEED_LONGLONG_ALIGN
-		offs += 4;
-# endif
-		break;
-	    case FLOATARRAY:
-		offs = (__intVal(startIndex) - 1) * sizeof(float);
-		break;
-	    case DOUBLEARRAY:
-		offs = (__intVal(startIndex) - 1) * sizeof(double);
-# ifdef __NEED_DOUBLE_ALIGN
-		offs += 4;
-# endif
-		break;
-	    default:
-		goto bad;
+#endif
+	__BEGIN_INTERRUPTABLE__
+#ifdef WIN32
+	do {
+	    __threadErrno = 0;
+	    n = STX_API_CALL4("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size);
+	} while ((n < 0) && (__threadErrno == EINTR));
+#else
+	do {
+	    if (extPtr) {
+		n = sendto(sock, extPtr + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
+	    } else {
+		n = sendto(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, _flags, sockaddr_ptr, sockaddr_size);
+	    }
+	} while ((n < 0) && (errno == EINTR));
+#endif
+	__END_INTERRUPTABLE__
+
+#ifdef WIN32
+	if (allocatedBuffer) {
+	    free(allocatedBuffer);
 	}
-	nBytes = __intVal(count);
-
-	nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
-	nInstBytes = OHDR_SIZE + nInstVars * sizeof(OBJ);
-	objSize = __qSize(aDataBuffer) - nInstBytes;
-	if ((offs + nBytes) > objSize) {
-# ifdef DGRAM_DEBUG
-	    printf("cut off ...\n");
-# endif
-	    nBytes = objSize - offs;
-	}
-
-	__BEGIN_INTERRUPTABLE__
-	do {
-	    sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
-	    cp = (char *)__InstPtr(aDataBuffer) + nInstBytes + offs;
-	    n = sendto(sock, cp, nBytes, _flags, sockaddr_ptr, sockaddr_size);
-	} while ((n < 0) && (errno == EINTR));
-	__END_INTERRUPTABLE__
+#endif
 
 	if (n < 0) {
 	    __INST(lastErrorNumber) = __MKSMALLINT(errno);
@@ -2007,22 +2136,24 @@
     portNrOrNameOrNil notNil ifTrue:[
 	addr port:portNrOrNameOrNil.
     ].
+    (portNrOrNameOrNil isNil or:[portNrOrNameOrNil == 0]) ifTrue:[
+	addr := addr copy.
+    ].
 
 %{  /* STACK: 100000 */
 #ifndef NO_SOCKET
     OBJ t = __INST(filePointer);
-    OBJ myDomain;
     int sock;
     union sockaddr_u sa;
     struct sockaddr *sockaddr_ptr;
     int sockaddr_size;
     int ret;
-    int on = 1;
     int sockAddrOffs;
 
     if (! __isBytes(addr)) {
 	addr = nil;
-	goto getOutOfHere;
+	fprintf(stderr, "Socket: bad sddr\n");
+	RETURN (false);
     }
 
     {
@@ -2034,13 +2165,19 @@
 	    sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
 	nIndex = __qSize(addr) - OHDR_SIZE;
 	sockaddr_size = nIndex - sockAddrOffs;
-	sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
+	if (sockaddr_size > sizeof(sa)) {
+	    fprintf(stderr, "Socket: bad socketAddr\n");
+	    RETURN (false);
+	}
+	bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
     }
 
     sock = fileno(__FILEVal(t));
 
 # ifdef SO_REUSEADDR
     if (reuse == true) {
+	int on = 1;
+
 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof (on)) < 0) {
 	    DBGPRINTF(("SOCKET: setsockopt - SO_REUSEADDR failed\n"));
 	}
@@ -2049,8 +2186,7 @@
 
     __BEGIN_INTERRUPTABLE__
     do {
-	sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + sockAddrOffs);
-	ret = bind(sock, sockaddr_ptr, sockaddr_size);
+	ret = bind(sock, (struct sockaddr *)&sa, sockaddr_size);
     } while ((ret < 0) && (errno == EINTR));
     __END_INTERRUPTABLE__
 
@@ -2064,13 +2200,19 @@
 	if (! __isSmallInteger(portNrOrNameOrNil)
 	 || (portNrOrNameOrNil == __MKSMALLINT(0))) {
 	    int p;
+	    int alen;
 
 	    /*
 	     * anonymous port - get the actual portNr
 	     */
-	    if (getsockname(sock, sockaddr_ptr, &sockaddr_size) < 0) {
+	    if (getsockname(sock, (struct sockaddr *)&sa, &alen) < 0) {
 		DBGPRINTF(("SOCKET: cannot get peername\n"));
 	    }
+	    if ((alen > sizeof(sa)) || (alen > sockaddr_size)) {
+		fprintf(stderr, "SOCKET: large addr returned\n");
+	    } else {
+		bcopy(&sa, (__byteArrayVal(addr) + sockAddrOffs), alen);
+	    }
 	}
     }
 
@@ -2093,6 +2235,14 @@
 	 bindTo:9999
 	 address:nil
     "
+!
+
+tryToBindTo:portNrOrNameOrNil
+    (self bindTo:portNrOrNameOrNil address:nil) ifFalse:[
+	self close.
+	^ nil
+    ].
+    ^ self.
 ! !
 
 !Socket protectedMethodsFor:'low level'!
@@ -2557,7 +2707,7 @@
 
 #ifndef NO_SOCKET
     OBJ t = __INST(filePointer);
-    struct sockaddr *sockaddr_ptr;
+    union sockaddr_u sa;
     int a, sock;
     FILE *fp;
     int ret, oldFlags;
@@ -2570,15 +2720,19 @@
     }
 
     {
-	int indx, nIndex;
+	int sockAddrOffs, nIndex;
 	OBJ cls;
 
-	indx = 0;
+	sockAddrOffs = 0;
 	if ((cls = __qClass(addr)) != @global(ByteArray))
-	    indx += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
+	    sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars));
 	nIndex = __qSize(addr) - OHDR_SIZE;
-	sockaddr_size = nIndex - indx;
-	sockaddr_ptr = (struct sockaddr *)(__byteArrayVal(addr) + indx);
+	sockaddr_size = nIndex - sockAddrOffs;
+	if (sockaddr_size > sizeof(sa)) {
+	    fprintf(stderr, "Socket: bad socketAddr\n");
+	    RETURN (false);
+	}
+	bcopy((__byteArrayVal(addr) + sockAddrOffs), &sa, sockaddr_size);
     }
 
     sock = fileno(__FILEVal(t));
@@ -2597,7 +2751,7 @@
      */
     __BEGIN_INTERRUPTABLE__
     do {
-	ret = connect(sock, sockaddr_ptr, sockaddr_size);
+	ret = connect(sock, (struct sockaddr *)&sa, sockaddr_size);
     } while ((ret < 0)
 	     && ((errno == EINTR)
 # ifdef EAGAIN
@@ -3183,5 +3337,5 @@
 !Socket class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.204 2004-12-20 11:13:54 cg Exp $'
+    ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.205 2004-12-20 19:57:03 cg Exp $'
 ! !