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

📄 tftpc.c

📁 基于东南大学开发的SEP3203的ARM7中的所有驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
*                                                                       
*       This function is responsible for receiving data from a TFTP      
*       server.  NU_Select is used to timeout.                           
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *tftp_con       The pointer to TFTP Control Block                
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       The number of bytes received when successful.                    
*       NU_NO_DATA  when NU_Select fails to find a data ready socket.    
*                                                                       
*************************************************************************/
INT32 TFTPC_Recv(TFTP_CB *tftp_con)
{
    FD_SET      readfs, writefs, exceptfs;
    INT32       bytes_received;
    INT16       status, clilen;
    
    /* Do a select on this socket.  In the case that the foreign port 
     * fails to respond we don't want to suspend on receive forever. 
     */
    NU_FD_Init(&readfs);
    NU_FD_Set(tftp_con->socket_number, &readfs);
    
    if((status = (INT16)(NU_Select(NSOCKETS, &readfs, &writefs, &exceptfs, 
        (tftp_con->options.timeout * SCK_Ticks_Per_Second)))) != NU_SUCCESS)
    {
        return(status);
    }
    
    /*  We must have received something.  Go get the server's response. */
    bytes_received = (INT32)(NU_Recv_From(tftp_con->socket_number,
        tftp_con->trans_buf,
        (UINT16)(tftp_con->options.blksize + TFTP_HEADER_SIZE), 
        0, &tftp_con->server_addr, &clilen));

    return(bytes_received);
} /* end TFTPC_Recv */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TFTPC_Process_Data                                               
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This function is responsible for processing a data packet        
*       whenever a read request is in progress.                          
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *tftp_con           The pointer to TFTP Control Block.
*       *bytes_received     Number of bytes in the packet.
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS whenever the expected data was received, -1 otherwise.
*                                                                       
*************************************************************************/
STATUS TFTPC_Process_Data(TFTP_CB *tftp_con, INT32 bytes_received)
{
    UINT16  data_size;
    INT32   bytes = 0;
    
    /* What kind of packet is this. */
    switch(GET16(tftp_con->trans_buf, 0))
    {
    case TFTP_OACK_OPCODE:
        
        /* Check that the returned options are valid */
        TFTPC_Check_Options(tftp_con, bytes_received);
        
        /* Acknowledge that we received the OACK */
        TFTPC_Ack(tftp_con);    
        
        /* Increment the block number */
        tftp_con->block_number++;
        
        break;
        
    case TFTP_DATA_OPCODE:
        
        /* Received a DATA packet that has already be acknowledged,
         * because our current block number is greater than the block
         * number of the packet - we do not want to exit, error, or
         * confirm this packet (because it has already been confirmed),
         * but go get the next packet 
         */
        if((tftp_con->block_number > GET16(tftp_con->trans_buf, 2))
            && (tftp_con->tid == tftp_con->server_addr.port))
            break;
        
        /* If data was received make sure block number and TID are
         * correct. 
         */
        else if((tftp_con->block_number == GET16(tftp_con->trans_buf, 2))             
            && (tftp_con->tid == tftp_con->server_addr.port))
        {
            /* Calculate the amount of data in this packet. */
            data_size = (UINT16)(bytes_received - TFTP_HEADER_SIZE);
            
            if (data_size > 0)
            {
                /* Write the data to the file */
                if ((bytes = (INT32)FAL_Fwrite(&(tftp_con->trans_buf[4]), data_size, 
                    tftp_con->file_desc)) <=0 )
                    return (FAL_Get_Last_Error());
            }
            
            /* If blksize bytes of data were copied, send an ACK.  We know
             * the other side will send at least one more data packet
             * and that all data in the current packet was accepted. 
             */
            if (bytes == tftp_con->options.blksize)
            {
                TFTPC_Ack(tftp_con);
            }
            
            /* Else if less data was copied than was received, we have
             * filled the user's buffer and can accept no more data.  
             * Send an error condition indicating that no more data can 
             * be accepted.
             */
            else if (bytes < (bytes_received - TFTP_HEADER_SIZE))
            {
                tftp_con->status = TRANSFER_COMPLETE;
                TFTPC_Error(tftp_con, 3, "Buffer Full. ");
            }
            
            /* Else the last data packet has been received.  
             * We are done. Send the last ACK. 
             */
            else
            {
                tftp_con->status = TRANSFER_COMPLETE;
                TFTPC_Ack(tftp_con);
            }
            
            /* Increment the block number. */
            tftp_con->block_number++;
        }
        else
            return(TFTP_CON_FAILURE);
        break;
        
    case TFTP_ERROR_OPCODE:
        
        if (GET16(tftp_con->trans_buf, 2) <= 8)
            return (tftp_errors[GET16(tftp_con->trans_buf, 2)]);
        else
            return(TFTP_CON_FAILURE);
        
    case TFTP_ACK_OPCODE:
    case TFTP_RRQ_OPCODE:
    case TFTP_WRQ_OPCODE:
    default:
        return (TFTP_CON_FAILURE);
    }
    return (NU_SUCCESS);
}  /* TFTPC_Process_Data */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TFTPC_Ack                                                        
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This function is responsible for sending an acknowledgement of   
*       a TFTP data packet.                                              
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *tftp_con       The pointer to TFTP Control Block                 
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       The Number of bytes sent on success.                             
*                                                                       
*************************************************************************/
STATUS TFTPC_Ack(TFTP_CB *tftp_con)
{
    /* Setup the ACK packet - a client always returns an ACK packet, 
     * regardless of the presence of options - only servers return
     * OACK packets 
     */
    PUT16(tftp_con->trans_buf, 0, TFTP_ACK_OPCODE);
    PUT16(tftp_con->trans_buf, 2, tftp_con->block_number);
    
    /* Send the ACK packet. */
    return ((INT)NU_Send_To(tftp_con->socket_number,
        tftp_con->trans_buf, 4, 0,
        &tftp_con->server_addr, 0));
} /* end TFTPC_Ack */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TFTPC_Process_Ack                                                
*                                                                       
*   DESCRIPTION                                                           
*                                                                       
*       This function is responsible processing an ACK packet whenever   
*       a write request is in progress.                                  
*                                                                       
*   INPUTS                                                                
*                                                                       
*       *tftp_con           The pointer to TFTP Control Block.
*       bytes_received      The number of bytes received in the last packet 
*                           received.
*                                                                       
*   OUTPUTS                                                               
*                                                                       
*       NU_SUCCESS whenever the expected data was received, -1 otherwise.
*                                                                       
*************************************************************************/
STATUS TFTPC_Process_Ack(TFTP_CB *tftp_con, INT32 bytes_received)
{
    STATUS  status;
    
    /* What kind of packet is this. */
    switch(GET16(tftp_con->trans_buf, 0))
    {
    case TFTP_OACK_OPCODE:
        
    /* Received an OACK packet that has already be acknowledged,
     * because our block number is greater than 0, and we only
     * receive one OACK when our block number is equal to 0 
     */
        if((tftp_con->block_number > 0)
            && (tftp_con->tid == tftp_con->server_addr.port))
        {
            status = NU_SUCCESS;
            break;
        }
        
        /* Check that the options returned are valid */
        else if ((status = TFTPC_Check_Options(tftp_con, bytes_received)) != NU_SUCCESS)                
            break;
        
        else
        {
            /* Increment block number */
            tftp_con->block_number++;              
            status = NU_SUCCESS;
        }
        
        break;
        
    case TFTP_ACK_OPCODE:
        
    /* Received an ACK packet that has already be acknowledged,
     * because our current block number is greater than the block
     * number of the packet - we do not want to exit, error, or
     * confirm this packet (because it has already been confirmed),
     * but go get the next packet 
     */
        if((tftp_con->block_number > GET16(tftp_con->trans_buf, 2))
            && (tftp_con->tid == tftp_con->server_addr.port))
        {
            status = NU_SUCCESS;
            break;
        }
        
        /* Make sure the block number and TID are correct. */
        else if((tftp_con->block_number == 
            GET16(tftp_con->trans_buf, 2))
            && (tftp_con->tid == tftp_con->server_addr.port))
            tftp_con->block_number++;
        
        else
        {
            status = TFTP_CON_FAILURE;
            break;
        }
        
        status = NU_SUCCESS;
        break;      
        
    case TFTP_ERROR_OPCODE:
        
        if (GET16(tftp_con->trans_buf, 2) <= 8)
            status = (tftp_errors[GET16(tftp_con->trans_buf, 2)]);
        else
            status = TFTP_CON_FAILURE;
        
        break;
        
    case TFTP_RRQ_OPCODE:
    case TFTP_WRQ_OPCODE:
    case TFTP_DATA_OPCODE:
    default:
        status = TFTP_CON_FAILURE;
        break;
    }
    return (status);
}  /* TFTPC_Process_Ack */

/*************************************************************************
*                                                                       
*   FUNCTION                                                              
*                                                                       
*       TFTPC_Send_Data                                                  
*                                                                       

⌨️ 快捷键说明

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