Added downstream window fragment timeout option (-j)

This commit is contained in:
frekky 2015-10-27 17:25:56 +08:00
parent 9fae60d241
commit 87edca99b4
3 changed files with 72 additions and 39 deletions

View File

@ -94,8 +94,9 @@ static time_t max_timeout_ms;
static time_t send_interval_ms; static time_t send_interval_ms;
static time_t min_send_interval_ms; static time_t min_send_interval_ms;
/* Server response timeout in ms */ /* Server response timeout in ms and downstream window timeout */
static time_t server_timeout_ms; static time_t server_timeout_ms;
static time_t downstream_timeout_ms;
static int autodetect_server_timeout; static int autodetect_server_timeout;
/* Cumulative Round-Trip-Time in ms */ /* Cumulative Round-Trip-Time in ms */
@ -185,6 +186,7 @@ client_init()
rtt_total_ms = 1000; rtt_total_ms = 1000;
send_interval_ms = 1000; send_interval_ms = 1000;
min_send_interval_ms = 1; min_send_interval_ms = 1;
downstream_timeout_ms = 5000;
outbuf = NULL; outbuf = NULL;
inbuf = NULL; inbuf = NULL;
@ -282,10 +284,11 @@ client_set_compression(int up, int down)
} }
void void
client_set_dnstimeout(double timeout, double servertimeout, int autodetect) client_set_dnstimeout(double timeout, double servertimeout, double downfrag, int autodetect)
{ {
max_timeout_ms = timeout * 1000; max_timeout_ms = timeout * 1000;
server_timeout_ms = servertimeout * 1000; server_timeout_ms = servertimeout * 1000;
downstream_timeout_ms = downfrag * 1000;
autodetect_server_timeout = autodetect; autodetect_server_timeout = autodetect;
} }
@ -385,11 +388,13 @@ update_server_timeout(int dns_fd, int handshake)
server_timeout_ms = max_timeout_ms - rtt_ms; server_timeout_ms = max_timeout_ms - rtt_ms;
if (server_timeout_ms <= 0) { if (server_timeout_ms <= 0) {
server_timeout_ms = 0; server_timeout_ms = 0;
fprintf(stderr, "Setting server timeout to 0 ms: if this continues try disabling lazy mode.\n"); fprintf(stderr, "Setting server timeout to 0 ms: if this continues try disabling lazy mode. (-L0)\n");
} }
} }
/* TODO: update window timeout */ /* update up/down window timeouts to something reasonable */
downstream_timeout_ms = rtt_ms * 2;
outbuf->timeout = ms_to_timeval(downstream_timeout_ms);
if (handshake) { if (handshake) {
/* Send ping handshake to set server timeout */ /* Send ping handshake to set server timeout */
@ -626,7 +631,7 @@ send_packet(int fd, char cmd, const uint8_t *data, const size_t datalen)
} }
int int
send_ping(int fd, int ping_response, int ack, int timeout) send_ping(int fd, int ping_response, int ack, int set_timeout)
{ {
num_pings++; num_pings++;
if (conn == CONN_DNS_NULL) { if (conn == CONN_DNS_NULL) {
@ -645,15 +650,17 @@ send_ping(int fd, int ping_response, int ack, int timeout)
} }
*(uint16_t *) (data + 6) = htons(server_timeout_ms); *(uint16_t *) (data + 6) = htons(server_timeout_ms);
*(uint16_t *) (data + 8) = htons(downstream_timeout_ms);
/* update server lazy timeout, ack flag, respond with ping flag */ /* update server frag/lazy timeout, ack flag, respond with ping flag */
data[8] = ((timeout & 1) << 3) | ((ack < 0 ? 0 : 1) << 2) | (ping_response & 1); data[10] = ((set_timeout & 1) << 4) | ((set_timeout & 1) << 3) | ((ack < 0 ? 0 : 1) << 2) | (ping_response & 1);
data[9] = (rand_seed >> 8) & 0xff; data[11] = (rand_seed >> 8) & 0xff;
data[10] = (rand_seed >> 0) & 0xff; data[12] = (rand_seed >> 0) & 0xff;
rand_seed += 263; rand_seed += 263;
DEBUG(3, " SEND PING: respond %d, ack %d, server timeout %ld, flags %02X", DEBUG(3, " SEND PING: respond %d, ack %d, %s(server %ld ms, downfrag %ld ms), flags %02X",
ping_response, ack, server_timeout_ms, data[8]); ping_response, ack, set_timeout ? "SET " : "", server_timeout_ms,
downstream_timeout_ms, data[8]);
id = send_packet(fd, 'p', data, sizeof(data)); id = send_packet(fd, 'p', data, sizeof(data));
@ -1014,7 +1021,7 @@ handshake_waitdns(int dns_fd, char *buf, size_t buflen, char cmd, int timeout)
if (r == 0) if (r == 0)
return -3; /* select timeout */ return -3; /* select timeout */
q.id = 0; q.id = -1;
q.name[0] = '\0'; q.name[0] = '\0';
rv = read_dns_withq(dns_fd, 0, (uint8_t *)buf, buflen, &q); rv = read_dns_withq(dns_fd, 0, (uint8_t *)buf, buflen, &q);
@ -1373,6 +1380,7 @@ client_tunnel(int tun_fd, int dns_fd)
if (sending > 0 || (total > 0 && lazymode)) { if (sending > 0 || (total > 0 && lazymode)) {
tv = ms_to_timeval(min_send_interval_ms); tv = ms_to_timeval(min_send_interval_ms);
tv.tv_usec += 1;
} else if (total > 0 && !lazymode) { } else if (total > 0 && !lazymode) {
/* use immediate mode send interval if nothing pending */ /* use immediate mode send interval if nothing pending */
tv = ms_to_timeval(send_interval_ms); tv = ms_to_timeval(send_interval_ms);
@ -1392,12 +1400,12 @@ client_tunnel(int tun_fd, int dns_fd)
num_recv - recv_since_report, (num_recv - recv_since_report) / stats); num_recv - recv_since_report, (num_recv - recv_since_report) / stats);
fprintf(stderr, " num IP rejected: %4lu, untracked: %4lu, lazy mode: %1d\n", fprintf(stderr, " num IP rejected: %4lu, untracked: %4lu, lazy mode: %1d\n",
num_badip, num_untracked, lazymode); num_badip, num_untracked, lazymode);
fprintf(stderr, " Min send: %4ld ms, Avg RTT: %4ld ms, immediate replies: %5lu\n", fprintf(stderr, " Min send: %5ld ms, Avg RTT: %5ld ms Timeout server: %4ld ms\n",
min_send_interval_ms, rtt_total_ms / num_immediate, num_immediate); min_send_interval_ms, rtt_total_ms / num_immediate, server_timeout_ms);
fprintf(stderr, " query timeouts: %4lu, target: %4ld ms, server: %4ld ms\n", fprintf(stderr, " Queries immediate: %5lu, timed out: %4lu target: %4ld ms\n",
num_timeouts, max_timeout_ms, server_timeout_ms); num_immediate, num_timeouts, max_timeout_ms);
fprintf(stderr, " Resent fragments up: %4u, downstream out of window: %4u\n", fprintf(stderr, " Frags resent: %4u, OOS: %4u down frag: %4ld ms\n",
outbuf->resends, inbuf->oos); outbuf->resends, inbuf->oos, downstream_timeout_ms);
fprintf(stderr, " TX fragments: %8lu" ", RX: %8lu" ", pings: %8lu" "\n\n", fprintf(stderr, " TX fragments: %8lu" ", RX: %8lu" ", pings: %8lu" "\n\n",
num_frags_sent, num_frags_recv, num_pings); num_frags_sent, num_frags_recv, num_pings);
@ -1568,8 +1576,8 @@ send_upenctest(int fd, char *s)
buf[3] = b32_5to8((rand_seed ) & 0x1f); buf[3] = b32_5to8((rand_seed ) & 0x1f);
rand_seed++; rand_seed++;
strncat(buf, s, 512); strncat(buf, s, 512 - strlen(buf));
strncat(buf, ".", 512); strncat(buf, ".", 512 - strlen(buf));
strncat(buf, topdomain, 512 - strlen(buf)); strncat(buf, topdomain, 512 - strlen(buf));
send_query(fd, (uint8_t *)buf); send_query(fd, (uint8_t *)buf);
} }
@ -2573,6 +2581,7 @@ handshake_set_timeout(int dns_fd)
read = handshake_waitdns(dns_fd, in, sizeof(in), 'P', i + 1); read = handshake_waitdns(dns_fd, in, sizeof(in), 'P', i + 1);
got_response(id, 1, 0); got_response(id, 1, 0);
fprintf(stderr, ".");
if (read > 0) { if (read > 0) {
if (strncmp("BADIP", in, 5) == 0) { if (strncmp("BADIP", in, 5) == 0) {
fprintf(stderr, "Server rejected sender IP address.\n"); fprintf(stderr, "Server rejected sender IP address.\n");
@ -2583,7 +2592,6 @@ handshake_set_timeout(int dns_fd)
break; break;
} }
fprintf(stderr, ".");
} }
if (!running) if (!running)
return; return;

View File

@ -44,7 +44,7 @@ int client_set_qtype(char *qtype);
char *client_get_qtype(); char *client_get_qtype();
void client_set_downenc(char *encoding); void client_set_downenc(char *encoding);
void client_set_compression(int up, int down); void client_set_compression(int up, int down);
void client_set_dnstimeout(double, double, int); void client_set_dnstimeout(double, double, double, int);
void client_set_lazymode(int lazy_mode); void client_set_lazymode(int lazy_mode);
void client_set_windowsize(size_t, size_t); void client_set_windowsize(size_t, size_t);
void client_set_hostname_maxlen(size_t i); void client_set_hostname_maxlen(size_t i);

View File

@ -70,7 +70,7 @@ print_usage()
extern char *__progname; extern char *__progname;
fprintf(stderr, "Usage: %s [-v] [-h] [-V sec] [-f] [-r] [-u user] [-t chrootdir] [-d device] " fprintf(stderr, "Usage: %s [-v] [-h] [-V sec] [-f] [-r] [-u user] [-t chrootdir] [-d device] "
"[-w downfrags] [-W upfrags] [-i sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] " "[-w downfrags] [-W upfrags] [-i sec -j sec] [-I sec] [-c 0|1] [-C 0|1] [-s ms] "
"[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] " "[-P password] [-m maxfragsize] [-M maxlen] [-T type] [-O enc] [-L 0|1] "
"[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [nameserverN ...]]]\n", __progname); "[-z context] [-F pidfile] topdomain [nameserver1 [nameserver2 [nameserverN ...]]]\n", __progname);
} }
@ -93,7 +93,7 @@ help()
fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n"); fprintf(stderr, " Base128, or (only for TXT:) Raw (default: autodetect)\n");
fprintf(stderr, " -I target interval between sending and receiving requests (default: 4 secs)\n"); fprintf(stderr, " -I target interval between sending and receiving requests (default: 4 secs)\n");
fprintf(stderr, " or ping interval in immediate mode (default: 1 sec)\n"); fprintf(stderr, " or ping interval in immediate mode (default: 1 sec)\n");
fprintf(stderr, " -s minimum interval between queries (default: 1ms)\n"); fprintf(stderr, " -s minimum interval between queries (default: 0ms)\n");
fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n"); fprintf(stderr, " -L 1: use lazy mode for low-latency (default). 0: don't (implies -I1)\n");
fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n"); fprintf(stderr, " -m max size of downstream fragments (default: autodetect)\n");
fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n"); fprintf(stderr, " -M max size of upstream hostnames (~100-255, default: 255)\n");
@ -101,11 +101,12 @@ help()
fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n\n"); fprintf(stderr, " -P password used for authentication (max 32 chars will be used)\n\n");
fprintf(stderr, "Fine-tuning options:\n"); fprintf(stderr, "Fine-tuning options:\n");
fprintf(stderr, " -w downstream fragment window size (default: 8)\n"); fprintf(stderr, " -w downstream fragment window size (default: 8 frags)\n");
fprintf(stderr, " -W upstream fragment window size (default: 8)\n"); 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, " -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, " -c 1: use downstream compression (default), 0: disable\n"); fprintf(stderr, " -c 1: use downstream compression (default), 0: disable\n");
fprintf(stderr, " -C 1: use upstream compression, 0: disable (default)\n\n"); fprintf(stderr, " -C 1: use upstream compression (default), 0: disable\n\n");
fprintf(stderr, "Other options:\n"); fprintf(stderr, "Other options:\n");
fprintf(stderr, " -v to print version info and exit\n"); fprintf(stderr, " -v to print version info and exit\n");
@ -162,6 +163,7 @@ main(int argc, char **argv)
int lazymode; int lazymode;
double target_interval_sec; double target_interval_sec;
double server_timeout_sec; double server_timeout_sec;
double downstream_timeout_sec;
int min_interval_ms; int min_interval_ms;
int autodetect_server_timeout; int autodetect_server_timeout;
int up_compression; int up_compression;
@ -183,6 +185,7 @@ main(int argc, char **argv)
int nameservaddr_len; int nameservaddr_len;
int nameserv_family; int nameserv_family;
/* Set default values */
nameserv_addrs_len = 0; nameserv_addrs_len = 0;
nameservaddr_len = 0; nameservaddr_len = 0;
nameserv_host = NULL; nameserv_host = NULL;
@ -208,12 +211,13 @@ main(int argc, char **argv)
raw_mode = 1; raw_mode = 1;
lazymode = 1; lazymode = 1;
target_interval_sec = 5; /* DNS RFC says 5 seconds minimum */ target_interval_sec = 5; /* DNS RFC says 5 seconds minimum */
min_interval_ms = 1; min_interval_ms = 0;
server_timeout_sec = 4; /* Safe value for RTT <1s */ server_timeout_sec = 4; /* Safe value for RTT <1s */
downstream_timeout_sec = 2;
autodetect_server_timeout = 1; autodetect_server_timeout = 1;
hostname_maxlen = 0xFF; hostname_maxlen = 0xFF;
nameserv_family = AF_UNSPEC; nameserv_family = AF_UNSPEC;
up_compression = 0; up_compression = 1;
down_compression = 1; down_compression = 1;
up_windowsize = 8; up_windowsize = 8;
@ -234,7 +238,7 @@ main(int argc, char **argv)
__progname++; __progname++;
#endif #endif
while ((choice = getopt(argc, argv, "46vfDhrs:V:c:C:i:u:t:d:R:P:w:W:m:M:F:T:O:L:I:")) != -1) { while ((choice = getopt(argc, argv, "46vfDhrs:V:c:C:i:j:u:t:d:R:P:w:W:m:M:F:T:O:L:I:")) != -1) {
switch(choice) { switch(choice) {
case '4': case '4':
nameserv_family = AF_INET; nameserv_family = AF_INET;
@ -315,24 +319,25 @@ main(int argc, char **argv)
lazymode = 1; lazymode = 1;
if (lazymode < 0) if (lazymode < 0)
lazymode = 0; lazymode = 0;
if (!lazymode && target_interval_sec > 1)
target_interval_sec = 1;
break; break;
case 'I': case 'I':
target_interval_sec = strtod(optarg, NULL); target_interval_sec = strtod(optarg, NULL);
if (target_interval_sec < 1)
target_interval_sec = 1;
break; break;
case 'i': case 'i':
server_timeout_sec = strtod(optarg, NULL); server_timeout_sec = strtod(optarg, NULL);
if (server_timeout_sec < 0.4)
server_timeout_sec = 0.4;
autodetect_server_timeout = 0; autodetect_server_timeout = 0;
break; break;
case 'j':
downstream_timeout_sec = strtod(optarg, NULL);
if (autodetect_server_timeout) {
autodetect_server_timeout = 0;
server_timeout_sec = 4;
}
break;
case 's': case 's':
min_interval_ms = atoi(optarg); min_interval_ms = atoi(optarg);
if (min_interval_ms < 1) if (min_interval_ms < 0)
min_interval_ms = 1; min_interval_ms = 0;
case 'w': case 'w':
down_windowsize = atoi(optarg); down_windowsize = atoi(optarg);
break; break;
@ -418,8 +423,28 @@ main(int argc, char **argv)
usage(); usage();
} }
if (target_interval_sec < 0.1) {
warnx("Target interval must be greater than 0.1 seconds!");
usage();
}
if (server_timeout_sec < 0.1 || server_timeout_sec >= target_interval_sec) {
warnx("Server timeout must be greater than 0.1 sec and less than target interval!");
usage();
}
if (downstream_timeout_sec < 0.1) {
warnx("Downstream fragment timeout must be more than 0.1 sec to prevent excessive retransmits.");
usage();
}
if (!lazymode && target_interval_sec > 1) {
warnx("Warning: Target interval of >1 second in immediate mode will cause high latency.");
usage();
}
client_set_compression(up_compression, down_compression); client_set_compression(up_compression, down_compression);
client_set_dnstimeout(target_interval_sec, server_timeout_sec, autodetect_server_timeout); client_set_dnstimeout(target_interval_sec, server_timeout_sec, downstream_timeout_sec, autodetect_server_timeout);
client_set_interval(target_interval_sec * 1000.0, min_interval_ms); client_set_interval(target_interval_sec * 1000.0, min_interval_ms);
client_set_lazymode(lazymode); client_set_lazymode(lazymode);
client_set_topdomain(topdomain); client_set_topdomain(topdomain);