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

📄 tcp.c

📁 凌阳SPCE3200 系统开发板随机自带源程序。共安排了32个子目录
💻 C
📖 第 1 页 / 共 4 页
字号:

    if ( partialMatch == INVALID_SOCKET )
        return UNKNOWN_SOCKET;
    else
        return INVALID_SOCKET;
}






/*********************************************************************
 * Function:        static void SwapTCPHeader(TCP_HEADER* header)
 *
 * PreCondition:    None
 *
 * Input:           header      - TCP Header to be swapped.
 *
 * Output:          Given header is swapped.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
static void SwapTCPHeader(TCP_HEADER* header)
{
    header->SourcePort      = swaps(header->SourcePort);
    header->DestPort        = swaps(header->DestPort);
    header->SeqNumber       = swapl(header->SeqNumber);
    header->AckNumber       = swapl(header->AckNumber);
    header->Window          = swaps(header->Window);
    header->Checksum        = swaps(header->Checksum);
    header->UrgentPointer   = swaps(header->UrgentPointer);
}



/*********************************************************************
 * Function:        static void CloseSocket(SOCKET_INFO* ps)
 *
 * PreCondition:    TCPInit() is already called
 *
 * Input:           ps  - Pointer to a socket info that is to be
 *                          closed.
 *
 * Output:          Given socket information is reset and any
 *                  buffer held by this socket is discarded.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
static void CloseSocket(SOCKET_INFO* ps)
{
    if ( ps->TxBuffer != INVALID_BUFFER )
    {
        MACDiscardTx(ps->TxBuffer);
        ps->TxBuffer            = INVALID_BUFFER;
        ps->Flags.bIsPutReady   = TRUE;
    }

    ps->remote.IPAddr.Val = 0x00;
    ps->remotePort = 0x00;
    if ( ps->Flags.bIsGetReady )
    {
        MACDiscardRx();
    }
    ps->Flags.bIsGetReady       = FALSE;
    ps->Flags.bACKValid			= FALSE;
    ps->TimeOut                 = TCP_START_TIMEOUT_VAL;

    ps->Flags.bIsTxInProgress   = FALSE;

    if ( ps->Flags.bServer )
    {
        ps->smState = TCP_LISTEN;
    }
    else
    {
        ps->smState = TCP_CLOSED;
    }
    return;
}



/*********************************************************************
 * Function:        static void HandleTCPSeg(TCP_SOCKET s,
 *                                      NODE_INFO *remote,
 *                                      TCP_HEADER* h,
 *                                      WORD len)
 *
 * PreCondition:    TCPInit() is already called     AND
 *                  TCPProcess() is the caller.
 *
 * Input:           s           - Socket that owns this segment
 *                  remote      - Remote node info
 *                  h           - TCP Header
 *                  len         - Total buffer length.
 *
 * Output:          TCP FSM is executed on given socket with
 *                  given TCP segment.
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
static void HandleTCPSeg(TCP_SOCKET s,
                        NODE_INFO *remote,
                        TCP_HEADER *h,
                        WORD len)
{
    DWORD ack;
    DWORD seq;
    DWORD prevAck, prevSeq;
    SOCKET_INFO *ps;
    BYTE flags;


    flags = 0x00;
    ps = &TCB[s];

 	// When you use TCPConnect() to connect to a remote socket, the 
 	// SND_ACK socket parameter needs to be initialized to the first 
 	// sequence number returned by the remote node.
    if(!ps->Flags.bACKValid)
    {
    	ps->SND_ACK = h->SeqNumber;
    	ps->Flags.bACKValid = TRUE;
    }

    /*
     * Remember current seq and ack for our connection so that if
     * we have to silently discard this packet, we can go back to
     * previous ack and seq numbers.
     */
    prevAck = ps->SND_ACK;
    prevSeq = ps->SND_SEQ;

    ack = h->SeqNumber;
    ack += (DWORD)len;
    seq = ps->SND_SEQ;

    /*
     * Clear retry counts and timeout tick counter.
     */
    ps->RetryCount  = 0;
    ps->startTick   = TickGet();
    ps->TimeOut = TCP_START_TIMEOUT_VAL;

	// Handle listening condition
    if ( ps->smState == TCP_LISTEN )
    {
        MACDiscardRx();

        ps->SND_SEQ     = ++ISS;
        ps->SND_ACK     = ++ack;
        seq             = ps->SND_SEQ;
        ++ps->SND_SEQ;
        if ( h->Flags.bits.flagSYN )
        {
            /*
             * This socket has received connection request.
             * Remember calling node, assign next segment seq. number
             * for this potential connection.
             */
            memcpy((void*)&ps->remote, (const void*)remote, sizeof(*remote));
            ps->remotePort  = h->SourcePort;

            /*
             * Grant connection request.
             */
            flags           = SYN | ACK;
            ps->smState     = TCP_SYN_RCVD;

        }
        else
        {
            /*
             * Anything other than connection request is ignored in
             * LISTEN state.
             */
            flags               = RST;
            seq                 = ack;
            ack                 = h->SeqNumber;
            ps->remote.IPAddr.Val = 0x00;
        }

    }
    // State is something other than TCP_LISTEN, handle it.
    else
    {
        /*
         * Reset FSM, if RST is received.
         */
        if ( h->Flags.bits.flagRST )
        {
            MACDiscardRx();
            CloseSocket(ps);
            return;

        }
			// Check to see if the incomming sequence number is what 
			// we expect (last transmitted ACK value).  Throw this packet 
			// away if it is wrong.
		else if ( h->SeqNumber == prevAck )
        {
	        // After receiving a SYNchronization request, we expect an 
	        // ACK to our transmitted SYN
            if ( ps->smState == TCP_SYN_RCVD )
            {
                if ( h->Flags.bits.flagACK )
                {
	                // ACK received as expected, this connection is 
	                // now established
                    ps->SND_ACK = ack;
                    ps->RetryCount = 0;
                    ps->startTick = TickGet();
                    ps->smState = TCP_EST;

					// Check if this first packet has application data 
					// in it.  Make it available if so.
                    if ( len > 0 )
                    {
                        ps->Flags.bIsGetReady   = TRUE;
                        ps->RxCount             = len;
                        ps->Flags.bFirstRead    = TRUE;
                    }
                    else
                        MACDiscardRx();
                }
                else	// No ACK to our SYN
                {
                    MACDiscardRx();
                }
            }
#ifdef STACK_CLIENT_MODE
            // The TCP_SYN_SENT state occurs when an application 
            // calls TCPConnect().  After an initial SYN is sent,
            // we expect a SYN + ACK before establishing the 
            // connection.
            else if ( ps->smState == TCP_SYN_SENT )
            {
	            // Check if this is a SYN packet
                if ( h->Flags.bits.flagSYN )
                {
                    ps->SND_ACK = ++ack;
                    // Check if this is a ACK packet, and if so,
                    // establish the connection
                    if ( h->Flags.bits.flagACK )
                    {
                        flags = ACK;
                        ps->smState = TCP_EST;
                    }
                    // No ACK received yet, expect it next time.
                    else
                    {
	                    // Send another SYNchronization request
                        flags = SYN | ACK;
                        ps->smState = TCP_SYN_RCVD;
                        ps->SND_SEQ = ++seq;
                    }

					// Check for application data and make it 
					// available, if present
                    if ( len > 0 )
                    {
                        ps->Flags.bIsGetReady   = TRUE;
                        ps->RxCount             = len;
                        ps->Flags.bFirstRead    = TRUE;
                    }
                    else	// No application data in this packet
                        MACDiscardRx();
                }
                // No use for (unexpected) non-SYN packets, so discard
                else
                {
                    MACDiscardRx();
                }
            }
#endif
            // Connection is established, closing, or otherwise
            else
            {

				// Save the seq+len value of the packet for our future 
				// ACK transmission, and so out of sequence packets 
				// can be detected in the future.
                ps->SND_ACK = ack;

				// Handle packets received while connection established.
                if ( ps->smState == TCP_EST )
                {
	                // If this packet has the ACK set, mark all 
	                // previous TX packets as no longer needed for 
	                // possible retransmission.
                    if ( h->Flags.bits.flagACK )
                    {
                        if ( ps->TxBuffer != INVALID_BUFFER )
                        {
                            MACDiscardTx(ps->TxBuffer);
                            ps->TxBuffer            = INVALID_BUFFER;
                            ps->Flags.bIsPutReady   = TRUE;
                        }
                    }

					// Check if the remote node is closing the connection
                    if ( h->Flags.bits.flagFIN )
                    {
                        flags = FIN | ACK;
                        seq = ps->SND_SEQ++;
                        ack = ++ps->SND_ACK;
                        ps->smState = TCP_LAST_ACK;
                    }

					// Check if there is any application data in 
					// this packet.
                    if ( len > 0 )
                    {
	                    // There is data.  Make it available if we 
	                    // don't already have data available.
                        if ( !ps->Flags.bIsGetReady )
                        {
                            ps->Flags.bIsGetReady   = TRUE;
                            ps->RxCount             = len;
                            ps->Flags.bFirstRead    = TRUE;

                             // 4/1/02
                            flags = ACK;
                       }
                       // There is data, but we cannot handle it at this time.
                       else
                       {
                            /*
                             * Since we cannot accept this packet,
                             * restore to previous seq and ack.
                             * and do not send anything back.
                             * Host has to resend this packet when
                             * we are ready.
                             */
                            flags = 0x00;
                            ps->SND_SEQ = prevSeq;
                            ps->SND_ACK = prevAck;

                            MACDiscardRx();
                        }
                    }
                    // There is no data in this packet, and thus it 
                    // can be thrown away.
                    else
                    {
                        MACDiscardRx();
                    }


                }
                // Connection is not established; check if we've sent 
                // a FIN and expect our last ACK
                else if ( ps->smState == TCP_LAST_ACK )
                {
                    MACDiscardRx();

                    if ( h->Flags.bits.flagACK )
                    {
                        CloseSocket(ps);
                    }
                }
                else if ( ps->smState == TCP_FIN_WAIT_1 )
                {
                    MACDiscardRx();

                    if ( h->Flags.bits.flagFIN )
                    {
                        flags = ACK;
                        ack = ++ps->SND_ACK;
                        if ( h->Flags.bits.flagACK )
                        {
                            CloseSocket(ps);
                        }
                        else
                        {
                            ps->smState = TCP_CLOSING;
                        }
                    }
                }
                else if ( ps->smState == TCP_CLOSING )
                {
                    MACDiscardRx();

                    if ( h->Flags.bits.flagACK )
                    {
                        CloseSocket(ps);
                    }
                }
            }
        }
        // This packet's sequence number does not match what we were 
        // expecting (the last value we ACKed).  Throw this packet 
        // away.  This may happen if packets are delivered out of order.
        // Not enough memory is available on our PIC or Ethernet 
        // controller to implement a robust stream reconstruction 
        // buffer.  As a result, the remote node will just have to 
        // retransmit its packets starting with the proper sequence number.
        else
        {
            MACDiscardRx();

			// Send a new ACK out in case if the previous one was lost 
			// (ACKs aren't ACKed).  This is required to prevent an 
			// unlikely but possible situation which would cause the 
			// connection to time out if the ACK was lost and the 
			// remote node keeps sending us older data than we are 
			// expecting.
			flags = ACK;	
			ack = prevAck;
        }
    }

    if ( flags > 0x00 )
    {
        SendTCP(remote,
                h->DestPort,
                h->SourcePort,
                seq,
                ack,
                flags);
    }
}



⌨️ 快捷键说明

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