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

📄 tcp_ip.c

📁 Analog公司的ADSP_BF532上面实现以太网接口的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
                    TCP_StateMachine = CLOSED;
                    TCP_Flags = 0;
                    TCP_SocketStatus = TCP_SOCK_ERR_CONN_RESET;
                }
                // drop segment
                break;
            }

            // SYN??
            if (TCPCode & TCP_CODE_SYN)
            {
                // get remote's ISN
                TCP_Ack_Nr = TCPSegSeq;

                // and increment by one...
                TCP_Ack_Nr++;

                if (TCPCode & TCP_CODE_ACK)
                {
                    // stop retransmission, other TCP got our SYN
                    TCP_StopTimer();

                    // advance our sequence number
                    TCP_Seq_Nr = TCP_UNA_Seq_Nr;

                    // ACK this ISN
                    TCP_Prep_TCP_FRAME(TCP_CODE_ACK);

                    // user may send data now :-)
                    TCP_StateMachine = ESTABLISHED;
                    TCP_SocketStatus |= TCP_SOCK_CONNECTED;
                    TCP_SocketStatus |= TCP_SOCK_TX_BUF_RELEASED;
                }
                else
                {
                    // our SYN isn't ACKed yet, now continue with sending
                    // SYN_ACK frames
                    TCP_StopTimer();
                    TCP_Prep_TCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
                    TCP_LastFrameSent = TCP_SYN_ACK_FRAME;
                    TCP_StartRetryTimer();
                    TCP_StateMachine = SYN_RECD;
                }
            }
            break;
        }

        default :
        {
            // drop segment if IP doesn't belong to current session
            if (memcmp(&TCP_RemoteIP, &TCP_Recd_Frame_IP, 4)) break;

            // drop segment if port doesn't match
            if (TCPSegSourcePort != TCP_RemotePort) break;

            // drop if it's not the segment we expect
            if (TCPSegSeq != TCP_Ack_Nr) break;

            // RST??
            if (TCPCode & TCP_CODE_RST)
            {
                // close the state machine
                // reset all flags, stop retransmission
                // indicate an error to user
                TCP_StateMachine = CLOSED;
                TCP_Flags = 0;
                TCP_SocketStatus = TCP_SOCK_ERR_CONN_RESET;
                break;
            }

            // SYN??
            if (TCPCode & TCP_CODE_SYN)
            {
                // is NOT allowed here! send a reset,
                TCP_Prep_TCP_FRAME(TCP_CODE_RST);

                // close connection...
                // reset all flags, stop retransmission...
                // fatal error!
                // ...and drop the frame
                TCP_StateMachine = CLOSED;
                TCP_Flags = 0;
                TCP_SocketStatus = TCP_SOCK_ERR_REMOTE;
                break;
            }

            // drop segment if the ACK bit is off
            if (!(TCPCode & TCP_CODE_ACK)) break;

            // is our last data sent ACKed?
            if (TCPSegAck == TCP_UNA_Seq_Nr)
            {
                // stop retransmission
                TCP_StopTimer();

                // advance our sequence number
                TCP_Seq_Nr = TCP_UNA_Seq_Nr;

                // change state if necessary
                switch (TCP_StateMachine)
                {
                    // ACK of our SYN?
                    case SYN_RECD :
                    {
                        // user may send data now
                        TCP_StateMachine = ESTABLISHED;
                        TCP_SocketStatus |= TCP_SOCK_CONNECTED;
                        break;
                    }

                    // ACK of our FIN?
                    case FIN_WAIT_1 :
                    {
                        TCP_StateMachine = FIN_WAIT_2;
                        break;
                    }

                    // ACK of our FIN?
                    case CLOSING :
                    {
                        TCP_StateMachine = TIME_WAIT;
                        break;
                    }

                    // ACK of our FIN?
                    case LAST_ACK :
                    {
                        // reset all flags, stop retransmission...
                        // clear all flags but data available
                        TCP_StateMachine = CLOSED;
                        TCP_Flags = 0;
                        TCP_SocketStatus &= TCP_SOCK_DATA_AVAILABLE;
                        break;
                    }

                    case TIME_WAIT :
                    {
                        // ACK a retransmission of remote FIN
                        // restart TIME_WAIT timeout
                        TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
                        TCP_RestartTimer();
                        break;
                    }
                }

                // if true, give the frame buffer back to user
                if (TCP_StateMachine == ESTABLISHED)
                    TCP_SocketStatus |= TCP_SOCK_TX_BUF_RELEASED;
            }

            if ((TCP_StateMachine == ESTABLISHED) || (TCP_StateMachine == FIN_WAIT_1) || (TCP_StateMachine == FIN_WAIT_2))
                // data available?
                if (NrOfDataBytes)
                    // rx data-buffer empty?
                    if (!(TCP_SocketStatus & TCP_SOCK_DATA_AVAILABLE))
                    {
                        // ignore window, checksum, urgent pointer
                        data +=3;
                        // fetch data and tell the user
                        // indicate the new data to user
                        memcpy(&TCP_RxTCPBuffer, data, NrOfDataBytes);
                        TCP_Rx_Data_Count = NrOfDataBytes;

                        TCP_SocketStatus |= TCP_SOCK_DATA_AVAILABLE;
                        TCP_Ack_Nr += NrOfDataBytes;

                        // ACK rec'd data
                        TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
                    }

            // FIN??
            if (TCPCode & TCP_CODE_FIN)
            {
                switch (TCP_StateMachine)
                {
                    case SYN_RECD :
                    case ESTABLISHED :
                    {
                        TCP_StateMachine = CLOSE_WAIT;
                        break;
                    }

                    // if our FIN was ACKed, we automatically
                    // enter FIN_WAIT_2 (look above) and therefore
                    // TIME_WAIT
                    case FIN_WAIT_1 :
                    {
                        TCP_StateMachine = CLOSING;
                        TCP_SocketStatus &= ~TCP_SOCK_CONNECTED;
                        break;
                    }

                    case FIN_WAIT_2 :
                    {
                        TCP_StartTimeWaitTimer();
                        TCP_StateMachine = TIME_WAIT;
                        TCP_SocketStatus &= ~TCP_SOCK_CONNECTED;
                        break;
                    }

                    case TIME_WAIT :
                    {
                        TCP_RestartTimer();
                        break;
                    }
                }
                // ACK remote's FIN flag
                TCP_Ack_Nr++;
                TCP_Prep_TCP_FRAME(TCP_CODE_ACK);
            }
        }
    }
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Prep_ARP_REQUEST()
 *
 * Purpose:
 *  prepares the TxFrame2-buffer to send an ARP-request
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Prep_ARP_REQUEST(void)
{
    // Ethernet
    // we don't know opposites MAC!
    memset(&TCP_TxFrame2[ETH_DA_OFS], 0xFF, 6);
    memcpy(&TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
    *(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_ARP;

    // ARP
    *(WORD *)&TCP_TxFrame2[ARP_HARDW_OFS] = HARDW_ETH10;
    *(WORD *)&TCP_TxFrame2[ARP_PROT_OFS] = FRAME_IP;
    *(WORD *)&TCP_TxFrame2[ARP_HLEN_PLEN_OFS] = IP_HLEN_PLEN;
    *(WORD *)&TCP_TxFrame2[ARP_OPCODE_OFS] = OP_ARP_REQUEST;
    memcpy( &TCP_TxFrame2[ARP_SENDER_HA_OFS], &TCP_MyMAC, 6);
    memcpy( &TCP_TxFrame2[ARP_SENDER_IP_OFS], &TCP_Local_IP, 4);

    // we don't know remote's MAC!
    memset( &TCP_TxFrame2[ARP_TARGET_HA_OFS], 0x00, 6);

    if (((TCP_RemoteIP[0] ^ TCP_Local_IP[0]) & TCP_SubnetMask[0]) || ((TCP_RemoteIP[1] ^ TCP_Local_IP[1]) & TCP_SubnetMask[1]))
        // IP not in subnet, use gateway
        memcpy(&TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_GatewayIP, 4);
    else
        // other IP is next to us...
        memcpy(&TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_RemoteIP, 4);

    TCP_TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
    TCP_TransmitControl |= TCP_SEND_FRAME2;
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Prep_ARP_ANSWER()
 *
 * Purpose:
 *  prepares the TxFrame2-buffer to send an ARP-answer (reply)
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Prep_ARP_ANSWER(void)
{
    // Ethernet
    memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_Recd_Frame_MAC, 6);
    memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
    *(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_ARP;

    // ARP
    *(WORD*)&TCP_TxFrame2[ARP_HARDW_OFS] = HARDW_ETH10;
    *(WORD*)&TCP_TxFrame2[ARP_PROT_OFS] = FRAME_IP;
    *(WORD*)&TCP_TxFrame2[ARP_HLEN_PLEN_OFS] = IP_HLEN_PLEN;
    *(WORD*)&TCP_TxFrame2[ARP_OPCODE_OFS] = OP_ARP_ANSWER;
    memcpy( &TCP_TxFrame2[ARP_SENDER_HA_OFS], &TCP_MyMAC, 6);
    memcpy( &TCP_TxFrame2[ARP_SENDER_IP_OFS], &TCP_Local_IP, 4);
    memcpy( &TCP_TxFrame2[ARP_TARGET_HA_OFS], &TCP_Recd_Frame_MAC, 6);
    memcpy( &TCP_TxFrame2[ARP_TARGET_IP_OFS], &TCP_Recd_Frame_IP, 4);

    TCP_TxFrame2Size = ETH_HEADER_SIZE + ARP_FRAME_SIZE;
    TCP_TransmitControl |= TCP_SEND_FRAME2;
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Prep_ICMP_ECHO_REPLY()
 *
 * Purpose:
 *  prepares the TxFrame2-buffer to send an ICMP-echo-reply
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Prep_ICMP_ECHO_REPLY(void)
{
    WORD ICMPDataCount;
    BYTE *bicmp = (BYTE*) LAN_rx_packet.data;
    bicmp += ICMP_DATA_OFS;


    // don't overload TX-buffer
    if (TCP_Recd_IP_Frame_Length > MAX_ETH_TX_SIZE)
        ICMPDataCount = MAX_ETH_TX_SIZE - IP_HEADER_SIZE - ICMP_HEADER_SIZE;
    else
        ICMPDataCount = TCP_Recd_IP_Frame_Length - IP_HEADER_SIZE - ICMP_HEADER_SIZE;

    // Ethernet
    memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_Recd_Frame_MAC, 6);
    memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
    *(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_IP;

    // IP
    *(WORD*)&TCP_TxFrame2[IP_VER_IHL_TOS_OFS] = swap_bytes(IP_VER_IHL);
    *(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount);

    *(WORD*)&TCP_TxFrame2[IP_IDENT_OFS] = 0;
    *(WORD*)&TCP_TxFrame2[IP_FLAGS_FRAG_OFS] = 0;
    *(WORD*)&TCP_TxFrame2[IP_TTL_PROT_OFS] = swap_bytes((DEFAULT_TTL << 8) | PROT_ICMP);
    *(WORD*)&TCP_TxFrame2[IP_HEAD_CHKSUM_OFS] = 0;
    memcpy( &TCP_TxFrame2[IP_SOURCE_OFS], &TCP_Local_IP, 4);
    memcpy( &TCP_TxFrame2[IP_DESTINATION_OFS], &TCP_Recd_Frame_IP, 4);
    *(WORD*)&TCP_TxFrame2[IP_HEAD_CHKSUM_OFS] = TCP_CalcChecksum(&TCP_TxFrame2[IP_VER_IHL_TOS_OFS], IP_HEADER_SIZE, 0);

    // ICMP
    *(WORD*)&TCP_TxFrame2[ICMP_TYPE_CODE_OFS] = swap_bytes(ICMP_ECHO_REPLY << 8);

    // initialize checksum field
    *(WORD*)&TCP_TxFrame2[ICMP_CHKSUM_OFS] = 0;

    // get data to echo...
    memcpy( &TCP_TxFrame2[ICMP_DATA_OFS], bicmp, ICMPDataCount);

    // compute checksum
    *(WORD*)&TCP_TxFrame2[ICMP_CHKSUM_OFS] = TCP_CalcChecksum(&TCP_TxFrame2[IP_DATA_OFS], ICMPDataCount + ICMP_HEADER_SIZE, 0);

    TCP_TxFrame2Size = ETH_HEADER_SIZE + IP_HEADER_SIZE + ICMP_HEADER_SIZE + ICMPDataCount;
    TCP_TransmitControl |= TCP_SEND_FRAME2;

}


/******************************************************************************
 * TCP_IP_STACK: TCP_Prep_TCP_FRAME()
 *
 * Purpose:
 *  prepares the TxFrame2-buffer to send a general TCP frame
 *  the TCPCode-field is passed as an argument
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Prep_TCP_FRAME(WORD TCPCode)
{
    // Ethernet
    memcpy( &TCP_TxFrame2[ETH_DA_OFS], &TCP_RemoteMAC, 6);
    memcpy( &TCP_TxFrame2[ETH_SA_OFS], &TCP_MyMAC, 6);
    *(WORD*)&TCP_TxFrame2[ETH_TYPE_OFS] = FRAME_IP;

    // IP
    *(WORD*)&TCP_TxFrame2[IP_VER_IHL_TOS_OFS] = swap_bytes(IP_VER_IHL | IP_TOS_D);

    // if SYN, we want to use the MSS option
    if (TCPCode & TCP_CODE_SYN)
        *(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + TCP_HEADER_SIZE + TCP_OPT_MSS_SIZE);
    else
        *(WORD*)&TCP_TxFrame2[IP_TOTAL_LENGTH_OFS] = swap_bytes(IP_HEADER_SIZE + TCP_HEADER_SIZE);

    *(WORD*)&TCP_TxFrame2[IP_IDENT_OFS] = 0;

⌨️ 快捷键说明

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