# HG changeset patch # User Claus Gittinger # Date 972579280 -7200 # Node ID 3dc0e3cd838ad3d23fd12df2b5fdd344dedb40eb # Parent 7db1f3375ac9c7da44ea631196f5996d74279340 added interface to send() and recv() diff -r 7db1f3375ac9 -r 3dc0e3cd838a Socket.st --- a/Socket.st Tue Oct 24 19:28:57 2000 +0200 +++ b/Socket.st Thu Oct 26 18:54:40 2000 +0200 @@ -2207,6 +2207,88 @@ !Socket methodsFor:'datagram transmission'! +receiveBuffer:aDataBuffer start:startIndex for:nBytes + "receive data + Return the number of bytes received, or a negative number on error. + On error, the unix error code is left in the lastErrorNumber + instance variable. + 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 sock; + int n; + char *cp; + 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); + } + if (__isSmallInteger(nBytes)) { + if (__intVal(nBytes) < objSize) { + objSize = __intVal(nBytes); + } + } + + __BEGIN_INTERRUPTABLE__ + do { + n = recv(sock, cp, objSize, flags); + } while ((n < 0) && (errno == EINTR)); + __END_INTERRUPTABLE__ + + if (n < 0) { + __INST(lastErrorNumber) = __MKSMALLINT(errno); + } + nReceived = __MKSMALLINT(n); + } +#endif +bad: ; +%}. + nReceived notNil ifTrue:[ + nReceived < 0 ifTrue:[ + 'Socket [warning]: ' infoPrint. + (OperatingSystem errorTextForNumber:lastErrorNumber) infoPrintCR. + ]. + ^ nReceived + ]. + " + arrive here if you try to receive into an invalid buffer + (i.e. not ByteArray-like), + or if the addressBuffer is nonNil AND not a ByteArray/String + or if the addressBuffer is nonNil AND too small. + " + self primitiveFailed +! + receiveFrom:anAddressBuffer buffer:aDataBuffer "receive datagramm data - put address of originating host into anAddressBuffer, data into aBuffer. @@ -2446,6 +2528,107 @@ self primitiveFailed ! +sendBuffer:aDataBuffer start:startIndex for:count 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). + Return the number of bytes transmitted, or a negative number on error. + On error, the unix error code is left in the lastErrorNumber + instance variable." + + |nReceived portNo| + +%{ +#ifndef NO_SOCKET + OBJ oClass; + OBJ fp = __INST(filePointer); + int nInstVars, nInstBytes, objSize; + int sock; + int n; + char *cp; + int _flags = 0; + int offs, nBytes; + unsigned long norder; + + _flags = __longIntVal(flags); + + if ((fp != nil) + && __isSmallInteger(startIndex) + && __isSmallInteger(count)) { + sock = fileno(__FILEVal(fp)); + + 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 + 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; + } + 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; + } + +# ifdef DGRAM_DEBUG + printf("sending %d bytes ...", nBytes); +# endif + + __BEGIN_INTERRUPTABLE__ + do { + n = send(sock, cp, nBytes, _flags); + } while ((n < 0) && (errno == EINTR)); + __END_INTERRUPTABLE__ + + if (n < 0) { + __INST(lastErrorNumber) = __MKSMALLINT(errno); + } + RETURN (__MKSMALLINT(n)); + } +#endif +bad: ; +%}. + " + arrive here if you try to send from an invalid buffer + (i.e. not ByteArray-like), + or if the addressBuffer is nonNil AND not a ByteArray/String + or if the addressBuffer is nonNil AND too small. + " + self primitiveFailed +! + sendTo:anAddressBuffer buffer:buffer "send datagramm data - fetch address of destination host from anAddressBuffer, data from aDataBuffer. @@ -4763,5 +4946,5 @@ !Socket class methodsFor:'documentation'! version - ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.149 2000-08-08 13:31:13 stefan Exp $' + ^ '$Header: /cvs/stx/stx/libbasic2/Socket.st,v 1.150 2000-10-26 16:54:40 cg Exp $' ! !