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"); |
