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

📄 tcp_ip.c

📁 Analog公司的ADSP_BF532上面实现以太网接口的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
            
            // clear all flags, stop timers etc.
            TCP_Flags = 0;
        }
        // clear tx-flag
        TCP_TransmitControl &= ~TCP_SEND_FRAME1;
    }
}


/******************************************************************************
 * TCP_IP_STACK: TCP_ProcessEthBroadcastFrame()
 *
 * Purpose:
 *  handles an incoming broadcast frame to prepare ARP reply
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Proc_EthBroadcast_Frame()
{
    WORD TargetIP[2];
    WORD* data = (WORD*) LAN_rx_packet.data;
    WORD cmp[5];

    //check protocol    if (LAN_hdr.Protocol == FRAME_ARP)
    if (data[6] == FRAME_ARP)
    {
        // store sender's MAC
        memcpy(&TCP_Recd_Frame_MAC, data+(ETH_SA_OFS>>1), 6);

        // offset pointer by 6 for ARP
        data += (ETH_TYPE_OFS >> 1);

        // parse for proper ARP by completing compare string
        cmp[0] = FRAME_ARP;
        cmp[1] = HARDW_ETH10;
        cmp[2] = FRAME_IP;
        cmp[3] = IP_HLEN_PLEN;
        cmp[4] = OP_ARP_REQUEST;

        if (!memcmp(data, cmp, 10))
        {
            // skip five flag words and sender's MAC addr
            data += 8;
            TCP_Recd_Frame_IP[0] = *data++;
            TCP_Recd_Frame_IP[1] = *data++;
            
            // skip Dst MAC addr
            data += 3;
            
            // read target IP
            TargetIP[0] = *data++;
            TargetIP[1] = *data;
            
            // is it for us?
            if (!memcmp(&TCP_Local_IP, &TargetIP, 4))
            
            // yes->create ARP_ANSWER frame
            TCP_Prep_ARP_ANSWER();
        }
    }
    // free LAN packet as we've processed or discarded it
    LAN_rx_packet.busy = 0;
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Proc_EthIA_Frame()
 *
 * Purpose:
 *  handles an incoming frame that passed IA address filter
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Proc_EthIA_Frame()
{
    WORD TargetIP[2];
    WORD ProtocolType;
    WORD* data = (WORD*) LAN_rx_packet.data;

    // store sender's MAC
    memcpy(&TCP_Recd_Frame_MAC, data+(ETH_SA_OFS>>1), 6);

    // ignore dst_addr, src_addr
    data += 6;

    // get frame type and switch upon
    switch (*data++)
    {
        // check for ARP
        case FRAME_ARP :
        {
          if ((TCP_Flags & (TCP_ACTIVE_OPEN | TCP_IP_ADDR_RESOLVED)) == TCP_ACTIVE_OPEN)
          
            // check for the right prot. etc.
            if (*data++ == HARDW_ETH10)
            
              // check protocol
              if (*data++ == FRAME_IP)
              
                // check HLEN, PLEN
                if (*data++ == IP_HLEN_PLEN)
                
                  // check for ARP request
                  if (*data++ == OP_ARP_ANSWER)
                  {
                    // OK, now we've the MAC we wanted ;-)
                    TCP_StopTimer();
                    
                    // extract remote station's MAC
                    TCP_RemoteMAC[0] = *data++;
                    TCP_RemoteMAC[1] = *data++;
                    TCP_RemoteMAC[2] = *data++;
                    
                    // Update flags
                    TCP_Flags |= TCP_IP_ADDR_RESOLVED;
                  }
          break;    // FRAME_ARP
        }

        // check for IP-type
        case FRAME_IP :
        {
            // check for IPv4, IHL=5 (20 Bytes Header)
            // ignore Type Of Service
            if ((*data++ & 0xFF ) == swap_bytes(IP_VER_IHL))
            {
                // get IP frame's length
                TCP_Recd_IP_Frame_Length = swap_bytes(*data++);

                // ignore identification
                data++;

                // only unfragm. frames
                if (! (swap_bytes(*data++)&(IP_FLAG_MOREFRAG|IP_FRAGOFS_MASK)))
                {
                    // get protocol, ignore TTL
                    ProtocolType = (*data++ >> 8) & 0xff;

                    // ignore checksum
                    *data++;

                    // get source IP
                    TCP_Recd_Frame_IP[0] = *data++;
                    TCP_Recd_Frame_IP[1] = *data++;

                    // get destination IP
                    TargetIP[0] = *data++;
                    TargetIP[1] = *data++;

                    // is it for us?
                    if (!memcmp(&TCP_Local_IP, &TargetIP, 4))

                    switch (ProtocolType)
                    {
                        case PROT_ICMP : 
                        { 
                            TCP_Proc_ICMP_Frame(); 
                            break; 
                        }
                        case PROT_TCP  : 
                        { 
                            TCP_Proc_TCP_Frame(); 
                            break; 
                        }
                        case PROT_UDP  : 
                            // not implemented yet
                            break; 
                    }
                }
            }
            break;  // FRAME_IP
        }
    }
    // free packet as we've processed or discarded it
    LAN_rx_packet.busy = 0;
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Proc_ICMP_Frame()
 *
 * Purpose:
 *  ICMP-frame (Internet Control Message Protocol) handling
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Proc_ICMP_Frame()
{
    WORD ICMPTypeAndCode;
    WORD* data = (WORD*) LAN_rx_packet.data;

    // get Message Type and Code
    data += (ICMP_TYPE_CODE_OFS>>1);

    ICMPTypeAndCode = *data;

    // ignore ICMP checksum
    data++;

    // check ICMP type
    switch (ICMPTypeAndCode)
    {
        // is echo request - ping request
        case ICMP_ECHO :
        {
            // echo as much as we can...
            TCP_Prep_ICMP_ECHO_REPLY();
            break;
        }
    }
}


/******************************************************************************
 * TCP_IP_STACK: TCP_Proc_TCP_Frame()
 *
 * Purpose:
 *  TCP-frame (Transmission Control Protocol) handling
 *
 * Actions:
 *
 *****************************************************************************/
MC void TCP_Proc_TCP_Frame()
{
    WORD  TCPSegSourcePort;       // segment's source port
    WORD  TCPSegDestPort;         // segment's destination port
    DWORD TCPSegSeq;              // segment's sequence number
    DWORD TCPSegAck;              // segment's acknowledge number
    WORD  TCPCode;                // TCP code and header length
    BYTE  TCPHeaderSize;          // real TCP header length
    WORD  NrOfDataBytes;          // real number of data

    WORD* data = (WORD*) LAN_rx_packet.data;

    // get offset of TCP/IP ports
    data += (TCP_SRCPORT_OFS>>1);

    TCPSegSourcePort = swap_bytes(*data++);
    TCPSegDestPort = swap_bytes(*data++);

    // drop segment if port doesn't match
    if (TCPSegDestPort != TCP_LocalPort) return;

    // get segment sequence nr.
    TCPSegSeq = (swap_bytes(*data++) << 16) | swap_bytes(*data++);
    
    // get segment acknowledge nr.
    TCPSegAck = (swap_bytes(*data++) << 16) | swap_bytes(*data++);

    // get control bits, header length...
//    TCPCode = swap_bytes(*data);
    TCPCode = swap_bytes(*data++);

    // header length in bytes
    TCPHeaderSize = (TCPCode & DATA_OFS_MASK) >> 10;

    // seg. text length
    NrOfDataBytes = TCP_Recd_IP_Frame_Length - IP_HEADER_SIZE - TCPHeaderSize;

    // packet too large for us
    if (NrOfDataBytes > MAX_TCP_RX_SIZE) return;

    // ignore options if any
    if (TCPHeaderSize > TCP_HEADER_SIZE)
//        data += (TCPHeaderSize - TCP_HEADER_SIZE);
        data += (TCPHeaderSize - TCP_HEADER_SIZE)>>1;

    // implement the TCP state machine
    switch (TCP_StateMachine)
    {
        case CLOSED :
        {
            if (!(TCPCode & TCP_CODE_RST))
            {
                TCP_RemotePort = TCPSegSourcePort;
                
                // save partner's MAC and IP for later use
                memcpy(&TCP_RemoteMAC, &TCP_Recd_Frame_MAC, 6);
                memcpy(&TCP_RemoteIP, &TCP_Recd_Frame_IP, 4);

                // make the reset sequence
                if (TCPCode & TCP_CODE_ACK)
                {
                    // acceptable to the other TCP
                    TCP_Seq_Nr = TCPSegAck;
                    TCP_Prep_TCP_FRAME(TCP_CODE_RST);
                }
                else
                {
                    TCP_Seq_Nr = 0;
                    TCP_Ack_Nr = TCPSegSeq + NrOfDataBytes;
                    if (TCPCode & (TCP_CODE_SYN | TCP_CODE_FIN))
                        TCP_Ack_Nr++;
                        
                    TCP_Prep_TCP_FRAME(TCP_CODE_RST | TCP_CODE_ACK);
                }
            }
            break;
        }

        case LISTENING :
        {
            // ignore segment containing RST
            if (!(TCPCode & TCP_CODE_RST))
            {
                TCP_RemotePort = TCPSegSourcePort;

                // save partner's MAC and IP for later use
                memcpy(&TCP_RemoteMAC, &TCP_Recd_Frame_MAC, 6);
                memcpy(&TCP_RemoteIP, &TCP_Recd_Frame_IP, 4);

                // reset a bad acknowledgement
                if (TCPCode & TCP_CODE_ACK)
                {
                    TCP_Seq_Nr = TCPSegAck;
                    TCP_Prep_TCP_FRAME(TCP_CODE_RST);
                }
                else if (TCPCode & TCP_CODE_SYN)
                {
                    // get remote ISN, next byte we expect
                    TCP_Ack_Nr = TCPSegSeq + 1;

                    // set local ISN
                    TCP_Seq_Nr = ((TCP_ISN_Gen_High << 16) | get_cycles());

                    // one byte out -> increase by one
                    TCP_UNA_Seq_Nr = TCP_Seq_Nr + 1;
                    TCP_Prep_TCP_FRAME(TCP_CODE_SYN | TCP_CODE_ACK);
                    TCP_LastFrameSent = TCP_SYN_ACK_FRAME;
                    TCP_StartRetryTimer();
                    TCP_StateMachine = SYN_RECD;
                }
            }
            break;
        }

        case SYN_SENT :
        {
            // drop segment if its 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;

            // ACK field significant?
            if (TCPCode & TCP_CODE_ACK)

                // is our ISN ACKed?
                if (TCPSegAck != TCP_UNA_Seq_Nr)
                {
                    if (!(TCPCode & TCP_CODE_RST))
                    {
                        TCP_Seq_Nr = TCPSegAck;
                        TCP_Prep_TCP_FRAME(TCP_CODE_RST);
                    }
                    // drop segment
                    break;
                }

            // RST??
            if (TCPCode & TCP_CODE_RST)
            {
                // if ACK was acceptable, reset connection
                if (TCPCode & TCP_CODE_ACK)
                {
                    // reset all flags, stop retransmission...

⌨️ 快捷键说明

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