aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Fox <pgf@brightstareng.com>2007-09-06 17:52:22 +0000
committerPaul Fox <pgf@brightstareng.com>2007-09-06 17:52:22 +0000
commit40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4 (patch)
tree62ba251d0311ef31e839b6f4d389cfbee62dd16d
parentdcf9bba3b76cc1b79d9f1c1a3cd6428a36699c9d (diff)
downloadbusybox-w32-40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4.tar.gz
busybox-w32-40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4.tar.bz2
busybox-w32-40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4.zip
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 6be265b4c..0b25f752d 100644
--- a/networking/tftp.c
+++ b/networking/tftp.c
@@ -21,12 +21,12 @@
21 21
22#include "libbb.h" 22#include "libbb.h"
23 23
24
25#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT 24#if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT
26 25
27#define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */ 26#define TFTP_BLOCKSIZE_DEFAULT 512 /* according to RFC 1350, don't change */
28#define TFTP_TIMEOUT 5 /* seconds */ 27#define TFTP_TIMEOUT 50000 /* 50ms, in microseconds */
29#define TFTP_NUM_RETRIES 5 /* number of retries */ 28#define TFTP_MAXTIMEOUT 999000 /* about 1 second, in microseconds */
29#define TFTP_NUM_RETRIES 12 /* number of backed-off retries */
30 30
31/* opcodes we support */ 31/* opcodes we support */
32#define TFTP_RRQ 1 32#define TFTP_RRQ 1
@@ -124,7 +124,7 @@ static int tftp( USE_GETPUT(const int cmd,)
124 uint16_t opcode; 124 uint16_t opcode;
125 uint16_t block_nr = 1; 125 uint16_t block_nr = 1;
126 uint16_t recv_blk; 126 uint16_t recv_blk;
127 int timeout = TFTP_NUM_RETRIES; 127 int retries, waittime;
128 char *cp; 128 char *cp;
129 129
130 unsigned org_port; 130 unsigned org_port;
@@ -206,6 +206,10 @@ static int tftp( USE_GETPUT(const int cmd,)
206 send_len = cp - xbuf; 206 send_len = cp - xbuf;
207 /* NB: send_len value is preserved in code below 207 /* NB: send_len value is preserved in code below
208 * for potential resend */ 208 * for potential resend */
209
210 retries = TFTP_NUM_RETRIES; /* re-initialize */
211 waittime = TFTP_TIMEOUT;
212
209 send_again: 213 send_again:
210#if ENABLE_DEBUG_TFTP 214#if ENABLE_DEBUG_TFTP
211 fprintf(stderr, "sending %u bytes\n", send_len); 215 fprintf(stderr, "sending %u bytes\n", send_len);
@@ -218,11 +222,10 @@ static int tftp( USE_GETPUT(const int cmd,)
218 if (finished && (opcode == TFTP_ACK)) 222 if (finished && (opcode == TFTP_ACK))
219 goto ret; 223 goto ret;
220 224
221 timeout = TFTP_NUM_RETRIES; /* re-initialize */
222 recv_again: 225 recv_again:
223 /* Receive packet */ 226 /* Receive packet */
224 tv.tv_sec = TFTP_TIMEOUT; 227 tv.tv_sec = 0;
225 tv.tv_usec = 0; 228 tv.tv_usec = waittime;
226 FD_ZERO(&rfds); 229 FD_ZERO(&rfds);
227 FD_SET(socketfd, &rfds); 230 FD_SET(socketfd, &rfds);
228 switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) { 231 switch (select(socketfd + 1, &rfds, NULL, NULL, &tv)) {
@@ -248,12 +251,18 @@ static int tftp( USE_GETPUT(const int cmd,)
248 goto recv_again; 251 goto recv_again;
249 goto process_pkt; 252 goto process_pkt;
250 case 0: 253 case 0:
251 timeout--; 254 retries--;
252 if (timeout == 0) { 255 if (retries == 0) {
253 bb_error_msg("last timeout"); 256 bb_error_msg("timeout");
254 goto ret; 257 goto ret;
255 } 258 }
256 bb_error_msg("last timeout" + 5); 259
260 /* exponential backoff with limit */
261 waittime += waittime/2;
262 if (waittime > TFTP_MAXTIMEOUT) {
263 waittime = TFTP_MAXTIMEOUT;
264 }
265
257 goto send_again; /* resend last sent pkt */ 266 goto send_again; /* resend last sent pkt */
258 default: 267 default:
259 bb_perror_msg("select"); 268 bb_perror_msg("select");