diff --git a/src/client.c b/src/client.c index 0c4b01d..9048962 100644 --- a/src/client.c +++ b/src/client.c @@ -213,7 +213,7 @@ update_server_timeout(int handshake) } /* update up/down window timeouts to something reasonable */ - this.downstream_timeout_ms = rtt_ms * 2; + this.downstream_timeout_ms = rtt_ms * this.downstream_delay_variance; this.outbuf->timeout = ms_to_timeval(this.downstream_timeout_ms); if (handshake) { @@ -289,6 +289,7 @@ got_response(int id, int immediate, int fail) { struct timeval now, rtt; time_t rtt_ms; + static time_t rtt_min_ms = 1; gettimeofday(&now, NULL); QTRACK_DEBUG(4, "Got answer id %d (%s)%s", id, immediate ? "immediate" : "lazy", @@ -326,8 +327,16 @@ got_response(int id, int immediate, int fail) this.rtt_total_ms += rtt_ms; this.num_immediate++; - if (this.autodetect_server_timeout && this.lazymode) + if (this.autodetect_server_timeout) { + if (this.autodetect_delay_variance) { + if (rtt_ms > 0 && (rtt_ms < rtt_min_ms || 1 == rtt_min_ms)) { + rtt_min_ms = rtt_ms; + } + this.downstream_delay_variance = (double) (this.rtt_total_ms / + this.num_immediate) / rtt_min_ms; + } update_server_timeout(0); + } } /* Remove query info from buffer to mark it as answered */ diff --git a/src/client.h b/src/client.h index e43a20f..92d6232 100644 --- a/src/client.h +++ b/src/client.h @@ -88,7 +88,9 @@ struct client_instance { /* Server response timeout in ms and downstream window timeout */ time_t server_timeout_ms; time_t downstream_timeout_ms; + double downstream_delay_variance; int autodetect_server_timeout; + int autodetect_delay_variance; /* Cumulative Round-Trip-Time in ms */ time_t rtt_total_ms; diff --git a/src/iodine.c b/src/iodine.c index 24b68a5..2326ed3 100644 --- a/src/iodine.c +++ b/src/iodine.c @@ -86,6 +86,8 @@ struct client_instance this; .next_downstream_ack = -1, \ .num_immediate = 1, \ .rtt_total_ms = 200, \ + .downstream_delay_variance = 2.0, \ + .autodetect_delay_variance = 0, \ .remote_forward_addr = {.ss_family = AF_UNSPEC} static struct client_instance preset_default = { @@ -221,7 +223,7 @@ print_usage() extern char *__progname; fprintf(stderr, "Usage: %s [-v] [-h] [-Y preset] [-V sec] [-X port] [-f] [-r] [-u user] [-t chrootdir] [-d device] " - "[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] " + "[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-J var] [-c 0|1] [-C 0|1] [-s ms] " "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] [-R port[,host] ] " "[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [...]]]\n", __progname); } @@ -268,6 +270,7 @@ help() fprintf(stderr, " -W upstream fragment window size (default: 8 frags)\n"); fprintf(stderr, " -i server-side request timeout in lazy mode (default: auto)\n"); fprintf(stderr, " -j downstream fragment ACK timeout, implies -i4 (default: 2 sec)\n"); + fprintf(stderr, " -J downstream fragment ACK delay variance factor (default: 2.0), 0: auto\n"); //fprintf(stderr, " --nodrop disable TCP packet-dropping optimisations\n"); fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n"); fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n"); @@ -423,7 +426,7 @@ main(int argc, char **argv) * This is so that all options override preset values regardless of order in command line */ int optind_orig = optind, preset_id = -1; - static char *iodine_args_short = "46vfDhrY:s:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:"; + static char *iodine_args_short = "46vfDhrY:s:V:c:C:i:j:J:u:t:d:R:P:w:W:m:M:F:T:O:L:I:"; while ((choice = getopt_long(argc, argv, iodine_args_short, iodine_args, NULL))) { /* Check if preset has been found yet so we don't process any other options */ @@ -577,6 +580,13 @@ main(int argc, char **argv) this.server_timeout_ms = 4000; } break; + case 'J': + this.downstream_delay_variance = strtod(optarg, NULL); + if (0.0 == this.downstream_delay_variance) { + this.autodetect_delay_variance = 1; + this.downstream_delay_variance = 2.0; + } + break; case 's': this.send_interval_ms = atoi(optarg); if (this.send_interval_ms < 0) @@ -695,6 +705,11 @@ main(int argc, char **argv) usage(); } + if (this.downstream_delay_variance < 0.1) { + warnx("Delay variance factor must be more than 0.1 to prevent excessive retransmits."); + usage(); + } + if (!this.lazymode && this.max_timeout_ms > 1000) { fprintf(stderr, "Warning: Target interval of >1 second in immediate mode will cause high latency.\n"); }