diff options
author | korgoth1 <vladislav.stakhov@gmail.com> | 2019-09-16 23:21:58 +0300 |
---|---|---|
committer | korgoth1 <vladislav.stakhov@gmail.com> | 2019-09-16 23:21:58 +0300 |
commit | f637f261d5a0b58e262e1a508a4e98cc2ddf0f5a (patch) | |
tree | b2cdbcb2b0cfe08ef8451430a58676b255468c16 | |
parent | e7722d808a0c5b9f58d7878cc59569e124e604d8 (diff) | |
parent | d4be8b2d633c57f8f3695dbe4ce9e3407bc1046b (diff) | |
download | rspamd-f637f261d5a0b58e262e1a508a4e98cc2ddf0f5a.tar.gz rspamd-f637f261d5a0b58e262e1a508a4e98cc2ddf0f5a.zip |
[Test] MAGIC ROBOT
-rw-r--r-- | contrib/libucl/lua_ucl.c | 6 | ||||
-rw-r--r-- | src/controller.c | 2 | ||||
-rw-r--r-- | src/fuzzy_storage.c | 21 | ||||
-rw-r--r-- | src/libserver/rspamd_control.c | 91 | ||||
-rw-r--r-- | src/libserver/rspamd_control.h | 22 | ||||
-rw-r--r-- | src/libserver/worker_util.c | 7 | ||||
-rw-r--r-- | src/lua/lua_cdb.c | 14 | ||||
-rw-r--r-- | src/lua/lua_common.c | 120 | ||||
-rw-r--r-- | src/lua/lua_common.h | 31 | ||||
-rw-r--r-- | src/lua/lua_cryptobox.c | 50 | ||||
-rw-r--r-- | src/lua/lua_dns_resolver.c | 15 | ||||
-rw-r--r-- | src/lua/lua_expression.c | 14 | ||||
-rw-r--r-- | src/lua/lua_ip.c | 14 | ||||
-rw-r--r-- | src/lua/lua_logger.c | 53 | ||||
-rw-r--r-- | src/lua/lua_mempool.c | 14 | ||||
-rw-r--r-- | src/lua/lua_redis.c | 12 | ||||
-rw-r--r-- | src/lua/lua_regexp.c | 14 | ||||
-rw-r--r-- | src/lua/lua_rsa.c | 36 | ||||
-rw-r--r-- | src/lua/lua_sqlite3.c | 22 | ||||
-rw-r--r-- | src/lua/lua_trie.c | 14 | ||||
-rw-r--r-- | src/lua/lua_upstream.c | 28 | ||||
-rw-r--r-- | src/lua/lua_worker.c | 142 | ||||
-rw-r--r-- | src/plugins/lua/reputation.lua | 2 | ||||
-rw-r--r-- | src/rspamd.c | 44 |
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); |