diff --git a/docs/readme.md b/docs/readme.md index da2f58a..8ab505b 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -881,7 +881,7 @@ tpws, как и nfqws, поддерживает множественную се Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8. При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`. Если вы его видите, это повод снизить количество сплит позиций. -Если это не вариант, есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части. +Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части. Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс. И производится оно только , если происходит split, и в ожидании есть реальная необходимость. diff --git a/tpws/helpers.c b/tpws/helpers.c index 667a4f4..afdcc44 100644 --- a/tpws/helpers.c +++ b/tpws/helpers.c @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __linux__ #include @@ -477,6 +478,24 @@ void msleep(unsigned int ms) } #ifdef __linux__ +bool socket_supports_notsent() +{ + int sfd; + struct tcp_info tcpi; + + sfd = socket(AF_INET,SOCK_STREAM,0); + if (sfd<0) return false; + + socklen_t ts = sizeof(tcpi); + if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0) + { + close(sfd); + return false; + } + close(sfd); + + return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state + sizeof(tcpi.tcpi_notsent_bytes)); +} bool socket_has_notsent(int sfd) { struct tcp_info tcpi; @@ -486,7 +505,7 @@ bool socket_has_notsent(int sfd) return false; if (tcpi.tcpi_state != 1) // TCP_ESTABLISHED return false; - size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state; + size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi + sizeof(tcpi.tcpi_notsent_bytes); if (ts < s) // old structure version return false; diff --git a/tpws/helpers.h b/tpws/helpers.h index f8b0e3a..3c8a372 100644 --- a/tpws/helpers.h +++ b/tpws/helpers.h @@ -120,6 +120,7 @@ static inline const struct in6_addr *mask_from_preflen6(uint8_t preflen) void msleep(unsigned int ms); #ifdef __linux__ +bool socket_supports_notsent(); bool socket_has_notsent(int sfd); bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms); #endif diff --git a/tpws/tpws.c b/tpws/tpws.c index 60a3c68..e675877 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -1236,6 +1236,11 @@ void parse_params(int argc, char *argv[]) } break; case 65: /* fix-seg */ + if (!socket_supports_notsent()) + { + DLOG_ERR("--fix-seg is supported since kernel 4.6\n"); + exit_clean(1); + } if (optarg) { i = atoi(optarg);