⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sock.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
            *psize = sizeof( uint );
            if( !ps->hIFTx )
                *(uint *)pbuf = 0;
            else
                *(uint *)pbuf = IFGetIndex( ps->hIFTx );
            return(0);
        }
    }

    // For the remainder, the property value is an int
    if( *psize < sizeof(int) )
        return( EINVAL );
    *psize = sizeof(int);

    switch( Prop )
    {
    case SO_BLOCKING:
        if( ps->StateFlags & SS_NBIO )
            *(int *)pbuf = 0;
        else
            *(int *)pbuf = 1;
        break;

    case SO_DEBUG:
    case SO_KEEPALIVE:
    case SO_DONTROUTE:
    case SO_USELOOPBACK:
    case SO_BROADCAST:
    case SO_REUSEADDR:
    case SO_REUSEPORT:
    case SO_OOBINLINE:
    case SO_TIMESTAMP:
        if( ps->OptionFlags & (uint)Prop )
            *(int *)pbuf = 1;
        else
            *(int *)pbuf = 0;
        break;

    case SO_SNDBUF:
        if( ps->hSBTx )
            *(int *)pbuf = (int)SBGetMax( ps->hSBTx );
        else
            *(int *)pbuf = SOCK_BUFMAX;
        break;

    case SO_RCVBUF:
        if( ps->hSBRx )
            *(int *)pbuf = (int)SBGetMax( ps->hSBRx );
        else
            *(int *)pbuf = SOCK_BUFMAX;
        break;

    case SO_SNDLOWAT:
        if( ps->hSBTx )
            *(int *)pbuf = (int)SBGetMin( ps->hSBTx );
        else
            *(int *)pbuf = SOCK_BUFMINRX;
        break;

    case SO_RCVLOWAT:
        if( ps->hSBRx )
            *(int *)pbuf = (int)SBGetMin( ps->hSBRx );
        else
            *(int *)pbuf = SOCK_BUFMINRX;
        break;

    case SO_ERROR:
        *(int *)pbuf = ps->ErrorPending;
        break;

    case SO_TYPE:
        *(int *)pbuf = (int)ps->SockType;
        break;

    default:
        error = ENOPROTOOPT;
        break;
    }

    return(error);
}

//--------------------------------------------------------------------
// SockRecv
//
// Receive data from a socket. Optionally fill in the Peer name.
//--------------------------------------------------------------------
int SockRecv
(
    HANDLE      h,
    char        *pBuf,
    INT32       size,
    int         flags,
    PSA         pPeer,
    INT32       *pRetSize
)
{
    SOCK     *ps = (SOCK *)h;
    int      retry    = 1;
    int      error    = 0;
    INT32    Total    = 0;
    INT32    SizeCopy = 0;
    IPN      dwIPFrom;
    uint     PortFrom;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockRecv: HTYPE %04x",ps->Type);
        return( ENOTSOCK );
    }
#endif

    // Check for a moron
    if( ps->OptionFlags & SO_ACCEPTCONN )
        return( EINVAL );

    // Check for a null read
    if( !size )
        goto rx_complete;

    // Check the OOB flag
    if( flags & MSG_OOB )
    {
        // MSG_OOB Specified

        // If in OOBINLINE mode, this flag is illegal, or
        // If stocket is not in OOB mode, it is illegal
        if( (ps->OptionFlags & SO_OOBINLINE) ||
                !(ps->StateFlags & SS_OOBACTIVE) )
            return( EINVAL );

        // If we don't have the OOB data yet, then we have a blocking
        // situation
        if( !(ps->StateFlags & SS_OOBDATAVALID) )
            return( EWOULDBLOCK );

        // We have the OOB Data ready - Complete the recv call
        *pBuf = ps->OOBData;
        SizeCopy = 1;

        // Clear the OOB mode if not PEEKING
        if( !(flags & MSG_PEEK) )
            ps->StateFlags &= ~(SS_OOBACTIVE | SS_OOBDATAVALID);

        goto rx_complete;
    }

rx_restart:
    // ATOMIC socket types get one shot at this...
    if( ps->StateFlags & SS_ATOMIC )
        retry = 0;

    // Get the total bytes available
    Total = SBGetTotal(ps->hSBRx);

    // Return a pending error if available
    if( ps->ErrorPending )
    {
        // Don't eat the error if we're returning data
        if( !SizeCopy )
        {
            error = ps->ErrorPending;
            ps->ErrorPending = 0;
        }
        // But don't get more data this time
        Total = 0;
        goto rx_dontblock;
    }

    // Check for blocking condition
    if( !Total )
    {
        //
        // Check all non-blocking conditions first
        //

        // Assume we can't block
        retry = 0;

        // Don't block if the socket is no longer connected (this is
        // actually an error condition)
        if( (ps->StateFlags & SS_CONNREQUIRED) &&
                !(ps->StateFlags & (SS_ISCONNECTED|SS_ISCONNECTING)) )
        {
            error = ENOTCONN;
            goto rx_dontblock;
        }

        // Don't block if the receiver is shut down
        if( ps->StateFlags & SS_CANTRCVMORE )
        {
            error = EPIPE;
            goto rx_dontblock;
        }

        // Don't block if there was an overriding request not to block
        if( flags & MSG_DONTWAIT )
            goto rx_dontblock;

        // Don't block on NBIO if there was NO overriding request to block
        if( !(flags & MSG_WAITALL) && (ps->StateFlags & SS_NBIO) )
            goto rx_dontblock;

        // If we copied the minimum and WAITALL is not set, then don't block
        // the minimum. (If ATOMIC, SizeCopy will be zero.)
        if( SizeCopy >= SBGetMin(ps->hSBRx) && !(flags&MSG_WAITALL) )
            goto rx_dontblock;

        // Finally, the blocking code

        // If we get a file event, then try the loop again
        if( FDWaitEvent( ps->hFd, FD_EVENT_READ, ps->dwRxTimeout ) )
        {
            retry = 1;
            goto rx_restart;
        }
    }

rx_dontblock:
    // Check for FATAL blocking condition
    if( !Total && !SizeCopy )
    {
        if( !error )
            error = EWOULDBLOCK;
        return( error );
    }

    // Get how much data to copy

    // Adjust to buffer size
    if( size < (Total+SizeCopy) )
        Total = size-SizeCopy;

    // Don't cross an OOB mark
    if( (ps->StateFlags & SS_OOBACTIVE) && ps->OOBMark && Total > ps->OOBMark )
    {
        retry = 0;
        Total = ps->OOBMark;
    }

    if( Total )
    {
        if( flags & MSG_PEEK )
            Total = SBRead( ps->hSBRx, Total, 0, (UINT8 *)(pBuf+SizeCopy),
                                                 &dwIPFrom, &PortFrom, 1 );
        else
        {
            Total = SBRead( ps->hSBRx, Total, 0, (UINT8 *)(pBuf+SizeCopy),
                                                 &dwIPFrom, &PortFrom, 0 );

            if( ps->StateFlags & SS_OOBACTIVE )
            {
                // Clear the OOB mode if at the mark
                if( !ps->OOBMark )
                    ps->StateFlags &= ~(SS_OOBACTIVE | SS_OOBDATAVALID);
                // Otherwise, move us towards the mark
                else
                    ps->OOBMark -= Total;
            }
        }

        if( pPeer )
        {
            // Get Peer Data from Socket
            pPeer->sin_len         = sizeof( SA );
            pPeer->sin_family      = (UINT8)ps->Family;

            if( ps->StateFlags & SS_ADDR )
            {
                pPeer->sin_port        = PortFrom;
                pPeer->sin_addr.s_addr = dwIPFrom;
            }
            else
            {
                pPeer->sin_port        = ps->FPort;
                pPeer->sin_addr.s_addr = ps->dwFIP;
            }
        }

        // Record that we received this data
        SizeCopy += Total;

        // Notify the protocol of status change
        SockPrRecv( ps );
    }

    // Try and get all the data if possible
    if( retry && size > SizeCopy )
        goto rx_restart;

rx_complete:
    *pRetSize = SizeCopy;
    if( SizeCopy )
        return(0);
    return(error);
}

//--------------------------------------------------------------------
// SockRecvNC
//
// Receive data from a socket without copy.
// Optionally fill in the Peer name.
//--------------------------------------------------------------------
int SockRecvNC( HANDLE h, int flags, PSA pPeer, HANDLE *phFrag )
{
    SOCK     *ps = (SOCK *)h;
    int      error    = 0;
    INT32    Total    = 0;
    IPN      dwIPFrom;
    uint     PortFrom;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockRecv: HTYPE %04x",ps->Type);
        return( ENOTSOCK );
    }
#endif

    // Check for a moron
    if( ps->OptionFlags & SO_ACCEPTCONN )
        return( EINVAL );

    // Check the OOB and PEEK flag
    if( flags & (MSG_OOB|MSG_PEEK) )
        return( EINVAL );

    // Must be ATOMIC socket
    if( !(ps->StateFlags & SS_ATOMICREAD) )
        return( EINVAL );

rx_restart:
    // Get the total bytes available
    Total = SBGetTotal(ps->hSBRx);

    // Return a pending error if available
    if( ps->ErrorPending )
    {
        error = ps->ErrorPending;
        ps->ErrorPending = 0;
        Total = 0;
        goto rx_dontblock;
    }

    // Check for blocking condition
    if( !Total )
    {
        //
        // Check all non-blocking conditions first
        //

        // Don't block if the socket is no longer connected (this is
        // actually an error condition)
        if( (ps->StateFlags & SS_CONNREQUIRED) &&
                !(ps->StateFlags & (SS_ISCONNECTED|SS_ISCONNECTING)) )
        {
            error = ENOTCONN;
            goto rx_dontblock;
        }

        // Don't block if the receiver is shut down
        if( ps->StateFlags & SS_CANTRCVMORE )
        {
            error = EPIPE;
            goto rx_dontblock;
        }

        // Don't block if there was an overriding request not to block
        if( flags & MSG_DONTWAIT )
            goto rx_dontblock;

        // Don't block on NBIO if there was NO overriding request to block
        if( !(flags & MSG_WAITALL) && (ps->StateFlags & SS_NBIO) )
            goto rx_dontblock;

        // Finally, the blocking code

        // If we get a file event, then try the loop again
        if( FDWaitEvent( ps->hFd, FD_EVENT_READ, ps->dwRxTimeout ) )
            goto rx_restart;
    }

rx_dontblock:
    // Check for FATAL blocking condition
    if( !Total )
    {
        if( !error )
            error = EWOULDBLOCK;
        return( error );
    }

    // We don't support OOB on this type of read, so clear any OOB mark
    if( ps->StateFlags & SS_OOBACTIVE )
        ps->StateFlags &= ~(SS_OOBACTIVE | SS_OOBDATAVALID);

    if( Total )
    {
        *phFrag = SBReadNC( ps->hSBRx, &dwIPFrom, &PortFrom );

        if( pPeer )
        {
            // Get Peer Data from Socket
            pPeer->sin_len         = sizeof( SA );
            pPeer->sin_family      = (UINT8)ps->Family;

            if( ps->StateFlags & SS_ADDR )
            {
                pPeer->sin_port        = PortFrom;
                pPeer->sin_addr.s_addr = dwIPFrom;
            }
            else
            {
                pPeer->sin_port        = ps->FPort;
                pPeer->sin_addr.s_addr = ps->dwFIP;
            }
        }

        // Notify the protocol of status change
        SockPrRecv( ps );
    }

    if( Total )
        return(0);
    return(error);
}

//--------------------------------------------------------------------
// SockSend()
//
// Send data to a socket.
//--------------------------------------------------------------------
int SockSend
(
    HANDLE   h,
    char     *pBuf,
    INT32    size,
    int      flags,
    INT32    *pRetSize
)
{
    SOCK     *ps = (SOCK *)h;
    int      DontRoute = 0, error = 0;
    INT32    SizeCopy = 0;
    INT32    AddCopy;

#ifdef _STRONG_CHECKING
    if( ps->Type != HTYPE_SOCK )
    {
        DbgPrintf(DBG_ERROR,"SockRecv: HTYPE %04x",ps->Type);
        return( ENOTSOCK );
    }
#endif

    // Set a flag to see if we should temporarily add SO_DONTROUTE
    if( (flags & MSG_DONTROUTE) && (ps->StateFlags & SS_ATOMICWRITE) &&
                                  !(ps->OptionFlags & SO_DONTROUTE) )
        DontRoute = 1;

    //
    // This routine doesn't actually enqueue any data, since "how"
    // the data is queued is dependent on the protocol.
    //
    // Since in a reduced memory stack (i.e.: us), it is possible to
    // run out of memory before buffer limits are reached, we don't
    // even bother to check memory status. The protocol returns the
    // number of bytes consumed, and hence, when to block.
    //
    while( SizeCopy < size )
    {
        //
        // Check error conditions in our loop since the error may
        // occur while we're sending
        //

        // Return any pending error
        if( ps->ErrorPending )
        {
            error = ps->ErrorPending;
            ps->ErrorPending = 0;
            break;
        }

        // Must be connected - our upper layer ALWAYS connects on a UDP
        // sendto().
        if( !(ps->StateFlags & SS_ISCONNECTED) )
        {
            error = ENOTCONN;
            break;
        }

        // Can't send if send shutdown
        if( ps->StateFlags & SS_CANTSENDMORE )
        {
            error = ESHUTDOWN;
            break;
        }

        // Send the Data
        if( DontRoute )
            ps->OptionFlags |= SO_DONTROUTE;
        if( flags & MSG_OOB )
            error = SockPrSendOOB( ps, (UINT8 *)(pBuf+SizeCopy),
                                                size-SizeCopy, &AddCopy );
        else
            error = SockPrSend( ps, (UINT8 *)(pBuf+SizeCopy),
                                              size-SizeCopy, &AddCopy );
        if( DontRoute )
            ps->OptionFlags &= ~SO_DONTROUTE;

        // Mark what we did copy
        SizeCopy += AddCopy;

        // Break out now on an error condition
        if( error )
            break;

        // If we're ATOMIC, we sent what we could - leave now
        if( ps->StateFlags & SS_ATOMICWRITE )
            break;

        // Check blocking condition
        if( SizeCopy < size && !AddCopy )
        {
            // We need to block (protocol did not handle the data )

            // Can't block a non-blocking socket
            // If we timeout, we have an error and break the loop
            if( (ps->StateFlags & SS_NBIO) || (flags & MSG_DONTWAIT) ||
                    !FDWaitEvent( ps->hFd, FD_EVENT_WRITE, ps->dwTxTimeout ) )
            {
                error = EWOULDBLOCK;
                break;
            }
        }
    }

    *pRetSize = SizeCopy;
    return( error );
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -