📄 tftp.c
字号:
tcxn.error = FALSE;
/* Use Mac address as pseudo-random port */
udp_prime_port((uint16)((nif->hwa[4] << 8) | nif->hwa[5]));
tcxn.my_port = udp_obtain_free_port();
udp_bind_port(tcxn.my_port,&tftp_handler);
retries = 4;
success = FALSE;
while (--retries)
{
/* Make the TFTP Read/Write Request */
if (!tftp_rwrq())
{
printf("Error: Couldn't send TFTP Write Request\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
timer_set_secs(TIMER_NETWORK, TFTP_TIMEOUT);
while (timer_get_reference(TIMER_NETWORK))
{
/* Has the server responded */
if (tcxn.open)
{
success = TRUE;
break;
}
}
/* If the connection is open, we are done here */
if (success || tcxn.error)
break;
}
if (!retries)
{
printf("TFTP could not make connection to server.\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
else if (tcxn.error)
{
printf("\bErrors in TFTP upload.\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
bytes_to_send = end - begin;
current = (uint8 *)begin;
blocknum = 1;
retries = 4;
success = FALSE;
while (--retries)
{
pNbuf = nbuf_alloc();
if (pNbuf == NULL)
{
#if defined(DEBUG_PRINT)
printf("TFTP: tftp_write() couldn't allocate Tx buffer\n");
#endif
return FALSE;
}
/* Build the packet */
data = (DATA *)&pNbuf->data[TFTP_HDR_OFFSET];
data->blocknum = blocknum;
data->opcode = TFTP_DATA;
this_size = (bytes_to_send > TFTP_PKTSIZE) ? \
TFTP_PKTSIZE : (uint16)bytes_to_send;
for (i = 0; i < this_size; i++)
{
data->data[i] = current[i];
}
/* Set the packet length */
pNbuf->length = (uint16)(4 + this_size);
/* Attempt to send the packet */
for (i=0; i<3; ++i)
{
result = udp_send(tcxn.nif,
tcxn.server_ip,
tcxn.my_port,
tcxn.server_port,
pNbuf);
if (result == 1)
break;
}
if (result == 0)
nbuf_free(pNbuf);
timer_set_secs(TIMER_NETWORK, TFTP_TIMEOUT);
while (timer_get_reference(TIMER_NETWORK))
{
/* Has the server responded */
if ((tcxn.exp_blocknum - 1) == blocknum)
{
success = TRUE;
break;
}
}
/* TFTP Write Compeleted successfully */
if (success && (this_size < TFTP_PKTSIZE))
{
tcxn.bytes_sent += this_size;
break;
}
if (tcxn.error)
break;
/* If an ACK was received, keep sending packets */
if (success)
{
tcxn.bytes_sent += TFTP_PKTSIZE;
bytes_to_send -= TFTP_PKTSIZE;
current += TFTP_PKTSIZE;
blocknum++;
retries = 4;
success = FALSE;
}
}
if (tcxn.error)
{
printf("TFTP lost connection to server.\n");
printf("Sent %d bytes (%d blocks)\n", \
tcxn.bytes_sent, tcxn.exp_blocknum - 1);
udp_free_port(tcxn.my_port);
return FALSE;
}
else
{
printf("\bTFTP upload successful\n");
printf("Sent %d bytes (%d blocks)\n", \
tcxn.bytes_sent, tcxn.exp_blocknum - 1);
udp_free_port(tcxn.my_port);
return TRUE;
}
}
/********************************************************************/
int
tftp_read (NIF *nif, char *fn, IP_ADDR_P server)
{
uint32 retries;
if (fn == 0 || server == 0)
return 0;
/* Setup initial connection status */
tcxn.nif = nif;
tcxn.file = fn;
tcxn.server_ip[0] = server[0];
tcxn.server_ip[1] = server[1];
tcxn.server_ip[2] = server[2];
tcxn.server_ip[3] = server[3];
tcxn.server_port = UDP_PORT_TFTP;
tcxn.exp_blocknum = 1;
tcxn.last_ack = 0;
tcxn.dir = TFTP_RRQ;
tcxn.open = FALSE;
tcxn.bytes_recv = 0;
tcxn.rem_bytes = 0;
tcxn.next_char = NULL;
tcxn.error = FALSE;
queue_init(&tcxn.queue);
/* Use Mac address as pseudo-random port */
udp_prime_port((uint16)((nif->hwa[4] << 8) | nif->hwa[5]));
tcxn.my_port = udp_obtain_free_port();
udp_bind_port(tcxn.my_port,&tftp_handler);
retries = 4;
while (--retries)
{
/* Make the TFTP Read/Write Request */
if (!tftp_rwrq())
{
printf("Error: Couldn't send TFTP Read Request\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
timer_set_secs(TIMER_NETWORK, TFTP_TIMEOUT);
while (timer_get_reference(TIMER_NETWORK))
{
/* Has the server responded */
if (tcxn.open == TRUE)
break;
}
/* If the connection is open, we are done here */
if ((tcxn.open == TRUE) || tcxn.error)
break;
}
if (!retries)
{
printf("TFTP could not make connection to server.\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
else if (tcxn.error)
{
printf("\bErrors in TFTP download.\n");
udp_free_port(tcxn.my_port);
return FALSE;
}
else
return TRUE;
}
/********************************************************************/
int
tftp_in_char (void)
{
union TFTPpacket *tftp_pkt;
int retval;
NBUF *pNbuf;
if (tcxn.next_char != NULL)
{
/*
* A buffer is already being worked on - grab next
* byte from it
*/
retval = *tcxn.next_char++;
if (--tcxn.rem_bytes <= 0)
{
/* The buffer is depleted; add it back to the free queue */
pNbuf = (NBUF *)queue_remove(&tcxn.queue);
ASSERT(pNbuf);
nbuf_free(pNbuf);
tcxn.next_char = NULL;
}
}
else
{
/* Is the connection still open? */
if (tcxn.open == FALSE)
{
/*
* The last packet has been received and the last data
* buffer has been exhausted
*/
retval = -1;
}
else
{
/* Get pointer to the next buffer */
pNbuf = (NBUF *)queue_peek(&tcxn.queue);
if (pNbuf == NULL)
{
int i;
/* There was no buffer in the queue */
for (i = 0; i < 3; ++i)
{
timer_set_secs(TIMER_NETWORK, 1);
while (timer_get_reference(TIMER_NETWORK))
{
/* Has the server sent another DATA packet? */
if (!queue_isempty(&tcxn.queue))
{
pNbuf = (NBUF *)queue_peek(&tcxn.queue);
break;
}
}
if (pNbuf != NULL)
break;
/* Ack the last packet again */
#ifdef DEBUG_PRINT
printf("Re-acking %d\n",tcxn.last_ack - 1);
#endif
retval = tftp_ack(tcxn.last_ack - 1);
ASSERT(retval);
}
}
if (pNbuf == NULL)
{
/* The server didn't respond with the expected packet */
tcxn.open = FALSE;
tcxn.error = TRUE;
printf("TFTP lost connection to server.\n");
retval = -1;
}
else
{
tftp_pkt = (union TFTPpacket *)&pNbuf->data[pNbuf->offset];
/* Subtract the TFTP header from the data length */
tcxn.rem_bytes = pNbuf->length - 4;
/* Point to first data byte in the packet */
tcxn.next_char = tftp_pkt->data.data;
/* Save off the block number */
tcxn.last_ack = tftp_pkt->data.blocknum;
/* Check to see if this is the last packet of the transfer */
if (tcxn.rem_bytes < TFTP_PKTSIZE)
tcxn.open = FALSE;
/* Check for empty termination packet */
if (tcxn.rem_bytes == 0)
{
pNbuf = (NBUF *)queue_remove(&tcxn.queue);
ASSERT(pNbuf);
nbuf_free(pNbuf);
tcxn.next_char = NULL;
retval = tftp_ack(tcxn.last_ack++);
ASSERT(retval);
retval = -1;
}
else
{
retval = tftp_ack(tcxn.last_ack++);
ASSERT(retval);
retval = *tcxn.next_char++;
/* Check for a single byte packet */
if (--tcxn.rem_bytes == 0)
{
/* The buffer is depleted; add it back to the free queue */
pNbuf = (NBUF *)queue_remove(&tcxn.queue);
ASSERT(pNbuf);
nbuf_free(pNbuf);
tcxn.next_char = NULL;
}
}
}
}
}
return retval;
}
/********************************************************************/
#endif /* #ifdef DBUG_NETWORK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -