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

📄 tcp.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
          UTL_Checksum (buf_ptr, LONGSWAP(tcp_chk->dest), 
                        LONGSWAP(tcp_chk->source), IP_TCP_PROT) );

    /* Send this packet. */
    /* Note that the IP source addresses and IP destination addresses are
       swapped.*/
    stat = IP_Send(buf_ptr, NU_NULL, LONGSWAP(tcp_chk->source), 
                   LONGSWAP(tcp_chk->dest), 0, IP_TIME_TO_LIVE, IP_TCP_PROT, 
                   IP_TYPE_OF_SERVICE, NU_NULL);

    if (stat == NU_SUCCESS)
    {
        /* Increment the number of TCP segments transmitted. */
        SNMP_tcpOutSegs_Inc;

        /* Increment the number of TCP resets sent. */
        SNMP_tcpOutRsts_Inc;
    }
    else
    {
        /* The packet was not sent.  Dealocate the buffer.  If the packet was
           transmitted it will be deallocated later by TCP. */
        MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
    }

    return (0);

}   /* end TCP_Reset_FIN() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCP_Update_Headers                                               
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Update the fields in the IP  and TCP headers that change from    
*       packet to packet.  Depending on the type parameter, call         
*       either tcpsend or tcp_sendack.                                   
*                                                                       
*   INPUTS                                                                
*                                                                       
*       pport                                                            
*       buf_ptr                                                          
*       tcp_hlen                                                         
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       INT16                   -1                                       
*                               NU_SUCCESS                               
*                                                                       
*************************************************************************/
INT16 TCP_Update_Headers (TCP_PORT *pport, NET_BUFFER *buf_ptr, UINT16 tcp_hlen)
{
    TCP_PORT            *prt;
    TCPLAYER            *tcp_ptr;

    prt = pport;
    
    /* Overlay the TCP header. */
    tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;

    if (prt == NU_NULL)
    {
        NERRS_Log_Error (NERR_RECOVERABLE, __FILE__, __LINE__);
        return (-1);
    } /* end if */

    /* Set the SEQ and ACK numbers. */
    PUT32(tcp_ptr, TCP_SEQ_OFFSET, pport->out.nxt);
    PUT32(tcp_ptr, TCP_ACK_OFFSET, pport->in.nxt);
    
    /* Save off the last ACK value that was sent. This will be used to 
       determine when the next one should be sent in the case of a delayed ACK. 
    */
    pport->in.ack = pport->in.nxt;

    /* Setup the source and destination port numbers. */
    PUT16(tcp_ptr, TCP_DEST_OFFSET, prt->out.port);
    PUT16(tcp_ptr, TCP_SRC_OFFSET, prt->in.port);

    /* Set the tcp header len */
    PUT8(tcp_ptr, TCP_HLEN_OFFSET, (UINT8)(tcp_hlen << 4) );


   /*
    *  if the port has some credit limit, use it instead of large
    *  window buffer.  Generally demanded by hardware limitations.
    */
    if ((INT32)(prt->credit) < (prt->in.size))
    {
        PUT16(tcp_ptr, TCP_WINDOW_OFFSET, prt->credit);
    }
    else
    {
        PUT16(tcp_ptr, TCP_WINDOW_OFFSET, (UINT16)prt->in.size);
    }

    /* Set the urgent pointer. */
    PUT16(tcp_ptr, TCP_URGENT_OFFSET, 0);

    /* Set the flags field. */
    PUT8(tcp_ptr, TCP_FLAGS_OFFSET, prt->out.tcp_flags);
    
    /* Clear the checksum filed to 0. It will be computed later. */
    PUT16(tcp_ptr, TCP_CHECK_OFFSET, 0);

    return NU_SUCCESS;

} /* end TCP_Update_Headers().  */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCP_Send_ACK                                                     
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Transmit an ack packet or a packet that contains options.        
*       Acks work this way so that we don't have to allocate a buffer    
*       for a packet that will contain no data.                          
*                                                                       
*   INPUTS                                                                
*                                                                       
*       pport                                                            
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       INT16   NU_NULL                                                  
*               NU_SUCCESS                                               
*                                                                       
*************************************************************************/
INT16 TCP_Send_ACK(TCP_PORT *pport)
{
    TCPLAYER    *tcp_ptr;
    NET_BUFFER  *buf_ptr;
    STATUS      stat;

    /*  Clear the PUSH flag if no data to be sent. */
    if (!pport->out.contain)
        pport->out.tcp_flags &= ~TPUSH;

    /* Allocate a buffer to place the ack packet in. */
    buf_ptr = MEM_Buffer_Dequeue(&MEM_Buffer_Freelist);

    if(buf_ptr == NU_NULL)
    {
        return (NU_NULL);
    }

    /* Initialize each field in the allocated buffer, adding on the TCP layer. */
    buf_ptr->mem_total_data_len = sizeof (TCPLAYER);
    buf_ptr->data_len           = sizeof (TCPLAYER);
    buf_ptr->next               = NU_NULL;
    buf_ptr->next_buffer        = NU_NULL;
    buf_ptr->mem_seqnum         = 0;
    buf_ptr->mem_dlist          = &MEM_Buffer_Freelist;

    /* Point to the location within the packet where the TCP header begins. */
    buf_ptr->data_ptr = (buf_ptr->mem_parent_packet + 
        (NET_MAX_TCP_HEADER_SIZE - sizeof (TCPLAYER)));

    /* Update the IP and TCP headers with the latest info.  The TCP header is
       always 5 words in size for an ACK packet. */
    TCP_Update_Headers(pport, buf_ptr, 5);

    /* Point at the TCP header. */
    tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;

    /* Compute and fill in the checksum. */
    PUT16(tcp_ptr, TCP_CHECK_OFFSET, 
        UTL_Checksum(buf_ptr, pport->tcp_laddr, pport->tcp_faddr, IP_TCP_PROT) );

    /* Send this packet. */
    stat = IP_Send((NET_BUFFER *)buf_ptr, &pport->tp_route, pport->tcp_faddr,
                   pport->tcp_laddr, 0, IP_TIME_TO_LIVE, 
                   IP_TCP_PROT, IP_TYPE_OF_SERVICE, NU_NULL);

    if (stat == NU_SUCCESS)
    {
        /* Increment the number of TCP segments transmitted. */
        SNMP_tcpOutSegs_Inc;
    }
    else
    {
        /* The packet was not sent.  Dealocate the buffer.  If the packet was
           transmitted it will be deallocated when transmission is complete. */
        MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
    }

    return(NU_SUCCESS);
}   /* end TCP_Send_ACK() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCP_Send                                                         
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Send a tcp packet.                                               
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *pport                                                            
*       *buf_ptr                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       The number of bytes sent.                                        
*       NU_HOST_UNREACHABLE                                              
*       NU_ACCESS                                                        
*       NU_MSGSIZE                                                       
*       NU_SUCCESS                                                       
*                                                                       
*************************************************************************/
STATUS TCP_Send(TCP_PORT *pport, NET_BUFFER *buf_ptr)
{
    TCPLAYER        *tcp_ptr;
    STATUS          stat;
    INT             tcp_hlen;

    /* Check to see if there is an ACK timer event set.  If so clear  it out
       because the data packet that is about to be sent will include the ack. */
    if(pport->portFlags & ACK_TIMER_SET)
    {
        /*  Delete the ACK timeout timer.  */
        UTL_Timerunset(TCPACK, (UNSIGNED)pport->pindex, (INT32)1 );

        /* Clear the ACK timer flag in the port. */
        pport->portFlags &= (~ACK_TIMER_SET);
    }

    /* Now add the TCP header and options to the size and update the data
       pointer to point to the header. */
    buf_ptr->data_ptr           -= (sizeof (TCPLAYER) + buf_ptr->mem_option_len);
    buf_ptr->data_len           += (sizeof (TCPLAYER) + buf_ptr->mem_option_len);
    buf_ptr->mem_total_data_len += (sizeof (TCPLAYER) + buf_ptr->mem_option_len);

    /* Compute the TCP header size in words. */
    tcp_hlen = ((sizeof(TCPLAYER) + buf_ptr->mem_option_len - 1) / 4) + 1;

    /* Update the header information. */
    TCP_Update_Headers(pport, buf_ptr, (UINT16)tcp_hlen);

    /* Calculate the next sequence number to be sent. */
    pport->out.nxt += buf_ptr->mem_tcp_data_len;

    /* Point to the beginning of the TCP header. */
    tcp_ptr = (TCPLAYER *)buf_ptr->data_ptr;

    /* Compute and fill in the checksum. */
    PUT16(tcp_ptr, TCP_CHECK_OFFSET, 
        UTL_Checksum(buf_ptr, pport->tcp_laddr, pport->tcp_faddr, IP_TCP_PROT) );

    /* Initialize the number of times this packet has been retransmitted. */
    buf_ptr->mem_retransmits = 0;

    /* If there is no timing being performed then time this transmission. */
    if (pport->p_rtt == 0)
    {
        pport->p_rtt = NU_Retrieve_Clock();
        pport->p_rtseq = buf_ptr->mem_seqnum;
    }

    /* Send this packet. */
    stat = IP_Send((NET_BUFFER *)buf_ptr, &pport->tp_route, pport->tcp_faddr,
                    pport->tcp_laddr, 0, IP_TIME_TO_LIVE, 
                    IP_TCP_PROT, IP_TYPE_OF_SERVICE, NU_NULL);

    if (stat == NU_SUCCESS)
    {
        /* Set a retransmit event for this packet. */
        UTL_Timerset (TCPRETRANS, (UNSIGNED)pport->pindex, 
                        (UNSIGNED)pport->p_rto, (INT32)pport->out.nxt);

        /* Increment the number of TCP segments transmitted. */
        SNMP_tcpOutSegs_Inc;
    }
    else
    {
        /* The packet was not sent.  Dealocate the buffer.  If the packet was
           transmitted it will be deallocated later by TCP. */
        MEM_One_Buffer_Chain_Free (buf_ptr, &MEM_Buffer_Freelist);
    }

    return(stat);

}   /* end TCP_Send() */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TCP_ACK_Check                                                    
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       Take an incoming packet and see if there is an ACK for the 
*       outgoing side.  Use that ACK to dequeue outgoing data.            
*                                                                       
*   INPUTS                                                                
*                                                                       
*       prt                                                              
*       tcp_pkt                                                          
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       INT16   1                                                        
*               TCP_NO_ACK                                               
*               TCP_INVALID_ACK                                          
*               NU_SUCCESS                                               
*                                                                       
*************************************************************************/
static INT16 TCP_ACK_Check(TCP_PORT *prt, TCPLAYER *tcp_pkt)
{
    INT32     ak;

#if (INCLUDE_SNMP == NU_TRUE)
    UINT8     tcp_laddr[4];
    UINT8     tcp_faddr[4];
#endif

    /*  We received a reset and the sequence number is within the current window
        then close the connection.  */
    if((GET8(tcp_pkt, TCP_FLAGS_OFFSET) & TRESET) &&
        (INT32_CMP(G

⌨️ 快捷键说明

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