소스 검색

[Rework] Move maps code to a separate lua unit

tags/1.2.0
Vsevolod Stakhov 8 년 전
부모
커밋
2f55351fca
5개의 변경된 파일475개의 추가작업 그리고 419개의 파일을 삭제
  1. 2
    1
      src/lua/CMakeLists.txt
  2. 2
    1
      src/lua/lua_common.h
  3. 5
    417
      src/lua/lua_config.c
  4. 438
    0
      src/lua/lua_map.c
  5. 28
    0
      src/lua/lua_map.h

+ 2
- 1
src/lua/CMakeLists.txt 파일 보기

@@ -26,6 +26,7 @@ SET(LUASRC ${CMAKE_CURRENT_SOURCE_DIR}/lua_common.c
${CMAKE_CURRENT_SOURCE_DIR}/lua_html.c
${CMAKE_CURRENT_SOURCE_DIR}/lua_fann.c
${CMAKE_CURRENT_SOURCE_DIR}/lua_sqlite3.c
${CMAKE_CURRENT_SOURCE_DIR}/lua_cryptobox.c)
${CMAKE_CURRENT_SOURCE_DIR}/lua_cryptobox.c
${CMAKE_CURRENT_SOURCE_DIR}/lua_map.c)

SET(RSPAMD_LUA ${LUASRC} PARENT_SCOPE)

+ 2
- 1
src/lua/lua_common.h 파일 보기

@@ -43,6 +43,8 @@ luaL_register (lua_State *L, const gchar *name, const struct luaL_reg *methods)
/* Interface definitions */
#define LUA_FUNCTION_DEF(class, name) static gint lua_ ## class ## _ ## name ( \
lua_State * L)
#define LUA_PUBLIC_FUNCTION_DEF(class, name) gint lua_ ## class ## _ ## name ( \
lua_State * L)
#define LUA_INTERFACE_DEF(class, name) { # name, lua_ ## class ## _ ## name }

extern const luaL_reg null_reg[];
@@ -80,7 +82,6 @@ struct rspamd_lua_regexp {
gint re_flags;
};


/* Common utility functions */

/**

+ 5
- 417
src/lua/lua_config.c 파일 보기

@@ -14,11 +14,10 @@
* limitations under the License.
*/
#include "lua_common.h"
#include "map.h"
#include "message.h"
#include "radix.h"
#include "expression.h"
#include "composites.h"
#include "libmime/message.h"
#include "libutil/expression.h"
#include "libserver/composites.h"
#include "lua/lua_map.h"
#include "utlist.h"

/***
@@ -78,7 +77,7 @@ local function foo(task)
return false
end
*/
LUA_FUNCTION_DEF (config, add_radix_map);
/***
* @method rspamd_config:radix_from_config(mname, optname)
* Creates new static map of IP/mask addresses from config.
@@ -96,7 +95,6 @@ local function foo(task)
return false
end
*/
LUA_FUNCTION_DEF (config, radix_from_config);
/***
* @method rspamd_config:add_hash_map(mapline[, description])
* Creates new dynamic map string objects.
@@ -114,7 +112,6 @@ local function foo(task)
return false
end
*/
LUA_FUNCTION_DEF (config, add_hash_map);
/***
* @method rspamd_config:add_kv_map(mapline[, description])
* Creates new dynamic map of key/values associations.
@@ -135,7 +132,6 @@ local function foo(task)
return false
end
*/
LUA_FUNCTION_DEF (config, add_kv_map);
/***
* @method rspamd_config:add_map(mapline[, description], callback)
* Creates new dynamic map with free-form callback
@@ -152,7 +148,6 @@ end

rspamd_config:add_map('http://example.com/map', "settings map", process_map)
*/
LUA_FUNCTION_DEF (config, add_map);
/***
* @method rspamd_config:get_classifier(name)
* Returns classifier config.
@@ -416,33 +411,6 @@ static const struct luaL_reg configlib_m[] = {
{NULL, NULL}
};

enum rspamd_lua_map_type {
RSPAMD_LUA_MAP_RADIX = 0,
RSPAMD_LUA_MAP_SET,
RSPAMD_LUA_MAP_HASH,
RSPAMD_LUA_MAP_CALLBACK
};

struct rspamd_lua_map {
struct rspamd_map *map;
enum rspamd_lua_map_type type;

union {
radix_compressed_t *radix;
GHashTable *hash;
gint cbref;
} data;
};

/* Radix tree */
LUA_FUNCTION_DEF (map, get_key);

static const struct luaL_reg maplib_m[] = {
LUA_INTERFACE_DEF (map, get_key),
{"__tostring", rspamd_lua_class_tostring},
{NULL, NULL}
};

struct rspamd_config *
lua_check_config (lua_State * L, gint pos)
{
@@ -451,14 +419,6 @@ lua_check_config (lua_State * L, gint pos)
return ud ? *((struct rspamd_config **)ud) : NULL;
}

static struct rspamd_lua_map *
lua_check_map (lua_State * L)
{
void *ud = luaL_checkudata (L, 1, "rspamd{map}");
luaL_argcheck (L, ud != NULL, 1, "'map' expected");
return ud ? *((struct rspamd_lua_map **)ud) : NULL;
}

/*** Config functions ***/
static gint
lua_config_get_api_version (lua_State *L)
@@ -761,161 +721,6 @@ lua_config_register_pre_filter (lua_State *L)
return 1;
}

static gint
lua_config_add_radix_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;

}

static gint
lua_config_radix_from_config (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *mname, *optname;
const ucl_object_t *obj;
struct rspamd_lua_map *map, **pmap;

if (!cfg) {
return luaL_error (L, "invalid arguments");
}

mname = luaL_checkstring (L, 2);
optname = luaL_checkstring (L, 3);

if (mname && optname) {
obj = rspamd_config_get_module_opt (cfg, mname, optname);
if (obj) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.radix = radix_create_compressed ();
map->type = RSPAMD_LUA_MAP_RADIX;
map->data.radix = radix_create_compressed ();
radix_add_generic_iplist (ucl_obj_tostring (obj), &map->data.radix);
pmap = lua_newuserdata (L, sizeof (void *));
*pmap = map;
rspamd_lua_setclass (L, "rspamd{map}", -1);
} else {
msg_warn_config ("Couldnt find config option [%s][%s]", mname,
optname);
lua_pushnil (L);
}

}
else {
return luaL_error (L, "invalid arguments");
}

return 1;
}

static gint
lua_config_add_hash_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;

}

static gint
lua_config_add_kv_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;
}

static gint
lua_config_get_key (lua_State *L)
{
@@ -1789,215 +1594,6 @@ lua_config_replace_regexp (lua_State *L)
return 0;
}

struct lua_map_callback_data {
lua_State *L;
gint ref;
GString *data;
struct rspamd_lua_map *lua_map;
};

static gchar *
lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len,
struct map_cb_data *data)
{
struct lua_map_callback_data *cbdata, *old;

if (data->cur_data == NULL) {
cbdata = g_slice_alloc0 (sizeof (*cbdata));
old = (struct lua_map_callback_data *)data->prev_data;
cbdata->L = old->L;
cbdata->ref = old->ref;
cbdata->lua_map = old->lua_map;
data->cur_data = cbdata;
}
else {
cbdata = (struct lua_map_callback_data *)data->cur_data;
}

if (cbdata->data == NULL) {
cbdata->data = g_string_new_len (chunk, len);
}
else {
g_string_append_len (cbdata->data, chunk, len);
}

return NULL;
}

void
lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data)
{
struct lua_map_callback_data *cbdata, *old;
struct rspamd_lua_map **pmap;

if (data->prev_data) {
/* Cleanup old data */
old = (struct lua_map_callback_data *)data->prev_data;
if (old->data) {
g_string_free (old->data, TRUE);
}
g_slice_free1 (sizeof (*old), old);
data->prev_data = NULL;
}

if (data->cur_data) {
cbdata = (struct lua_map_callback_data *)data->cur_data;
}
else {
msg_err_pool ("no data read for map");
return;
}

if (cbdata->data != NULL && cbdata->data->len != 0) {
lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->ref);
lua_pushlstring (cbdata->L, cbdata->data->str, cbdata->data->len);
pmap = lua_newuserdata (cbdata->L, sizeof (void *));
*pmap = cbdata->lua_map;
rspamd_lua_setclass (cbdata->L, "rspamd{map}", -1);

if (lua_pcall (cbdata->L, -1, 0, 0) != 0) {
msg_info_pool ("call to %s failed: %s", "local function",
lua_tostring (cbdata->L, -1));
lua_pop (cbdata->L, 1);
}
}
}

static gint
lua_config_add_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct lua_map_callback_data *cbdata, **pcbdata;
struct rspamd_lua_map *map;
struct rspamd_map *m;
int cbidx;

if (cfg) {
map_line = luaL_checkstring (L, 2);

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

if (lua_type (L, cbidx) == LUA_TFUNCTION) {
cbdata = g_slice_alloc (sizeof (*cbdata));
cbdata->L = L;
cbdata->data = NULL;
lua_pushvalue (L, cbidx);
/* Get a reference */
cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
map = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (*map));
map->type = RSPAMD_LUA_MAP_CALLBACK;
map->data.cbref = cbdata->ref;
cbdata->lua_map = map;
pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata));
*pcbdata = cbdata;

if ((m = rspamd_map_add (cfg, map_line, description,
lua_map_read, lua_map_fin,
(void **)pcbdata)) == NULL) {
msg_warn_config ("invalid hash map %s", map_line);
lua_pushboolean (L, false);
}
else {
map->map = m;
lua_pushboolean (L, true);
}
}
else {
msg_warn_config ("invalid callback argument for map %s", map_line);
lua_pushboolean (L, false);
}
}
else {
return luaL_error (L, "invalid arguments");
}

return 1;
}

/* Radix and hash table functions */
static gint
lua_map_get_key (lua_State * L)
{
struct rspamd_lua_map *map = lua_check_map (L);
radix_compressed_t *radix;
struct rspamd_lua_ip *addr = NULL;
const gchar *key, *value = NULL;
gpointer ud;
guint32 key_num = 0;
gboolean ret = FALSE;

if (map) {
if (map->type == RSPAMD_LUA_MAP_RADIX) {
radix = map->data.radix;

if (lua_type (L, 2) == LUA_TNUMBER) {
key_num = luaL_checknumber (L, 2);
key_num = htonl (key_num);
}
else if (lua_type (L, 2) == LUA_TUSERDATA) {
ud = luaL_checkudata (L, 2, "rspamd{ip}");
if (ud != NULL) {
addr = *((struct rspamd_lua_ip **)ud);
if (addr->addr == NULL) {
msg_err ("rspamd{ip} is not valid");
addr = NULL;
}
}
else {
msg_err ("invalid userdata type provided, rspamd{ip} expected");
}
}

if (addr != NULL) {
if (radix_find_compressed_addr (radix, addr->addr)
!= RADIX_NO_VALUE) {
ret = TRUE;
}
}
else if (key_num != 0) {
if (radix_find_compressed (radix, (guint8 *)&key_num, sizeof (key_num))
!= RADIX_NO_VALUE) {
ret = TRUE;
}
}
}
else if (map->type == RSPAMD_LUA_MAP_SET) {
key = lua_tostring (L, 2);

if (key) {
ret = g_hash_table_lookup (map->data.hash, key) != NULL;
}
}
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");
}

lua_pushboolean (L, ret);
return 1;
}

void
luaopen_config (lua_State * L)
{
@@ -2005,11 +1601,3 @@ luaopen_config (lua_State * L)

lua_pop (L, 1);
}

void
luaopen_map (lua_State * L)
{
rspamd_lua_new_class (L, "rspamd{map}", maplib_m);

lua_pop (L, 1);
}

+ 438
- 0
src/lua/lua_map.c 파일 보기

@@ -0,0 +1,438 @@
/*-
* Copyright 2016 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.
*/

#include "lua_common.h"
#include "libutil/map.h"
#include "libutil/map_private.h"
#include "libutil/radix.h"
#include "lua/lua_map.h"

/***
* This module is used to manage rspamd maps and map like objects
*
* @module rspamd_map
*/

/* Radix tree */
LUA_FUNCTION_DEF (map, get_key);

static const struct luaL_reg maplib_m[] = {
LUA_INTERFACE_DEF (map, get_key),
{"__tostring", rspamd_lua_class_tostring},
{NULL, NULL}
};

enum rspamd_lua_map_type {
RSPAMD_LUA_MAP_RADIX = 0,
RSPAMD_LUA_MAP_SET,
RSPAMD_LUA_MAP_HASH,
RSPAMD_LUA_MAP_CALLBACK
};

struct rspamd_map;
struct radix_tree_compressed;

struct rspamd_lua_map {
struct rspamd_map *map;
enum rspamd_lua_map_type type;

union {
struct radix_tree_compressed *radix;
GHashTable *hash;
gint cbref;
} data;
};

struct lua_map_callback_data {
lua_State *L;
gint ref;
GString *data;
struct rspamd_lua_map *lua_map;
};

static struct rspamd_lua_map *
lua_check_map (lua_State * L)
{
void *ud = luaL_checkudata (L, 1, "rspamd{map}");
luaL_argcheck (L, ud != NULL, 1, "'map' expected");
return ud ? *((struct rspamd_lua_map **)ud) : NULL;
}

gint
lua_config_add_radix_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;

}

gint
lua_config_radix_from_config (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *mname, *optname;
const ucl_object_t *obj;
struct rspamd_lua_map *map, **pmap;

if (!cfg) {
return luaL_error (L, "invalid arguments");
}

mname = luaL_checkstring (L, 2);
optname = luaL_checkstring (L, 3);

if (mname && optname) {
obj = rspamd_config_get_module_opt (cfg, mname, optname);
if (obj) {
map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map));
map->data.radix = radix_create_compressed ();
map->type = RSPAMD_LUA_MAP_RADIX;
map->data.radix = radix_create_compressed ();
radix_add_generic_iplist (ucl_obj_tostring (obj), &map->data.radix);
pmap = lua_newuserdata (L, sizeof (void *));
*pmap = map;
rspamd_lua_setclass (L, "rspamd{map}", -1);
} else {
msg_warn_config ("Couldnt find config option [%s][%s]", mname,
optname);
lua_pushnil (L);
}

}
else {
return luaL_error (L, "invalid arguments");
}

return 1;
}

gint
lua_config_add_hash_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;

}

gint
lua_config_add_kv_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct rspamd_lua_map *map, **pmap;
struct rspamd_map *m;

if (cfg) {
map_line = luaL_checkstring (L, 2);
description = lua_tostring (L, 3);
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;
}

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");
}

return 1;
}


static gchar *
lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len,
struct map_cb_data *data)
{
struct lua_map_callback_data *cbdata, *old;

if (data->cur_data == NULL) {
cbdata = g_slice_alloc0 (sizeof (*cbdata));
old = (struct lua_map_callback_data *)data->prev_data;
cbdata->L = old->L;
cbdata->ref = old->ref;
cbdata->lua_map = old->lua_map;
data->cur_data = cbdata;
}
else {
cbdata = (struct lua_map_callback_data *)data->cur_data;
}

if (cbdata->data == NULL) {
cbdata->data = g_string_new_len (chunk, len);
}
else {
g_string_append_len (cbdata->data, chunk, len);
}

return NULL;
}

static void
lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data)
{
struct lua_map_callback_data *cbdata, *old;
struct rspamd_lua_map **pmap;

if (data->prev_data) {
/* Cleanup old data */
old = (struct lua_map_callback_data *)data->prev_data;
if (old->data) {
g_string_free (old->data, TRUE);
}
g_slice_free1 (sizeof (*old), old);
data->prev_data = NULL;
}

if (data->cur_data) {
cbdata = (struct lua_map_callback_data *)data->cur_data;
}
else {
msg_err_pool ("no data read for map");
return;
}

if (cbdata->data != NULL && cbdata->data->len != 0) {
lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->ref);
lua_pushlstring (cbdata->L, cbdata->data->str, cbdata->data->len);
pmap = lua_newuserdata (cbdata->L, sizeof (void *));
*pmap = cbdata->lua_map;
rspamd_lua_setclass (cbdata->L, "rspamd{map}", -1);

if (lua_pcall (cbdata->L, -1, 0, 0) != 0) {
msg_info_pool ("call to %s failed: %s", "local function",
lua_tostring (cbdata->L, -1));
lua_pop (cbdata->L, 1);
}
}
}

gint
lua_config_add_map (lua_State *L)
{
struct rspamd_config *cfg = lua_check_config (L, 1);
const gchar *map_line, *description;
struct lua_map_callback_data *cbdata, **pcbdata;
struct rspamd_lua_map *map;
struct rspamd_map *m;
int cbidx;

if (cfg) {
map_line = luaL_checkstring (L, 2);

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

if (lua_type (L, cbidx) == LUA_TFUNCTION) {
cbdata = g_slice_alloc (sizeof (*cbdata));
cbdata->L = L;
cbdata->data = NULL;
lua_pushvalue (L, cbidx);
/* Get a reference */
cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
map = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (*map));
map->type = RSPAMD_LUA_MAP_CALLBACK;
map->data.cbref = cbdata->ref;
cbdata->lua_map = map;
pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata));
*pcbdata = cbdata;

if ((m = rspamd_map_add (cfg, map_line, description,
lua_map_read, lua_map_fin,
(void **)pcbdata)) == NULL) {
msg_warn_config ("invalid hash map %s", map_line);
lua_pushboolean (L, false);
}
else {
map->map = m;
lua_pushboolean (L, true);
}
}
else {
msg_warn_config ("invalid callback argument for map %s", map_line);
lua_pushboolean (L, false);
}
}
else {
return luaL_error (L, "invalid arguments");
}

return 1;
}

/* Radix and hash table functions */
static gint
lua_map_get_key (lua_State * L)
{
struct rspamd_lua_map *map = lua_check_map (L);
radix_compressed_t *radix;
struct rspamd_lua_ip *addr = NULL;
const gchar *key, *value = NULL;
gpointer ud;
guint32 key_num = 0;
gboolean ret = FALSE;

if (map) {
if (map->type == RSPAMD_LUA_MAP_RADIX) {
radix = map->data.radix;

if (lua_type (L, 2) == LUA_TNUMBER) {
key_num = luaL_checknumber (L, 2);
key_num = htonl (key_num);
}
else if (lua_type (L, 2) == LUA_TUSERDATA) {
ud = luaL_checkudata (L, 2, "rspamd{ip}");
if (ud != NULL) {
addr = *((struct rspamd_lua_ip **)ud);
if (addr->addr == NULL) {
msg_err ("rspamd{ip} is not valid");
addr = NULL;
}
}
else {
msg_err ("invalid userdata type provided, rspamd{ip} expected");
}
}

if (addr != NULL) {
if (radix_find_compressed_addr (radix, addr->addr)
!= RADIX_NO_VALUE) {
ret = TRUE;
}
}
else if (key_num != 0) {
if (radix_find_compressed (radix, (guint8 *)&key_num, sizeof (key_num))
!= RADIX_NO_VALUE) {
ret = TRUE;
}
}
}
else if (map->type == RSPAMD_LUA_MAP_SET) {
key = lua_tostring (L, 2);

if (key) {
ret = g_hash_table_lookup (map->data.hash, key) != NULL;
}
}
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");
}

lua_pushboolean (L, ret);
return 1;
}

void
luaopen_map (lua_State * L)
{
rspamd_lua_new_class (L, "rspamd{map}", maplib_m);

lua_pop (L, 1);
}

+ 28
- 0
src/lua/lua_map.h 파일 보기

@@ -0,0 +1,28 @@
/*-
* Copyright 2016 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.
*/
#ifndef SRC_LUA_LUA_MAP_H_
#define SRC_LUA_LUA_MAP_H_

#include "lua_common.h"

LUA_PUBLIC_FUNCTION_DEF (config, add_radix_map);
LUA_PUBLIC_FUNCTION_DEF (config, radix_from_config);
LUA_PUBLIC_FUNCTION_DEF (config, add_map);
LUA_PUBLIC_FUNCTION_DEF (config, add_hash_map);
LUA_PUBLIC_FUNCTION_DEF (config, add_kv_map);
LUA_PUBLIC_FUNCTION_DEF (config, add_map);

#endif /* SRC_LUA_LUA_MAP_H_ */

Loading…
취소
저장