--- 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 $'
! !