Browse Source

Add an emitter from rcl object to lua.

tags/0.6.0
Vsevolod Stakhov 10 years ago
parent
commit
33d45e2650
6 changed files with 178 additions and 165 deletions
  1. 3
    8
      src/cfg_file.h
  2. 8
    85
      src/cfg_utils.c
  3. 2
    1
      src/lua/CMakeLists.txt
  4. 8
    0
      src/lua/lua_common.h
  5. 9
    71
      src/lua/lua_config.c
  6. 148
    0
      src/lua/lua_rcl.c

+ 3
- 8
src/cfg_file.h View File

@@ -348,8 +348,7 @@ struct config_file {
GList *workers; /**< linked list of all workers params */
struct rspamd_worker_cfg_parser *wrk_parsers; /**< hash for worker config parsers, indexed by worker quarks */
gchar *filters_str; /**< string of filters */
GHashTable* modules_opts; /**< hash for module options indexed by module name */
GHashTable* modules_metas; /**< hash for module meta options indexed by module name*/
rspamd_cl_object_t *rcl_obj; /**< rcl object */
GHashTable* variables; /**< hash of $variables defined in config, indexed by variable name */
GHashTable* metrics; /**< hash of metrics indexed by metric name */
GList* symbols_groups; /**< groups of symbols */
@@ -449,7 +448,8 @@ void free_config (struct config_file *cfg);
* @param opt_name name of option to get
* @return module value or NULL if option does not defined
*/
gchar* get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name);
rspamd_cl_object_t* get_module_opt (struct config_file *cfg, const gchar *module_name,
const gchar *opt_name);

/**
* Parse limit
@@ -534,11 +534,6 @@ gboolean parse_normalizer (struct config_file *cfg, struct statfile *st, const g
*/
gboolean read_xml_config (struct config_file *cfg, const gchar *filename);

/*
* Check modules configuration for semantic validity
*/
gboolean check_modules_config (struct config_file *cfg);

/*
* Register symbols of classifiers inside metrics
*/

+ 8
- 85
src/cfg_utils.c View File

@@ -241,8 +241,6 @@ init_defaults (struct config_file *cfg)
cfg->max_diff = 20480;

cfg->max_statfile_size = DEFAULT_STATFILE_SIZE;
cfg->modules_opts = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->modules_metas = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->variables = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->metrics = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
cfg->c_modules = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
@@ -267,9 +265,7 @@ free_config (struct config_file *cfg)
struct symbols_group *gr;

remove_all_maps (cfg);
g_hash_table_remove_all (cfg->modules_opts);
g_hash_table_unref (cfg->modules_opts);
g_hash_table_unref (cfg->modules_metas);
rspamd_cl_obj_unref (cfg->rcl_obj);
g_hash_table_remove_all (cfg->variables);
g_hash_table_unref (cfg->variables);
g_hash_table_remove_all (cfg->metrics);
@@ -303,51 +299,17 @@ free_config (struct config_file *cfg)
memory_pool_delete (cfg->cfg_pool);
}

gchar *
get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name)
rspamd_cl_object_t *
get_module_opt (struct config_file *cfg, const gchar *module_name, const gchar *opt_name)
{
GList *cur_opt;
struct module_opt *cur;
static gchar numbuf[64];
rspamd_cl_object_t *res = NULL, *sec;

cur_opt = g_hash_table_lookup (cfg->modules_opts, module_name);
if (cur_opt == NULL) {
return NULL;
sec = rspamd_cl_obj_get_key (cfg->rcl_obj, module_name);
if (sec != NULL) {
res = rspamd_cl_obj_get_key (cfg->rcl_obj, opt_name);
}

while (cur_opt) {
cur = cur_opt->data;
if (strcmp (cur->param, opt_name) == 0) {
/* Check if it is lua variable */
if (! cur->is_lua) {
/* Plain variable */
return cur->value;
}
else {
/* Check type */
switch (cur->lua_type) {
case LUA_VAR_NUM:
/* numbuf is static, so it is safe to return it "as is" */
snprintf (numbuf, sizeof (numbuf), "%f", *(double *)cur->actual_data);
return numbuf;
case LUA_VAR_BOOLEAN:
snprintf (numbuf, sizeof (numbuf), "%s", *(gboolean *)cur->actual_data ? "yes" : "no");
return numbuf;
case LUA_VAR_STRING:
return (gchar *)cur->actual_data;
case LUA_VAR_FUNCTION:
msg_info ("option %s is dynamic, so it cannot be aqquired statically", opt_name);
return NULL;
case LUA_VAR_UNKNOWN:
msg_info ("option %s has unknown type, maybe there is error in LUA code", opt_name);
return NULL;
}
}
}
cur_opt = g_list_next (cur_opt);
}

return NULL;
return res;
}

guint64
@@ -696,7 +658,6 @@ post_load_config (struct config_file *cfg)
struct metric *def_metric;

g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg);
g_hash_table_foreach (cfg->modules_opts, substitute_module_variables, cfg);
fill_cfg_params (cfg);

#ifdef HAVE_CLOCK_GETTIME
@@ -1042,44 +1003,6 @@ read_xml_config (struct config_file *cfg, const gchar *filename)
return res;
}

static void
modules_config_callback (gpointer key, gpointer value, gpointer ud)
{
extern GHashTable *module_options;
GHashTable *cur_module;
GList *cur;
struct module_opt *opt;
const gchar *mname = key;
gboolean *res = ud;

if ((cur_module = g_hash_table_lookup (module_options, mname)) == NULL) {
msg_warn ("module %s has not registered any options but is presented in configuration", mname);
*res = FALSE;
return;
}

cur = value;
while (cur) {
opt = cur->data;

if (!opt->is_lua && !check_module_option (mname, opt->param, opt->value)) {
*res = FALSE;
return;
}

cur = g_list_next (cur);
}
}

gboolean
check_modules_config (struct config_file *cfg)
{
gboolean res = TRUE;

g_hash_table_foreach (cfg->modules_opts, modules_config_callback, &res);
return res;
}

static void
symbols_classifiers_callback (gpointer key, gpointer value, gpointer ud)
{

+ 2
- 1
src/lua/CMakeLists.txt View File

@@ -15,7 +15,8 @@ SET(LUASRC lua_common.c
lua_session.c
lua_buffer.c
lua_dns.c
lua_rsa.c)
lua_rsa.c
lua_rcl.c)

ADD_LIBRARY(rspamd-lua ${LINK_TYPE} ${LUASRC})
SET_TARGET_PROPERTIES(rspamd-lua PROPERTIES VERSION ${RSPAMD_VERSION})

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

@@ -6,6 +6,7 @@

#include "main.h"
#include "cfg_file.h"
#include "rcl/rcl.h"
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@@ -101,6 +102,13 @@ struct lua_locked_state* init_lua_locked (struct config_file *cfg);
*/
void free_lua_locked (struct lua_locked_state *st);

/**
* Push an rcl object to lua
* @param L lua state
* @param obj object to push
*/
gint lua_rcl_obj_push (lua_State *L, rspamd_cl_object_t *obj);

/**
* Open libraries functions
*/

+ 9
- 71
src/lua/lua_config.c View File

@@ -153,17 +153,17 @@ static gint
lua_config_get_module_opt (lua_State * L)
{
struct config_file *cfg = lua_check_config (L);
const gchar *mname, *optname, *val;
const gchar *mname, *optname;
rspamd_cl_object_t *obj;

if (cfg) {
mname = luaL_checkstring (L, 2);
optname = luaL_checkstring (L, 3);

if (mname && optname) {
val = get_module_opt (cfg, (gchar *)mname, (gchar *)optname);
if (val) {
lua_pushstring (L, val);
return 1;
obj = get_module_opt (cfg, mname, optname);
if (obj) {
return lua_rcl_obj_push (L, obj);
}
}
}
@@ -185,83 +185,21 @@ lua_config_get_mempool (lua_State * L)
return 1;
}

static gint
opt_compare (gconstpointer a, gconstpointer b)
{
const struct module_opt *o1 = a,
*o2 = b;
return g_ascii_strcasecmp (o1->param, o2->param);
}

static gint
lua_config_get_all_opt (lua_State * L)
{
struct config_file *cfg = lua_check_config (L);
const gchar *mname;
GList *cur_opt, *next_opt;
struct module_opt *opt, *tmp;
gint i;
rspamd_cl_object_t *obj;

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

if (mname) {
cur_opt = g_hash_table_lookup (cfg->modules_opts, mname);
if (cur_opt == NULL) {
lua_pushnil (L);
return 1;
obj = rspamd_cl_obj_get_key (cfg->rcl_obj, mname);
if (obj != NULL) {
return lua_rcl_obj_push (L, obj);
}
/* Sort options in alphabet order by param name */
cur_opt = g_list_sort (cur_opt, opt_compare);
g_hash_table_insert (cfg->modules_opts, (gpointer)mname, cur_opt);

lua_newtable (L);
while (cur_opt) {
opt = cur_opt->data;
next_opt = g_list_next (cur_opt);
if (next_opt) {
tmp = next_opt->data;
if (g_ascii_strcasecmp (tmp->param, opt->param) == 0) {
/* We have some common values */
lua_pushstring (L, opt->param);
lua_newtable (L);
/* Now stack looks like:
* table - parent associated table of options
* key - string key of this option
* table - array of values, beginig from 1
*/
for (i = 1; ; i++) {
lua_pushinteger (L, i);
lua_pushstring (L, opt->value);
lua_settable (L, -3);

cur_opt = g_list_next (cur_opt);
if (!cur_opt) {
break;
}
tmp = cur_opt->data;
if (g_ascii_strcasecmp (tmp->param, opt->param) != 0) {
break;
}
opt = tmp;
}
/* Now set index in parent table */
lua_settable (L, -3);
/* Now continue in outter cycle */
continue;
}
else {
lua_set_table_index (L, opt->param, opt->value);
}
}
else {
lua_set_table_index (L, opt->param, opt->value);
}
cur_opt = next_opt;
}
return 1;
}
}
lua_pushnil (L);

+ 148
- 0
src/lua/lua_rcl.c View File

@@ -0,0 +1,148 @@
/* Copyright (c) 2013, Vsevolod Stakhov
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "lua_common.h"
#include "rcl/rcl.h"

/**
* @file lua rcl bindings
*/

static gint lua_rcl_obj_push_array (lua_State *L, rspamd_cl_object_t *obj);
static gint lua_rcl_obj_push_simple (lua_State *L, rspamd_cl_object_t *obj);

/**
* Push a single element of an object to lua
* @param L
* @param key
* @param obj
*/
static void
lua_rcl_obj_push_elt (lua_State *L, const char *key, rspamd_cl_object_t *obj)
{
lua_pushstring (L, key);
lua_push_obj_simple (L, obj);
lua_settable (L, -3);
}

/**
* Push a single object to lua
* @param L
* @param obj
* @return
*/
static gint
lua_rcl_obj_push_obj (lua_State *L, rspamd_cl_object_t *obj)
{
rspamd_cl_object_t *cur, *tmp;

if (obj->next != NULL) {
/* Actually we need to push this as an array */
return lua_rcl_obj_push_array (L, obj);
}

lua_newtable (L);
HASH_ITER (hh, obj, cur, tmp) {
lua_rcl_obj_push_elt (L, obj->key, obj);
}

return 1;
}

/**
* Push an array to lua as table indexed by integers
* @param L
* @param obj
* @return
*/
static gint
lua_rcl_obj_push_array (lua_State *L, rspamd_cl_object_t *obj)
{
rspamd_cl_object_t *cur;
gint i = 1;

lua_newtable (L);

LL_FOREACH (obj, cur) {
lua_rcl_obj_push (L, cur);
lua_rawseti (L, -2, i);
i ++;
}

return 1;
}

/**
* Push a simple object to lua depending on its actual type
*/
static gint
lua_rcl_obj_push_simple (lua_State *L, rspamd_cl_object_t *obj)
{
if (obj->next != NULL) {
/* Actually we need to push this as an array */
return lua_rcl_obj_push_array (L, obj);
}

switch (obj->type) {
case RSPAMD_CL_BOOLEAN:
lua_pushboolean (L, rspamd_cl_obj_toboolean (obj));
break;
case RSPAMD_CL_STRING:
lua_pushstring (L, rspamd_cl_obj_tostring (obj));
break;
case RSPAMD_CL_INT:
#if LUA_VERSION_NUM >= 501
lua_pushinteger (L, rspamd_cl_obj_toint (obj));
#else
lua_pushnumber (L, rspamd_cl_obj_toint (obj));
#endif
break;
case RSPAMD_CL_FLOAT:
case RSPAMD_CL_TIME:
lua_pushnumber (L, rspamd_cl_obj_todouble (obj));
break;
default:
lua_pushnil (L);
break;
}

return 1;
}

/**
* Push an object to lua
* @param L lua state
* @param obj object to push
*/
gint
lua_rcl_obj_push (lua_State *L, rspamd_cl_object_t *obj)
{
switch (obj->type) {
case RSPAMD_CL_OBJECT:
return lua_rcl_obj_push_obj (L, obj->value.ov);
case RSPAMD_CL_ARRAY:
return lua_rcl_obj_push_array (L, obj->value.ov);
default:
return lua_rcl_obj_push_simple (L, obj);
}
}

Loading…
Cancel
Save