mirror of
https://github.com/bol-van/zapret2.git
synced 2026-08-28 21:02:17 +04:00
nfqws2: timers
This commit is contained in:
@@ -280,3 +280,7 @@ v0.9.4.3
|
||||
0.9.4.7
|
||||
|
||||
* nfqws2: do not fail tls_mod if dupsid,rndsni,padencap fail
|
||||
|
||||
0.9.5
|
||||
|
||||
* nfqws2: timers
|
||||
|
||||
+18
-1
@@ -15,7 +15,7 @@ end
|
||||
function test_all(...)
|
||||
test_run({
|
||||
test_crypto, test_bin, test_time, test_gzip, test_ipstr, test_dissect, test_csum, test_resolve,
|
||||
test_get_source_ip, test_ifaddrs, test_rawsend},...)
|
||||
test_get_source_ip, test_ifaddrs, test_rawsend, test_timer},...)
|
||||
end
|
||||
|
||||
|
||||
@@ -907,6 +907,23 @@ function test_ifaddrs(opts)
|
||||
end
|
||||
end
|
||||
|
||||
function timer1(name, data)
|
||||
print("timer "..name.." fired. data="..tostring(data))
|
||||
end
|
||||
function timer2(name, data)
|
||||
data.n = data.n+1
|
||||
print("timer "..name.." fired. data.n="..tostring(data.n))
|
||||
if data.n>=3 then
|
||||
timer_del(name)
|
||||
end
|
||||
end
|
||||
function test_timer(opts)
|
||||
timer_set("t1","timer1",500,true,"sample_data");
|
||||
tbl = {n=0}
|
||||
timer_set("t2","timer2",700,false,tbl);
|
||||
end
|
||||
|
||||
|
||||
function test_rawsend(opts)
|
||||
print("* rawsend")
|
||||
|
||||
|
||||
+32
-7
@@ -1627,14 +1627,33 @@ static bool windivert_recv_exit(void)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count)
|
||||
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)
|
||||
{
|
||||
UINT recv_len;
|
||||
DWORD rd;
|
||||
DWORD rd,twait,tmax;
|
||||
unsigned int wac;
|
||||
|
||||
if (windivert_recv_exit()) return false;
|
||||
|
||||
tmax = win_timer_check(timer_callback, bt_prev);
|
||||
|
||||
wac = *wa_count * sizeof(WINDIVERT_ADDRESS);
|
||||
if (WinDivertRecvEx(hFilter, packet, *len, &recv_len, 0, wa, &wac, &ovl))
|
||||
{
|
||||
@@ -1647,10 +1666,16 @@ static bool windivert_recv_filter(HANDLE hFilter, uint8_t *packet, size_t *len,
|
||||
switch(w_win32_error)
|
||||
{
|
||||
case ERROR_IO_PENDING:
|
||||
// make signals working
|
||||
while (WaitForSingleObject(ovl.hEvent,50)==WAIT_TIMEOUT)
|
||||
// need to check for signals periodically
|
||||
for(;;)
|
||||
{
|
||||
if (windivert_recv_exit()) return false;
|
||||
twait = tmax>50 ? 50 : tmax;
|
||||
tmax -= twait;
|
||||
// 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 (!GetOverlappedResult(hFilter,&ovl,&rd,FALSE))
|
||||
{
|
||||
@@ -1675,9 +1700,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)
|
||||
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)
|
||||
{
|
||||
return windivert_recv_filter(w_filter,packet,len,wa,wa_count);
|
||||
return windivert_recv_filter(w_filter,packet,len,wa,wa_count,timer_callback,bt_prev);
|
||||
}
|
||||
|
||||
static bool windivert_send_filter(HANDLE hFilter, const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa)
|
||||
|
||||
+2
-1
@@ -135,7 +135,8 @@ bool logical_net_filter_present(void);
|
||||
bool logical_net_filter_match(void);
|
||||
bool nlm_list(bool bAll);
|
||||
bool windivert_init(const char *filter);
|
||||
bool windivert_recv(uint8_t *packet, size_t *len, WINDIVERT_ADDRESS *wa, unsigned int *wa_count);
|
||||
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_send(const uint8_t *packet, size_t len, const WINDIVERT_ADDRESS *wa);
|
||||
#else
|
||||
#define ensure_dir_access(dir) ensure_file_access(dir)
|
||||
|
||||
@@ -739,6 +739,14 @@ time_t boottime(void)
|
||||
struct timespec ts;
|
||||
return clock_gettime(CLOCK_BOOT_OR_UPTIME, &ts) ? 0 : ts.tv_sec;
|
||||
}
|
||||
uint64_t boottime_ms(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
if (clock_gettime(CLOCK_BOOT_OR_UPTIME, &ts))
|
||||
return 0;
|
||||
else
|
||||
return ts.tv_sec*1000ULL + ts.tv_nsec/1000000;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
|
||||
@@ -122,6 +122,7 @@ bool parse_int16(const char *p, int16_t *v);
|
||||
#endif
|
||||
|
||||
time_t boottime(void);
|
||||
uint64_t boottime_ms(void);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
uint32_t mask_from_bitcount(uint32_t zct);
|
||||
|
||||
+61
-1
@@ -3787,6 +3787,60 @@ static int luacall_timegm(lua_State *L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int luacall_timer_set(lua_State *L)
|
||||
{
|
||||
// timer_set(name, func, period, oneshot, data)
|
||||
lua_check_argc_range(L,"timer_set",3,5);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
int argc=lua_gettop(L);
|
||||
const char *name = luaL_checkstring(L,1);
|
||||
const char *func = luaL_checkstring(L,2);
|
||||
lua_Integer period = luaL_checkinteger(L,3);
|
||||
if (period<10) luaL_error(L,"invalid timer period. must be >=10 ms");
|
||||
bool oneshot = argc>=4 && lua_toboolean(L,4);
|
||||
|
||||
lua_getglobal(L, func);
|
||||
bool is_f = lua_isfunction(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (!is_f) luaL_error(L, "timer function '%s' does not exist", func);
|
||||
|
||||
timer_pool *timer = TimerPoolSearch(params.timers, name);
|
||||
if (timer) luaL_error(L,"timer '%s' already present", name);
|
||||
|
||||
timer = TimerPoolAdd(¶ms.timers, name, func, period, oneshot);
|
||||
if (!timer) luaL_error(L,"could not create timer");
|
||||
|
||||
if (argc>=5)
|
||||
{
|
||||
lua_pushvalue(L, 5);
|
||||
timer->lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
DLOG("timer: '%s' created. function '%s' period %llu oneshot %u\n", timer->str, timer->func, timer->period, timer->oneshot);
|
||||
|
||||
LUA_STACK_GUARD_RETURN(L,0)
|
||||
}
|
||||
static int luacall_timer_del(lua_State *L)
|
||||
{
|
||||
// timer_del(name)
|
||||
lua_check_argc(L,"timer_del",1);
|
||||
|
||||
LUA_STACK_GUARD_ENTER(L)
|
||||
|
||||
const char *name = luaL_checkstring(L,1);
|
||||
timer_pool *timer = TimerPoolSearch(params.timers, name);
|
||||
if (timer)
|
||||
{
|
||||
DLOG("timer: '%s' deleted\n", timer->str);
|
||||
TimerPoolDel(¶ms.timers, timer);
|
||||
}
|
||||
else
|
||||
DLOG("timer: '%s' not found\n", timer->str);
|
||||
lua_pushboolean(L, !!timer);
|
||||
LUA_STACK_GUARD_RETURN(L,1)
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
|
||||
void lua_cleanup(lua_State *L)
|
||||
@@ -3794,6 +3848,8 @@ void lua_cleanup(lua_State *L)
|
||||
lua_desync_ctx_destroy(L);
|
||||
// conntrack holds lua state. must clear it before lua shoudown
|
||||
ConntrackPoolDestroy(¶ms.conntrack);
|
||||
// timer can hold custom lua object
|
||||
TimerPoolDestroy(¶ms.timers);
|
||||
}
|
||||
|
||||
void lua_shutdown()
|
||||
@@ -4438,7 +4494,11 @@ static void lua_init_functions(void)
|
||||
{"localtime",luacall_localtime},
|
||||
{"gmtime",luacall_gmtime},
|
||||
{"timelocal",luacall_timelocal},
|
||||
{"timegm",luacall_timegm}
|
||||
{"timegm",luacall_timegm},
|
||||
|
||||
// timers
|
||||
{"timer_set",luacall_timer_set},
|
||||
{"timer_del",luacall_timer_del}
|
||||
};
|
||||
for(int i=0;i<(sizeof(lfunc)/sizeof(*lfunc));i++)
|
||||
lua_register(params.L,lfunc[i].name,lfunc[i].f);
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef LUAJIT
|
||||
#include "luajit.h"
|
||||
#include <luajit.h>
|
||||
#else
|
||||
#include <lua.h>
|
||||
#endif
|
||||
|
||||
+114
-18
@@ -11,6 +11,7 @@
|
||||
#include "ipset.h"
|
||||
#include "gzip.h"
|
||||
#include "pools.h"
|
||||
#include "timer.h"
|
||||
#include "lua.h"
|
||||
#include "crypto/aes.h"
|
||||
|
||||
@@ -239,6 +240,28 @@ static int write_pidfile(FILE **Fpid)
|
||||
return true;
|
||||
}
|
||||
|
||||
void NoInterceptLoop(void)
|
||||
{
|
||||
useconds_t usec = params.timer_res * 1000;
|
||||
|
||||
if (params.timers)
|
||||
{
|
||||
DLOG("processing timers\n");
|
||||
|
||||
while(params.timers)
|
||||
{
|
||||
if (bQuit) goto quit;
|
||||
usleep(usec);
|
||||
if (bQuit) goto quit;
|
||||
ReloadCheck();
|
||||
lua_do_gc();
|
||||
TimerPoolRun(¶ms.timers, 0);
|
||||
}
|
||||
}
|
||||
quit:
|
||||
DLOG_CONDUP("quit requested\n");
|
||||
}
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
@@ -417,6 +440,9 @@ static int nfq_main(void)
|
||||
FILE *Fpid = NULL;
|
||||
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;
|
||||
|
||||
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
|
||||
{
|
||||
@@ -454,6 +480,7 @@ static int nfq_main(void)
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
NoInterceptLoop();
|
||||
DLOG_CONDUP("no intercept quit\n");
|
||||
goto exok;
|
||||
}
|
||||
@@ -491,26 +518,58 @@ static int nfq_main(void)
|
||||
notify_ready();
|
||||
|
||||
fd = nfq_fd(h);
|
||||
bt_prev=0;
|
||||
do
|
||||
{
|
||||
if (bQuit) goto quit;
|
||||
while ((rd = recv(fd, buf, NFQ_MAX_RECV_SIZE, 0)) >= 0)
|
||||
for(;;)
|
||||
{
|
||||
if (!rd)
|
||||
FD_ZERO(&fdset);
|
||||
FD_SET(fd, &fdset);
|
||||
res = select(fd+1, &fdset, NULL, NULL, &tv);
|
||||
if (bQuit) goto quit;
|
||||
if (res == -1)
|
||||
{
|
||||
DLOG_ERR("recv from nfq returned 0 !\n");
|
||||
if (errno == EINTR) continue;
|
||||
DLOG_PERROR("select");
|
||||
goto err;
|
||||
}
|
||||
ReloadCheck();
|
||||
lua_do_gc();
|
||||
ReloadCheck();
|
||||
if (res)
|
||||
{
|
||||
rd = recv(fd, buf, NFQ_MAX_RECV_SIZE, 0);
|
||||
if (rd<0) break;
|
||||
if (!rd)
|
||||
{
|
||||
DLOG_ERR("recv from nfq returned 0 !\n");
|
||||
goto err;
|
||||
}
|
||||
#ifdef HAS_FILTER_SSID
|
||||
if (params.filter_ssid_present)
|
||||
if (!wlan_info_get_rate_limited())
|
||||
DLOG_ERR("cannot get wlan info\n");
|
||||
if (params.filter_ssid_present)
|
||||
if (!wlan_info_get_rate_limited())
|
||||
DLOG_ERR("cannot get wlan info\n");
|
||||
#endif
|
||||
int r = nfq_handle_packet(h, (char *)buf, (int)rd);
|
||||
if (r<0) DLOG_ERR("nfq_handle_packet result %d, errno %d : %s\n", r, errno, strerror(errno));
|
||||
if (bQuit) goto quit;
|
||||
res = nfq_handle_packet(h, (char *)buf, (int)rd);
|
||||
if (res<0) DLOG_ERR("nfq_handle_packet result %d, errno %d : %s\n", res, errno, strerror(errno));
|
||||
}
|
||||
|
||||
bt = boottime_ms();
|
||||
dbt = bt-bt_prev;
|
||||
if (dbt>=params.timer_res)
|
||||
{
|
||||
TimerPoolRun(¶ms.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 (errno==EINTR)
|
||||
continue;
|
||||
@@ -553,11 +612,13 @@ static int dvt_main(void)
|
||||
unsigned int id = 0;
|
||||
socklen_t socklen;
|
||||
ssize_t rd, wr;
|
||||
fd_set fdset;
|
||||
FILE *Fpid = NULL;
|
||||
struct sockaddr_in bp4;
|
||||
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;
|
||||
|
||||
if (*params.pidfile && !(Fpid = fopen(params.pidfile, "w")))
|
||||
{
|
||||
@@ -633,6 +694,7 @@ static int dvt_main(void)
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
NoInterceptLoop();
|
||||
DLOG("no intercept quit\n");
|
||||
goto exitok;
|
||||
}
|
||||
@@ -640,7 +702,7 @@ static int dvt_main(void)
|
||||
if (params.daemon) daemonize();
|
||||
if (!write_pidfile(&Fpid)) goto exiterr;
|
||||
|
||||
for (;;)
|
||||
for (bt_prev=0;;)
|
||||
{
|
||||
if (bQuit)
|
||||
{
|
||||
@@ -649,7 +711,7 @@ static int dvt_main(void)
|
||||
}
|
||||
FD_ZERO(&fdset);
|
||||
for (i = 0; i < fdct; i++) FD_SET(fd[i], &fdset);
|
||||
r = select(fdmax, &fdset, NULL, NULL, NULL);
|
||||
r = select(fdmax, &fdset, NULL, NULL, &tv);
|
||||
if (bQuit)
|
||||
{
|
||||
DLOG_CONDUP("quit requested\n");
|
||||
@@ -661,6 +723,8 @@ static int dvt_main(void)
|
||||
DLOG_PERROR("select");
|
||||
goto exiterr;
|
||||
}
|
||||
ReloadCheck();
|
||||
lua_do_gc();
|
||||
for (i = 0; i < fdct; i++)
|
||||
{
|
||||
if (FD_ISSET(fd[i], &fdset))
|
||||
@@ -680,9 +744,6 @@ static int dvt_main(void)
|
||||
size_t modlen, len = rd;
|
||||
const char *ifin, *ifout;
|
||||
|
||||
ReloadCheck();
|
||||
lua_do_gc();
|
||||
|
||||
// in any BSD addr of incoming packet is set to the first addr of the interface. addr of outgoing packet is set to zero
|
||||
bool bIncoming = sa_has_addr((struct sockaddr*)&sa_from);
|
||||
ifin = bIncoming ? "unknown" : "";
|
||||
@@ -734,6 +795,22 @@ static int dvt_main(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
bt = boottime_ms();
|
||||
dbt = bt-bt_prev;
|
||||
if (dbt>=params.timer_res)
|
||||
{
|
||||
TimerPoolRun(¶ms.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);
|
||||
}
|
||||
}
|
||||
|
||||
exitok:
|
||||
@@ -754,7 +831,12 @@ 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 int win_main()
|
||||
static void win_timer_callback(uint64_t bt)
|
||||
{
|
||||
TimerPoolRun(¶ms.timers, bt);
|
||||
}
|
||||
|
||||
static int win_main(void)
|
||||
{
|
||||
size_t len, packet_len, left, modlen;
|
||||
unsigned int id;
|
||||
@@ -766,6 +848,7 @@ static int win_main()
|
||||
WINDIVERT_ADDRESS wa[WINDIVERT_BULK_MAX];
|
||||
uint8_t *packets = NULL, *packet, *mod=NULL;
|
||||
unsigned int n,wa_count;
|
||||
uint64_t bt_prev = 0;
|
||||
|
||||
// windows emulated fork logic does not cover objects outside of cygwin world. have to daemonize before inits
|
||||
if (params.daemon) daemonize();
|
||||
@@ -830,6 +913,7 @@ static int win_main()
|
||||
|
||||
if (!params.intercept)
|
||||
{
|
||||
NoInterceptLoop();
|
||||
DLOG("no intercept quit\n");
|
||||
goto ex;
|
||||
}
|
||||
@@ -838,7 +922,7 @@ static int win_main()
|
||||
{
|
||||
len = WINDIVERT_PACKET_BUF_SIZE;
|
||||
wa_count = WINDIVERT_BULK_MAX;
|
||||
if (!windivert_recv(packets, &len, wa, &wa_count))
|
||||
if (!windivert_recv(packets, &len, wa, &wa_count, win_timer_callback, &bt_prev))
|
||||
{
|
||||
if (errno == ENOBUFS)
|
||||
{
|
||||
@@ -1743,6 +1827,7 @@ 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"
|
||||
@@ -1818,6 +1903,7 @@ 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,
|
||||
@@ -1900,6 +1986,7 @@ enum opt_indices {
|
||||
IDX_IPCACHE_LIFETIME,
|
||||
IDX_IPCACHE_HOSTNAME,
|
||||
IDX_REASM_DISABLE,
|
||||
IDX_TIMER_RES,
|
||||
#ifdef __linux__
|
||||
IDX_FWMARK,
|
||||
#elif defined(SO_USER_COOKIE)
|
||||
@@ -2005,6 +2092,7 @@ 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)
|
||||
@@ -2407,6 +2495,14 @@ 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)
|
||||
|
||||
@@ -559,6 +559,7 @@ void cleanup_params(struct params_s *params)
|
||||
ipcacheDestroy(¶ms->ipcache);
|
||||
blob_collection_destroy(¶ms->blobs);
|
||||
strlist_destroy(¶ms->lua_init_scripts);
|
||||
TimerPoolDestroy(¶ms->timers);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
strlist_destroy(¶ms->ssid_filter);
|
||||
@@ -587,6 +588,7 @@ 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(¶ms->hostlists);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "protocol.h"
|
||||
#include "helpers.h"
|
||||
#include "sec.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/types.h>
|
||||
@@ -36,6 +37,8 @@
|
||||
|
||||
#define IPCACHE_LIFETIME 7200
|
||||
|
||||
#define TIMER_RES_DEFAULT 50
|
||||
|
||||
#define MAX_GIDS 64
|
||||
|
||||
#define MAX_BLOB_SIZE (16*1024)
|
||||
@@ -192,6 +195,9 @@ struct params_s
|
||||
bool writeable_dir_enable;
|
||||
char writeable_dir[PATH_MAX];
|
||||
|
||||
int timer_res; // timer resolution in msec
|
||||
timer_pool *timers;
|
||||
|
||||
int lua_gc;
|
||||
int ref_desync_ctx; // desync ctx userdata registry ref
|
||||
lua_State *L;
|
||||
|
||||
@@ -5,33 +5,6 @@
|
||||
#include <stdio.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#define DESTROY_STR_POOL(etype, ppool) \
|
||||
etype *elem, *tmp; \
|
||||
HASH_ITER(hh, *ppool, elem, tmp) { \
|
||||
free(elem->str); \
|
||||
HASH_DEL(*ppool, elem); \
|
||||
free(elem); \
|
||||
}
|
||||
|
||||
#define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \
|
||||
etype *elem; \
|
||||
if (!(elem = (etype*)malloc(sizeof(etype)))) \
|
||||
return false; \
|
||||
if (!(elem->str = malloc(keystr_len + 1))) \
|
||||
{ \
|
||||
free(elem); \
|
||||
return false; \
|
||||
} \
|
||||
memcpy(elem->str, keystr, keystr_len); \
|
||||
elem->str[keystr_len] = 0; \
|
||||
oom = false; \
|
||||
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
|
||||
if (oom) \
|
||||
{ \
|
||||
free(elem->str); \
|
||||
free(elem); \
|
||||
return false; \
|
||||
}
|
||||
#define ADD_HOSTLIST_POOL(etype, ppool, keystr, keystr_len, flg) \
|
||||
etype *elem_find; \
|
||||
HASH_FIND(hh, *ppool, keystr, keystr_len, elem_find); \
|
||||
|
||||
@@ -27,6 +27,34 @@
|
||||
else \
|
||||
LIST_INSERT_HEAD(head, elm, field); }
|
||||
|
||||
#define DESTROY_STR_POOL(etype, ppool) \
|
||||
etype *elem, *tmp; \
|
||||
HASH_ITER(hh, *ppool, elem, tmp) { \
|
||||
free(elem->str); \
|
||||
HASH_DEL(*ppool, elem); \
|
||||
free(elem); \
|
||||
}
|
||||
|
||||
#define ADD_STR_POOL(etype, ppool, keystr, keystr_len) \
|
||||
etype *elem; \
|
||||
if (!(elem = (etype*)malloc(sizeof(etype)))) \
|
||||
return false; \
|
||||
if (!(elem->str = malloc(keystr_len + 1))) \
|
||||
{ \
|
||||
free(elem); \
|
||||
return NULL; \
|
||||
} \
|
||||
memcpy(elem->str, keystr, keystr_len); \
|
||||
elem->str[keystr_len] = 0; \
|
||||
oom = false; \
|
||||
HASH_ADD_KEYPTR(hh, *ppool, elem->str, keystr_len, elem); \
|
||||
if (oom) \
|
||||
{ \
|
||||
free(elem->str); \
|
||||
free(elem); \
|
||||
return NULL; \
|
||||
}
|
||||
|
||||
|
||||
typedef struct hostlist_pool {
|
||||
char *str; /* key */
|
||||
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
#include "timer.h"
|
||||
#include "params.h"
|
||||
#include "helpers.h"
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
#undef uthash_nonfatal_oom
|
||||
#define uthash_nonfatal_oom(elt) ut_oom_recover(elt)
|
||||
|
||||
static bool oom = false;
|
||||
static void ut_oom_recover(void *elem)
|
||||
{
|
||||
oom = true;
|
||||
}
|
||||
|
||||
static unsigned int timer_n=0;
|
||||
|
||||
|
||||
static void TimerPoolDestroyItem(timer_pool *elem)
|
||||
{
|
||||
free(elem->str);
|
||||
free(elem->func);
|
||||
luaL_unref(params.L, LUA_REGISTRYINDEX, elem->lua_ref);
|
||||
}
|
||||
void TimerPoolDel(timer_pool **pp, timer_pool *p)
|
||||
{
|
||||
TimerPoolDestroyItem(p);
|
||||
HASH_DEL(*pp,p);
|
||||
free(p);
|
||||
}
|
||||
void TimerPoolDestroy(timer_pool **pp)
|
||||
{
|
||||
timer_pool *elem, *tmp;
|
||||
HASH_ITER(hh, *pp, elem, tmp) TimerPoolDel(pp,elem);
|
||||
}
|
||||
struct timer_pool *TimerPoolSearch(timer_pool *p, const char *str)
|
||||
{
|
||||
timer_pool *elem_find;
|
||||
HASH_FIND_STR(p, str, elem_find);
|
||||
return elem_find;
|
||||
}
|
||||
struct timer_pool *TimerPoolAdd(timer_pool **pp, const char *str, const char *func, uint64_t period, bool oneshot)
|
||||
{
|
||||
ADD_STR_POOL(timer_pool, pp, str, strlen(str))
|
||||
if (!(elem->func = strdup(func)))
|
||||
{
|
||||
TimerPoolDel(pp,elem);
|
||||
return NULL;
|
||||
}
|
||||
elem->period = period;
|
||||
elem->oneshot = oneshot;
|
||||
elem->lua_ref = LUA_NOREF;
|
||||
elem->bt_prev = boottime_ms();
|
||||
elem->n = ++timer_n;
|
||||
return elem;
|
||||
}
|
||||
|
||||
static bool TimerPoolRunTimer(timer_pool *p)
|
||||
{
|
||||
lua_getglobal(params.L, p->func);
|
||||
if (!lua_isfunction(params.L, -1))
|
||||
{
|
||||
lua_pop(params.L, 1);
|
||||
DLOG_ERR("timer: '%s' function '%s' does not exist\n",p->str,p->func);
|
||||
return false;
|
||||
}
|
||||
lua_pushstring(params.L, p->str);
|
||||
lua_rawgeti(params.L, LUA_REGISTRYINDEX, p->lua_ref);
|
||||
DLOG("\ntimer: '%s' function '%s' period %llu oneshot %u\n",p->str,p->func,p->period,p->oneshot);
|
||||
int status = lua_pcall(params.L, 2, 0, 0);
|
||||
if (status)
|
||||
{
|
||||
lua_dlog_error();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void TimerPoolRun(timer_pool **pp, uint64_t bt)
|
||||
{
|
||||
if (!pp) return; // no timers
|
||||
|
||||
if (!bt) bt = boottime_ms();
|
||||
|
||||
timer_pool *elem, *tmp, *p;
|
||||
char *name;
|
||||
const char *del;
|
||||
unsigned int n;
|
||||
HASH_ITER(hh, *pp, elem, tmp)
|
||||
{
|
||||
if (bt >= (elem->bt_prev + elem->period))
|
||||
{
|
||||
if (!(name = strdup(elem->str)))
|
||||
return;
|
||||
n = elem->n;
|
||||
|
||||
del = NULL;
|
||||
if (!TimerPoolRunTimer(elem))
|
||||
del = "timer: '%s' deleted because of error\n";
|
||||
else if (elem->oneshot)
|
||||
del = "timer: '%s' deleted because of oneshot\n";
|
||||
if (del)
|
||||
{
|
||||
// timer function could delete the timer itself or recreate with the same name
|
||||
p = TimerPoolSearch(*pp, name);
|
||||
if (p==elem && p->n==n)
|
||||
{
|
||||
DLOG(del,name);
|
||||
TimerPoolDel(pp, elem);
|
||||
}
|
||||
}
|
||||
else
|
||||
elem->bt_prev = bt;
|
||||
|
||||
free(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "pools.h"
|
||||
|
||||
typedef struct timer_pool {
|
||||
char *str; /* key */
|
||||
char *func;
|
||||
uint64_t period;
|
||||
bool oneshot;
|
||||
int lua_ref;
|
||||
uint64_t bt_prev;
|
||||
unsigned int n;
|
||||
UT_hash_handle hh; /* makes this structure hashable */
|
||||
} timer_pool;
|
||||
|
||||
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);
|
||||
Reference in New Issue
Block a user