From: Vsevolod Stakhov Date: Thu, 15 Mar 2018 16:24:44 +0000 (+0000) Subject: [Project] Add some generic code to squeeze lua rules X-Git-Tag: 1.7.1~38 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=5321190dc5e445cb5a81143be7bfd6fe0afc13b0;p=rspamd.git [Project] Add some generic code to squeeze lua rules --- diff --git a/lualib/lua_squeeze_rules.lua b/lualib/lua_squeeze_rules.lua new file mode 100644 index 000000000..d740e2ee0 --- /dev/null +++ b/lualib/lua_squeeze_rules.lua @@ -0,0 +1,97 @@ +--[[ +Copyright (c) 2018, Vsevolod Stakhov + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +]]-- + +local exports = {} +local logger = require 'rspamd_logger' + +-- Squeezed rules part +local squeezed_rules = {} -- plain vector of all rules squeezed +local squeezed_symbols = {} -- indexed by name of symbol +local squeezed_deps = {} -- squeezed deps +local SN = 'lua_squeeze' +local squeeze_function_id + +local function lua_squeeze_function(task) + if not squeezed_symbols then + for k,v in pairs(squeezed_symbols) do + if not squeezed_exceptions[k] then + logger.debugm(SN, task, 'added squeezed rule: %s', k) + table.insert(squeezed_rules, v) + else + logger.debugm(SN, task, 'skipped squeezed rule: %s', k) + end + end + + squeezed_symbols = nil + end + + for _,func in ipairs(squeezed_rules) do + local ret = func(task) + + if ret then + -- Function has returned something, so it is rule, not a plugin + logger.errx(task, 'hui: %s', ret) + end + end +end + +exports.squeeze_rule = function(s, func) + if s then + if not squeezed_symbols[s] then + squeezed_symbols[s] = { + cb = func, + order = 0, + } + logger.debugm(SN, rspamd_config, 'squeezed rule: %s', s) + else + logger.warnx(rspamd_config, 'duplicate symbol registered: %s, skip', s) + end + else + -- Unconditionally add function to the squeezed rules + logger.debugm(SN, rspamd_config, 'squeezed unnamed rule: %s', #squeezed_rules) + table.insert(squeezed_rules, func) + end + + if not squeeze_function_id then + squeeze_function_id = rspamd_config:register_symbol{ + type = 'callback', + callback = lua_squeeze_function, + name = 'LUA_SQUEEZE', + description = 'Meta rule for Lua rules that can be squeezed', + no_squeeze = true, -- to avoid infinite recursion + } + end + + return squeeze_function_id +end + +exports.squeeze_dependency = function(from, to) + logger.debugm(SN, rspamd_config, 'squeeze dep %s->%s', to, from) + + if not squeezed_deps[to] then + squeezed_deps[to] = {} + end + + if not squeezed_symbols[to][from] then + squeezed_symbols[to][from] = true + else + logger.warnx('duplicate dependency %s->%s', to, from) + end + + return true +end + +return exports \ No newline at end of file diff --git a/lualib/lua_util.lua b/lualib/lua_util.lua index d41d79fea..33d7e3714 100644 --- a/lualib/lua_util.lua +++ b/lualib/lua_util.lua @@ -22,6 +22,7 @@ limitations under the License. local exports = {} local lpeg = require 'lpeg' + local split_grammar = {} local function rspamd_str_split(s, sep) local gr = split_grammar[sep] diff --git a/rules/headers_checks.lua b/rules/headers_checks.lua index 334e0ab93..00f2e505a 100644 --- a/rules/headers_checks.lua +++ b/rules/headers_checks.lua @@ -310,7 +310,7 @@ rspamd_config:register_symbol{ group = 'headers', } -rspamd_config:register_dependency(check_replyto_id, 'FROM_NAME_HAS_TITLE') +rspamd_config:register_dependency('CHECK_REPLYTO', 'FROM_NAME_HAS_TITLE') local check_mime_id = rspamd_config:register_symbol{ name = 'CHECK_MIME', diff --git a/rules/misc.lua b/rules/misc.lua index 702431c1a..2646e42d6 100644 --- a/rules/misc.lua +++ b/rules/misc.lua @@ -338,8 +338,8 @@ local freemail_reply_neq_from_id = rspamd_config:register_symbol({ score = 3.0, group = 'headers', }) -rspamd_config:register_dependency(freemail_reply_neq_from_id, 'FREEMAIL_REPLYTO') -rspamd_config:register_dependency(freemail_reply_neq_from_id, 'FREEMAIL_FROM') +rspamd_config:register_dependency('FREEMAIL_REPLYTO_NEQ_FROM_DOM', 'FREEMAIL_REPLYTO') +rspamd_config:register_dependency('FREEMAIL_REPLYTO_NEQ_FROM_DOM', 'FREEMAIL_FROM') rspamd_config.OMOGRAPH_URL = { callback = function(task) diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c index b03c11910..d6a4ad550 100644 --- a/src/lua/lua_config.c +++ b/src/lua/lua_config.c @@ -1277,13 +1277,13 @@ rspamd_register_symbol_fromlua (lua_State *L, if (ref != -1) { /* - * We call for routine called lua_util.squeeze_rule if it exists + * We call for routine called lua_squeeze_rules.squeeze_rule if it exists */ lua_pushcfunction (L, &rspamd_lua_traceback); err_idx = lua_gettop (L); if (!no_squeeze && (type & (SYMBOL_TYPE_CALLBACK|SYMBOL_TYPE_NORMAL)) && - rspamd_lua_require_function (L, "lua_util", "squeeze_rule")) { + rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_rule")) { if (name) { lua_pushstring (L, name); } @@ -1297,14 +1297,16 @@ rspamd_register_symbol_fromlua (lua_State *L, /* Now call for squeeze function */ if (lua_pcall (L, 2, 1, err_idx) != 0) { GString *tb = lua_touserdata (L, -1); - msg_err_config ("call to finishing script failed: %v", tb); + msg_err_config ("call to squeeze_rule failed: %v", tb); if (tb) { g_string_free (tb, TRUE); } } - if (!lua_toboolean (L, -1)) { + ret = lua_tonumber (L, -1); + + if (ret == -1) { /* Do direct registration */ cd = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (struct lua_callback_data)); @@ -1324,6 +1326,9 @@ rspamd_register_symbol_fromlua (lua_State *L, cd, type, parent); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } } else { @@ -1345,6 +1350,9 @@ rspamd_register_symbol_fromlua (lua_State *L, cd, type, parent); + rspamd_mempool_add_destructor (cfg->cfg_pool, + (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, + cd); } /* Cleanup lua stack */ @@ -1360,10 +1368,6 @@ rspamd_register_symbol_fromlua (lua_State *L, parent); } - rspamd_mempool_add_destructor (cfg->cfg_pool, - (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, - cd); - return ret; } @@ -1812,12 +1816,52 @@ lua_config_register_callback_symbol_priority (lua_State * L) return 1; } +static gboolean +rspamd_lua_squeeze_dependency (lua_State *L, struct rspamd_config *cfg, + const gchar *name, + const gchar *from) +{ + gint err_idx; + gboolean ret = FALSE; + + lua_pushcfunction (L, &rspamd_lua_traceback); + err_idx = lua_gettop (L); + + if (rspamd_lua_require_function (L, "lua_squeeze_rules", "squeeze_dependency")) { + lua_pushstring (L, name); + + if (from) { + lua_pushstring (L, from); + } + else { + lua_pushnil (L); + } + + if (lua_pcall (L, 2, 1, err_idx) != 0) { + GString *tb = lua_touserdata (L, -1); + msg_err_config ("call to squeeze_dependency script failed: %v", tb); + + if (tb) { + g_string_free (tb, TRUE); + } + } + else { + ret = lua_toboolean (L, -1); + } + } + + lua_settop (L, err_idx - 1); + + return ret; +} + static gint lua_config_register_dependency (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *name = NULL, *from = NULL; gint id; + gboolean skip_squeeze = FALSE; if (cfg == NULL) { lua_error (L); @@ -1828,16 +1872,36 @@ lua_config_register_dependency (lua_State * L) id = luaL_checknumber (L, 2); name = luaL_checkstring (L, 3); + if (lua_isboolean (L, 4)) { + skip_squeeze = lua_toboolean (L, 4); + } + + msg_warn_config ("calling for obsolete method to register deps for symbol %d->%s", + id, name); + if (id > 0 && name != NULL) { - rspamd_symbols_cache_add_dependency (cfg->cache, id, name); + + if (skip_squeeze || !rspamd_lua_squeeze_dependency (L, cfg, name, + rspamd_symbols_cache_symbol_by_id (cfg->cache, id))) { + rspamd_symbols_cache_add_dependency (cfg->cache, id, name); + } } } else { from = luaL_checkstring (L,2); name = luaL_checkstring (L, 3); + if (lua_isboolean (L, 4)) { + skip_squeeze = lua_toboolean (L, 4); + } + if (from != NULL && name != NULL) { - rspamd_symbols_cache_add_delayed_dependency (cfg->cache, from, name); + + if (skip_squeeze || !rspamd_lua_squeeze_dependency (L, cfg, name, from)) { + rspamd_symbols_cache_add_delayed_dependency (cfg->cache, from, + name); + } + } }