# HG changeset patch # User Stefan Vogel # Date 1448477643 -3600 # Node ID ed7fe78f2587b340ab261e81cf3ad95ad931174b # Parent eb81fa3d84079f722fc6d94283c41047d524b864 #OTHER class: Socket changed: #connect:withTimeout: allow connect: to be interrupted (Windows) return immediately on connect error (Linux) diff -r eb81fa3d8407 -r ed7fe78f2587 Socket.st --- a/Socket.st Tue Nov 24 12:12:21 2015 +0100 +++ b/Socket.st Wed Nov 25 19:54:03 2015 +0100 @@ -141,72 +141,72 @@ static int setupBufferParameters(OBJ aDataBuffer, OBJ startIndex, char **p_extPtr, INT *p_offs, size_t *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; - - extPtr = (char *)0; - 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; + 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; + + extPtr = (char *)0; + 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; + offs += 4; # endif - break; - case FLOATARRAY: - offs = sIdx * sizeof(float); - break; - case DOUBLEARRAY: - offs = sIdx * sizeof(double); + break; + case FLOATARRAY: + offs = sIdx * sizeof(float); + break; + case DOUBLEARRAY: + offs = sIdx * sizeof(double); # ifdef __NEED_DOUBLE_ALIGN - offs += 4; + offs += 4; # endif - break; - default: - *p_objSize = -1; - return 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; - return 1; + break; + default: + *p_objSize = -1; + return 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; + return 1; } %} ! ! @@ -2158,7 +2158,9 @@ sock = SOCKET_FROM_FILE_OBJECT(fp); -# if defined(O_NONBLOCK) && !defined(WIN32) +#ifdef WIN32 + ioctlsocket(sock, FIONBIO, &on); +#elif defined(O_NONBLOCK) /* * set to non-blocking and wait later */ @@ -2171,7 +2173,9 @@ * connect */ -# if defined(DO_WRAP_CALLS) +// we do not use wrap calls any longer, bacuse they have problems with aborting. +// we use nonblocking accept() instead. +# if 0 && defined(DO_WRAP_CALLS) // __setWrapCallDebugging(1,1); @@ -2188,26 +2192,42 @@ if (getsockopt(sock, SOL_SOCKET, SO_ERROR, &errno, &optLen) == SOCKET_ERROR) { DBGFPRINTF((stderr, "SOCKET: getsockopt(SO_ERROR) failed: %d\n", WSAGetLastError())); } -#endif +#endif // 0 } // __setWrapCallDebugging(1,0); -# else +# else // !DO_WRAP_CALLS + +# if !defined(WIN32) && !defined(O_NONBLOCK) __BEGIN_INTERRUPTABLE__ +# endif do { ret = connect(sock, (struct sockaddr *)&sa, sockaddr_size); } while ((ret < 0) +# ifdef WIN32 + && (errno = WSAGetLastError()) +# endif && ((errno == EINTR) -# ifdef EAGAIN +# ifdef EAGAIN || (errno == EAGAIN) -# endif +# endif )); +# if !defined(WIN32) && !defined(O_NONBLOCK) __END_INTERRUPTABLE__ +# endif +#endif + +#if defined(WIN32) && !defined(EINPROGRESS) +# define EINPROGRESSS WSAEINPROGRESSS +# define EALREADY WSAEALREADY #endif if (ret < 0) { # if defined(EINPROGRESS) || defined(EALREADY) if (0 +# ifdef WIN32 + || (errno == WSAEWOULDBLOCK) +# endif # ifdef EINPROGRESS || (errno == EINPROGRESS) # endif @@ -2241,7 +2261,12 @@ } } -# if defined(O_NONBLOCK) && !defined(WIN32) +# ifdef WIN32 + { + int off = 0; + ioctlsocket(sock, FIONBIO, &off); + } +# elif defined(O_NONBLOCK) // Linux / Unix fcntl(sock, F_SETFL, oldFlags); # endif @@ -2261,9 +2286,10 @@ "/ (OperatingSystem errorHolderForNumber:err) reportError. ]. isAsync == true ifTrue:[ - (self writeWaitWithTimeoutMs:timeout) ifTrue:[ + (self writeExceptionWaitWithTimeoutMs:timeout) ifTrue:[ "/ a timeout occured "/ should I cancel the connect? + lastErrorNumber := OperatingSystem errorNumberFor:#ETIMEDOUT. ^ false. ]. err := self getSocketError. @@ -2312,67 +2338,67 @@ OBJ fp = __INST(handle); if (fp != nil) { - SOCKET sock; - INT objSize, offs; - INT n; - char *extPtr; - unsigned char *buffer; - unsigned char *allocatedBuffer = NULL; - INT flags = 0; - - sock = SOCKET_FROM_FILE_OBJECT(fp); - - if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; - if (__isSmallInteger(nBytes)) { - if (__intVal(nBytes) < objSize) { - objSize = __intVal(nBytes); - } - } + SOCKET sock; + INT objSize, offs; + INT n; + char *extPtr; + unsigned char *buffer; + unsigned char *allocatedBuffer = NULL; + INT flags = 0; + + sock = SOCKET_FROM_FILE_OBJECT(fp); + + if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; + if (__isSmallInteger(nBytes)) { + if (__intVal(nBytes) < objSize) { + objSize = __intVal(nBytes); + } + } # ifdef DO_WRAP_CALLS - if (extPtr) { - buffer = extPtr + offs; - } else { - allocatedBuffer = buffer = (char *)malloc(objSize); - } - - do { - __threadErrno = 0; - n = (INT)STX_WSA_NOINT_CALL4("recv", recv, sock, buffer, objSize, flags); - } while ((n < 0) && (__threadErrno == EINTR)); - if (n < 0) { - errno = __threadErrno; - } - - if (allocatedBuffer) { - if (n > 0) { - bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n); - } - free(allocatedBuffer); - } + if (extPtr) { + buffer = extPtr + offs; + } else { + allocatedBuffer = buffer = (char *)malloc(objSize); + } + + do { + __threadErrno = 0; + n = (INT)STX_WSA_NOINT_CALL4("recv", recv, sock, buffer, objSize, flags); + } while ((n < 0) && (__threadErrno == EINTR)); + if (n < 0) { + errno = __threadErrno; + } + + if (allocatedBuffer) { + if (n > 0) { + bcopy(allocatedBuffer, (char *)__InstPtr(aDataBuffer) + offs, n); + } + free(allocatedBuffer); + } # else - __BEGIN_INTERRUPTABLE__ - do { - if (extPtr) { - n = recv(sock, extPtr + offs, objSize, flags); - } else { - n = recv(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags); - } - } while ((n < 0) && (errno == EINTR)); - __END_INTERRUPTABLE__ + __BEGIN_INTERRUPTABLE__ + do { + if (extPtr) { + n = recv(sock, extPtr + offs, objSize, flags); + } else { + n = recv(sock, (char *)__InstPtr(aDataBuffer) + offs, objSize, flags); + } + } while ((n < 0) && (errno == EINTR)); + __END_INTERRUPTABLE__ # endif - if (n < 0) { - error = __INST(lastErrorNumber) = __MKSMALLINT(errno); - } else { - RETURN(__MKSMALLINT(n)); - } + if (n < 0) { + error = __INST(lastErrorNumber) = __MKSMALLINT(errno); + } else { + RETURN(__MKSMALLINT(n)); + } } #endif bad: ; %}. error notNil ifTrue:[ - ^ self readError:error. + ^ self readError:error. ]. " arrive here if you try to receive into an invalid buffer (i.e. not ByteArray-like) @@ -2412,17 +2438,17 @@ domainClass := self class socketAddressClassForDomain:domain. domainClass isNil ifTrue:[ - ^ self error:'invalid (unsupported) domain'. + ^ self error:'invalid (unsupported) domain'. ]. (anAddressBuffer isKindOf:SocketAddress) ifTrue:[ - anAddressBuffer class == domainClass ifFalse:[ - ^ self error:'addressBuffer class mismatch (domain)'. - ]. - addr := anAddressBuffer. + anAddressBuffer class == domainClass ifFalse:[ + ^ self error:'addressBuffer class mismatch (domain)'. + ]. + addr := anAddressBuffer. ] ifFalse:[ - anAddressBuffer notNil ifTrue:[ - addr := domainClass new. - ]. + anAddressBuffer notNil ifTrue:[ + addr := domainClass new. + ]. ]. %{ @@ -2430,103 +2456,103 @@ OBJ fp = __INST(handle); if (fp != nil) { - SOCKET sock; - size_t objSize; - union sockaddr_u sa; - socklen_t alen = 0; - INT n, offs; - int _flags = __longIntVal(flags); - char *extPtr; - unsigned char *allocatedBuffer = NULL, *buffer = NULL; - - sock = SOCKET_FROM_FILE_OBJECT(fp); - - if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; - if (__isSmallInteger(nBytes)) { - if (__intVal(nBytes) < objSize) { - objSize = __intVal(nBytes); - } - } + SOCKET sock; + size_t objSize; + union sockaddr_u sa; + socklen_t alen = 0; + INT n, offs; + int _flags = __longIntVal(flags); + char *extPtr; + unsigned char *allocatedBuffer = NULL, *buffer = NULL; + + sock = SOCKET_FROM_FILE_OBJECT(fp); + + if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; + if (__isSmallInteger(nBytes)) { + if (__intVal(nBytes) < objSize) { + objSize = __intVal(nBytes); + } + } # ifdef DO_WRAP_CALLS - if (extPtr) { - buffer = extPtr + offs; - } else { - allocatedBuffer = buffer = (char *)malloc(objSize); - } - - do { - __threadErrno = 0; - alen = sizeof(sa); - n = (INT)STX_WSA_NOINT_CALL6("recvfrom", recvfrom, sock, buffer, objSize, _flags, (struct sockaddr *)&sa, &alen); - } while ((n < 0) && (__threadErrno == EINTR)); - if (n < 0) { - errno = __threadErrno; - } - - if (allocatedBuffer) { - if (n > 0) { - memcpy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, n); - } - free(allocatedBuffer); - } + if (extPtr) { + buffer = extPtr + offs; + } else { + allocatedBuffer = buffer = (char *)malloc(objSize); + } + + do { + __threadErrno = 0; + alen = sizeof(sa); + n = (INT)STX_WSA_NOINT_CALL6("recvfrom", recvfrom, sock, buffer, objSize, _flags, (struct sockaddr *)&sa, &alen); + } while ((n < 0) && (__threadErrno == EINTR)); + if (n < 0) { + errno = __threadErrno; + } + + if (allocatedBuffer) { + if (n > 0) { + memcpy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, n); + } + free(allocatedBuffer); + } # else - __BEGIN_INTERRUPTABLE__ - do { - alen = sizeof(sa); - 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)); - __END_INTERRUPTABLE__ + __BEGIN_INTERRUPTABLE__ + do { + alen = sizeof(sa); + 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)); + __END_INTERRUPTABLE__ # 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; - addrPtr = (char *)__InstPtr(addr) + nInstBytes; - if (objSize < alen) - goto bad; - - /* - * extract the datagrams address - */ - memcpy(addrPtr, (char *)&sa, alen); - addrLen = __MKSMALLINT(alen); - } - } - if (n < 0) { - error = __INST(lastErrorNumber) = __MKSMALLINT(errno); - } - nReceived = __MKSMALLINT(n); + 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; + addrPtr = (char *)__InstPtr(addr) + nInstBytes; + if (objSize < alen) + goto bad; + + /* + * extract the datagrams address + */ + memcpy(addrPtr, (char *)&sa, alen); + addrLen = __MKSMALLINT(alen); + } + } + if (n < 0) { + error = __INST(lastErrorNumber) = __MKSMALLINT(errno); + } + nReceived = __MKSMALLINT(n); } #endif bad: ; %}. error notNil ifTrue:[ - ^ self readError:error. + ^ self readError:error. ]. nReceived notNil ifTrue:[ - addrLen notNil ifTrue:[ - (addr == anAddressBuffer) ifFalse:[ - self obsoleteFeatureWarning:'please use a socketAddress argument'. - - "can be a ByteArray for backward compatibility" - anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress). - ]. - ]. - ^ nReceived + addrLen notNil ifTrue:[ + (addr == anAddressBuffer) ifFalse:[ + self obsoleteFeatureWarning:'please use a socketAddress argument'. + + "can be a ByteArray for backward compatibility" + anAddressBuffer replaceFrom:1 to:addrLen with:(addr hostAddress). + ]. + ]. + ^ nReceived ]. " arrive here if you try to receive into an invalid buffer @@ -2554,68 +2580,68 @@ if ((fp != nil) && __isSmallInteger(startIndex) && __isSmallInteger(nBytes)) { - SOCKET sock; - INT objSize, n, offs; - char *extPtr; - int _flags = __longIntVal(flags); - unsigned long norder; - unsigned char *buffer, *allocatedBuffer = NULL; - - sock = SOCKET_FROM_FILE_OBJECT(fp); - - if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; - if (__isSmallInteger(nBytes)) { - if (__intVal(nBytes) < objSize) { - objSize = __intVal(nBytes); - } - } + SOCKET sock; + INT objSize, n, offs; + char *extPtr; + int _flags = __longIntVal(flags); + unsigned long norder; + unsigned char *buffer, *allocatedBuffer = NULL; + + sock = SOCKET_FROM_FILE_OBJECT(fp); + + if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; + if (__isSmallInteger(nBytes)) { + if (__intVal(nBytes) < objSize) { + objSize = __intVal(nBytes); + } + } # ifdef DGRAM_DEBUG - console_printf("sending %d bytes ...\n", nBytes); + console_printf("sending %d bytes ...\n", nBytes); # endif #ifdef DO_WRAP_CALLS - if (extPtr) { - buffer = extPtr + offs; - } else { - allocatedBuffer = buffer = (char *)malloc(objSize); - bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); - } - - do { - __threadErrno = 0; - n = (INT)STX_WSA_NOINT_CALL4("send", send, sock, buffer, objSize, _flags); - } while ((n < 0) && (__threadErrno == EINTR)); - if (n < 0) { - errno = __threadErrno; - } - - if (allocatedBuffer) { - free(allocatedBuffer); - } + if (extPtr) { + buffer = extPtr + offs; + } else { + allocatedBuffer = buffer = (char *)malloc(objSize); + bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); + } + + do { + __threadErrno = 0; + n = (INT)STX_WSA_NOINT_CALL4("send", send, sock, buffer, objSize, _flags); + } while ((n < 0) && (__threadErrno == EINTR)); + if (n < 0) { + errno = __threadErrno; + } + + if (allocatedBuffer) { + free(allocatedBuffer); + } #else - __BEGIN_INTERRUPTABLE__ - 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)); - __END_INTERRUPTABLE__ + __BEGIN_INTERRUPTABLE__ + 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)); + __END_INTERRUPTABLE__ #endif - if (n < 0) { - error = __INST(lastErrorNumber) = __MKSMALLINT(errno); - } else { - RETURN (__MKSMALLINT(n)); - } + if (n < 0) { + error = __INST(lastErrorNumber) = __MKSMALLINT(errno); + } else { + RETURN (__MKSMALLINT(n)); + } } #endif bad: ; %}. error notNil ifTrue:[ - self writeError:error. + self writeError:error. ]. " @@ -2663,16 +2689,16 @@ |domainClass addr error| (anAddressBuffer isKindOf:SocketAddress) ifTrue:[ - addr := anAddressBuffer. + addr := anAddressBuffer. ] ifFalse:[ - anAddressBuffer isByteArray ifFalse:[ - ^ self error:'bad socketAddress argument' - ]. - domainClass := self class socketAddressClassForDomain:domain. - domainClass isNil ifTrue:[ - ^ self error:'invalid (unsupported) domain'. - ]. - addr := domainClass hostAddress:anAddressBuffer. + anAddressBuffer isByteArray ifFalse:[ + ^ self error:'bad socketAddress argument' + ]. + domainClass := self class socketAddressClassForDomain:domain. + domainClass isNil ifTrue:[ + ^ self error:'invalid (unsupported) domain'. + ]. + addr := domainClass hostAddress:anAddressBuffer. ]. %{ #ifndef NO_SOCKET @@ -2681,90 +2707,90 @@ if ((fp != nil) && __isSmallInteger(startIndex) && __isSmallInteger(nBytes)) { - SOCKET sock; - INT objSize; - struct sockaddr *sockaddr_ptr; - union sockaddr_u sa; - socklen_t sockaddr_size, alen = 0; - INT sockAddrOffs; - INT n, offs; - char *extPtr; - int _flags = __longIntVal(flags); - unsigned long norder; - unsigned char *buffer; - unsigned char *allocatedBuffer = NULL; - - sock = SOCKET_FROM_FILE_OBJECT(fp); - - if (! __isBytes(addr)) { - sockaddr_size = 0; - sockaddr_ptr = (struct sockaddr *)0; - } else { - int nIndex; - OBJ cls; - - sockAddrOffs = 0; - if ((cls = __qClass(addr)) != @global(ByteArray)) - sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); - nIndex = __qSize(addr) - OHDR_SIZE; - sockaddr_size = nIndex - sockAddrOffs; - if (sockaddr_size > sizeof(sa)) { - console_fprintf(stderr, "Socket [warning]: bad socketAddr\n"); - goto bad; - } - memcpy(&sa, (__byteArrayVal(addr) + sockAddrOffs), sockaddr_size); - sockaddr_ptr = (struct sockaddr *)(&sa); - } - - if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; - if (__isSmallInteger(nBytes)) { - if (__intVal(nBytes) < objSize) { - objSize = __intVal(nBytes); - } - } + SOCKET sock; + INT objSize; + struct sockaddr *sockaddr_ptr; + union sockaddr_u sa; + socklen_t sockaddr_size, alen = 0; + INT sockAddrOffs; + INT n, offs; + char *extPtr; + int _flags = __longIntVal(flags); + unsigned long norder; + unsigned char *buffer; + unsigned char *allocatedBuffer = NULL; + + sock = SOCKET_FROM_FILE_OBJECT(fp); + + if (! __isBytes(addr)) { + sockaddr_size = 0; + sockaddr_ptr = (struct sockaddr *)0; + } else { + int nIndex; + OBJ cls; + + sockAddrOffs = 0; + if ((cls = __qClass(addr)) != @global(ByteArray)) + sockAddrOffs += __OBJS2BYTES__(__intVal(__ClassInstPtr(cls)->c_ninstvars)); + nIndex = __qSize(addr) - OHDR_SIZE; + sockaddr_size = nIndex - sockAddrOffs; + if (sockaddr_size > sizeof(sa)) { + console_fprintf(stderr, "Socket [warning]: bad socketAddr\n"); + goto bad; + } + memcpy(&sa, (__byteArrayVal(addr) + sockAddrOffs), sockaddr_size); + sockaddr_ptr = (struct sockaddr *)(&sa); + } + + if (! setupBufferParameters(aDataBuffer, startIndex, &extPtr, &offs, &objSize)) goto bad; + if (__isSmallInteger(nBytes)) { + if (__intVal(nBytes) < objSize) { + objSize = __intVal(nBytes); + } + } #ifdef DO_WRAP_CALLS - if (extPtr) { - buffer = extPtr + offs; - } else { - allocatedBuffer = buffer = (char *)malloc(objSize); - bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); - } - - do { - __threadErrno = 0; - n = (INT)STX_WSA_NOINT_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size); - } while ((n < 0) && (__threadErrno == EINTR)); - if (n < 0) { - errno = __threadErrno; - } - - if (allocatedBuffer) { - free(allocatedBuffer); - } + if (extPtr) { + buffer = extPtr + offs; + } else { + allocatedBuffer = buffer = (char *)malloc(objSize); + bcopy((char *)__InstPtr(aDataBuffer) + offs, allocatedBuffer, objSize); + } + + do { + __threadErrno = 0; + n = (INT)STX_WSA_NOINT_CALL6("sendto", sendto, sock, buffer, objSize, _flags, sockaddr_ptr, sockaddr_size); + } while ((n < 0) && (__threadErrno == EINTR)); + if (n < 0) { + errno = __threadErrno; + } + + if (allocatedBuffer) { + free(allocatedBuffer); + } #else - __BEGIN_INTERRUPTABLE__ - 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)); - __END_INTERRUPTABLE__ + __BEGIN_INTERRUPTABLE__ + 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)); + __END_INTERRUPTABLE__ #endif - if (n < 0) { - error = __INST(lastErrorNumber) = __MKSMALLINT(errno); - } else { - RETURN (__MKSMALLINT(n)); - } + if (n < 0) { + error = __INST(lastErrorNumber) = __MKSMALLINT(errno); + } else { + RETURN (__MKSMALLINT(n)); + } } #endif bad: ; %}. error notNil ifTrue:[ - self writeError:error. + self writeError:error. ]. " @@ -2910,7 +2936,7 @@ |serverSocketHandle addr domainClass newHandle| handle notNil ifTrue:[ - ^ self errorAlreadyOpen + ^ self errorAlreadyOpen ]. domain := aServerSocket domain. @@ -2918,12 +2944,12 @@ handleType := aServerSocket handleType. serverSocketHandle := aServerSocket fileHandle. serverSocketHandle isNil ifTrue:[ - ^ self error:'invalid server socket' + ^ self error:'invalid server socket' ]. "unix domain sockets do not return a valid peer name on accept" domainClass := self class socketAddressClassForDomain:domain. domainClass isNil ifTrue:[ - ^ self error:'invalid (unsupported) domain'. + ^ self error:'invalid (unsupported) domain'. ]. addr := domainClass new. newHandle := OperatingSystem socketAccessor new. @@ -2945,25 +2971,25 @@ # if defined(O_NONBLOCK) && defined(SET_NDELAY) if (blocking == false) { - flags = fcntl(serverSocket, F_GETFL); - fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK); + flags = fcntl(serverSocket, F_GETFL); + fcntl(serverSocket, F_SETFL, flags | O_NONBLOCK); } # endif # ifdef DO_WRAP_CALLS do { - __threadErrno = 0; - alen = sizeof(sa); - newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen); + __threadErrno = 0; + alen = sizeof(sa); + newSock = (SOCKET)STX_WSA_CALL3("accept", accept, serverSocket, &sa, &alen); } while ((newSock < 0) && (__threadErrno == EINTR)); if (newSock < 0) { - errno = __threadErrno; + errno = __threadErrno; } # else __BEGIN_INTERRUPTABLE__ do { - alen = sizeof(sa); - newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen); + alen = sizeof(sa); + newSock = accept(serverSocket, (struct sockaddr *) &sa, &alen); } while ((newSock < 0) && (errno == EINTR)); __END_INTERRUPTABLE__ # endif @@ -2971,41 +2997,41 @@ # if defined(O_NDELAY) && defined(SET_NDELAY) if (blocking == false) { - fcntl(serverSocket, F_SETFL, flags); + fcntl(serverSocket, F_SETFL, flags); } # endif if (newSock == -1) { - DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno)); - __INST(lastErrorNumber) = __MKSMALLINT(errno); - RETURN (false); + DBGPRINTF(("SOCKET: accept call failed errno=%d\n", errno)); + __INST(lastErrorNumber) = __MKSMALLINT(errno); + RETURN (false); } if (__isNonNilObject(addr)) { - OBJ oClass = __qClass(addr); - int nInstVars, nInstBytes, objSize; - char *addrP; - - if (! __isBytes(addr) ) { - DBGPRINTF(("SOCKET: bad addr\n")); - closesocket(newSock); - RETURN (false); - } - - nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); - nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); - objSize = __qSize(addr) - nInstBytes; - addrP = (char *)__InstPtr(addr) + nInstBytes; - if (objSize < alen) { - DBGPRINTF(("SOCKET: bad addr\n")); - closesocket(newSock); - RETURN (false); - } - - /* - * extract the partners address - */ - memcpy(addrP, (char *)&sa, alen); + OBJ oClass = __qClass(addr); + int nInstVars, nInstBytes, objSize; + char *addrP; + + if (! __isBytes(addr) ) { + DBGPRINTF(("SOCKET: bad addr\n")); + closesocket(newSock); + RETURN (false); + } + + nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars); + nInstBytes = OHDR_SIZE + (nInstVars * sizeof(OBJ)); + objSize = __qSize(addr) - nInstBytes; + addrP = (char *)__InstPtr(addr) + nInstBytes; + if (objSize < alen) { + DBGPRINTF(("SOCKET: bad addr\n")); + closesocket(newSock); + RETURN (false); + } + + /* + * extract the partners address + */ + memcpy(addrP, (char *)&sa, alen); } /* @@ -3023,19 +3049,19 @@ # else // ! WIN32 fp = fdopen(newSock, "r+"); if (! fp) { - DBGPRINTF(("SOCKET: fdopen call failed\n")); - __INST(lastErrorNumber) = __MKSMALLINT(errno); - closesocket(newSock); - DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock)); - RETURN (false); + DBGPRINTF(("SOCKET: fdopen call failed\n")); + __INST(lastErrorNumber) = __MKSMALLINT(errno); + closesocket(newSock); + DBGFPRINTF((stderr, "SOCKET: close (fdopen failed) (%d)\n", newSock)); + RETURN (false); } # endif // ! WIN32 if ((@global(FileOpenTrace) == true) || __debugging__) { # ifdef WIN32 - console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock); + console_fprintf(stderr, "fdopen [Socket accept] -> fd: %d (H: %"_lx_")\n", _fd, (INT)newSock); # else - console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock); + console_fprintf(stderr, "fdopen [Socket accept] -> %"_lx_" (fd: %d)\n", (INT)fp, newSock); # endif } @@ -3643,7 +3669,7 @@ |domainName domainCode typeCode error newHandle| handle notNil ifTrue:[ - ^ self errorAlreadyOpen + ^ self errorAlreadyOpen ]. domainName := SocketAddress domainCodeFromName:domainArg. domainCode := OperatingSystem domainCodeOf:domainName. @@ -3665,19 +3691,19 @@ # endif if (! __isSmallInteger(domainCode)) { - error = @symbol(badArgument1); - goto out; + error = @symbol(badArgument1); + goto out; } if (! __isSmallInteger(typeCode)) { - error = @symbol(badArgument2); - goto out; + error = @symbol(badArgument2); + goto out; } if (protocolNumber != nil) { - if (!__isSmallInteger(protocolNumber)) { - error = @symbol(badArgument3); - goto out; - } - proto = __intVal(protocolNumber); + if (!__isSmallInteger(protocolNumber)) { + error = @symbol(badArgument3); + goto out; + } + proto = __intVal(protocolNumber); } /* @@ -3689,91 +3715,91 @@ # ifdef WIN32 sock = WSASocket(dom, typ, proto, 0, 0, noInheritFlag); if (sock == INVALID_SOCKET && noInheritFlag) { - // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT - // This fails on older windows versions, e.g. Windows XP - sock = WSASocket(dom, typ, proto, 0, 0, 0); - if (sock != INVALID_SOCKET) { - // no error without WSA_FLAG_NO_HANDLE_INHERIT, - // never use this flag again! - noInheritFlag = 0; - } + // tried to open socket with WSA_FLAG_NO_HANDLE_INHERIT + // This fails on older windows versions, e.g. Windows XP + sock = WSASocket(dom, typ, proto, 0, 0, 0); + if (sock != INVALID_SOCKET) { + // no error without WSA_FLAG_NO_HANDLE_INHERIT, + // never use this flag again! + noInheritFlag = 0; + } } if (sock == INVALID_SOCKET) { - errno = WSAGetLastError(); + errno = WSAGetLastError(); # else // !WIN32 sock = socket(dom, typ, proto); # if defined(EPROTONOSUPPORT) /* for SGI */ if ((sock < 0) && (proto != 0) && (errno == EPROTONOSUPPORT)) { - DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n")); - proto = 0; - sock = socket(dom, typ, 0); + DBGPRINTF(("SOCKET: retry with UNSPEC protocol\n")); + proto = 0; + sock = socket(dom, typ, 0); } # endif if (sock < 0) { # endif // !WIN32 - DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno)); - error = __MKSMALLINT(errno); + DBGPRINTF(("SOCKET: socket(dom=%d typ=%d proto=%d) call failed errno=%d\n", dom, typ, proto, errno)); + error = __MKSMALLINT(errno); } else { # if defined(SET_LINGER_WHEN_CREATING_SOCKET) && defined(SO_LINGER) - { - struct linger l; - - l.l_onoff = 1; - l.l_linger = 30; - setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); - } + { + struct linger l; + + l.l_onoff = 1; + l.l_linger = 30; + setsockopt( sock, SOL_SOCKET, SO_LINGER, &l, sizeof(l)); + } # endif # ifdef WIN32 - /* - * make it blocking - */ - { - unsigned long zero = 0; - ioctlsocket(sock, FIONBIO, &zero); - } - { + /* + * make it blocking + */ + { + unsigned long zero = 0; + ioctlsocket(sock, FIONBIO, &zero); + } + { # if 0 && (defined( __BORLANDC__ ) || defined( __MINGW__ )) - /* - * make it a FILE * - */ - __stxWrapApiEnterCritical(); - _fd = _open_osfhandle((long)sock, 0); - __stxWrapApiLeaveCritical(); + /* + * make it a FILE * + */ + __stxWrapApiEnterCritical(); + _fd = _open_osfhandle((long)sock, 0); + __stxWrapApiLeaveCritical(); # else - _fd = (int)sock; + _fd = (int)sock; # endif - DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd)); - } + DBGPRINTF(("SOCKET: sock=%d fd=%d\n", sock, _fd)); + } # else // !WIN32 - fp = fdopen(sock, "r+"); - if (! fp) { - DBGPRINTF(("SOCKET: fdopen call failed\n")); - error = __MKSMALLINT(errno); - __BEGIN_INTERRUPTABLE__ - closesocket(sock); - DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock)); - __END_INTERRUPTABLE__ - goto out; - } + fp = fdopen(sock, "r+"); + if (! fp) { + DBGPRINTF(("SOCKET: fdopen call failed\n")); + error = __MKSMALLINT(errno); + __BEGIN_INTERRUPTABLE__ + closesocket(sock); + DBGFPRINTF((stderr, "SOCKET: fdopen failed (%d)\n", sock)); + __END_INTERRUPTABLE__ + goto out; + } # endif // !WIN32 - if (@global(FileOpenTrace) == true) { + if (@global(FileOpenTrace) == true) { # ifdef WIN32 - console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock); + console_fprintf(stderr, "fdopen [Socket create] -> fd: %d (H: %"_lx_")\n", (INT)_fd, (INT)sock); # else - console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock); + console_fprintf(stderr, "fdopen [Socket] -> %"_lx_" (fd: %d)\n", (INT)fp, sock); # endif - } + } # ifdef WIN32 - __externalAddressVal(newHandle) = _fd; - __INST(handleType) = @symbol(socketHandle); + __externalAddressVal(newHandle) = _fd; + __INST(handleType) = @symbol(socketHandle); # else - __externalAddressVal(newHandle) = fp; - __INST(handleType) = @symbol(socketFilePointer); + __externalAddressVal(newHandle) = fp; + __INST(handleType) = @symbol(socketFilePointer); # endif } #endif @@ -3782,15 +3808,15 @@ "all ok?" handleType notNil ifTrue:[ - handle := newHandle. - domain := domainArg. - socketType := typeArg. - self registerForFinalization. - ^ self. + handle := newHandle. + domain := domainArg. + socketType := typeArg. + self registerForFinalization. + ^ self. ]. error isInteger ifTrue:[ - lastErrorNumber := error. - ^ self openError:error. + lastErrorNumber := error. + ^ self openError:error. ]. ^ self primitiveFailed:error. @@ -4146,13 +4172,13 @@ |newSock| (self readWaitWithTimeout:timeoutSecondsOrNil) ifTrue:[ - "a timeout occurred - no connection within timeout" - ^ nil + "a timeout occurred - no connection within timeout" + ^ nil ]. newSock := self class new. (newSock primAcceptOn:self blocking:false) ifFalse:[ - "should raise an error here" - ^ nil + "should raise an error here" + ^ nil ]. ^ newSock ! !