summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fox2007-09-06 17:52:22 +0000
committerPaul Fox2007-09-06 17:52:22 +0000
commit40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4 (patch)
tree62ba251d0311ef31e839b6f4d389cfbee62dd16d
parentdcf9bba3b76cc1b79d9f1c1a3cd6428a36699c9d (diff)
downloadbusybox-40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4.zip
busybox-40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4.tar.gz
fix infinite retry bug. also, reduce per-packet receive timeout
to something more reasonable than 5 seconds, and add simple exponential backoff to compensate. improves performance on marginal networks.
-rw-r--r--networking/tftp.c31
1 files changed, 20 insertions, 11 deletions
diff --git a/networking/tftp.c b/networking/tftp.c
index 6be265b..0b25f75 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -21,12 +21,12 @@
#include "libbb.h"
-
#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
#define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */
-#define TFTP_TIMEOUT 5 /* seconds */
-#define TFTP_NUM_RETRIES 5 /* number of retries */
+#define TFTP_TIMEOUT 50000 /* 50ms, in microseconds */
+#define TFTP_MAXTIMEOUT 999000 /* about 1 second, in microseconds */
+#define TFTP_NUM_RETRIES 12 /* number of backed-off retries */
/* opcodes we support */
#define TFTP_RRQ 1
@@ -124,7 +124,7 @@ static int tftp( USE_GETPUT(const int cmd,)
uint16_t opcode;
uint16_t block_nr = 1;
uint16_t recv_blk;
- int timeout = TFTP_NUM_RETRIES;
+ int retries, waittime;
char *cp;
unsigned org_port;
@@ -206,6 +206,10 @@ static int tftp( USE_GETPUT(const int cmd,)
send_len = cp - xbuf;
/* NB: send_len value is preserved in code below
* for potential resend */
+
+ retries = TFTP_NUM_RETRIES; /* re-initialize */
+ waittime = TFTP_TIMEOUT;
+
send_again:
#if ENABLE_DEBUG_TFTP
fprintf(stderr, "sending %u bytes\n", send_len);
@@ -218,11 +222,10 @@ static int tftp( USE_GETPUT(const int cmd,)
if (finished && (opcode == TFTP_ACK))
goto ret;
- timeout = TFTP_NUM_RETRIES; /* re-initialize */
recv_again:
/* Receive packet */
- tv.tv_sec = TFTP_TIMEOUT;
- tv.tv_usec = 0;
+ tv.tv_sec = 0;
+ tv.tv_usec = waittime;
FD_ZERO(&rfds);
FD_SET(socketfd, &rfds);
switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) {
@@ -248,12 +251,18 @@ static int tftp( USE_GETPUT(const int cmd,)
goto recv_again;
goto process_pkt;
case 0:
- timeout--;
- if (timeout == 0) {
- bb_error_msg("last timeout");
+ retries--;
+ if (retries == 0) {
+ bb_error_msg("timeout");
goto ret;
}
- bb_error_msg("last timeout" + 5);
+
+ /* exponential backoff with limit */
+ waittime += waittime/2;
+ if (waittime > TFTP_MAXTIMEOUT) {
+ waittime = TFTP_MAXTIMEOUT;
+ }
+
goto send_again; /* resend last sent pkt */
default:
bb_perror_msg("select");