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

📄 tcpout.c

📁 代码在ti的c67系列单片机上实现了完整的TCPIP协议栈
💻 C
📖 第 1 页 / 共 2 页
字号:
            tcps.dwSndRexmitByte+=len;  // Retransmit bytes
        }
        else
        {
            tcps.dwSndPack++;           // Send packets
            tcps.dwSndByte+=len;        // Send bytes
        }

        // Copy in the payload (with PEEK flag set to "1")
        SBRead( pt->hSBTx, len, off, pPayload, 0, 0, 1 );

        // If sending the last bit of data, set the PSH flag
        if( (len+off) == TxbTotal )
            flags |= TCP_PSH;
    }
    else
    {
        //
        // We're Not Sending Data
        //

        // Update the send type stats
        if( pt->t_flags & TF_ACKNOW )
            tcps.dwSndAcks++;           // Peek ACKS sent
        else if( flags & (TCP_SYN | TCP_FIN | TCP_RST) )
            tcps.dwSndCtrl++;           // Control packets sent
        else if( SEQ_GT( pt->snd_up, pt->snd_una ) )
            tcps.dwSndUrg++;            // URG only packets else
        else
            tcps.dwSndWinUp++;          // Window update packets
    }

    //
    // Fill in TCP Header
    //

    // Set some TCP header stuff
    pTcpHdr->HdrLen  = (UINT8)(((TCPHDR_SIZE+optlen)>>2)<<4);
    pTcpHdr->SrcPort = SockGetLPort(pt->hSock);
    pTcpHdr->DstPort = SockGetFPort(pt->hSock);

    //
    // Fill in Sequence Numbers
    //

    // If resending a FIN make sure to use to old sequence number
    if((flags&TCP_FIN) && (pt->t_flags&TF_SENTFIN) && (pt->snd_nxt==pt->snd_max))
        pt->snd_nxt--;

    // Since we may have resent data, snd_nxt can be less than snd_max. If
    // we're sending data or SYN/FIN flag, we'll use snd_nxt. For status
    // updates, we use snd_max.
    if( len || (flags&(TCP_SYN|TCP_FIN)) )
        dwTmp = HNC32(pt->snd_nxt);
    else
        dwTmp = HNC32(pt->snd_max);

    WrNet32( &pTcpHdr->dwSeq, dwTmp );

#ifdef TCP_DEBUG
    printf("Send %04X, F=%04X, S=%08lX, ",(int)pt,flags,HNC32(dwTmp));
    printf("A=%08lX, ",pt->rcv_nxt);
#endif

    dwTmp = HNC32(pt->rcv_nxt);
    WrNet32( &pTcpHdr->dwAck, dwTmp );

    // Copy in TCP header options
    if( optlen )
        mmCopy( pTcpHdr->Options, opt, (uint)optlen );

    // Calculate Window Size
    //
    // If less than 25% free and can't take a full segent, close window
    if( (win < SBGetMax(pt->hSBRx)/4) && (win < mss) )
        win = 0;

    // Don't shrink the window that's already been advertised
    if( win < (INT32)(pt->rcv_adv - pt->rcv_nxt) )
        win = (INT32)(pt->rcv_adv - pt->rcv_nxt);

    pTcpHdr->WindowSize = HNC16(((uint)win));

#ifdef TCP_DEBUG
    printf("L=%ld, W=%ld\n",len,win);
#endif

    // Check for Urgent data
    if( SEQ_GT( pt->snd_up, pt->snd_nxt ) )
    {
        dwTmp = pt->snd_up - pt->snd_nxt;
        pTcpHdr->UrgPtr = HNC16(((uint)dwTmp));
        flags |= TCP_URG;
    }
    else
    {
        // Keep "up" bumped over to the far left
        pt->snd_up = pt->snd_una;
        pTcpHdr->UrgPtr = 0;
    }

    // Now we can set flags
    pTcpHdr->Flags = flags;

    // Fixup packet frag info
    dwTmp = len+TCPHDR_SIZE+optlen;
    dwTmp = (UINT32)(HNC16(((uint)dwTmp)));

    // Checksum Header
    tpseudo.dwIPSrc  = SockGetLIP(pt->hSock);
    tpseudo.dwIPDst  = SockGetFIP(pt->hSock);
    tpseudo.Null     = 0;
    tpseudo.Protocol = 6;
    tpseudo.Length   = (UINT16)dwTmp;
    TcpChecksum( pTcpHdr );

    //
    // The packet is all set to go, but we need to update some of
    // our sequences and timers.
    //

    // If in persist state, just update snd_max
    if( pt->t_flags & TF_PERSIST )
    {
        // Length is always 1
        if( SEQ_GT( pt->snd_nxt+len, pt->snd_max ) )
            pt->snd_max = pt->snd_nxt+len;
    }
    else
    {
        //
        // Update sequences and timers
        //
        dwTmp = pt->snd_nxt;            // Save this for later

        // Advance snd_nxt
        //
        // SYN and FIN count as a squence byte
        if( flags & TCP_SYN )
            pt->snd_nxt++;
        if( flags & TCP_FIN )
        {
            pt->snd_nxt++;
            pt->t_flags |= TF_SENTFIN;
        }

        // Count actual payload bytes
        pt->snd_nxt += len;

        // If sending new data, bump snd_max, and potentially time
        // segment
        if( SEQ_GT( pt->snd_nxt, pt->snd_max ) )
        {
            pt->snd_max = pt->snd_nxt;

            // If timer isn't going, time this sequence
            if( !pt->t_trtt )
            {
                pt->t_trtt = 1;
                pt->t_rttseq = dwTmp;
                tcps.dwSegsTimed++;
            }
        }

        // Set the Retransmit timer if not already set, unless we don't
        // expect an ACK (snd_nxt == snd_una)
        if( !pt->dwTicksRexmt && (pt->snd_nxt != pt->snd_una) )
        {
            pt->dwTicksRexmt = pt->t_trtx;

            // Since we just sent a packet, we don't "persist"
            if( pt->dwTicksPersist )
            {
                pt->dwTicksPersist = 0;
                pt->t_rtxindex = 0;
            }
        }
    }

    // If we've advertised a larger window, remember it
    if( win > 0 && SEQ_GT( pt->rcv_nxt + win, pt->rcv_adv ) )
        pt->rcv_adv = pt->rcv_nxt + win;

    // Clear ACK related flags
    pt->t_flags &= ~(TF_NEEDOUTPUT|TF_ACKNOW|TF_DELACK|TF_PERSIST);

    // Indicate the preferred route
    PktSetRoute( hPkt, SockGetRoute( pt->hSock ) );

    // Count it
    tcps.dwSndTotal++;

    // Send the packet
    error = IPTxPacket( hPkt,
                        SockGetOptionFlags(pt->hSock) & FLG_IPTX_SOSUPPORTED );

    // Handle error cases
    if( error )
    {
        if( (error == EHOSTUNREACH || error == EHOSTDOWN) &&
            pt->t_state >= TSTATE_SYNRCVD )
        {
            pt->t_softerror = error;
            return( 0 );
        }
        return( error );
    }

    if( sendmore )
        goto sendagain;

    return(0);
}

//--------------------------------------------------------------------
// TcpGenPacket()
//
// Called to send quick and dirty TCP packets
//--------------------------------------------------------------------
void TcpGenPacket
(
    TCPPROT *pt,
    IPN     dwIPDst,
    uint    PortDst,
    IPN     dwIPSrc,
    uint    PortSrc,
    UINT32  ack,
    UINT32  seq,
    int flags
)
{
    HANDLE      hPkt,hFrag;
    uint        Offset,IPHdrLen,win;
    UINT8       *pb;
    TCPHDR      *pTcpHdr;
    IPHDR       *pIpHdr;

    if( !pt )
        hPkt = SockCreatePacket( 0, 0, TCPHDR_SIZE);
    else
        hPkt = SockCreatePacket( pt->hSock, 0, TCPHDR_SIZE);

    if( !hPkt )
        return;

    // Get the frag
    hFrag = PktGetFrag( hPkt );

    // Get the buffer parameters
    pb = FragGetBufParams( hFrag, 0, 0, &Offset );

    // Get the IP header len
    IPHdrLen = PktGetSizeNet( hPkt );

    // Assign an IP header pointer
    pIpHdr = (IPHDR *)(pb + Offset);

    // Assign a UDP header pointer
    pTcpHdr = (TCPHDR *)(pb + Offset + IPHdrLen);

    //
    // Fill in TCP/IP Header
    //

    // Override some IP header stuff
    pIpHdr->Protocol = 6;
    WrNet32( &pIpHdr->dwIPSrc, dwIPSrc );
    WrNet32( &pIpHdr->dwIPDst, dwIPDst );

    // Set some TCP header stuff
    pTcpHdr->HdrLen  = TCPHDR_SIZE*4;
    pTcpHdr->SrcPort = PortSrc;
    pTcpHdr->DstPort = PortDst;
    pTcpHdr->UrgPtr  = 0;
    seq = HNC32(seq);
    WrNet32( &pTcpHdr->dwSeq, seq );
    ack = HNC32(ack);
    WrNet32( &pTcpHdr->dwAck, ack );

    // Setup the window size we wish to advertise
    // This is the space we have left in the RX buffer
    if( !pt )
        pTcpHdr->WindowSize = 0;
    else
    {
        win = (uint)SBGetSpace(pt->hSBRx);
        pTcpHdr->WindowSize = HNC16(win);
    }

    // Set flags
    pTcpHdr->Flags = flags;

    // Checksum Header
    tpseudo.dwIPSrc  = dwIPSrc;
    tpseudo.dwIPDst  = dwIPDst;
    tpseudo.Null     = 0;
    tpseudo.Protocol = 6;
    tpseudo.Length   = HNC16(TCPHDR_SIZE);
    TcpChecksum( pTcpHdr );

    // Count it
    tcps.dwSndTotal++;

    // Send the packet
    if( pt )
        IPTxPacket( hPkt, SockGetOptionFlags(pt->hSock)&FLG_IPTX_SOSUPPORTED );
    else
        IPTxPacket( hPkt, 0 );
}

⌨️ 快捷键说明

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