tfZeroCopyRecvFrom
Table of Contents >> Programmer's Reference
| #include <trsocket.h> |
| int tfZeroCopyRecvFrom | ( |
| int socketDescriptor, | |
| ttUserMessage TM_FAR * bufferHandlePtr, | |
| char TM_FAR * TM_FAR * dataPtrPtr, | |
| int maxDataLength, | |
| int flags, | |
| struct sockaddr TM_FAR * fromAddressPtr, | |
| int TM_FAR * fromAddressLengthPtr | |
| ); |
Contents
Function Description
This function is used to recv a zero copy message. It operates identically to recvfrom() with the exception that it takes a zero copy buffer handle as a parameter and puts the beginning of the data into a passed pointer.
| The user must call tfFreeZeroCopyBuffer() in order to free the buffer after the user has finished with it. |
Parameters
- socketDescriptor
- The socket descriptor to receive data from.
- bufferHandlePtr
- The zero copy buffer that contains the message.
- dataPtrPtr
- A pointer ot a (char *) of the beginning of the stored data.
- maxDataLength
- The length of the message.
- flags
- See below for possible flags parameters that can be OR'ed together.
- fromAddressPtr
- The source address of the packet.
- fromAddressLengthPtr
- The length of the source address.
Flags
Value Meaning MSG_DONTWAIT Don't wait for data, but rather return immediately. MSG_PEEK "Peek" at the data present on the socket; the data is returned, but not consumed, so that a subsequent receive operation will see the same data. MSG_SCATTERED If the receive data is scattered, it will be passed to the user as is, and will not get copied into a new buffer to make the data contiguous. Upon return, bufferHandlePtr will point to a scattered buffer, as explained below.
MSG_SCATTERED Flag
When the MSG_SCATTERED bit is set in the flags parameters, then upon successful return from tfZeroCopyRecvFrom(), the bufferHandlePtr parameter should be cast to a pointer to a ttUserPacket structure, where ttUserPacket is defined as follows:
#define trsocket.h /* * Data type used for the linked list of packets passed to the device * driver single call scattered send function prototype. */ typedef struct tsUserPacket { /* Next tsUserPacket for scattered data */ /* struct tsUserPacket TM_FAR *pktuLinkNextPtr; */ void TM_FAR *pktuLinkNextPtr; /* Pointer to data */ ttUser8BitPtr pktuLinkDataPtr; #ifdef TM_DSP /* byte offset of start of data, in word pointed to by pktuLinkDataPtr */ int pktuLinkDataByteOffset; #endif /* TM_DSP */ #if defined(TM_DEV_SEND_OFFLOAD) || defined(TM_DEV_RECV_OFFLOAD) ttUserVoidPtr pktuDevOffloadPtr; #endif /* TM_DEV_SEND_OFFLOAD || TM_DEV_RECV_OFFLOAD */ /* Size of data pointed by pktuLinkDataPtr */ ttPktLen pktuLinkDataLength; /* * Total packet length (of chained scattered data). Valid in first link * only */ ttPktLen pktuChainDataLength; /* * Number of links linked to this one (not including this one). * Valid in first link only. */ int pktuLinkExtraCount; #ifdef TM_USE_USER_PARAM /* User-defined data */ ttUserGenericUnion pktuUserParam; #endif /* TM_USE_USER_PARAM */ } ttUserPacket; typedef ttUserPacket TM_FAR * ttUserPacketPtr;
Example
The following code extract shows how to navigate a scattered recv buffer, and copies it into bufferArray[].
#define TM_BUF_ARRAY_SIZE 3000 char bufferArray[TM_BUF_ARRAY_SIZE]; ... retCode = tfZeroCopyRecvFrom(ssd, &recvMessageHandle, &dataPtr, sizeof(bufferArray), MSG_SCATTERED, tempSockAddrFrom.sockPtr, &fromAddressLength); if (retCode > 0) { recvdLength += retCode; tm_assert(testzUdpToFrom, retCode == sendDataLength); scatteredRecvCopyNCheck(recvMessageHandle, (ttUser8BitPtr)dataPtr, (ttPktLen)retCode); (void)tfFreeZeroCopyBuffer(recvMessageHandle); } void scatteredRecvCopyNCheck(ttUserMessage recvMessageHandle, ttUser8BitPtr dataPtr, ttPktLen msgLength) { ttUserPacketPtr recvPacketUPtr; char * bufferPtr; int extraCount; extraCount = -1; recvPacketUPtr = (ttUserPacketPtr)recvMessageHandle; bufferPtr = &bufferArray[0]; tm_assert(testzUdp, msgLength == recvPacketUPtr->pktuChainDataLength); tm_assert(testzUdp, msgLength <= sizeof(bufferArray)); tm_assert(testzUdp, dataPtr == recvPacketUPtr->pktuLinkDataPtr); do { tm_assert(testzUdp, msgLength >= recvPacketUPtr->pktuLinkDataLength); tm_assert(testzUdp, (recvPacketUPtr->pktuLinkDataPtr != (ttUser8BitPtr)0)); tm_bcopy(recvPacketUPtr->pktuLinkDataPtr, bufferPtr, recvPacketUPtr->pktuLinkDataLength); bufferPtr += recvPacketUPtr->pktuLinkDataLength; msgLength -= recvPacketUPtr->pktuLinkDataLength; recvPacketUPtr = recvPacketUPtr->pktuLinkNextPtr; extraCount++; } while ( (msgLength != (ttPktLen)0) && (recvPacketUPtr != (ttUserPacketPtr)0) ); tm_assert(testUdp, msgLength == 0); recvPacketUPtr = (ttUserPacketPtr)recvMessageHandle; tm_assert(testUdp, extraCount == recvPacketUPtr->pktuLinkExtraCount); }
| See also tfZeroCopySendTo(). |
Returns
- TM_ENOERROR
- EOF.
- >= 0
- The number of bytes received.
- TM_SOCKET_ERROR
- Failure.
| TM_SOCKET_ERROR means that this socket call has failed and the errorCode has been set on the socket itself.
To retrieve the socket error the user must call tfGetSocketError(socketDescriptor). |
Possible socket errors
- TM_EBADF
- The socket descriptor is invalid.
- TM_EMSGSIZE
- The socket requires that the message be received atomically and bufferLength was too small.
- TM_EWOULDBLOCK
- The socket is marked as non-blocking or the MSG_DONTWAIT flag is used and no data is available to be read.
- TM_ESHUTDOWN
- The remote socket has closed the connection and there is no more data to be received (TCP socket only).
- TM_EINVAL
- One of the parameters is invalid.
- TM_ENOTCONN
- The socket is not connected.