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

📄 tcpprot.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
字号:
//--------------------------------------------------------------------------
// Ip Stack
//--------------------------------------------------------------------------
// TCPPROT.C
//
// TCP Protocol Functions + Misc Functions
//
// Author: Michael A. Denio
// Copyright 1999 by Texas Instruments Inc.
//-------------------------------------------------------------------------
#include <stkmain.h>
#include "tcp.h"

//--------------------------------------------------------------------
// TcpPrAttach()
//
// Creates a new TCP side "socket"
//--------------------------------------------------------------------
int TcpPrAttach( HANDLE h, HANDLE *phTcp )
{
    TCPPROT *pt;

    // Allocate the TCP Protocol Control Block
    if( !(pt = mmAlloc(sizeof(TCPPROT))) )
    {
        DbgPrintf(DBG_WARN,"TcpPrAttach: OOM");
        ExecLowResource();

        // Return the error
        return( ENOMEM );
    }

    // Default init to zero
    mmZeroInit( pt, sizeof(TCPPROT) );

    // Initialize the TCP Protocol Control Block
    pt->hSock    = h;
    pt->t_state  = TSTATE_CLOSED;
    pt->t_mss    = TCP_MSS_DEFAULT;
    pt->t_flags  = TCP_TFLAGS_DEFAULT;

    pt->t_srtt   = TCPTV_SRTTBASE << TCP_FIXP_SHIFT;
    pt->t_rttvar = TCPTV_RTTDFLT << TCP_FIXP_SHIFT;
    pt->t_trtx   = pt->t_rttvar >> (TCP_FIXP_SHIFT-1);

    pt->snd_cwnd     = TCP_MAXWIN;

    // Get local copies of the SOCK buffers
    pt->hSBRx = SockGetRx( h );
    pt->hSBTx = SockGetTx( h );

    // Initialize our handle in the SOCK object
    *phTcp = (HANDLE)pt;

    // Now we attach the Socket to our handler list
    SockPcbAttach( h );
    TcpTimeoutAdd( pt );

    return(0);
}

//--------------------------------------------------------------------
// TcpPrDetach()
//
// Closes a TCP side "socket", detaches, and free resources
//--------------------------------------------------------------------
int TcpPrDetach( HANDLE hSock, HANDLE *phTcp, int fatal )
{
    TCPPROT *pt = *(TCPPROT **)phTcp;

    // Mark this so close doesn't notify the socket layer
    pt->t_flags |= TF_DETACHED;

    //
    // We CLOSE an unconnected socket, but if something is in progress,
    // use DROP. We are detaching, so can't do anything gracefully.
    //
    if( !fatal && pt->t_state >= TSTATE_SYNRCVD && pt->t_state != TSTATE_TIMEWAIT )
        TcpDrop( pt, 0 );       // TcpDrop() calls TcpClose()
    else
        TcpClose( pt );         // Must call - frees some resources

    //
    // Detach the socket and free the TCP control
    //
    TcpTimeoutRemove( pt );
    SockPcbDetach( hSock );

    // Zap the TCP Proto Structure
    *phTcp = 0;

    mmFree( pt );

    return(0);
}

//--------------------------------------------------------------------
// TcpPrListen()
//
// Called to mark TCP "socket" as a listening socket
//--------------------------------------------------------------------
int TcpPrListen( HANDLE h, HANDLE hTcp )
{
    TCPPROT  *pt = (TCPPROT *)hTcp;

    (void)h;

    // This really kills the socket as far as TCP is concerned.
    // It simply becomes a "spawnable" mark in the PCB table

    // Lets not take any chances on this...
    pt->t_state = TSTATE_CLOSED;

    // Also free held resources
    if( pt->hFrag )
        FragFree( pt->hFrag );
    pt->hFrag = 0;

    // Also zap the local copy of the buffer handles
    pt->hSBRx = pt->hSBTx = 0;

    return(0);
}

//--------------------------------------------------------------------
// TcpPrConnect()
//
// Request a connection for a TCP side socket
//--------------------------------------------------------------------
int TcpPrConnect( HANDLE h, HANDLE hTcp )
{
    TCPPROT *pt = (TCPPROT *)hTcp;
    int     error = 0;

    (void)h;

    // Bump the stats
    tcps.dwConnAttempt++;

    // Set inititial send sequence number
    pt->snd_una = pt->snd_nxt = pt->snd_max = pt->snd_up = pt->iss = tcp_iss;
    tcp_iss += TCP_ISSINCR / 2;

    // Send the SYN ("KeepAlive" timer is also our connection timeout timer)
    pt->t_state     = TSTATE_SYNSENT;
    pt->dwTicksKeep = TCPTV_KEEP_INIT;

    error = TcpOutput( hTcp );

    return( error );
}

//--------------------------------------------------------------------
// TcpPrDisconnect()
//
// Disconnects a TCP side "socket" - performs "half close"
//--------------------------------------------------------------------
int TcpPrDisconnect( HANDLE h, HANDLE hTcp )
{
    (void)h;

    // Close the write side
    TcpUsrClose( hTcp );
    return(0);
}

//--------------------------------------------------------------------
// TcpPrRecv()
//
// Deal with Rx data being removed from buffer
//--------------------------------------------------------------------
int TcpPrRecv( HANDLE h, HANDLE hTcp )
{
    (void)h;

    // A read may cause us to readjust our window
    return( TcpOutput( hTcp ) );
}

//--------------------------------------------------------------------
// TcpPrSend()
//
// Send data
//--------------------------------------------------------------------
int TcpPrSend( HANDLE h, HANDLE hTcp, UINT8 *pBuf, INT32 Size, INT32 *pRetSize )
{
    TCPPROT  *pt = (TCPPROT *)hTcp;
    INT32    Space;

    (void)h;

    // Append as much data as possible to the output buffer
    Space = SBGetSpace( pt->hSBTx );
    if( Space < Size )
        Size = Space;

    // Copy out the data
    if( Size )
        Size = SBWrite( pt->hSBTx, Size, pBuf, 0 );
    *pRetSize = Size;

    // Data write may cause us to send data
    if( Size )
        return( TcpOutput( hTcp ) );
    else
        return( 0 );
}

//--------------------------------------------------------------------
// TcpPrSendOOB()
//
// Send data
//--------------------------------------------------------------------
int TcpPrSendOOB( HANDLE h, HANDLE hTcp, UINT8 *pBuf,
                  INT32 Size, INT32 *pRetSize )
{
    TCPPROT  *pt = (TCPPROT *)hTcp;
    INT32    Space;
    int      error;

    (void)h;

    // Append as much data as possible to the output buffer
    Space = SBGetSpace( pt->hSBTx );
    if( Space < Size )
        Size = Space;

    // Copy out the data
    if( Size )
        Size = SBWrite( pt->hSBTx, Size, pBuf, 0 );
    *pRetSize = Size;

    // Update urgent pointer
    pt->snd_up = pt->snd_una + SBGetTotal(pt->hSBTx);

    // Data write may cause us to send data
    error = TcpOutput(pt);

    return( error );
}

//--------------------------------------------------------------------
// TcpPrInherit()
//
// Send data
//--------------------------------------------------------------------
void TcpPrInherit( HANDLE hParent, HANDLE hTcpParent,
                   HANDLE hChild, HANDLE hTcpChild )
{
    TCPPROT  *ptP = (TCPPROT *)hTcpParent;
    TCPPROT  *ptC = (TCPPROT *)hTcpChild;

    (void)hParent;
    (void)hChild;

    ptC->t_flags |= ptP->t_flags & (TF_NOPUSH|TF_NOOPT|TF_NODELAY);
}

//--------------------------------------------------------------------
// TcpPrGetState()
//
// Return TCP State
//--------------------------------------------------------------------
uint TcpPrGetState( HANDLE hParent, HANDLE hTcp )
{
    (void)hParent;

    return( ((TCPPROT *)hTcp)->t_state );
}

//--------------------------------------------------------------------
// TcpPrSetOptions()
//
// Set TCP Options
//--------------------------------------------------------------------
int TcpPrSetOption(HANDLE h, HANDLE hTcp, int Prop, void *pBuf, int size)
{
    TCPPROT  *pt = (TCPPROT *)hTcp;
    int      value;

    (void)h;

    if( size != sizeof(int) || !pBuf )
        return( EINVAL );

    value = *(int *)pBuf;

    switch( Prop )
    {
    case TCP_NODELAY:
        if( value )
            pt->t_flags |= TF_NODELAY;
        else
            pt->t_flags &= ~TF_NODELAY;
        return( 0 );

    case TCP_NOPUSH:
        if( value )
            pt->t_flags |= TF_NOPUSH;
        else
            pt->t_flags &= ~TF_NOPUSH;
        return( 0 );

    case TCP_NOOPT:
        if( value )
            pt->t_flags |= TF_NOOPT;
        else
            pt->t_flags &= ~TF_NOOPT;
        return( 0 );

    case TCP_MAXSEG:
        if( (uint)value < pt->t_mss )
            TcpValidateMetrics( pt, (uint)value );
        return( 0 );
    }
    return( EINVAL );
}

//--------------------------------------------------------------------
// TcpPrGetOptions()
//
// Get TCP Options
//--------------------------------------------------------------------
int TcpPrGetOption(HANDLE h, HANDLE hTcp, int Prop, void *pBuf, int *psize)
{
    TCPPROT  *pt = (TCPPROT *)hTcp;

    (void)h;

    if( *psize < sizeof(int) )
        return( EINVAL );

    *psize = sizeof(int);

    switch( Prop )
    {
    case TCP_NODELAY:
        if( pt->t_flags & TF_NODELAY )
            *(int *)pBuf = 1;
        else
            *(int *)pBuf = 0;
        return( 0 );

    case TCP_NOPUSH:
        if( pt->t_flags & TF_NOPUSH )
            *(int *)pBuf = 1;
        else
            *(int *)pBuf = 0;
        return( 0 );

    case TCP_NOOPT:
        if( pt->t_flags & TF_NOOPT )
            *(int *)pBuf = 1;
        else
            *(int *)pBuf = 0;
        return( 0 );

    case TCP_MAXSEG:
        *(int *)pBuf = (int)pt->t_mss;
        return( 0 );
    }
    return( EINVAL );
}

//--------------------------------------------------------------------
// TcpPrCtlError()
//
// Inform TCP of an error
//--------------------------------------------------------------------
void TcpPrCtlError( HANDLE h, HANDLE hTcp, uint Code, int Error )
{
    TCPPROT  *pt = (TCPPROT *)hTcp;

    // Quench - close congestion window
    if( Code == PRC_QUENCH )
        pt->snd_cwnd = pt->t_mss;
    else if( Error )
    {
        // Depending on state, we may ignore some errors
        if( pt->t_state == TSTATE_ESTAB &&
                ( Error == EHOSTUNREACH || Error == EHOSTDOWN ) )
            return;

       if( pt->t_state<TSTATE_ESTAB && pt->t_rtxindex>3 && pt->t_softerror )
            SockSetError( h, Error );
       else
            pt->t_softerror = Error;

       SockNotify( h, SOCK_NOTIFY_ERROR );
    }
}

//--------------------------------------------------------------------
//
// The following are protocol support functions
//
//--------------------------------------------------------------------

//--------------------------------------------------------------------
// TcpDrop()
//
// Drops a TCP side "socket" with ABORT
//--------------------------------------------------------------------
void TcpDrop( TCPPROT *pt, int Error )
{
    // Drop the connection with "ABORTED" error
    if( pt->t_state >= TSTATE_SYNRCVD )
    {
        pt->t_state = TSTATE_CLOSED;
        TcpOutput( pt );
        tcps.dwDrops++;
    }
    else
        tcps.dwConnDrops++;

    // Change a TIMEOUT to the soft error if any, and set error code
    if( Error == ETIMEDOUT && pt->t_softerror )
        Error = pt->t_softerror;
    SockSetError( pt->hSock, Error );

    TcpClose( pt );
}

//--------------------------------------------------------------------
// TcpUsrClose()
//
// User requested close
//--------------------------------------------------------------------
void TcpUsrClose( TCPPROT *pt )
{
    if( pt->t_state < TSTATE_ESTAB )
        TcpClose( pt );
    else if( pt->t_state < TSTATE_CLOSEWAIT )
    {
        pt->t_state = TSTATE_FINWAIT1;
        TcpOutput( pt );
    }
    else if( pt->t_state == TSTATE_CLOSEWAIT )
    {
        pt->t_state = TSTATE_LASTACK;
        TcpOutput( pt );
    }

    // Notify the Socket
    if( pt->t_state >= TSTATE_FINWAIT2 )
        SockNotify( pt->hSock, SOCK_NOTIFY_DISCONNECT );
}

//--------------------------------------------------------------------
// TcpClose()
//
// Closes down the TCP protocol block
//--------------------------------------------------------------------
void TcpClose( TCPPROT *pt )
{
    pt->t_state = TSTATE_CLOSED;

    // Free held resources
    if( pt->hFrag )
        FragFree( pt->hFrag );
    pt->hFrag = 0;

    // Notify the Socket (if not already detached)
    if( !(pt->t_flags & TF_DETACHED) )
        SockNotify( pt->hSock, SOCK_NOTIFY_CLOSED );
}

//--------------------------------------------------------------------
// TcpValidateMetrics
//
// Called to update TCP information based on socket route
// Returns current MSS to advertise
//--------------------------------------------------------------------
uint TcpValidateMetrics( TCPPROT *pt, uint rcvmss )
{
    HANDLE hRoute;
    uint ourmss;

    // Validate the route plus any route related metrics (like t_mss)
    if( !(hRoute = SockGetRoute( pt->hSock )) )
        hRoute = SockValidateRoute( pt->hSock );

    // Get our (best case) mss
    if( !hRoute )
        ourmss = TCP_MSS_DEFAULT_NR;
    else
        ourmss = RtGetMTU( hRoute );

    // Take off IpHdr & TcpHdr
    ourmss -= SockGetIpHdrSize(pt->hSock) + TCPHDR_SIZE;

    // A previous write overrides us
    if( (pt->t_flags & TF_RCVD_MSS) && pt->t_mss < ourmss )
        ourmss = pt->t_mss;

    // If we have received an mss, record it
    if( rcvmss )
    {
        // Use the smallest of the valid mss values
        pt->t_flags |= TF_RCVD_MSS;
        if( rcvmss < ourmss )
            pt->t_mss = rcvmss;
        else
            pt->t_mss = ourmss;
    }

    // If we have a valid (negotiated) mss, return it. Else,
    // return what we'd like to advertise.
    if( pt->t_flags & TF_RCVD_MSS )
        return( pt->t_mss );
    return( ourmss );
}

⌨️ 快捷键说明

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