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

📄 tcp.c

📁 凌阳SPCE3200 系统开发板随机自带源程序。共安排了32个子目录
💻 C
📖 第 1 页 / 共 4 页
字号:
         */
        switch(ps->smState)
        {
        case TCP_SYN_SENT:
            /*
             * Keep sending SYN until we hear from remote node.
             * This may be for infinite time, in that case
             * caller must detect it and do something.
             * Bug Fix: 11/1/02
             */
            flags = SYN;
            break;

        case TCP_SYN_RCVD:
            /*
             * We must receive ACK before timeout expires.
             * If not, resend SYN+ACK.
             * Abort, if maximum attempts counts are reached.
             */
            if ( ps->RetryCount < MAX_RETRY_COUNTS )
            {
                flags = SYN | ACK;
            }
            else
                CloseSocket(ps);
            break;

        case TCP_EST:
#if !defined(TCP_NO_WAIT_FOR_ACK)
            /*
             * Don't let this connection idle for very long time.
             * If we did not receive or send any message before timeout
             * expires, close this connection.
             */
            if ( ps->RetryCount <= MAX_RETRY_COUNTS )
            {
                if ( ps->TxBuffer != INVALID_BUFFER )
                {
                    MACSetTxBuffer(ps->TxBuffer, 0);
                    MACFlush();
                }
                else
                    flags = ACK;
            }
            else
            {
                // Forget about previous transmission.
                if ( ps->TxBuffer != INVALID_BUFFER )
                    MACDiscardTx(ps->TxBuffer);
                ps->TxBuffer = INVALID_BUFFER;

#endif
                // Request closure.
                flags = FIN | ACK;

                ps->smState = TCP_FIN_WAIT_1;
#if !defined(TCP_NO_WAIT_FOR_ACK)
            }
#endif
            break;

        case TCP_FIN_WAIT_1:
        case TCP_LAST_ACK:
            /*
             * If we do not receive any response to out close request,
             * close it outselves.
             */
            if ( ps->RetryCount > MAX_RETRY_COUNTS )
                CloseSocket(ps);
            else
                flags = FIN;
            break;

        case TCP_CLOSING:
        case TCP_TIMED_WAIT:
            /*
             * If we do not receive any response to out close request,
             * close it outselves.
             */
            if ( ps->RetryCount > MAX_RETRY_COUNTS )
                CloseSocket(ps);
            else
                flags = ACK;
            break;
        }

        if ( flags > 0x00 )
        {
            if ( flags != ACK )
                seq = ps->SND_SEQ++;
            else
                seq = ps->SND_SEQ;

            SendTCP(&ps->remote,
                    ps->localPort,
                    ps->remotePort,
                    seq,
                    ps->SND_ACK,
                    flags);
        }
    }
#else
    return;
#endif
}



/*********************************************************************
 * Function:        BOOL TCPProcess(NODE_INFO* remote,
 *                                  IP_ADDR *localIP,
 *                                  WORD len)
 *
 * PreCondition:    TCPInit() is already called     AND
 *                  TCP segment is ready in MAC buffer
 *
 * Input:           remote      - Remote node info
 *                  len         - Total length of TCP semgent.
 *
 * Output:          TRUE if this function has completed its task
 *                  FALSE otherwise
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
BOOL TCPProcess(NODE_INFO *remote, IP_ADDR *localIP, WORD len)
{
    TCP_HEADER      TCPHeader;
    PSEUDO_HEADER   pseudoHeader;
    TCP_SOCKET      socket;
    WORD_VAL        checksum;
    BYTE            optionsSize;


    // Retrieve TCP header.
    MACGetArray((BYTE*)&TCPHeader, sizeof(TCPHeader));

    SwapTCPHeader(&TCPHeader);

    // Calculate IP pseudoheader checksum.
    pseudoHeader.SourceAddress      = remote->IPAddr;
    pseudoHeader.DestAddress.v[0]   = localIP->v[0];
    pseudoHeader.DestAddress.v[1]   = localIP->v[1];
    pseudoHeader.DestAddress.v[2]   = localIP->v[2];
    pseudoHeader.DestAddress.v[3]   = localIP->v[3];
    pseudoHeader.Zero               = 0x0;
    pseudoHeader.Protocol           = IP_PROT_TCP;
    pseudoHeader.TCPLength          = len;

    SwapPseudoTCPHeader(pseudoHeader);


    checksum.Val = ~CalcIPChecksum((BYTE*)&pseudoHeader,
                                    sizeof(pseudoHeader));


    // Set TCP packet checksum = pseudo header checksum in MAC RAM.
    IPSetRxBuffer(16);
    MACPut(checksum.v[0]);
	// In case if the end of the RX buffer is reached and a wraparound is needed, set the next address to prevent writing to the wrong address.
    IPSetRxBuffer(17);			
    MACPut(checksum.v[1]);
    IPSetRxBuffer(0);

    // Now calculate TCP packet checksum in NIC RAM - including
    // pesudo header.
    checksum.Val = CalcIPBufferChecksum(len);

    if ( checksum.Val != TCPHeader.Checksum )
    {
        MACDiscardRx();
        return TRUE;
    }

    // Skip over options and retrieve all data bytes.
    optionsSize = (BYTE)((TCPHeader.DataOffset.Val << 2)-
                            sizeof(TCPHeader));
    len = len - optionsSize - sizeof(TCPHeader);

    // Position packet read pointer to start of data area.
    IPSetRxBuffer((TCPHeader.DataOffset.Val << 2));

    // Find matching socket.
    socket = FindMatchingSocket(&TCPHeader, remote);
    if ( socket < INVALID_SOCKET )
    {
        HandleTCPSeg(socket, remote, &TCPHeader, len);
    }
    else
    {
        /*
         * If this is an unknown socket, discard it and
         * send RESET to remote node.
         */
        MACDiscardRx();

        if ( socket == UNKNOWN_SOCKET )
        {

            TCPHeader.AckNumber += len;
            if ( TCPHeader.Flags.bits.flagSYN ||
                 TCPHeader.Flags.bits.flagFIN )
                TCPHeader.AckNumber++;

            SendTCP(remote,
                    TCPHeader.DestPort,
                    TCPHeader.SourcePort,
                    TCPHeader.AckNumber,
                    TCPHeader.SeqNumber,
                    RST);
        }

    }

    return TRUE;
}


/*********************************************************************
 * Function:        static void TransmitTCP(NODE_INFO* remote
 *                                          TCP_PORT localPort,
 *                                          TCP_PORT remotePort,
 *                                          DWORD seq,
 *                                          DWORD ack,
 *                                          BYTE flags,
 *                                          BUFFER buffer,
 *                                          WORD len)
 *
 * PreCondition:    TCPInit() is already called     AND
 *                  TCPIsPutReady() == TRUE
 *
 * Input:           remote      - Remote node info
 *                  localPort   - Source port number
 *                  remotePort  - Destination port number
 *                  seq         - Segment sequence number
 *                  ack         - Segment acknowledge number
 *                  flags       - Segment flags
 *                  buffer      - Buffer to which this segment
 *                                is to be transmitted
 *                  len         - Total data length for this segment.
 *
 * Output:          A TCP segment is assembled and put to transmit.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
static void TransmitTCP(NODE_INFO *remote,
                        TCP_PORT localPort,
                        TCP_PORT remotePort,
                        DWORD tseq,
                        DWORD tack,
                        BYTE flags,
                        BUFFER buffer,
                        WORD len)
{
    WORD_VAL        checkSum;
    TCP_HEADER      header;
    TCP_OPTIONS     options;
    PSEUDO_HEADER   pseudoHeader;

    /*
     * When using SLIP (USART), packet transmission takes some time
     * and hence before sending another packet, we must make sure
     * that, last packet is transmitted.
     * When using ethernet controller, transmission occurs very fast
     * and by the time next packet is transmitted, previous is
     * transmitted and we do not need to check for last packet.
     */
    while( !IPIsTxReady() );

    header.SourcePort           = localPort;
    header.DestPort             = remotePort;
    header.SeqNumber            = tseq;
    header.AckNumber            = tack;
    header.Flags.bits.Reserved2 = 0;
    header.DataOffset.Reserved3 = 0;
    header.Flags.byte           = flags;
    // Receive window = MAC Free buffer size - TCP header (20) - IP header (20)
    //                  - ETHERNET header (14 if using NIC) .
    header.Window               = MACGetFreeRxSize();
#if !defined(STACK_USE_SLIP)
    /*
     * Limit one segment at a time from remote host.
     * This limit increases overall throughput as remote host does not
     * flood us with packets and later retry with significant delay.
     */
    if ( header.Window >= MAC_RX_BUFFER_SIZE )
        header.Window = MAC_RX_BUFFER_SIZE;

    else if ( header.Window > 54 )
    {
        header.Window -= 54;
    }
    else
        header.Window = 0;
#else
    if ( header.Window > 40 )
    {
        header.Window -= 40;
    }
    else
        header.Window = 0;
#endif

    header.Checksum             = 0;
    header.UrgentPointer        = 0;

    SwapTCPHeader(&header);

    len += sizeof(header);

    if ( flags & SYN )
    {
        len += sizeof(options);
        options.Kind = TCP_OPTIONS_MAX_SEG_SIZE;
        options.Length = 0x04;

        // Load MSS in already swapped order.
        options.MaxSegSize.v[0]  = (MAC_RX_BUFFER_SIZE >> 8); // 0x05;
        options.MaxSegSize.v[1]  = (MAC_RX_BUFFER_SIZE & 0xff); // 0xb4;

        header.DataOffset.Val   = (sizeof(header) + sizeof(options)) >> 2;
    }
    else
        header.DataOffset.Val   = sizeof(header) >> 2;


    // Calculate IP pseudoheader checksum.
    pseudoHeader.SourceAddress.v[0] = MY_IP_BYTE1;
    pseudoHeader.SourceAddress.v[1] = MY_IP_BYTE2;
    pseudoHeader.SourceAddress.v[2] = MY_IP_BYTE3;
    pseudoHeader.SourceAddress.v[3] = MY_IP_BYTE4;
    pseudoHeader.DestAddress    = remote->IPAddr;
    pseudoHeader.Zero           = 0x0;
    pseudoHeader.Protocol       = IP_PROT_TCP;
    pseudoHeader.TCPLength      = len;

    SwapPseudoTCPHeader(pseudoHeader);

    header.Checksum = ~CalcIPChecksum((BYTE*)&pseudoHeader,
                        sizeof(pseudoHeader));
    checkSum.Val = header.Checksum;

    if ( buffer == INVALID_BUFFER )
        buffer = MACGetTxBuffer();

    IPSetTxBuffer(buffer, 0);

    // Write IP header.
    IPPutHeader(remote, IP_PROT_TCP, len);
    IPPutArray((BYTE*)&header, sizeof(header));

    if ( flags & SYN )
        IPPutArray((BYTE*)&options, sizeof(options));

    IPSetTxBuffer(buffer, 0);

    checkSum.Val = CalcIPBufferChecksum(len);

    // Update the checksum.
    IPSetTxBuffer(buffer, 16);
    MACPut(checkSum.v[1]);
    MACPut(checkSum.v[0]);
    MACSetTxBuffer(buffer, 0);

    MACFlush();
}



/*********************************************************************
 * Function:        static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h,
 *                                      NODE_INFO* remote)
 *
 * PreCondition:    TCPInit() is already called
 *
 * Input:           h           - TCP Header to be matched against.
 *                  remote      - Node who sent this header.
 *
 * Output:          A socket that matches with given header and remote
 *                  node is searched.
 *                  If such socket is found, its index is returned
 *                  else INVALID_SOCKET is returned.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
static TCP_SOCKET FindMatchingSocket(TCP_HEADER *h, NODE_INFO *remote)
{
    SOCKET_INFO *ps;
    TCP_SOCKET s;
    TCP_SOCKET partialMatch;

    partialMatch = INVALID_SOCKET;

    for ( s = 0; s < MAX_SOCKETS; s++ )
    {
        ps = &TCB[s];

        if ( ps->smState != TCP_CLOSED )
        {
            if ( ps->localPort == h->DestPort )
            {
                if ( ps->smState == TCP_LISTEN )
                    partialMatch = s;

                if ( ps->remotePort == h->SourcePort &&
                     ps->remote.IPAddr.Val == remote->IPAddr.Val )
                {
                        return s;
                }
            }
        }
    }

    ps = &TCB[partialMatch];

    if ( partialMatch != INVALID_SOCKET &&
         ps->smState == TCP_LISTEN )
    {
        memcpy((void*)&ps->remote, (void*)remote, sizeof(*remote));
        //ps->remote              = *remote;
        ps->localPort           = h->DestPort;
        ps->remotePort          = h->SourcePort;
        ps->Flags.bIsGetReady   = FALSE;
        ps->TxBuffer            = INVALID_BUFFER;
        ps->Flags.bIsPutReady   = TRUE;

        return partialMatch;
    }

⌨️ 快捷键说明

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