Browse Source

[Feature] Add config:add_map table form method, add regexp maps

tags/1.2.0
Vsevolod Stakhov 8 years ago
parent
commit
ddb8489d1b
3 changed files with 195 additions and 54 deletions
  1. 2
    0
      src/lua/lua_common.h
  2. 19
    11
      src/lua/lua_config.c
  3. 174
    43
      src/lua/lua_map.c

+ 2
- 0
src/lua/lua_common.h View File

@@ -90,6 +90,7 @@ enum rspamd_lua_map_type {
RSPAMD_LUA_MAP_RADIX = 0,
RSPAMD_LUA_MAP_SET,
RSPAMD_LUA_MAP_HASH,
RSPAMD_LUA_MAP_REGEXP,
RSPAMD_LUA_MAP_CALLBACK
};

@@ -104,6 +105,7 @@ struct rspamd_lua_map {
struct radix_tree_compressed *radix;
GHashTable *hash;
struct lua_map_callback_data *cbdata;
struct rspamd_regexp_map *re_map;
} data;
};


+ 19
- 11
src/lua/lua_config.c View File

@@ -65,7 +65,7 @@ LUA_FUNCTION_DEF (config, get_mempool);
* Creates new dynamic map of IP/mask addresses.
* @param {string} mapline URL for a map
* @param {string} description optional map description
* @return {radix} radix tree object
* @return {map} radix tree object
* @example
local ip_map = rspamd_config:add_radix_map ('file:///path/to/file', 'my radix map')
...
@@ -80,10 +80,10 @@ end

/***
* @method rspamd_config:radix_from_config(mname, optname)
* Creates new static map of IP/mask addresses from config.
* Creates new embedded map of IP/mask addresses from config.
* @param {string} mname name of module
* @param {string} optname option to get
* @return {radix} radix tree object
* @return {map} radix tree object
* @example
local ip_map = rspamd_config:radix_from_config ('mymodule', 'ips')
...
@@ -100,7 +100,7 @@ end
* Creates new dynamic map string objects.
* @param {string} mapline URL for a map
* @param {string} description optional map description
* @return {hash} hash set object
* @return {map} hash set object
* @example
local hash_map = rspamd_config:add_hash_map ('file:///path/to/file', 'my hash map')
...
@@ -117,7 +117,7 @@ end
* Creates new dynamic map of key/values associations.
* @param {string} mapline URL for a map
* @param {string} description optional map description
* @return {hash} hash table object
* @return {map} hash table object
* @example
local kv_map = rspamd_config:add_kv_map ('file:///path/to/file', 'my kv map')
...
@@ -133,12 +133,20 @@ local function foo(task)
end
*/
/***
* @method rspamd_config:add_map(mapline[, description], callback)
* Creates new dynamic map with free-form callback
* @param {string} mapline URL for a map
* @param {string} description optional map description
* @param {function} callback function to be called on map load and/or update
* @return {bool} `true` if map has been added
* @method rspamd_config:add_map({args})
* Creates new dynamic map according to the attributes passed.
*
* - `type`: type of map to be created, can be one of the following set:
* + `set`: set of strings
* + `radix`: map of IP addresses to strings
* + `map`: map of strings to strings
* + `regexp`: map of regexps to strings
* + `callback`: map processed by lua callback
* - `url`: url to load map from
* - `description`: map's description
* - `callback`: lua callback for the map
*
* @return {map} `true` if map has been added
* @example

local str = ''

+ 174
- 43
src/lua/lua_map.c View File

@@ -342,58 +342,176 @@ gint
lua_config_add_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
const gchar *map_line = NULL, *description = NULL;
const gchar *type = NULL;
struct lua_map_callback_data *cbdata;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;
int cbidx;
int cbidx = -1, ret;
GError *err = NULL;

if (cfg) {
map_line = luaL_checkstring (L, 2);
if (lua_type (L, 2) == LUA_TTABLE) {
if (!rspamd_lua_parse_table_arguments (L, 2, &err,
"type=*S;description=S;callback=F;url=*S",
&type, &description, &cbidx, &map_line)) {
ret = luaL_error (L, "invalid table arguments: %s", err->message);
g_error_free (err);

return ret;
}

if (lua_gettop (L) == 4) {
description = lua_tostring (L, 3);
cbidx = 4;
}
else {
description = NULL;
cbidx = 3;
}
g_assert (type != NULL && map_line != NULL);

map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->type = RSPAMD_LUA_MAP_CALLBACK;
map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
sizeof (*map->data.cbdata));
cbdata = map->data.cbdata;
cbdata->L = L;
cbdata->data = NULL;
cbdata->lua_map = map;

if (lua_type (L, cbidx) == LUA_TFUNCTION) {
lua_pushvalue (L, cbidx);
/* Get a reference */
cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
}
else {
/*
* Now we can create maps with delayed callbacks, to allow better
* closures generation
*/
cbdata->ref = -1;
}
if (strcmp (type, "callback") == 0) {
if (cbidx == -1) {
ret = luaL_error (L, "invalid table arguments: callback missing");
return ret;
}

map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->type = RSPAMD_LUA_MAP_CALLBACK;
map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
sizeof (*map->data.cbdata));
cbdata = map->data.cbdata;
cbdata->L = L;
cbdata->data = NULL;
cbdata->lua_map = map;
cbdata->ref = cbidx;

if ((m = rspamd_map_add (cfg, map_line, description,
lua_map_read, lua_map_fin,
(void **)&map->data.cbdata)) == NULL) {
msg_warn_config ("invalid map %s", map_line);
luaL_unref (L, LUA_REGISTRYINDEX, cbidx);
lua_pushnil (L);

return 1;
}
}
else if (strcmp (type, "set") == 0) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.hash = g_hash_table_new (rspamd_strcase_hash,
rspamd_strcase_equal);
map->type = RSPAMD_LUA_MAP_SET;

if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_hosts_read,
rspamd_hosts_fin,
(void **)&map->data.hash)) == NULL) {
msg_warn_config ("invalid set map %s", map_line);
g_hash_table_destroy (map->data.hash);
lua_pushnil (L);

return 1;
}
}
else if (strcmp (type, "map") == 0) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.hash = g_hash_table_new (rspamd_strcase_hash,
rspamd_strcase_equal);
map->type = RSPAMD_LUA_MAP_HASH;

if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_kv_list_read,
rspamd_kv_list_fin,
(void **)&map->data.hash)) == NULL) {
msg_warn_config ("invalid hash map %s", map_line);
g_hash_table_destroy (map->data.hash);
lua_pushnil (L);
return 1;
}
}
else if (strcmp (type, "radix") == 0) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.radix = radix_create_compressed ();
map->type = RSPAMD_LUA_MAP_RADIX;

if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_radix_read,
rspamd_radix_fin,
(void **)&map->data.radix)) == NULL) {
msg_warn_config ("invalid radix map %s", map_line);
radix_destroy_compressed (map->data.radix);
lua_pushnil (L);
return 1;
}
}
else if (strcmp (type, "regexp") == 0) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.radix = radix_create_compressed ();
map->type = RSPAMD_LUA_MAP_RADIX;

if ((m = rspamd_map_add (cfg, map_line, description,
rspamd_regexp_list_read,
rspamd_regexp_list_fin,
(void **)&map->data.re_map)) == NULL) {
msg_warn_config ("invalid regexp map %s", map_line);
lua_pushnil (L);
return 1;
}
}
else {
ret = luaL_error (L, "invalid arguments: unknown type '%s'", type);

return ret;
}

if ((m = rspamd_map_add (cfg, map_line, description,
lua_map_read, lua_map_fin,
(void **)&map->data.cbdata)) == NULL) {
msg_warn_config ("invalid map %s", map_line);
lua_pushnil (L);
}
else {
map->map = m;
pmap = lua_newuserdata (L, sizeof (void *));
*pmap = map;
rspamd_lua_setclass (L, "rspamd{map}", -1);
}
else {
/*
* Legacy format add_map(map_line, description, callback)
*/
map_line = luaL_checkstring (L, 2);

if (lua_gettop (L) == 4) {
description = lua_tostring (L, 3);
cbidx = 4;
}
else {
description = NULL;
cbidx = 3;
}

map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->type = RSPAMD_LUA_MAP_CALLBACK;
map->data.cbdata = rspamd_mempool_alloc0 (cfg->cfg_pool,
sizeof (*map->data.cbdata));
cbdata = map->data.cbdata;
cbdata->L = L;
cbdata->data = NULL;
cbdata->lua_map = map;

if (lua_type (L, cbidx) == LUA_TFUNCTION) {
lua_pushvalue (L, cbidx);
/* Get a reference */
cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
}
else {
/*
* Now we can create maps with delayed callbacks, to allow better
* closures generation
*/
cbdata->ref = -1;
}

if ((m = rspamd_map_add (cfg, map_line, description,
lua_map_read, lua_map_fin,
(void **)&map->data.cbdata)) == NULL) {
msg_warn_config ("invalid map %s", map_line);
lua_pushnil (L);
}
else {
map->map = m;
pmap = lua_newuserdata (L, sizeof (void *));
*pmap = map;
rspamd_lua_setclass (L, "rspamd{map}", -1);
}
}
}
else {
return luaL_error (L, "invalid arguments");
@@ -411,6 +529,7 @@ lua_map_get_key (lua_State * L)
struct rspamd_lua_ip *addr = NULL;
const gchar *key, *value = NULL;
gpointer ud;
gsize len;
guint32 key_num = 0;
gboolean ret = FALSE;

@@ -456,12 +575,11 @@ lua_map_get_key (lua_State * L)
ret = g_hash_table_lookup (map->data.hash, key) != NULL;
}
}
else {
/* key-value map */
key = lua_tostring (L, 2);
else if (map->type == RSPAMD_LUA_MAP_REGEXP) {
key = lua_tolstring (L, 2, &len);

if (key) {
value = g_hash_table_lookup (map->data.hash, key);
value = rspamd_match_regexp_map (map->data.re_map, key, len);

if (value) {
lua_pushstring (L, value);
@@ -469,6 +587,19 @@ lua_map_get_key (lua_State * L)
}
}
}
else {
/* key-value map */
key = lua_tostring (L, 2);

if (key) {
value = g_hash_table_lookup (map->data.hash, key);
}

if (value) {
lua_pushstring (L, value);
return 1;
}
}
}
else {
return luaL_error (L, "invalid arguments");

Loading…
Cancel
Save