mirror of
https://github.com/bol-van/zapret.git
synced 2025-02-05 06:44:19 +05:00
tpws: segmentation failure warning and fix
This commit is contained in:
parent
46eb30a897
commit
06147836d0
@ -11,6 +11,10 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
#include <linux/tcp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#include "andr/ifaddrs.h"
|
#include "andr/ifaddrs.h"
|
||||||
#else
|
#else
|
||||||
@ -461,3 +465,55 @@ bool parse_cidr6(char *s, struct cidr6 *cidr)
|
|||||||
if (p) *p = d; // restore char
|
if (p) *p = d; // restore char
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void msleep(unsigned int ms)
|
||||||
|
{
|
||||||
|
struct timespec time = {
|
||||||
|
.tv_nsec = (ms % 1000) * 1000000,
|
||||||
|
.tv_sec = ms / 1000
|
||||||
|
};
|
||||||
|
nanosleep(&time, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
bool socket_has_notsent(int sfd)
|
||||||
|
{
|
||||||
|
struct tcp_info tcpi;
|
||||||
|
socklen_t ts = sizeof(tcpi);
|
||||||
|
|
||||||
|
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)
|
||||||
|
return false;
|
||||||
|
if (tcpi.tcpi_state != 1)
|
||||||
|
return false;
|
||||||
|
size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state;
|
||||||
|
if (ts < s)
|
||||||
|
return false;
|
||||||
|
return !!tcpi.tcpi_notsent_bytes;
|
||||||
|
}
|
||||||
|
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms)
|
||||||
|
{
|
||||||
|
struct timespec tres;
|
||||||
|
unsigned int mtick;
|
||||||
|
|
||||||
|
if (wasted_ms) *wasted_ms=0;
|
||||||
|
if (!socket_has_notsent(sfd)) return true;
|
||||||
|
|
||||||
|
if (clock_getres(CLOCK_MONOTONIC,&tres))
|
||||||
|
{
|
||||||
|
tres.tv_nsec = 10000000;
|
||||||
|
tres.tv_sec = 0;
|
||||||
|
}
|
||||||
|
mtick = (unsigned int)(tres.tv_sec*1000) + (unsigned int)(tres.tv_nsec/1000000);
|
||||||
|
if (mtick<1) mtick=1;
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
msleep(mtick);
|
||||||
|
if (wasted_ms) *wasted_ms+=mtick;
|
||||||
|
if (!socket_has_notsent(sfd)) return true;
|
||||||
|
if (delay_ms<=mtick) break;
|
||||||
|
delay_ms-=mtick;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -117,3 +117,9 @@ static inline const struct in6_addr *mask_from_preflen6(uint8_t preflen)
|
|||||||
{
|
{
|
||||||
return ip6_mask+preflen;
|
return ip6_mask+preflen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void msleep(unsigned int ms);
|
||||||
|
#ifdef __linux__
|
||||||
|
bool socket_has_notsent(int sfd);
|
||||||
|
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
|
||||||
|
#endif
|
||||||
|
@ -104,6 +104,7 @@ struct params_s
|
|||||||
uint8_t proxy_type;
|
uint8_t proxy_type;
|
||||||
bool no_resolve;
|
bool no_resolve;
|
||||||
bool skip_nodelay;
|
bool skip_nodelay;
|
||||||
|
bool fix_seg;
|
||||||
bool droproot;
|
bool droproot;
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
11
tpws/tpws.c
11
tpws/tpws.c
@ -169,6 +169,9 @@ static void exithelp(void)
|
|||||||
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
" --uid=uid[:gid]\t\t\t; drop root privs\n"
|
||||||
#if defined(__FreeBSD__)
|
#if defined(__FreeBSD__)
|
||||||
" --enable-pf\t\t\t\t; enable PF redirector support. required in FreeBSD when used with PF firewall.\n"
|
" --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"
|
||||||
#endif
|
#endif
|
||||||
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
" --debug=0|1|2|syslog|@<filename>\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"
|
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||||
@ -635,8 +638,9 @@ void parse_params(int argc, char *argv[])
|
|||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
||||||
{ "mss",required_argument,0,0 }, // optidx=64
|
{ "mss",required_argument,0,0 }, // optidx=64
|
||||||
|
{ "fix-seg",no_argument,0,0 }, // optidx=65
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
{ "nosplice",no_argument,0,0 }, // optidx=65
|
{ "nosplice",no_argument,0,0 }, // optidx=66
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
||||||
@ -1228,8 +1232,11 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 65: /* fix-seg */
|
||||||
|
params.fix_seg = true;
|
||||||
|
break;
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
case 65: /* nosplice */
|
case 66: /* nosplice */
|
||||||
params.nosplice = true;
|
params.nosplice = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1244,7 +1244,21 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
|||||||
if (wr>0) conn->partner->twr += wr;
|
if (wr>0) conn->partner->twr += wr;
|
||||||
break;
|
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;
|
from = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user