tfZeroCopyRecvFrom

Jump to: navigation, search

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
);


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.


Note Note: 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);
}


Note Note: See also tfZeroCopySendTo().


Returns

  • TM_ENOERROR
    EOF.
  • >= 0
    The number of bytes received.
  • TM_SOCKET_ERROR
    Failure.


Note Note: 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.


Table of Contents >> Programmer's Reference