📄 tftpc.c
字号:
INT32 TFTPC_Put(UINT8 *remote_ip, CHAR *rpath, CHAR *lpath, TFTP_OPTIONS *ops)
{
TFTP_CB *tftp_con;
STATUS status;
INT16 retransmits;
INT32 bytes_sent = 0;
INT32 total_bytes, bytes_received;
UINT32 file_size;
FAL_FILE file_desc;
/* Open the requested file - if an error occurs, return the error */
if ((file_desc = FAL_Open (lpath, PO_RDWR|PO_BINARY, FAL_IWRITE)) < 0)
return (FAL_Get_Last_Error());
/* Get the file size of the file */
file_size = FAL_Handle_File_Length(file_desc);
/* Check that the requested options are valid */
TFTPC_Set_Options(file_size, ops);
/* We will need at least BUFFER_SIZE_MIN bytes to transmit a request
* packet, so if the requested blksize is less than BUFFER_SIZE_MIN,
* we still need to allocate BUFFER_SIZE_MIN bytes in memory for the
* transmission buffer
*/
if (ops->blksize < TFTP_BUFFER_SIZE_MIN)
{
/* Allocate memory for the TFTP Control Block & transmission buffer */
status = NU_Allocate_Memory (&System_Memory, (VOID **)&tftp_con,
sizeof(TFTP_CB) + TFTP_BUFFER_SIZE_MIN +
TFTP_HEADER_SIZE, NU_SUSPEND);
}
/* Otherwise, the blksize is large enough to transmit a request packet */
else
{
/* Allocate memory for the TFTP Control Block & transmission buffer */
status = NU_Allocate_Memory (&System_Memory, (VOID **)&tftp_con,
(UNSIGNED)(sizeof(TFTP_CB) + ops->blksize +
TFTP_HEADER_SIZE), NU_SUSPEND);
}
/* If we cannot allocate the necessary memory for the control block and
* transmission buffer, return with an error
*/
if (status != NU_SUCCESS)
{
FAL_Fclose(tftp_con->file_desc, 0);
return(TFTP_DISK_FULL);
}
/* Set the options that will be transmitted to the server in the request
* packet
*/
tftp_con->options.timeout = ops->timeout;
tftp_con->options.blksize = ops->blksize;
tftp_con->options.tsize = file_size;
/* Setup the file descriptor, path and READ_TYPE */
tftp_con->file_desc = file_desc;
tftp_con->type = WRITE_TYPE;
tftp_con->file_name = rpath;
tftp_con->trans_buf = (CHAR *)((UINT32)tftp_con + sizeof(TFTP_CB));
/* Send a write request to the server. */
if (TFTPC_Request(remote_ip, rpath, tftp_con) <= 0)
{
FAL_Fclose(tftp_con->file_desc, 0);
NU_Deallocate_Memory((VOID *) tftp_con);
return(TFTP_CON_FAILURE);
}
/* Initialize the retransmit counter. */
retransmits = 0;
/* While an ACK or OACK of the write request has not been received and
* the maximum number of retransmits has not yet been reached.
* Retransmit the write request.
*/
while(((bytes_received = TFTPC_Recv(tftp_con)) == NU_NO_DATA) &&
(retransmits < TFTP_NUM_RETRANS))
{
TFTPC_Retransmit(tftp_con, bytes_sent);
retransmits++;
}
/* If we received a response, then set up the server's TID.
* Else return an error.
*/
if (bytes_received > 0)
tftp_con->tid = tftp_con->server_addr.port;
else
{
FAL_Fclose(tftp_con->file_desc, 0);
NU_Close_Socket(tftp_con->socket_number);
NU_Deallocate_Memory((VOID *) tftp_con);
return(TFTP_CON_FAILURE);
}
/* If we did not receive an OACK, the server is not RFC 2347 compliant;
* therefore, we must set our values to conform to RFC 1350.
*/
if(GET16(tftp_con->trans_buf, 0) != TFTP_OACK_OPCODE)
{
tftp_con->options.blksize = TFTP_BLOCK_SIZE_DEFAULT;
tftp_con->options.timeout = TFTP_TIMEOUT_DEFAULT;
}
/* Process the server's response (ACK or OACK) */
if((status = TFTPC_Process_Ack(tftp_con, bytes_received)) != NU_SUCCESS)
{
FAL_Fclose(tftp_con->file_desc, 0);
NU_Close_Socket(tftp_con->socket_number);
NU_Deallocate_Memory((VOID *) tftp_con);
return(status);
}
/* The connection is now established. While the status is ok
* continue to transmit the remainder of the file.
*/
while (tftp_con->status == TRANSFERRING_FILE)
{
/* Send a data packet. */
if((bytes_sent = (TFTPC_Send_Data(tftp_con))) < 0)
{
status = TFTP_CON_FAILURE;
break;
}
/* Initialize the retransmit counter. */
retransmits = 0;
/* While an ACK of the data packet has not been received and
* the maximum number of retransmits has not yet been reached.
* Retransmit the last data packet.
*/
while(((bytes_received = TFTPC_Recv(tftp_con)) == NU_NO_DATA) &&
(retransmits < TFTP_NUM_RETRANS))
{
TFTPC_Retransmit(tftp_con, bytes_sent);
retransmits++;
}
/* Process the ACK. */
if (bytes_received > 0)
{
if((status = TFTPC_Process_Ack(tftp_con, bytes_received)) != NU_SUCCESS)
break;
}
/* Exit the loop and return an ERROR */
else
{
status = TFTP_CON_FAILURE;
tftp_con->status = TFTP_CON_FAILURE;
}
} /* while transferring file. */
/* Close the file */
FAL_Fclose(tftp_con->file_desc, 0);
/* If everything went okay, then calculate the number of bytes
* that were sent. Else we should return the last error code that was
* received.
*/
if(status == NU_SUCCESS)
total_bytes = file_size;
else
total_bytes = status;
/* Close the socket, freeing any resources that were used. */
NU_Close_Socket(tftp_con->socket_number);
/* Deallocate the memory used for the TFTP control block. */
NU_Deallocate_Memory((VOID *) tftp_con);
return(total_bytes);
} /* end TFTPC_Put */
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Read_Request
*
* DESCRIPTION
*
* This function is responsible for sending a TFTP read request to
* a TFTP server.
*
* INPUTS
*
* *remote_ip Pointer to the server's ip address.
* *remote_fname The remote file to read.
* *tftp_con The pointer to the TFTP Control Block
*
* OUTPUTS
*
* NU_SUCCESS The request was successfully sent.
* NU_NO_MEMORY The socket descriptor was not allocated.
* NU_NO_SOCKET_SPACE All socket descriptors are used.
*
*************************************************************************/
STATUS TFTPC_Request(UINT8 *remote_ip, CHAR *remote_fname, TFTP_CB *tftp_con)
{
INT bytes_sent, send_size;
INT8 temp[10];
/* Create a socket. */
if ((tftp_con->socket_number =
(INT16)(NU_Socket(NU_FAMILY_IP, NU_TYPE_DGRAM, 0))) < 0)
return(TFTP_CON_FAILURE);
/* fill in a structure with the server address */
tftp_con->server_addr.family = NU_FAMILY_IP;
tftp_con->server_addr.port = 69;
memcpy(tftp_con->server_addr.id.is_ip_addrs, remote_ip, 4);
tftp_con->server_addr.name = "tftp";
/* Initialize block_number (to 0 per RFC 2347) and transfer status. */
tftp_con->block_number = 0;
tftp_con->status = TRANSFERRING_FILE;
if (tftp_con->type == READ_TYPE)
PUT16(tftp_con->trans_buf, 0, TFTP_RRQ_OPCODE);
else
PUT16(tftp_con->trans_buf, 0, TFTP_WRQ_OPCODE);
/* Fill in the file name and mode - both null terminated */
/* send_size += (INT16)(sprintf(&(tftp_con->trans_buf[2]), "%s%c%s%c",
remote_fname, 0, "octet", 0)); */
strcpy(&(tftp_con->trans_buf[2]), remote_fname);
send_size = strlen(remote_fname) + 2;
tftp_con->trans_buf[send_size++] = 0;
strcpy(&(tftp_con->trans_buf[send_size]), "octet");
send_size += strlen("octet");
tftp_con->trans_buf[send_size++] = 0;
/* Check if there is a blksize, timeout or tsize option indicated, if so,
* append the option name and option value to the end of the packet -
* all null terminated
*/
if (tftp_con->options.blksize != TFTP_BLOCK_SIZE_DEFAULT)
{
/* send_size += sprintf(&(tftp_con->trans_buf[send_size]), "%s%c%d%c",
"blksize", 0, tftp_con->options.blksize, 0); */
strcpy(&(tftp_con->trans_buf[send_size]), "blksize");
send_size = strlen("blksize") + send_size;
tftp_con->trans_buf[send_size++] = 0;
strcpy(&(tftp_con->trans_buf[send_size]), (CHAR *)(NU_ITOA((INT)tftp_con->options.blksize, temp, 10)) );
send_size += strlen(temp);
tftp_con->trans_buf[send_size++] = 0;
}
if (tftp_con->options.timeout != 0)
{
/* send_size += sprintf(&(tftp_con->trans_buf[send_size]), "%s%c%d%c",
"timeout", 0, tftp_con->options.timeout, 0); */
strcpy(&(tftp_con->trans_buf[send_size]), "timeout");
send_size = strlen("timeout") + send_size;
tftp_con->trans_buf[send_size++] = 0;
strcpy(&(tftp_con->trans_buf[send_size]), (CHAR *)(NU_ITOA((INT)tftp_con->options.timeout, temp, 10)) );
send_size += strlen(temp);
tftp_con->trans_buf[send_size++] = 0;
}
if ((tftp_con->options.tsize == 0) && (tftp_con->type == READ_TYPE))
{
/* send_size += sprintf(&(tftp_con->trans_buf[send_size]), "%s%c%c%c",
"tsize", 0, 0, 0); */
strcpy(&(tftp_con->trans_buf[send_size]), "tsize");
send_size = strlen("tsize") + send_size;
tftp_con->trans_buf[send_size++] = 0;
tftp_con->trans_buf[send_size++] = 0;
tftp_con->trans_buf[send_size++] = 0;
}
if ((tftp_con->options.tsize != 0) && (tftp_con->type == WRITE_TYPE))
{
/* send_size += sprintf(&(tftp_con->trans_buf[send_size]), "%s%c%d%c",
"tsize", 0, tftp_con->options.tsize, 0); */
strcpy(&(tftp_con->trans_buf[send_size]), "tsize");
send_size = strlen("tsize") + send_size;
tftp_con->trans_buf[send_size++] = 0;
strcpy(&(tftp_con->trans_buf[send_size]), (CHAR *)(NU_ULTOA(tftp_con->options.tsize, temp, 10)) );
send_size += strlen(temp);
tftp_con->trans_buf[send_size++] = 0;
}
/* Send the request. */
bytes_sent = (INT16)(NU_Send_To(tftp_con->socket_number,
tftp_con->trans_buf, (UINT16)(send_size), 0,
&tftp_con->server_addr, 0));
if (bytes_sent <= 0)
NU_Close_Socket(tftp_con->socket_number);
return (bytes_sent);
} /* end TFTPC_Request */
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Recv
*
* DESCRIPTION
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -