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

📄 sock.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:

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

    // If connection required, this call is invalid
    if( ps->StateFlags & SS_CONNREQUIRED )
        return( EINVAL );

    // Make sure we are connected
    if( !(ps->StateFlags & (SS_ISCONNECTED | SS_ISCONNECTING)) )
        return( ENOTCONN );

    // Disconnect (back to idle)
    ps->StateFlags &= ~(SS_ISCONNECTING|SS_ISCONNECTED|SS_CLOSING);

    // Revert to strict bindings
    ps->dwLIP = ps->dwBIP;
    ps->LPort = ps->BPort;
    ps->dwFIP = 0;
    ps->FPort = 0;

    // Toss any cached route
    if( ps->hRoute )
    {
        RtDeRef( ps->hRoute );
        ps->hRoute = 0;
    }

    return( 0 );
}

//--------------------------------------------------------------------
// SockBind()
//
// Bind Address and Port to Socket
//--------------------------------------------------------------------
int SockBind( HANDLE h, PSA pName )
{
    SOCK *ps = (SOCK *)h;
    int  error = 0;

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

    // The only obvious error is that we're already bound
    // Note: Even AF_TASK type sockets will have an "IP" (Socket Id)
    if( ps->LPort || !pName )
        return( EINVAL );

    error = SockPcbBind( ps, pName->sin_addr.s_addr, pName->sin_port );

    if( !error )
    {
        ps->dwBIP  = ps->dwLIP;
        ps->BPort = ps->LPort;
    }

    return( error );
}

//--------------------------------------------------------------------
// SockGetName
//
// Get Local and/or Peer Address and Port of Socket
//--------------------------------------------------------------------
int SockGetName( HANDLE h, PSA pSockName, PSA pPeerName)
{
    SOCK *ps = (SOCK *)h;

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

    if( pSockName )
    {
        pSockName->sin_len         = sizeof( SA );
        pSockName->sin_family      = (UINT8)ps->Family;
        pSockName->sin_port        = ps->LPort;
        pSockName->sin_addr.s_addr = ps->dwLIP;
    }

    if( pPeerName )
    {
        pPeerName->sin_len         = sizeof( SA );
        pPeerName->sin_family      = (UINT8)ps->Family;
        pPeerName->sin_port        = ps->FPort;
        pPeerName->sin_addr.s_addr = ps->dwFIP;
    }

    return( 0 );
}

//--------------------------------------------------------------------
// SockListen()
//
// Listen for socket connections
//--------------------------------------------------------------------
int SockListen( HANDLE h, int maxcon )
{
    SOCK *ps = (SOCK *)h;
    int  error = 0;

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

    // To listen, we must be connection oriented
    if( !(ps->StateFlags & SS_CONNREQUIRED) )
        return( EOPNOTSUPP );

    // We also can't already be connected
    if( ps->StateFlags & (SS_ISCONNECTED | SS_ISCONNECTING) )
        return( EISCONN );

    // Call the protocol to start the listening process
    if( !(error = SockPrListen(ps)) )
    {
        // Success - Setup our state change

        // Set the listen bit
        ps->OptionFlags |= SO_ACCEPTCONN;

        // Once listening, there's no way to stop. Hence, we
        // can free the socket buffers
        if( ps->hSBRx )
            SBFree( ps->hSBRx );
        if( ps->hSBTx )
            SBFree( ps->hSBTx );
        ps->hSBRx = ps->hSBTx = 0;

        // Bound maxcon and set
        if( maxcon < 0 )
            maxcon = 0;
        if( maxcon > SOCK_MAXCONNECT )
            maxcon = SOCK_MAXCONNECT;
        ps->ConnMax = maxcon;
    }

    return( error );
}

//--------------------------------------------------------------------
// SockAccept()
//
// Accept a socket connection from a listening socket
//--------------------------------------------------------------------
int SockAccept( HANDLE h, HANDLE hFd, HANDLE *phSock )
{
    SOCK   *ps = (SOCK *)h;
    SOCK   *psRet;
    int    error = 0;

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

    // If not accepting, then we can't listen
    if( !(ps->OptionFlags & SO_ACCEPTCONN) )
        return( EINVAL );

    // If no connections available and we're non-blocking, then
    // return
    if( !ps->pReady && (ps->StateFlags & SS_NBIO) )
        return( EWOULDBLOCK );

    // While we don't have a connection, spin
    while( !ps->pReady && !ps->ErrorPending )
    {
        // If we're full, signal an error
        if( ps->StateFlags & SS_CANTRCVMORE )
        {
            ps->ErrorPending = ECONNABORTED;
            break;
        }

        // Wait forever (until wake)
        FDWaitEvent( ps->hFd, FD_EVENT_READ, 0 );
    }

    // Return Error if Error
    if( ps->ErrorPending )
    {
        error = ps->ErrorPending;
        ps->ErrorPending = 0;
        return( error );
    }

    // Unchain the next socket
    psRet              = ps->pReady;
    ps->pReady         = psRet->pReady;
    psRet->pReady      = 0;
    psRet->pParent     = 0;
    psRet->StateFlags &= ~SS_READYQ;
    ps->ConnTotal--;

    // Set owning file desc.
    psRet->hFd = hFd;

    *phSock = (HANDLE)psRet;

    return(0);
}

//--------------------------------------------------------------------
// SockSet()
//
// Set Socket Parameter Value
//--------------------------------------------------------------------
int SockSet(HANDLE hSock, int Type, int Prop, void *pbuf, int size)
{
    SOCK *ps = (SOCK *)hSock;
    int  value,error = 0;

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

    // Check size and pointer, just to be safe
    if( size && !pbuf )
        return( EINVAL );

    //
    // We also handle IPPROTO_IP and IPROTO_TCP
    //
    if( Type != SOL_SOCKET )
    {
        if( Type == IPPROTO_TCP )
        {
            if( ps->SockProt == SOCKPROT_TCP )
                return( TcpPrSetOption( hSock, ps->hTP, Prop, pbuf, size ) );
            else
                return( EINVAL );
        }
        if( Type == IPPROTO_IP )
        {
            if( Prop != IP_OPTIONS )
            {
                if( size != sizeof(int) )
                    return( EINVAL );
                value = *(int *)pbuf;
            }

            // Set Property
            switch( Prop )
            {
            case IP_TOS:
                ps->IpTos = (uint)value;
                break;

            case IP_TTL:
                ps->IpTtl = (uint)value;
                break;

            case IP_HDRINCL:
                // Only RAW sockets support this option
                if( ps->SockProt != SOCKPROT_RAW )
                    return( EINVAL );
                if( value )
                    ps->IpFlags |= SOCK_IP_HDRINCL;
                else
                    ps->IpFlags &= ~SOCK_IP_HDRINCL;
                break;

            case IP_OPTIONS:
                // Connection oriented sockets do not support options
                if( (ps->StateFlags & SS_CONNREQUIRED) || size > 40 )
                    return( EINVAL );
                ps->IpOptSize = (size + 3) & ~3;
                if( ps->IpOptSize )
                    mmCopy( ps->IpOptions, pbuf, ps->IpOptSize );
                break;
            }
        }
        return( 0 );
    }

    //
    // Socket Properties
    //

    //
    // Handle the structure based first
    //

    switch( Prop )
    {
    case SO_LINGER:
        {
            struct linger *pl = (struct linger *)pbuf;

            if( size != sizeof(struct linger) )
                return( EINVAL );
            if( pl->l_onoff )
                ps->OptionFlags |= SO_LINGER;
            else
                ps->OptionFlags &= ~SO_LINGER;
            ps->dwLingerTime = (UINT32)pl->l_linger * 1000;

            return(0);
        }

    case SO_SNDTIMEO:
    case SO_RCVTIMEO:
        {
            struct timeval *ptv = (struct timeval *)pbuf;
            UINT32         dwTime;

            if( size != sizeof(struct timeval) )
                return( EINVAL );

            dwTime = (UINT32)ptv->tv_sec*1000l;
            dwTime += (UINT32)ptv->tv_usec;

            if( Prop == SO_SNDTIMEO )
                ps->dwTxTimeout = dwTime;
            else
                ps->dwRxTimeout = dwTime;
            return(0);
        }

    case SO_IFDEVICE:
        {
            HANDLE h;

            // Only DGRAM sockets can use the IFDEVICE option
            if( !(ps->StateFlags & SS_ADDR) || size != sizeof(uint) )
                return( EINVAL );
            h = IFIndexGetHandle( *(uint *)pbuf );
            if( !h || (ExecHType(h) != HTYPE_ETH) )
                return( EINVAL );
            ps->hIFTx = h;
            return(0);
        }
    }

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

    switch( Prop )
    {
    case SO_BLOCKING:
        if( value )
            ps->StateFlags &= ~SS_NBIO;
        else
            ps->StateFlags |= SS_NBIO;
        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( value )
            ps->OptionFlags |= (uint)Prop;
        else
            ps->OptionFlags &= (uint)~Prop;
        break;

    case SO_SNDBUF:
        if( value > SOCK_BUFMAX )
            error = ENOBUFS;
        break;

    case SO_RCVBUF:
        if( value > SOCK_BUFMAX )
            error = ENOBUFS;
        break;

    case SO_SNDLOWAT:
        if( ps->hSBTx )
            SBSetMin( ps->hSBTx, value );
        break;

    case SO_RCVLOWAT:
        if( ps->hSBRx )
            SBSetMin( ps->hSBRx, value );
        break;

    case SO_ERROR:
        ps->ErrorPending = value;
        break;

    default:
        error = ENOPROTOOPT;
        break;
    }

    return(error);
}

//--------------------------------------------------------------------
// SockGet()
//
// Get Socket Parameter Value
//--------------------------------------------------------------------
int SockGet(HANDLE hSock, int Type, int Prop, void *pbuf, int *psize)
{
    SOCK *ps = (SOCK *)hSock;
    int  error = 0;

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

    // Check pointers, just to be safe
    if( !psize || !pbuf )
        return( EINVAL );

    //
    // We also handle IPPROTO_IP and IPROTO_TCP
    //
    if( Type != SOL_SOCKET )
    {
        if( Type == IPPROTO_TCP )
        {
            if( ps->SockProt == SOCKPROT_TCP )
                return( TcpPrGetOption( hSock, ps->hTP, Prop, pbuf, psize ) );
            else
                return( EINVAL );
        }
        if( Type == IPPROTO_IP )
        {
            if( Prop != IP_OPTIONS )
            {
                if( *psize < sizeof(int) )
                    return( EINVAL );
                *psize = sizeof(int);
            }

            switch( Prop )
            {
            case IP_TOS:
                *(int *)pbuf = (int)ps->IpTos;
                return(0);

            case IP_TTL:
                *(int *)pbuf = (int)ps->IpTtl;
                return(0);

            case IP_HDRINCL:
                if( ps->IpFlags & SOCK_IP_HDRINCL )
                    *(int *)pbuf = 1;
                else
                    *(int *)pbuf = 0;
                return(0);

            case IP_OPTIONS:
                if( *psize < (int)ps->IpOptSize )
                    return( EINVAL );
                *psize = (int)ps->IpOptSize;
                mmCopy( pbuf, ps->IpOptions, ps->IpOptSize );
                return(0);
            }
        }
        return( EINVAL );
    }

    //
    // Socket Properties
    //

    //
    // Handle the structure based first
    //

    switch( Prop )
    {
    case SO_LINGER:
        {
            struct linger *pl = (struct linger *)pbuf;
            if( *psize < sizeof( struct linger ) )
                return( EINVAL );
            *psize = sizeof( struct linger );
            if( ps->OptionFlags & SO_LINGER )
                pl->l_onoff = 1;
            else
                pl->l_onoff = 0;
            pl->l_linger = (int)(ps->dwLingerTime/1000);
            return(0);
        }

    case SO_SNDTIMEO:
    case SO_RCVTIMEO:
        {
            struct timeval *ptv = (struct timeval *)pbuf;

            if( *psize < sizeof(struct timeval) )
                return( EINVAL );
            *psize = sizeof( struct timeval );
            if( Prop == SO_SNDTIMEO )
            {
                ptv->tv_sec = ps->dwTxTimeout / 1000;
                ptv->tv_usec = ps->dwTxTimeout % 1000;
            }
            else
            {
                ptv->tv_sec = ps->dwRxTimeout / 1000;
                ptv->tv_usec = ps->dwRxTimeout % 1000;
            }
            return(0);
        }

    case SO_IFDEVICE:
        {
            if( *psize < sizeof( uint ) )
                return( EINVAL );

⌨️ 快捷键说明

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