aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkorgoth1 <vladislav.stakhov@gmail.com>2019-09-16 23:21:58 +0300
committerkorgoth1 <vladislav.stakhov@gmail.com>2019-09-16 23:21:58 +0300
commitf637f261d5a0b58e262e1a508a4e98cc2ddf0f5a (patch)
treeb2cdbcb2b0cfe08ef8451430a58676b255468c16
parente7722d808a0c5b9f58d7878cc59569e124e604d8 (diff)
parentd4be8b2d633c57f8f3695dbe4ce9e3407bc1046b (diff)
downloadrspamd-f637f261d5a0b58e262e1a508a4e98cc2ddf0f5a.tar.gz
rspamd-f637f261d5a0b58e262e1a508a4e98cc2ddf0f5a.zip
[Test] MAGIC ROBOT
-rw-r--r--contrib/libucl/lua_ucl.c6
-rw-r--r--src/controller.c2
-rw-r--r--src/fuzzy_storage.c21
-rw-r--r--src/libserver/rspamd_control.c91
-rw-r--r--src/libserver/rspamd_control.h22
-rw-r--r--src/libserver/worker_util.c7
-rw-r--r--src/lua/lua_cdb.c14
-rw-r--r--src/lua/lua_common.c120
-rw-r--r--src/lua/lua_common.h31
-rw-r--r--src/lua/lua_cryptobox.c50
-rw-r--r--src/lua/lua_dns_resolver.c15
-rw-r--r--src/lua/lua_expression.c14
-rw-r--r--src/lua/lua_ip.c14
-rw-r--r--src/lua/lua_logger.c53
-rw-r--r--src/lua/lua_mempool.c14
-rw-r--r--src/lua/lua_redis.c12
-rw-r--r--src/lua/lua_regexp.c14
-rw-r--r--src/lua/lua_rsa.c36
-rw-r--r--src/lua/lua_sqlite3.c22
-rw-r--r--src/lua/lua_trie.c14
-rw-r--r--src/lua/lua_upstream.c28
-rw-r--r--src/lua/lua_worker.c142
-rw-r--r--src/plugins/lua/reputation.lua2
-rw-r--r--src/rspamd.c44
24 files changed, 472 insertions, 316 deletions
diff --git a/contrib/libucl/lua_ucl.c b/contrib/libucl/lua_ucl.c
index 049b1d08c..d240d12e0 100644
--- a/contrib/libucl/lua_ucl.c
+++ b/contrib/libucl/lua_ucl.c
@@ -807,8 +807,8 @@ struct _rspamd_lua_text {
/***
* @method parser:parse_text(input)
- * Parse UCL object from file.
- * @param {string} input string to parse
+ * Parse UCL object from text object (Rspamd specific).
+ * @param {rspamd_text} input text to parse
* @return {bool[, string]} if res is `true` then file has been parsed successfully, otherwise an error string is also returned
*/
static int
@@ -820,7 +820,7 @@ lua_ucl_parser_parse_text (lua_State *L)
int ret = 2;
parser = lua_ucl_parser_get (L, 1);
- t = luaL_checkudata (L, 2, "rspamd{text}");
+ t = lua_touserdata (L, 2);
if (lua_type (L, 3) == LUA_TSTRING) {
type = lua_ucl_str_to_parse_type (lua_tostring (L, 3));
diff --git a/src/controller.c b/src/controller.c
index 450c730dc..2f76bcc69 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -3471,7 +3471,7 @@ luaopen_controller (lua_State * L)
struct rspamd_http_connection_entry *
lua_check_controller_entry (lua_State * L, gint pos)
{
- void *ud = luaL_checkudata (L, pos, "rspamd{csession}");
+ void *ud = rspamd_lua_check_udata (L, pos, "rspamd{csession}");
luaL_argcheck (L, ud != NULL, pos, "'csession' expected");
return ud ? *((struct rspamd_http_connection_entry **)ud) : NULL;
}
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index 7913c56b9..257c9893b 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -141,7 +141,6 @@ struct rspamd_fuzzy_storage_ctx {
gdouble expire;
gdouble sync_timeout;
struct rspamd_radix_map_helper *update_ips;
- struct rspamd_radix_map_helper *master_ips;
struct rspamd_radix_map_helper *blocked_ips;
struct rspamd_radix_map_helper *ratelimit_whitelist;
@@ -152,7 +151,6 @@ struct rspamd_fuzzy_storage_ctx {
guint keypair_cache_size;
ev_timer stat_ev;
ev_io peer_ev;
- ev_tstamp stat_timeout;
/* Local keypair */
struct rspamd_cryptobox_keypair *default_keypair; /* Bad clash, need for parse keypair */
@@ -161,6 +159,7 @@ struct rspamd_fuzzy_storage_ctx {
gboolean encrypted_only;
gboolean read_only;
struct rspamd_keypair_cache *keypair_cache;
+ struct rspamd_http_context *http_ctx;
rspamd_lru_hash_t *errors_ips;
rspamd_lru_hash_t *ratelimit_buckets;
struct rspamd_fuzzy_backend *backend;
@@ -825,7 +824,7 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session)
if (G_UNLIKELY (cmd == NULL || up_len == 0)) {
result.v1.value = 500;
- result.v1.prob = 0.0;
+ result.v1.prob = 0.0f;
rspamd_fuzzy_make_reply (cmd, &result, session, encrypted, is_shingle);
return;
}
@@ -833,7 +832,7 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session)
if (session->ctx->encrypted_only && !encrypted) {
/* Do not accept unencrypted commands */
result.v1.value = 403;
- result.v1.prob = 0.0;
+ result.v1.prob = 0.0f;
rspamd_fuzzy_make_reply (cmd, &result, session, encrypted, is_shingle);
return;
}
@@ -860,13 +859,13 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session)
}
else {
result.v1.value = 403;
- result.v1.prob = 0.0;
+ result.v1.prob = 0.0f;
result.v1.flag = 0;
rspamd_fuzzy_make_reply (cmd, &result, session, encrypted, is_shingle);
}
}
else if (cmd->cmd == FUZZY_STAT) {
- result.v1.prob = 1.0;
+ result.v1.prob = 1.0f;
result.v1.value = 0;
result.v1.flag = session->ctx->stat.fuzzy_hashes;
rspamd_fuzzy_make_reply (cmd, &result, session, encrypted, is_shingle);
@@ -881,7 +880,7 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session)
if (rspamd_match_hash_map (session->ctx->skip_hashes, hexbuf)) {
result.v1.value = 401;
- result.v1.prob = 0.0;
+ result.v1.prob = 0.0f;
goto reply;
}
@@ -911,11 +910,11 @@ rspamd_fuzzy_process_command (struct fuzzy_session *session)
}
result.v1.value = 0;
- result.v1.prob = 1.0;
+ result.v1.prob = 1.0f;
}
else {
result.v1.value = 403;
- result.v1.prob = 0.0;
+ result.v1.prob = 0.0f;
}
reply:
rspamd_fuzzy_make_reply (cmd, &result, session, encrypted, is_shingle);
@@ -1880,6 +1879,10 @@ start_fuzzy (struct rspamd_worker *worker)
worker->srv->cfg);
rspamd_upstreams_library_config (worker->srv->cfg, ctx->cfg->ups_ctx,
ctx->event_loop, ctx->resolver->r);
+ /* Since this worker uses maps it needs a valid HTTP context */
+ ctx->http_ctx = rspamd_http_context_create (ctx->cfg, ctx->event_loop,
+ ctx->cfg->ups_ctx);
+
if (ctx->keypair_cache_size > 0) {
/* Create keypairs cache */
ctx->keypair_cache = rspamd_keypair_cache_new (ctx->keypair_cache_size);
diff --git a/src/libserver/rspamd_control.c b/src/libserver/rspamd_control.c
index 2ebdbc4d6..699317ff5 100644
--- a/src/libserver/rspamd_control.c
+++ b/src/libserver/rspamd_control.c
@@ -36,7 +36,8 @@ struct rspamd_control_reply_elt {
struct rspamd_control_reply reply;
struct rspamd_io_ev ev;
struct ev_loop *event_loop;
- struct rspamd_worker *wrk;
+ GQuark wrk_type;
+ pid_t wrk_pid;
gpointer ud;
gint attached_fd;
struct rspamd_control_reply_elt *prev, *next;
@@ -102,6 +103,8 @@ static const struct rspamd_control_cmd_match {
},
};
+static void rspamd_control_ignore_io_handler (int fd, short what, void *ud);
+
void
rspamd_control_send_error (struct rspamd_control_session *session,
gint code, const gchar *error_msg, ...)
@@ -193,15 +196,15 @@ rspamd_control_write_reply (struct rspamd_control_session *session)
/* Skip incompatible worker for fuzzy_stat */
if ((session->cmd.type == RSPAMD_CONTROL_FUZZY_STAT ||
session->cmd.type == RSPAMD_CONTROL_FUZZY_SYNC) &&
- elt->wrk->type != g_quark_from_static_string ("fuzzy")) {
+ elt->wrk_type != g_quark_from_static_string ("fuzzy")) {
continue;
}
- rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%P", elt->wrk->pid);
+ rspamd_snprintf (tmpbuf, sizeof (tmpbuf), "%P", elt->wrk_pid);
cur = ucl_object_typed_new (UCL_OBJECT);
ucl_object_insert_key (cur, ucl_object_fromstring (g_quark_to_string (
- elt->wrk->type)), "type", 0, false);
+ elt->wrk_type)), "type", 0, false);
switch (session->cmd.type) {
case RSPAMD_CONTROL_STAT:
@@ -340,7 +343,7 @@ rspamd_control_wrk_io (gint fd, short what, gpointer ud)
r = recvmsg (fd, &msg, 0);
if (r == -1) {
msg_err ("cannot read reply from the worker %P (%s): %s",
- elt->wrk->pid, g_quark_to_string (elt->wrk->type),
+ elt->wrk_pid, g_quark_to_string (elt->wrk_type),
strerror (errno));
}
else if (r >= (gssize)sizeof (elt->reply)) {
@@ -352,7 +355,7 @@ rspamd_control_wrk_io (gint fd, short what, gpointer ud)
else {
/* Timeout waiting */
msg_warn ("timeout waiting reply from %P (%s)",
- elt->wrk->pid, g_quark_to_string (elt->wrk->type));
+ elt->wrk_pid, g_quark_to_string (elt->wrk_type));
}
session->replies_remain --;
@@ -384,9 +387,11 @@ rspamd_control_error_handler (struct rspamd_http_connection *conn, GError *err)
static struct rspamd_control_reply_elt *
rspamd_control_broadcast_cmd (struct rspamd_main *rspamd_main,
- struct rspamd_control_command *cmd,
- gint attached_fd,
- void (*handler) (int, short, void *), gpointer ud)
+ struct rspamd_control_command *cmd,
+ gint attached_fd,
+ rspamd_ev_cb handler,
+ gpointer ud,
+ pid_t except_pid)
{
GHashTableIter it;
struct rspamd_worker *wrk;
@@ -407,6 +412,10 @@ rspamd_control_broadcast_cmd (struct rspamd_main *rspamd_main,
continue;
}
+ if (except_pid != 0 && wrk->pid == except_pid) {
+ continue;
+ }
+
memset (&msg, 0, sizeof (msg));
/* Attach fd to the message */
@@ -430,7 +439,8 @@ rspamd_control_broadcast_cmd (struct rspamd_main *rspamd_main,
if (r == sizeof (*cmd)) {
rep_elt = g_malloc0 (sizeof (*rep_elt));
- rep_elt->wrk = wrk;
+ rep_elt->wrk_pid = wrk->pid;
+ rep_elt->wrk_type = wrk->type;
rep_elt->event_loop = rspamd_main->event_loop;
rep_elt->ud = ud;
rspamd_ev_watcher_init (&rep_elt->ev,
@@ -455,6 +465,15 @@ rspamd_control_broadcast_cmd (struct rspamd_main *rspamd_main,
return res;
}
+void
+rspamd_control_broadcast_srv_cmd (struct rspamd_main *rspamd_main,
+ struct rspamd_control_command *cmd,
+ pid_t except_pid)
+{
+ rspamd_control_broadcast_cmd (rspamd_main, cmd, -1,
+ rspamd_control_ignore_io_handler, NULL, except_pid);
+}
+
static gint
rspamd_control_finish_handler (struct rspamd_http_connection *conn,
struct rspamd_http_message *msg)
@@ -493,7 +512,7 @@ rspamd_control_finish_handler (struct rspamd_http_connection *conn,
/* Send command to all workers */
session->replies = rspamd_control_broadcast_cmd (
session->rspamd_main, &session->cmd, -1,
- rspamd_control_wrk_io, session);
+ rspamd_control_wrk_io, session, 0);
DL_FOREACH (session->replies, cur) {
session->replies_remain ++;
@@ -676,8 +695,8 @@ rspamd_control_default_worker_handler (EV_P_ ev_io *w, int revents)
}
void
-rspamd_control_worker_add_default_handler (struct rspamd_worker *worker,
- struct ev_loop *ev_base)
+rspamd_control_worker_add_default_cmd_handlers (struct rspamd_worker *worker,
+ struct ev_loop *ev_base)
{
struct rspamd_worker_control_data *cd;
@@ -887,7 +906,7 @@ rspamd_srv_handler (EV_P_ ev_io *w, int revents)
sizeof (wcmd.cmd.hs_loaded.cache_dir));
wcmd.cmd.hs_loaded.forced = cmd.cmd.hs_loaded.forced;
rspamd_control_broadcast_cmd (srv, &wcmd, rfd,
- rspamd_control_ignore_io_handler, NULL);
+ rspamd_control_ignore_io_handler, NULL, worker->pid);
break;
case RSPAMD_SRV_MONITORED_CHANGE:
/* Broadcast command to all workers */
@@ -899,14 +918,14 @@ rspamd_srv_handler (EV_P_ ev_io *w, int revents)
wcmd.cmd.monitored_change.alive = cmd.cmd.monitored_change.alive;
wcmd.cmd.monitored_change.sender = cmd.cmd.monitored_change.sender;
rspamd_control_broadcast_cmd (srv, &wcmd, rfd,
- rspamd_control_ignore_io_handler, NULL);
+ rspamd_control_ignore_io_handler, NULL, 0);
break;
case RSPAMD_SRV_LOG_PIPE:
memset (&wcmd, 0, sizeof (wcmd));
wcmd.type = RSPAMD_CONTROL_LOG_PIPE;
wcmd.cmd.log_pipe.type = cmd.cmd.log_pipe.type;
rspamd_control_broadcast_cmd (srv, &wcmd, rfd,
- rspamd_control_log_pipe_io_handler, NULL);
+ rspamd_control_log_pipe_io_handler, NULL, 0);
break;
case RSPAMD_SRV_ON_FORK:
rdata->rep.reply.on_fork.status = 0;
@@ -1108,3 +1127,43 @@ rspamd_srv_send_command (struct rspamd_worker *worker,
rd->worker->srv_pipe[1], EV_WRITE);
ev_io_start (ev_base, &rd->io_ev);
}
+
+enum rspamd_control_type
+rspamd_control_command_from_string (const gchar *str)
+{
+ enum rspamd_control_type ret = RSPAMD_CONTROL_MAX;
+
+ if (!str) {
+ return ret;
+ }
+
+ if (g_ascii_strcasecmp (str, "hyperscan_loaded") == 0) {
+ ret = RSPAMD_CONTROL_HYPERSCAN_LOADED;
+ }
+ else if (g_ascii_strcasecmp (str, "stat") == 0) {
+ ret = RSPAMD_CONTROL_STAT;
+ }
+ else if (g_ascii_strcasecmp (str, "reload") == 0) {
+ ret = RSPAMD_CONTROL_RELOAD;
+ }
+ else if (g_ascii_strcasecmp (str, "reresolve") == 0) {
+ ret = RSPAMD_CONTROL_RERESOLVE;
+ }
+ else if (g_ascii_strcasecmp (str, "recompile") == 0) {
+ ret = RSPAMD_CONTROL_RECOMPILE;
+ }
+ else if (g_ascii_strcasecmp (str, "log_pipe") == 0) {
+ ret = RSPAMD_CONTROL_LOG_PIPE;
+ }
+ else if (g_ascii_strcasecmp (str, "fuzzy_stat") == 0) {
+ ret = RSPAMD_CONTROL_FUZZY_STAT;
+ }
+ else if (g_ascii_strcasecmp (str, "fuzzy_sync") == 0) {
+ ret = RSPAMD_CONTROL_FUZZY_SYNC;
+ }
+ else if (g_ascii_strcasecmp (str, "monitored_change") == 0) {
+ ret = RSPAMD_CONTROL_MONITORED_CHANGE;
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/src/libserver/rspamd_control.h b/src/libserver/rspamd_control.h
index 87e5e3186..b04fca09d 100644
--- a/src/libserver/rspamd_control.h
+++ b/src/libserver/rspamd_control.h
@@ -210,8 +210,8 @@ void rspamd_control_process_client_socket (struct rspamd_main *rspamd_main,
/**
* Register default handlers for a worker
*/
-void rspamd_control_worker_add_default_handler (struct rspamd_worker *worker,
- struct ev_loop *ev_base);
+void rspamd_control_worker_add_default_cmd_handlers (struct rspamd_worker *worker,
+ struct ev_loop *ev_base);
/**
* Register custom handler for a specific control command for this worker
@@ -240,6 +240,24 @@ void rspamd_srv_send_command (struct rspamd_worker *worker,
rspamd_srv_reply_handler handler,
gpointer ud);
+/**
+ * Broadcast srv cmd from rspamd_main to workers
+ * @param rspamd_main
+ * @param cmd
+ * @param except_pid
+ */
+void
+rspamd_control_broadcast_srv_cmd (struct rspamd_main *rspamd_main,
+ struct rspamd_control_command *cmd,
+ pid_t except_pid);
+
+/**
+ * Returns command from a specified string (case insensitive)
+ * @param str
+ * @return
+ */
+enum rspamd_control_type rspamd_control_command_from_string (const gchar *str);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/libserver/worker_util.c b/src/libserver/worker_util.c
index 56fdd70c1..58d75da5d 100644
--- a/src/libserver/worker_util.c
+++ b/src/libserver/worker_util.c
@@ -365,7 +365,7 @@ rspamd_prepare_worker (struct rspamd_worker *worker, const char *name,
worker->srv->event_loop = event_loop;
rspamd_worker_init_signals (worker, event_loop);
- rspamd_control_worker_add_default_handler (worker, event_loop);
+ rspamd_control_worker_add_default_cmd_handlers (worker, event_loop);
rspamd_worker_heartbeat_start (worker, event_loop);
#ifdef WITH_HIREDIS
rspamd_redis_pool_config (worker->srv->cfg->redis_pool,
@@ -722,7 +722,10 @@ rspamd_main_heartbeat_cb (EV_P_ ev_timer *w, int revents)
time_from_last -= wrk->hb.last_event;
rspamd_main = wrk->srv;
- if (time_from_last > 0 && time_from_last > rspamd_main->cfg->heartbeat_interval) {
+ if (wrk->hb.last_event > 0 &&
+ time_from_last > 0 &&
+ time_from_last >= rspamd_main->cfg->heartbeat_interval * 2) {
+
rspamd_localtime (wrk->hb.last_event, &tm);
r = strftime (timebuf, sizeof (timebuf), "%F %H:%M:%S", &tm);
rspamd_snprintf (usec_buf, sizeof (usec_buf), "%.5f",
diff --git a/src/lua/lua_cdb.c b/src/lua/lua_cdb.c
index 5d4c499a7..1f9b48260 100644
--- a/src/lua/lua_cdb.c
+++ b/src/lua/lua_cdb.c
@@ -151,17 +151,7 @@ lua_load_cdb (lua_State *L)
void
luaopen_cdb (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{cdb}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cdb}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cdblib_m);
- lua_pop (L, 1); /* remove metatable from stack */
-
+ rspamd_lua_new_class (L, "rspamd{cdb}", cdblib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cdb", lua_load_cdb);
}
diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c
index 5de0fa9ce..bfd572532 100644
--- a/src/lua/lua_common.c
+++ b/src/lua/lua_common.c
@@ -45,6 +45,25 @@ lua_error_quark (void)
return g_quark_from_static_string ("lua-routines");
}
+/* idea from daurnimator */
+#if defined(WITH_LUAJIT) && (defined(_LP64) || defined(_LLP64) || defined(__arch64__) || defined (__arm64__) || defined (__aarch64__) || defined(_WIN64))
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 1
+#else
+#define RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK 0
+#endif
+
+#if RSPAMD_USE_47BIT_LIGHTUSERDATA_HACK
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)((uintptr_t)(p) & ((1UL<<47)-1)))
+#else
+#define RSPAMD_LIGHTUSERDATA_MASK(p) ((void *)(p))
+#endif
+
+/*
+ * Used to map string to a pointer
+ */
+KHASH_INIT (lua_class_set, const gchar *, bool, 0, rspamd_str_hash, rspamd_str_equal);
+khash_t (lua_class_set) *lua_classes = NULL;
+
/* Util functions */
/**
* Create new class and store metatable on top of the stack (must be popped if not needed)
@@ -57,33 +76,48 @@ rspamd_lua_new_class (lua_State * L,
const gchar *classname,
const struct luaL_reg *methods)
{
- luaL_newmetatable (L, classname); /* mt */
+ void *class_ptr;
+ khiter_t k;
+ gint r, nmethods = 0;
+
+ if (lua_classes == NULL) {
+ lua_classes = kh_init (lua_class_set);
+ }
+
+ k = kh_put (lua_class_set, lua_classes, classname, &r);
+ class_ptr = RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k));
+
+ if (methods) {
+ for (;;) {
+ if (methods[nmethods].name != NULL) {
+ nmethods ++;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ lua_createtable (L, 0, 3 + nmethods);
lua_pushstring (L, "__index");
lua_pushvalue (L, -2); /* pushes the metatable */
lua_settable (L, -3); /* metatable.__index = metatable */
- lua_pushstring (L, "class"); /* mt,"class" */
- lua_pushstring (L, classname); /* mt,"class",classname */
- lua_rawset (L, -3); /* mt */
+ lua_pushstring (L, "class");
+ lua_pushstring (L, classname);
+ lua_rawset (L, -3);
+
+ lua_pushstring (L, "class_ptr");
+ lua_pushlightuserdata (L, class_ptr);
+ lua_rawset (L, -3);
if (methods) {
luaL_register (L, NULL, methods); /* pushes all methods as MT fields */
}
- /* MT is left on stack ! */
-}
-/**
- * Create and register new class with static methods and store metatable on top of the stack
- */
-void
-rspamd_lua_new_class_full (lua_State *L,
- const gchar *classname,
- const gchar *static_name,
- const struct luaL_reg *methods,
- const struct luaL_reg *func)
-{
- rspamd_lua_new_class (L, classname, methods);
- luaL_register (L, static_name, func);
+ lua_pushvalue (L, -1); /* Preserves metatable */
+ lua_rawsetp (L, LUA_REGISTRYINDEX, class_ptr);
+ /* MT is left on stack ! */
}
static const gchar *
@@ -97,14 +131,7 @@ rspamd_lua_class_tostring_buf (lua_State *L, gboolean print_pointer, gint pos)
goto err;
}
- lua_pushstring (L, "__index");
- lua_gettable (L, -2);
pop ++;
-
- if (!lua_istable (L, -1)) {
- goto err;
- }
-
lua_pushstring (L, "class");
lua_gettable (L, -2);
pop ++;
@@ -150,7 +177,14 @@ rspamd_lua_class_tostring (lua_State * L)
void
rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
{
- luaL_getmetatable (L, classname);
+ khiter_t k;
+
+ k = kh_get (lua_class_set, lua_classes, classname);
+
+ g_assert (k != kh_end (lua_classes));
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
+
if (objidx < 0) {
objidx--;
}
@@ -161,7 +195,6 @@ rspamd_lua_setclass (lua_State * L, const gchar *classname, gint objidx)
void
rspamd_lua_table_set (lua_State * L, const gchar *index, const gchar *value)
{
-
lua_pushstring (L, index);
if (value) {
lua_pushstring (L, value);
@@ -929,16 +962,10 @@ rspamd_lua_init (bool wipe_mem)
lua_settop (L, 0);
#endif
- luaL_newmetatable (L, "rspamd{ev_base}");
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{ev_base}");
- lua_rawset (L, -3);
+ rspamd_lua_new_class (L, "rspamd{ev_base}", NULL);
lua_pop (L, 1);
- luaL_newmetatable (L, "rspamd{session}");
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{session}");
- lua_rawset (L, -3);
+ rspamd_lua_new_class (L, "rspamd{session}", NULL);
lua_pop (L, 1);
rspamd_lua_add_preload (L, "lpeg", luaopen_lpeg);
@@ -1206,12 +1233,23 @@ gpointer
rspamd_lua_check_class (lua_State *L, gint index, const gchar *name)
{
gpointer p;
+ khiter_t k;
if (lua_type (L, index) == LUA_TUSERDATA) {
p = lua_touserdata (L, index);
if (p) {
if (lua_getmetatable (L, index)) {
- lua_getfield (L, LUA_REGISTRYINDEX, name); /* get correct metatable */
+ k = kh_get (lua_class_set, lua_classes, name);
+
+ if (k == kh_end (lua_classes)) {
+ lua_pop (L, 1);
+
+ return NULL;
+ }
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
+
if (lua_rawequal (L, -1, -2)) { /* does it have the correct mt? */
lua_pop (L, 2); /* remove both metatables */
return p;
@@ -1824,6 +1862,7 @@ rspamd_lua_check_udata_common (lua_State *L, gint pos, const gchar *classname,
{
void *p = lua_touserdata (L, pos);
guint i, top = lua_gettop (L);
+ khiter_t k;
if (p == NULL) {
goto err;
@@ -1831,7 +1870,14 @@ rspamd_lua_check_udata_common (lua_State *L, gint pos, const gchar *classname,
else {
/* Match class */
if (lua_getmetatable (L, pos)) {
- luaL_getmetatable (L, classname);
+ k = kh_get (lua_class_set, lua_classes, (gchar *)classname);
+
+ if (k == kh_end (lua_classes)) {
+ goto err;
+ }
+
+ lua_rawgetp (L, LUA_REGISTRYINDEX,
+ RSPAMD_LIGHTUSERDATA_MASK (kh_key (lua_classes, k)));
if (!lua_rawequal (L, -1, -2)) {
goto err;
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index 507925e80..9878cc521 100644
--- a/src/lua/lua_common.h
+++ b/src/lua/lua_common.h
@@ -40,6 +40,28 @@ luaL_register (lua_State *L, const gchar *name, const struct luaL_reg *methods)
}
#endif
+#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 501
+static inline int lua_absindex (lua_State *L, int i) {
+ if (i < 0 && i > LUA_REGISTRYINDEX)
+ i += lua_gettop(L) + 1;
+ return i;
+}
+static inline int lua_rawgetp (lua_State *L, int i, const void *p) {
+ int abs_i = lua_absindex(L, i);
+ lua_pushlightuserdata(L, (void*)p);
+ lua_rawget(L, abs_i);
+ return lua_type(L, -1);
+}
+
+static inline void lua_rawsetp (lua_State *L, int i, const void *p) {
+ int abs_i = lua_absindex(L, i);
+ luaL_checkstack(L, 1, "not enough stack slots");
+ lua_pushlightuserdata(L, (void*)p);
+ lua_insert(L, -2);
+ lua_rawset(L, abs_i);
+}
+#endif
+
/* Interface definitions */
#define LUA_FUNCTION_DEF(class, name) static int lua_ ## class ## _ ## name ( \
lua_State * L)
@@ -133,15 +155,6 @@ void rspamd_lua_new_class (lua_State *L,
const struct luaL_reg *methods);
/**
- * Create and register new class with static methods
- */
-void rspamd_lua_new_class_full (lua_State *L,
- const gchar *classname,
- const gchar *static_name,
- const struct luaL_reg *methods,
- const struct luaL_reg *func);
-
-/**
* Set class name for object at @param objidx position
*/
void rspamd_lua_setclass (lua_State *L, const gchar *classname, gint objidx);
diff --git a/src/lua/lua_cryptobox.c b/src/lua/lua_cryptobox.c
index 35faa0037..645b2495f 100644
--- a/src/lua/lua_cryptobox.c
+++ b/src/lua/lua_cryptobox.c
@@ -2437,54 +2437,20 @@ lua_load_cryptobox (lua_State * L)
void
luaopen_cryptobox (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{cryptobox_pubkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_pubkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxpubkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_pubkey}", cryptoboxpubkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_pubkey", lua_load_pubkey);
- luaL_newmetatable (L, "rspamd{cryptobox_keypair}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_keypair}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxkeypairlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_keypair}", cryptoboxkeypairlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_keypair", lua_load_keypair);
- luaL_newmetatable (L, "rspamd{cryptobox_signature}");
-
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_signature}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxsignlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_signature}", cryptoboxsignlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_signature", lua_load_signature);
- luaL_newmetatable (L, "rspamd{cryptobox_hash}");
-
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{cryptobox_hash}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, cryptoboxhashlib_m);
+ rspamd_lua_new_class (L, "rspamd{cryptobox_hash}", cryptoboxhashlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_cryptobox_hash", lua_load_hash);
rspamd_lua_add_preload (L, "rspamd_cryptobox", lua_load_cryptobox);
diff --git a/src/lua/lua_dns_resolver.c b/src/lua/lua_dns_resolver.c
index a4e3b4b03..5478ab65a 100644
--- a/src/lua/lua_dns_resolver.c
+++ b/src/lua/lua_dns_resolver.c
@@ -693,15 +693,7 @@ void
luaopen_dns_resolver (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{resolver}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{resolver}");
- lua_rawset (L, -3);
-
+ rspamd_lua_new_class (L, "rspamd{resolver}", dns_resolverlib_m);
{
LUA_ENUM (L, DNS_A, RDNS_REQUEST_A);
LUA_ENUM (L, DNS_PTR, RDNS_REQUEST_PTR);
@@ -713,8 +705,7 @@ luaopen_dns_resolver (lua_State * L)
LUA_ENUM (L, DNS_SOA, RDNS_REQUEST_SOA);
}
- luaL_register (L, NULL, dns_resolverlib_m);
- rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
+ lua_pop (L, 1);
- lua_pop (L, 1); /* remove metatable from stack */
+ rspamd_lua_add_preload (L, "rspamd_resolver", lua_load_dns_resolver);
}
diff --git a/src/lua/lua_expression.c b/src/lua/lua_expression.c
index c0e75fe84..60ee8fdf7 100644
--- a/src/lua/lua_expression.c
+++ b/src/lua/lua_expression.c
@@ -511,17 +511,7 @@ lua_load_expression (lua_State * L)
void
luaopen_expression (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{expr}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{expr}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, exprlib_m);
+ rspamd_lua_new_class (L, "rspamd{expr}", exprlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_expression", lua_load_expression);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
diff --git a/src/lua/lua_ip.c b/src/lua/lua_ip.c
index 3c3ef2d51..1d44af2bf 100644
--- a/src/lua/lua_ip.c
+++ b/src/lua/lua_ip.c
@@ -584,17 +584,7 @@ lua_load_ip (lua_State * L)
void
luaopen_ip (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{ip}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{ip}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, iplib_m);
- rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
-
+ rspamd_lua_new_class (L, "rspamd{ip}", iplib_m);
lua_pop (L, 1);
+ rspamd_lua_add_preload (L, "rspamd_ip", lua_load_ip);
}
diff --git a/src/lua/lua_logger.c b/src/lua/lua_logger.c
index bca4bc6e3..f76db8877 100644
--- a/src/lua/lua_logger.c
+++ b/src/lua/lua_logger.c
@@ -575,31 +575,34 @@ lua_logger_out_type (lua_State *L, gint pos,
trace->cur_level ++;
switch (type) {
- case LUA_TNUMBER:
- r = lua_logger_out_num (L, pos, outbuf, len, trace);
- break;
- case LUA_TBOOLEAN:
- r = lua_logger_out_boolean (L, pos, outbuf, len, trace);
- break;
- case LUA_TTABLE:
- r = lua_logger_out_table (L, pos, outbuf, len, trace, esc_type);
- break;
- case LUA_TUSERDATA:
- r = lua_logger_out_userdata (L, pos, outbuf, len, trace);
- break;
- case LUA_TFUNCTION:
- r = rspamd_snprintf (outbuf, len + 1, "function");
- break;
- case LUA_TNIL:
- r = rspamd_snprintf (outbuf, len + 1, "nil");
- break;
- case LUA_TNONE:
- r = rspamd_snprintf (outbuf, len + 1, "no value");
- break;
- default:
- /* Try to push everything as string using tostring magic */
- r = lua_logger_out_str (L, pos, outbuf, len, trace, esc_type);
- break;
+ case LUA_TNUMBER:
+ r = lua_logger_out_num (L, pos, outbuf, len, trace);
+ break;
+ case LUA_TBOOLEAN:
+ r = lua_logger_out_boolean (L, pos, outbuf, len, trace);
+ break;
+ case LUA_TTABLE:
+ r = lua_logger_out_table (L, pos, outbuf, len, trace, esc_type);
+ break;
+ case LUA_TUSERDATA:
+ r = lua_logger_out_userdata (L, pos, outbuf, len, trace);
+ break;
+ case LUA_TFUNCTION:
+ r = rspamd_snprintf (outbuf, len + 1, "function");
+ break;
+ case LUA_TLIGHTUSERDATA:
+ r = rspamd_snprintf (outbuf, len + 1, "0x%p", lua_topointer (L, pos));
+ break;
+ case LUA_TNIL:
+ r = rspamd_snprintf (outbuf, len + 1, "nil");
+ break;
+ case LUA_TNONE:
+ r = rspamd_snprintf (outbuf, len + 1, "no value");
+ break;
+ default:
+ /* Try to push everything as string using tostring magic */
+ r = lua_logger_out_str (L, pos, outbuf, len, trace, esc_type);
+ break;
}
trace->cur_level --;
diff --git a/src/lua/lua_mempool.c b/src/lua/lua_mempool.c
index 62d294111..06dcd2d5c 100644
--- a/src/lua/lua_mempool.c
+++ b/src/lua/lua_mempool.c
@@ -582,17 +582,7 @@ lua_load_mempool (lua_State * L)
void
luaopen_mempool (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{mempool}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{mempool}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, mempoollib_m);
+ rspamd_lua_new_class (L, "rspamd{mempool}", mempoollib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_mempool", lua_load_mempool);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
diff --git a/src/lua/lua_redis.c b/src/lua/lua_redis.c
index ac1a8c297..279f84ffa 100644
--- a/src/lua/lua_redis.c
+++ b/src/lua/lua_redis.c
@@ -1603,17 +1603,7 @@ lua_load_redis (lua_State * L)
void
luaopen_redis (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{redis}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{redis}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, redislib_m);
+ rspamd_lua_new_class (L, "rspamd{redis}", redislib_m);
lua_pop (L, 1);
-
rspamd_lua_add_preload (L, "rspamd_redis", lua_load_redis);
}
diff --git a/src/lua/lua_regexp.c b/src/lua/lua_regexp.c
index 4033722a3..95f40f8f0 100644
--- a/src/lua/lua_regexp.c
+++ b/src/lua/lua_regexp.c
@@ -880,22 +880,12 @@ lua_load_regexp (lua_State * L)
void
luaopen_regexp (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{regexp}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{regexp}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, regexplib_m);
+ rspamd_lua_new_class (L, "rspamd{regexp}", regexplib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_regexp", lua_load_regexp);
if (regexp_static_pool == NULL) {
regexp_static_pool = rspamd_mempool_new (rspamd_mempool_suggest_size (),
"regexp_lua_pool");
}
-
- lua_settop (L, 0);
}
diff --git a/src/lua/lua_rsa.c b/src/lua/lua_rsa.c
index 58607f92c..4b2caa2bf 100644
--- a/src/lua/lua_rsa.c
+++ b/src/lua/lua_rsa.c
@@ -719,40 +719,16 @@ lua_load_rsa (lua_State * L)
void
luaopen_rsa (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{rsa_pubkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_pubkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsapubkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_pubkey}", rsapubkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_pubkey", lua_load_pubkey);
- luaL_newmetatable (L, "rspamd{rsa_privkey}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_privkey}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsaprivkeylib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_privkey}", rsaprivkeylib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_privkey", lua_load_privkey);
- luaL_newmetatable (L, "rspamd{rsa_signature}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{rsa_signature}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, rsasignlib_m);
+ rspamd_lua_new_class (L, "rspamd{rsa_signature}", rsasignlib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_rsa_signature", lua_load_signature);
rspamd_lua_add_preload (L, "rspamd_rsa", lua_load_rsa);
diff --git a/src/lua/lua_sqlite3.c b/src/lua/lua_sqlite3.c
index 87d798666..95104d1b0 100644
--- a/src/lua/lua_sqlite3.c
+++ b/src/lua/lua_sqlite3.c
@@ -373,28 +373,10 @@ lua_load_sqlite3 (lua_State * L)
void
luaopen_sqlite3 (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{sqlite3}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{sqlite3}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, sqlitelib_m);
+ rspamd_lua_new_class (L, "rspamd{sqlite3}", sqlitelib_m);
lua_pop (L, 1);
- luaL_newmetatable (L, "rspamd{sqlite3_stmt}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{sqlite3_stmt}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, sqlitestmtlib_m);
+ rspamd_lua_new_class (L, "rspamd{sqlite3_stmt}", sqlitestmtlib_m);
lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_sqlite3", lua_load_sqlite3);
diff --git a/src/lua/lua_trie.c b/src/lua/lua_trie.c
index 82d11c50c..58a669832 100644
--- a/src/lua/lua_trie.c
+++ b/src/lua/lua_trie.c
@@ -441,17 +441,7 @@ lua_load_trie (lua_State *L)
void
luaopen_trie (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{trie}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{trie}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, trielib_m);
+ rspamd_lua_new_class (L, "rspamd{trie}", trielib_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_trie", lua_load_trie);
-
- lua_pop (L, 1); /* remove metatable from stack */
}
diff --git a/src/lua/lua_upstream.c b/src/lua/lua_upstream.c
index 3c4f3f4c3..7ba77839f 100644
--- a/src/lua/lua_upstream.c
+++ b/src/lua/lua_upstream.c
@@ -569,30 +569,10 @@ lua_load_upstream_list (lua_State * L)
void
luaopen_upstream (lua_State * L)
{
- luaL_newmetatable (L, "rspamd{upstream_list}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{upstream_list}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, upstream_list_m);
+ rspamd_lua_new_class (L, "rspamd{upstream_list}", upstream_list_m);
+ lua_pop (L, 1);
rspamd_lua_add_preload (L, "rspamd_upstream_list", lua_load_upstream_list);
- lua_pop (L, 1); /* remove metatable from stack */
-
- luaL_newmetatable (L, "rspamd{upstream}");
- lua_pushstring (L, "__index");
- lua_pushvalue (L, -2);
- lua_settable (L, -3);
-
- lua_pushstring (L, "class");
- lua_pushstring (L, "rspamd{upstream}");
- lua_rawset (L, -3);
-
- luaL_register (L, NULL, upstream_m);
-
- lua_pop (L, 1); /* remove metatable from stack */
+ rspamd_lua_new_class (L, "rspamd{upstream}", upstream_m);
+ lua_pop (L, 1);
}
diff --git a/src/lua/lua_worker.c b/src/lua/lua_worker.c
index c3c9e729e..1768b1c2a 100644
--- a/src/lua/lua_worker.c
+++ b/src/lua/lua_worker.c
@@ -25,6 +25,7 @@
#endif
#include <sys/wait.h>
+#include <src/libserver/rspamd_control.h>
/***
* @module rspamd_worker
@@ -42,6 +43,7 @@ LUA_FUNCTION_DEF (worker, is_scanner);
LUA_FUNCTION_DEF (worker, is_primary_controller);
LUA_FUNCTION_DEF (worker, spawn_process);
LUA_FUNCTION_DEF (worker, get_mem_stats);
+LUA_FUNCTION_DEF (worker, add_control_handler);
const luaL_reg worker_reg[] = {
LUA_INTERFACE_DEF (worker, get_name),
@@ -53,6 +55,7 @@ const luaL_reg worker_reg[] = {
LUA_INTERFACE_DEF (worker, is_scanner),
LUA_INTERFACE_DEF (worker, is_primary_controller),
LUA_INTERFACE_DEF (worker, get_mem_stats),
+ LUA_INTERFACE_DEF (worker, add_control_handler),
{"__tostring", rspamd_lua_class_tostring},
{NULL, NULL}
};
@@ -240,6 +243,145 @@ lua_worker_is_primary_controller (lua_State *L)
return 1;
}
+struct rspamd_control_cbdata {
+ lua_State *L;
+ rspamd_mempool_t *pool;
+ struct rspamd_worker *w;
+ struct rspamd_config *cfg;
+ struct ev_loop *event_loop;
+ struct rspamd_async_session *session;
+ enum rspamd_control_type cmd;
+ gint cbref;
+ gint fd;
+};
+
+static gboolean
+lua_worker_control_fin_session (void *ud)
+{
+ struct rspamd_control_reply rep;
+ struct rspamd_control_cbdata *cbd = (struct rspamd_control_cbdata *)ud;
+ rspamd_mempool_t *pool;
+ lua_State *L;
+
+ L = cbd->L;
+ pool = cbd->pool;
+
+ memset (&rep, 0, sizeof (rep));
+ rep.type = cbd->cmd;
+
+ if (write (cbd->fd, &rep, sizeof (rep)) != sizeof (rep)) {
+ msg_err_pool ("cannot write reply to the control socket: %s",
+ strerror (errno));
+ }
+
+ return TRUE;
+}
+
+static void
+lua_worker_control_session_dtor (void *ud)
+{
+ struct rspamd_control_cbdata *cbd = (struct rspamd_control_cbdata *)ud;
+
+ rspamd_mempool_delete (cbd->pool);
+}
+
+static gboolean
+lua_worker_control_handler (struct rspamd_main *rspamd_main,
+ struct rspamd_worker *worker,
+ gint fd,
+ gint attached_fd,
+ struct rspamd_control_command *cmd,
+ gpointer ud)
+{
+ struct rspamd_async_session *session, **psession;
+ struct rspamd_control_cbdata *cbd = (struct rspamd_control_cbdata *)ud;
+ rspamd_mempool_t *pool;
+ lua_State *L;
+ gint err_idx;
+
+ L = cbd->L;
+ pool = cbd->pool;
+ session = rspamd_session_create (cbd->pool,
+ lua_worker_control_fin_session,
+ NULL,
+ lua_worker_control_session_dtor,
+ cbd);
+ cbd->session = session;
+ cbd->fd = fd;
+
+ lua_pushcfunction (L, &rspamd_lua_traceback);
+ err_idx = lua_gettop (L);
+ lua_rawgeti (L, LUA_REGISTRYINDEX, cbd->cbref);
+ psession = lua_newuserdata (L, sizeof (*psession));
+ rspamd_lua_setclass (L, "rspamd{session}", -1);
+ *psession = session;
+
+ if (lua_pcall (L, 1, 0, err_idx) != 0) {
+ msg_err_pool ("cannot init lua parser script: %s", lua_tostring (L, -1));
+ lua_settop (L, err_idx - 1);
+
+ struct rspamd_control_reply rep;
+
+ memset (&rep, 0, sizeof (rep));
+ rep.type = cbd->cmd;
+ rep.reply.monitored_change.status = -1;
+
+ if (write (fd, &rep, sizeof (rep)) != sizeof (rep)) {
+ msg_err_pool ("cannot write reply to the control socket: %s",
+ strerror (errno));
+ }
+
+ rspamd_session_destroy (session);
+ }
+ else {
+ lua_settop (L, err_idx - 1);
+ rspamd_session_pending (session);
+ }
+
+ return TRUE;
+}
+
+static gint
+lua_worker_add_control_handler (lua_State *L)
+{
+ struct rspamd_worker *w = lua_check_worker (L, 1);
+ struct rspamd_config *cfg = lua_check_config (L, 2);
+ struct ev_loop *event_loop = lua_check_ev_base (L, 3);
+ const gchar *cmd_name = luaL_checkstring (L, 4);
+ enum rspamd_control_type cmd;
+ struct rspamd_control_cbdata *cbd;
+
+ if (w && cfg && event_loop && cmd_name && lua_isfunction (L, 5)) {
+ cmd = rspamd_control_command_from_string (cmd_name);
+
+ if (cmd == RSPAMD_CONTROL_MAX) {
+ return luaL_error (L, "invalid command type: %s", cmd_name);
+ }
+
+ rspamd_mempool_t *pool = rspamd_mempool_new (
+ rspamd_mempool_suggest_size (), "lua_control");
+ cbd = rspamd_mempool_alloc0 (pool, sizeof (*cbd));
+ cbd->pool = pool;
+ cbd->event_loop = event_loop;
+ cbd->w = w;
+ cbd->cfg = cfg;
+ cbd->cmd = cmd;
+ cbd->L = L;
+ /* Refcount callback */
+ lua_pushvalue (L, 5);
+ cbd->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
+
+ rspamd_control_worker_add_cmd_handler (w, cmd, lua_worker_control_handler,
+ cbd);
+ }
+ else {
+ return luaL_error (L, "invalid arguments, need worker, cfg, "
+ "ev_loop, cmd_name and callback function");
+ }
+
+ return 0;
+}
+
#ifdef WITH_JEMALLOC
static void
lua_worker_jemalloc_stats_cb (void *ud, const char *msg)
diff --git a/src/plugins/lua/reputation.lua b/src/plugins/lua/reputation.lua
index 4c92eab94..648efa53f 100644
--- a/src/plugins/lua/reputation.lua
+++ b/src/plugins/lua/reputation.lua
@@ -503,7 +503,7 @@ local ip_selector = {
['country'] = 0.01,
['ip'] = 1.0
},
- symbol_spam = 'SENDER_REP', -- symbol to be inserted
+ symbol = 'SENDER_REP', -- symbol to be inserted
split_symbols = true,
asn_prefix = 'a:', -- prefix for ASN hashes
country_prefix = 'c:', -- prefix for country hashes
diff --git a/src/rspamd.c b/src/rspamd.c
index 808ca6aaa..d0dd7ff10 100644
--- a/src/rspamd.c
+++ b/src/rspamd.c
@@ -83,6 +83,8 @@ static void rspamd_cld_handler (EV_P_ ev_child *w,
/* Control socket */
static gint control_fd;
static ev_io control_ev;
+static struct rspamd_stat old_stat;
+static ev_timer stat_ev;
static gboolean valgrind_mode = FALSE;
@@ -969,6 +971,39 @@ rspamd_usr1_handler (struct ev_loop *loop, ev_signal *w, int revents)
}
static void
+rspamd_stat_update_handler (struct ev_loop *loop, ev_timer *w, int revents)
+{
+ struct rspamd_main *rspamd_main = (struct rspamd_main *)w->data;
+ struct rspamd_stat cur_stat;
+ gchar proctitle[128];
+
+ memcpy (&cur_stat, rspamd_main->stat, sizeof (cur_stat));
+
+ if (old_stat.messages_scanned > 0 &&
+ cur_stat.messages_scanned > old_stat.messages_scanned) {
+ gdouble rate = (double)(cur_stat.messages_scanned - old_stat.messages_scanned) /
+ w->repeat;
+ gdouble old_spam = old_stat.actions_stat[METRIC_ACTION_REJECT] +
+ old_stat.actions_stat[METRIC_ACTION_ADD_HEADER] +
+ old_stat.actions_stat[METRIC_ACTION_REWRITE_SUBJECT];
+ gdouble old_ham = old_stat.actions_stat[METRIC_ACTION_NOACTION];
+ gdouble new_spam = cur_stat.actions_stat[METRIC_ACTION_REJECT] +
+ cur_stat.actions_stat[METRIC_ACTION_ADD_HEADER] +
+ cur_stat.actions_stat[METRIC_ACTION_REWRITE_SUBJECT];
+ gdouble new_ham = cur_stat.actions_stat[METRIC_ACTION_NOACTION];
+
+ rspamd_snprintf (proctitle, sizeof (proctitle),
+ "main process; %.1f msg/sec, %.1f msg/sec spam, %.1f msg/sec ham",
+ rate,
+ (new_spam - old_spam) / w->repeat,
+ (new_ham - old_ham) / w->repeat);
+ setproctitle (proctitle);
+ }
+
+ memcpy (&old_stat, &cur_stat, sizeof (cur_stat));
+}
+
+static void
rspamd_hup_handler (struct ev_loop *loop, ev_signal *w, int revents)
{
struct rspamd_main *rspamd_main = (struct rspamd_main *)w->data;
@@ -1375,6 +1410,15 @@ main (gint argc, gchar **argv, gchar **env)
rspamd_main->usr1_ev.data = rspamd_main;
ev_signal_start (event_loop, &rspamd_main->usr1_ev);
+ /* Update proctitle according to number of messages processed */
+ static const ev_tstamp stat_update_time = 10.0;
+
+ memset (&old_stat, 0, sizeof (old_stat));
+ stat_ev.data = rspamd_main;
+ ev_timer_init (&stat_ev, rspamd_stat_update_handler,
+ stat_update_time, stat_update_time);
+ ev_timer_start (event_loop, &stat_ev);
+
rspamd_check_core_limits (rspamd_main);
rspamd_mempool_lock_mutex (rspamd_main->start_mtx);
spawn_workers (rspamd_main, event_loop);