diff --git a/docs/readme.md b/docs/readme.md index d4c7255..5b13353 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -812,7 +812,7 @@ tpws - это transparent proxy. --skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split. --local-tcp-user-timeout= ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение) --remote-tcp-user-timeout= ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение) ---fix-seg ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления +--fix-seg= ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс. --split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации --split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS) diff --git a/tpws/helpers.c b/tpws/helpers.c index 801b213..667a4f4 100644 --- a/tpws/helpers.c +++ b/tpws/helpers.c @@ -484,10 +484,11 @@ bool socket_has_notsent(int sfd) if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0) return false; - if (tcpi.tcpi_state != 1) + if (tcpi.tcpi_state != 1) // TCP_ESTABLISHED return false; size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state; if (ts < s) + // old structure version return false; return !!tcpi.tcpi_notsent_bytes; } diff --git a/tpws/params.h b/tpws/params.h index 3cbcb81..fca406f 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -18,6 +18,8 @@ #define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3 #define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60 +#define FIX_SEG_DEFAULT_MAX_WAIT 30 + enum bindll { unwanted=0, no, prefer, force }; #define MAX_BINDS 32 @@ -102,13 +104,13 @@ struct params_s char connect_bind6_ifname[IF_NAMESIZE]; uint8_t proxy_type; + unsigned int fix_seg; bool no_resolve; bool skip_nodelay; - bool fix_seg; bool droproot; + bool daemon; uid_t uid; gid_t gid; - bool daemon; char pidfile[256]; int maxconn,resolver_threads,maxfiles,max_orphan_time; int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf; diff --git a/tpws/tpws.c b/tpws/tpws.c index eae386f..60a3c68 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -171,7 +171,7 @@ static void exithelp(void) " --enable-pf\t\t\t\t; enable PF redirector support. required in FreeBSD when used with PF firewall.\n" #endif #if defined(__linux__) - " --fix-seg\t\t\t\t; fix segmentation failures at the cost of possible slowdown\n" + " --fix-seg=\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n" #endif " --debug=0|1|2|syslog|@\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n" " --debug-level=0|1|2\t\t\t; specify debug level\n" @@ -218,6 +218,9 @@ static void exithelp(void) " --tamper-cutoff=[n]\t\t; do not tamper anymore after specified outbound stream position. default is unlimited.\n", #if defined(__linux__) || defined(__APPLE__) DEFAULT_TCP_USER_TIMEOUT_LOCAL,DEFAULT_TCP_USER_TIMEOUT_REMOTE, +#endif +#ifdef __linux__ + FIX_SEG_DEFAULT_MAX_WAIT, #endif HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT ); @@ -638,7 +641,7 @@ void parse_params(int argc, char *argv[]) { "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62 { "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63 { "mss",required_argument,0,0 }, // optidx=64 - { "fix-seg",no_argument,0,0 }, // optidx=65 + { "fix-seg",optional_argument,0,0 }, // optidx=65 #ifdef SPLICE_PRESENT { "nosplice",no_argument,0,0 }, // optidx=66 #endif @@ -1233,7 +1236,18 @@ void parse_params(int argc, char *argv[]) } break; case 65: /* fix-seg */ - params.fix_seg = true; + if (optarg) + { + i = atoi(optarg); + if (i < 0 || i > 1000) + { + DLOG_ERR("fix_seg value must be within 0..1000\n"); + exit_clean(1); + } + params.fix_seg = i; + } + else + params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT; break; #ifdef SPLICE_PRESENT case 66: /* nosplice */ diff --git a/tpws/tpws_conn.c b/tpws/tpws_conn.c index daeb644..5b9559f 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -1231,6 +1231,22 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32 bApplyDisorder = !(i & 1) && ipartner->fd, params.fix_seg, &wasted); + if (wasted) + VPRINT("WARNING ! wasted %u ms to fix segmenation\n", wasted); + if (!bWaitOK) + DLOG_ERR("WARNING ! segmentation failed\n"); + } + else + { + if (socket_has_notsent(conn->partner->fd)) + DLOG_ERR("WARNING ! segmentation failed\n"); + } +#endif VPRINT("Sending multisplit part %d %zd-%zd (len %zd)%s%s : ", i+1, from, to, len, bApplyDisorder ? " with disorder" : "", bApplyOOB ? " with OOB" : ""); packet_debug(buf+from,len); wr = send_oob(conn->partner->fd, buf+from, len, bApplyDisorder, bApplyOOB, conn->track.dp ? conn->track.dp->oob_byte : 0); @@ -1244,21 +1260,6 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32 if (wr>0) conn->partner->twr += wr; break; } -#ifdef __linux__ - if (params.fix_seg) - { - unsigned int wasted; - if (!socket_wait_notsent(conn->partner->fd, 20, &wasted)) - DLOG_ERR("WARNING ! segmentation failed\n"); - if (wasted) - VPRINT("WARNING ! wasted %u ms to fix segmenation\n", wasted); - } - else - { - if (socket_has_notsent(conn->partner->fd)) - DLOG_ERR("WARNING ! segmentation failed\n"); - } -#endif from = to; } }