nfqws2: timer rework. remove timer-res

This commit is contained in:
bol-van committed 2026-04-30 13:12:56 +03:00
1 parent eb35bb34f5
commit 7db50c018a
8 files changed
+129 -93

No files matched your search

+37 -22
View File
@@ -20,6 +20,8 @@
#include "nfqws.h"
#ifdef __CYGWIN__
#include "timer.h"
#include <sys/cygwin.h>
#include <wlanapi.h>
@@ -1627,32 +1629,34 @@ static bool windivert_recv_exit(void)
}
return false;
}
static DWORD win_timer_check(t_timer_callback timer_callback, uint64_t *bt_prev)
{
uint64_t bt,dbt;
bt = boottime_ms();
dbt = bt-*bt_prev;
if (dbt>=params.timer_res)
{
timer_callback(bt);
*bt_prev = bt;
return params.timer_res;
}
else
return params.timer_res-(int)dbt;
}
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, t_timer_callback timer_callback, uint64_t *bt_prev)
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, uint64_t *bt_next)
{
UINT recv_len;
DWORD rd,twait,tmax;
unsigned int wac;
uint64_t bt;
if (windivert_recv_exit()) return false;
if (windivert_recv_exit())
return false;
tmax = win_timer_check(timer_callback, bt_prev);
if (params.timers)
{
if (!*bt_next) *bt_next = TimerPoolNext(params.timers, &params.timers_dirty);
bt = boottime_ms();
tmax = *bt_next>bt ? (DWORD)(*bt_next-bt) : 0;
if (!tmax || params.timers_dirty)
{
*bt_next = TimerPoolRun(&params.timers, &params.timers_dirty, bt);
bt = boottime_ms();
tmax = *bt_next>bt ? (DWORD)(*bt_next-bt) : 0;
}
}
else
{
*bt_next = 0;
tmax = 0;
}
wac = *wa_count * sizeof(WINDIVERT_ADDRESS);
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, &wac, &ovl))
@@ -1668,14 +1672,25 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
case ERROR_IO_PENDING:
// need to check for signals periodically
for(;;)
{
if (params.timers)
{
twait = tmax>50 ? 50 : tmax;
tmax -= twait;
}
else
twait = 50;
// make signals working
if (WaitForSingleObject(ovl.hEvent,twait)!=WAIT_TIMEOUT) break;
if (windivert_recv_exit())
return false;
if (!tmax) tmax = win_timer_check(timer_callback, bt_prev);
if (params.timers && !tmax)
{
bt = boottime_ms();
*bt_next = TimerPoolRun(&params.timers, &params.timers_dirty, bt);
bt = boottime_ms();
tmax = *bt_next>bt ? (DWORD)(*bt_next-bt) : 0;
}
}
if (!GetOverlappedResult(hFilter,&ovl,&rd,FALSE))
{
@@ -1700,9 +1715,9 @@ cancel:
GetOverlappedResult(hFilter, &ovl, &rd, TRUE);
return false;
}
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, t_timer_callback timer_callback, uint64_t *bt_prev)
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, uint64_t *bt_next)
{
return windivert_recv_filter(w_filter,packet,len,wa,wa_count,timer_callback,bt_prev);
return windivert_recv_filter(w_filter,packet,len,wa,wa_count,bt_next);
}
static bool windivert_send_filter(HANDLE hFilter, const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa)
+1 -2
View File
@@ -135,8 +135,7 @@ bool logical_net_filter_present(void);
bool logical_net_filter_match(void);
bool nlm_list(bool bAll);
bool windivert_init(const char *filter);
typedef void (*t_timer_callback)(uint64_t bt);
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, t_timer_callback timer_callback, uint64_t *bt_prev);
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count, uint64_t *bt_next);
bool windivert_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
#else
#define ensure_dir_access(dir) ensure_file_access(dir)
+3 -1
View File
@@ -3825,6 +3825,7 @@ static int luacall_timer_set(lua_State *L)
timer->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
}
DLOG("timer: '%s' %s. function '%s' period %llu oneshot %u\n", timer->str, action, timer->func, timer->period, timer->oneshot);
params.timers_dirty = true;
LUA_STACK_GUARD_RETURN(L,0)
}
@@ -3841,13 +3842,14 @@ static int luacall_timer_del(lua_State *L)
{
DLOG("timer: '%s' deleted\n", timer->str);
TimerPoolDel(&params.timers, timer);
params.timers_dirty = true;
}
else
DLOG("timer: '%s' not found\n", name);
lua_pushboolean(L, !!timer);
LUA_STACK_GUARD_RETURN(L,1)
}
static int lua_push_timer_info(lua_State *L, const timer_pool *timer)
static void lua_push_timer_info(lua_State *L, const timer_pool *timer)
{
lua_newtable(L);
if (timer->str) lua_pushf_str(L, "name", timer->str);
+47 -58
View File
@@ -242,20 +242,27 @@ static int write_pidfile(FILE **Fpid)
void NoInterceptLoop(void)
{
useconds_t usec = params.timer_res * 1000;
uint64_t bt, bt_next;
useconds_t usec;
if (params.timers)
{
DLOG("processing timers\n");
bt_next = TimerPoolNext(params.timers, &params.timers_dirty);
while(params.timers)
{
if (bQuit) goto quit;
bt = boottime_ms();
if (bt_next>bt)
{
usec = (useconds_t)(bt_next-bt)*1000U;
usleep(usec);
if (bQuit) goto quit;
}
ReloadCheck();
lua_do_gc();
TimerPoolRun(&params.timers, 0);
bt_next = TimerPoolRun(&params.timers, &params.timers_dirty, 0);
}
}
return;
@@ -442,8 +449,8 @@ static int nfq_main(void)
uint8_t *buf=NULL, *mod=NULL;
struct nfq_cb_data cbdata = { .sock = -1, .mod = NULL };
fd_set fdset;
struct timeval tv = {.tv_sec = params.timer_res/1000, .tv_usec = params.timer_res%1000*1000};
unsigned int bt,bt_prev,dbt;
struct timeval tv;
uint64_t bt,dbt,bt_next;
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -519,7 +526,7 @@ static int nfq_main(void)
notify_ready();
fd = nfq_fd(h);
bt_prev=0;
bt_next = bt = 0;
do
{
if (bQuit) goto quit;
@@ -527,6 +534,12 @@ static int nfq_main(void)
{
if (params.timers)
{
if (!bt_next) bt_next = TimerPoolNext(params.timers, &params.timers_dirty);
bt = boottime_ms();
dbt = bt_next>bt ? bt_next-bt : 0;
tv.tv_sec = (time_t)(dbt/1000);
tv.tv_usec = (suseconds_t)(dbt%1000*1000);
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
res = select(fd+1, &fdset, NULL, NULL, &tv);
@@ -540,6 +553,7 @@ static int nfq_main(void)
}
else
{
bt_next = bt = 0;
if (bQuit) goto quit;
res = 1;
}
@@ -566,21 +580,10 @@ static int nfq_main(void)
if (params.timers)
{
bt = boottime_ms();
dbt = bt-bt_prev;
if (dbt>=params.timer_res)
{
TimerPoolRun(&params.timers, bt);
bt_prev = bt;
tv.tv_sec = params.timer_res/1000;
tv.tv_usec = params.timer_res%1000*1000;
}
else
{
dbt = params.timer_res-dbt;
tv.tv_sec = (time_t)(dbt/1000);
tv.tv_usec = (suseconds_t)(dbt%1000*1000);
}
if (bt>=bt_next)
bt_next = TimerPoolRun(&params.timers, &params.timers_dirty, bt);
else if (params.timers_dirty)
bt_next = 0;
}
}
if (errno==EINTR)
@@ -629,8 +632,8 @@ static int dvt_main(void)
struct sockaddr_in6 bp6;
uint8_t buf[RECONSTRUCT_MAX_SIZE] __attribute__((aligned));
fd_set fdset;
struct timeval tv = {.tv_sec = params.timer_res/1000, .tv_usec = params.timer_res%1000*1000};
unsigned int bt,bt_prev,dbt;
struct timeval tv;
uint64_t bt,bt_next,dbt;
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
{
@@ -714,16 +717,29 @@ static int dvt_main(void)
if (params.daemon) daemonize();
if (!write_pidfile(&Fpid)) goto exiterr;
for (bt_prev=0;;)
for (bt=bt_next=0;;)
{
if (bQuit)
{
DLOG_CONDUP("quit requested\n");
goto exitok;
}
FD_ZERO(&fdset);
for (i = 0; i < fdct; i++) FD_SET(fd[i], &fdset);
r = select(fdmax, &fdset, NULL, NULL, params.timers ? &tv : NULL);
if (params.timers)
{
if (!bt_next) bt_next = TimerPoolNext(params.timers, &params.timers_dirty);
bt = boottime_ms();
dbt = bt_next>bt ? bt_next-bt : 0;
tv.tv_sec = (time_t)(dbt/1000);
tv.tv_usec = (suseconds_t)(dbt%1000*1000);
r = select(fdmax, &fdset, NULL, NULL, &tv);
}
else
r = select(fdmax, &fdset, NULL, NULL, NULL);
if (bQuit)
{
DLOG_CONDUP("quit requested\n");
@@ -810,21 +826,10 @@ static int dvt_main(void)
if (params.timers)
{
bt = boottime_ms();
dbt = bt-bt_prev;
if (dbt>=params.timer_res)
{
TimerPoolRun(&params.timers, bt);
bt_prev = bt;
tv.tv_sec = params.timer_res/1000;
tv.tv_usec = params.timer_res%1000*1000;
}
else
{
dbt = params.timer_res-dbt;
tv.tv_sec = (time_t)(dbt/1000);
tv.tv_usec = (suseconds_t)(dbt%1000*1000);
}
if (bt>=bt_next)
bt_next = TimerPoolRun(&params.timers, &params.timers_dirty, bt);
else if (params.timers_dirty)
bt_next = 0;
}
}
@@ -846,11 +851,6 @@ exiterr:
// do not make it less than 65536 - loopback packets can be up to 64K
#define WINDIVERT_PACKET_BUF_SIZE 196608 // 3*64K, 128*1500=192000
static void win_timer_callback(uint64_t bt)
{
TimerPoolRun(&params.timers, bt);
}
static int win_main(void)
{
size_t len, packet_len, left, modlen;
@@ -863,7 +863,7 @@ static int win_main(void)
WINDIVERT_ADDRESS wa[WINDIVERT_BULK_MAX];
uint8_t *packets = NULL, *packet, *mod=NULL;
unsigned int n,wa_count;
uint64_t bt_prev = 0;
uint64_t bt_next;
// windows emulated fork logic does not cover objects outside of cygwin world. have to daemonize before inits
if (params.daemon) daemonize();
@@ -933,11 +933,12 @@ static int win_main(void)
goto ex;
}
bt_next = 0;
for (id = 0;;)
{
len = WINDIVERT_PACKET_BUF_SIZE;
wa_count = WINDIVERT_BULK_MAX;
if (!windivert_recv(packets, &len, wa, &wa_count, win_timer_callback, &bt_prev))
if (!windivert_recv(packets, &len, wa, &wa_count, &bt_next))
{
if (errno == ENOBUFS)
{
@@ -1839,7 +1840,6 @@ static void exithelp(void)
" --ipcache-lifetime=<int>\t\t\t\t; time in seconds to keep cached hop count and domain name (default %u). 0 = no expiration\n"
" --ipcache-hostname=[0|1]\t\t\t\t; 1 or no argument enables ip->hostname caching\n"
" --reasm-disable=[type[,type]]\t\t\t\t; disable reasm for these L7 payloads : tls_client_hello quic_initial . if no argument - disable all reasm.\n"
" --timer-res=msec\t\t\t\t\t; Lua timer resolution. default %d ms\n"
#ifdef __CYGWIN__
"\nWINDIVERT FILTER:\n"
" --wf-iface=<int>[.<int>]\t\t\t\t; numeric network interface and subinterface indexes\n"
@@ -1915,7 +1915,6 @@ static void exithelp(void)
#endif
CTRACK_T_SYN, CTRACK_T_EST, CTRACK_T_FIN, CTRACK_T_UDP,
IPCACHE_LIFETIME,
TIMER_RES_DEFAULT,
LUA_GC_INTERVAL,
all_protos,
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT,
@@ -1998,7 +1997,6 @@ enum opt_indices {
IDX_IPCACHE_LIFETIME,
IDX_IPCACHE_HOSTNAME,
IDX_REASM_DISABLE,
IDX_TIMER_RES,
#ifdef __linux__
IDX_FWMARK,
#elif defined(SO_USER_COOKIE)
@@ -2104,7 +2102,6 @@ static const struct option long_options[] = {
[IDX_IPCACHE_LIFETIME] = {"ipcache-lifetime", required_argument, 0, 0},
[IDX_IPCACHE_HOSTNAME] = {"ipcache-hostname", optional_argument, 0, 0},
[IDX_REASM_DISABLE] = {"reasm-disable", optional_argument, 0, 0},
[IDX_TIMER_RES] = {"timer-res", required_argument, 0, 0},
#ifdef __linux__
[IDX_FWMARK] = {"fwmark", required_argument, 0, 0},
#elif defined(SO_USER_COOKIE)
@@ -2507,14 +2504,6 @@ int main(int argc, char **argv)
else
params.reasm_payload_disable = L7P_ALL;
break;
case IDX_TIMER_RES:
params.timer_res = atoi(optarg);
if (params.timer_res<10)
{
DLOG_ERR("Invalid timer resolution. must be >=10 ms\n");
exit_clean(1);
}
break;
#if defined(__linux__)
case IDX_FWMARK:
#elif defined(SO_USER_COOKIE)
-1
View File
@@ -588,7 +588,6 @@ void init_params(struct params_s *params)
params->ctrack_t_fin = CTRACK_T_FIN;
params->ctrack_t_udp = CTRACK_T_UDP;
params->ipcache_lifetime = IPCACHE_LIFETIME;
params->timer_res = TIMER_RES_DEFAULT;
params->lua_gc = LUA_GC_INTERVAL;
LIST_INIT(&params->hostlists);
+1 -3
View File
@@ -37,8 +37,6 @@
#define IPCACHE_LIFETIME 7200
#define TIMER_RES_DEFAULT 50
#define MAX_GIDS 64
#define MAX_BLOB_SIZE (16*1024)
@@ -195,8 +193,8 @@ struct params_s
bool writeable_dir_enable;
char writeable_dir[PATH_MAX];
int timer_res; // timer resolution in msec
timer_pool *timers;
bool timers_dirty; // changed something in timers
int lua_gc;
int ref_desync_ctx; // desync ctx userdata registry ref
+37 -5
View File
@@ -77,22 +77,40 @@ static bool TimerPoolRunTimer(timer_pool *p)
}
return true;
}
void TimerPoolRun(timer_pool **pp, uint64_t bt)
uint64_t TimerPoolNext(const timer_pool *p, bool *dirty)
{
if (!pp) return; // no timers
const timer_pool *elem, *tmp;
uint64_t nexttime, mintime=0x7FFFFFFFFFFFFFFF;
if (!bt) bt = boottime_ms();
if (!p) return 0;
HASH_ITER(hh, p, elem, tmp)
{
nexttime = elem->bt_prev + elem->period;
if (nexttime<mintime) mintime = nexttime;
}
*dirty = false;
return mintime;
}
uint64_t TimerPoolRun(timer_pool **pp, bool *dirty, uint64_t bt)
{
*dirty = false;
if (!*pp) return 0; // no timers
timer_pool *elem, *tmp, *p;
char *name;
const char *del;
unsigned int n;
uint64_t nexttime, mintime=0x7FFFFFFFFFFFFFFF;
if (!bt) bt = boottime_ms();
HASH_ITER(hh, *pp, elem, tmp)
{
if (bt >= (elem->bt_prev + elem->period))
nexttime = elem->bt_prev + elem->period;
if (bt >= nexttime)
{
if (!(name = strdup(elem->str)))
return;
return 0;
n = elem->n;
del = NULL;
@@ -110,12 +128,26 @@ void TimerPoolRun(timer_pool **pp, uint64_t bt)
{
DLOG(del,name);
TimerPoolDel(pp, elem);
elem = NULL;
}
else
{
elem->bt_prev = bt;
nexttime = elem->bt_prev + elem->period;
}
}
free(name);
}
if (elem)
{
if (nexttime<mintime) mintime = nexttime;
}
}
if (!*pp) return 0; // no timers
if (*dirty)
// something changed in the timer pool (deleted or added in the lua timer code)
// rescan all timers for mintime
mintime = TimerPoolNext(*pp, dirty);
return mintime;
}
+3 -1
View File
@@ -20,4 +20,6 @@ void TimerPoolDestroy(timer_pool **pp);
struct timer_pool *TimerPoolSearch(timer_pool *p, const char *str);
struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, const char *func, uint64_t period, bool oneshot);
void TimerPoolDel(timer_pool **pp, timer_pool *p);
void TimerPoolRun(timer_pool **pp, uint64_t bt);
// return next timer fire time
uint64_t TimerPoolRun(timer_pool **pp, bool *dirty, uint64_t bt);
uint64_t TimerPoolNext(const timer_pool *p, bool *dirty);