diff options
author | Paul Fox <pgf@brightstareng.com> | 2007-09-06 17:52:22 +0000 |
---|---|---|
committer | Paul Fox <pgf@brightstareng.com> | 2007-09-06 17:52:22 +0000 |
commit | 40f0bcf9d3f8f8a8d14a9b2cff51761019c75cf4 (patch) | |
tree | 62ba251d0311ef31e839b6f4d389cfbee62dd16d | |
parent | dcf9bba3b76cc1b79d9f1c1a3cd6428a36699c9d (diff) | |
download | busybox-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.c | 31 |
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"); |