Module: sip-router Branch: master Commit: bcf3fff9389fc06a0fcc92f7e9875b185929987f URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=bcf3fff9...
Author: Miklos Tirpak miklos@iptel.org Committer: Miklos Tirpak miklos@iptel.org Date: Tue Jun 30 17:33:52 2009 +0200
cfg framework: read variables by name with a handle
- read_cfg_var() is introduced which allows reading even the custom declared variables from the modules. It requires a handle returned by read_cfg_var_fixup() - read_cfg_var_int() and read_cfg_var_str() are wrapper functions
---
cfg/cfg_ctx.c | 4 +- cfg/cfg_ctx.h | 4 ++ cfg/cfg_select.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++++- cfg/cfg_select.h | 24 +++++++++ 4 files changed, 171 insertions(+), 3 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c index 04ee5f1..ef3661c 100644 --- a/cfg/cfg_ctx.c +++ b/cfg/cfg_ctx.c @@ -129,7 +129,7 @@ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def) static char *temp_string = NULL;
/* convert the value to the requested type */ -static int convert_val(unsigned int val_type, void *val, +int convert_val(unsigned int val_type, void *val, unsigned int var_type, void **new_val) { static str s; @@ -482,7 +482,7 @@ static int cfg_var_size(cfg_mapping_t *var) return sizeof(void *);
default: - LOG(L_CRIT, "BUG: cfg_var_sizeK(): unknown type: %u\n", + LOG(L_CRIT, "BUG: cfg_var_size(): unknown type: %u\n", CFG_VAR_TYPE(var)); return 0; } diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h index 07cf734..e738c96 100644 --- a/cfg/cfg_ctx.h +++ b/cfg/cfg_ctx.h @@ -108,6 +108,10 @@ int cfg_help(cfg_ctx_t *ctx, str *group_name, str *var_name, /* notify the drivers about the new config definition */ void cfg_notify_drivers(char *group_name, int group_name_len, cfg_def_t *def);
+/* convert the value to the requested type */ +int convert_val(unsigned int val_type, void *val, + unsigned int var_type, void **new_val); + /* initialize the handle for cfg_get_group_next() */ #define cfg_get_group_init(handle) \ (*(handle)) = (void *)cfg_group diff --git a/cfg/cfg_select.c b/cfg/cfg_select.c index 72168d7..45aeb94 100644 --- a/cfg/cfg_select.c +++ b/cfg/cfg_select.c @@ -33,6 +33,7 @@ #include "../select.h" #include "../ut.h" #include "cfg_struct.h" +#include "cfg_ctx.h" #include "cfg_select.h"
/* It may happen that the select calls cannot be fixed up before shmizing @@ -200,7 +201,7 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg) if (!group || !var) return -1;
/* use the module's handle to access the variable, so the variables - are read from private memory */ + are read from the local config */ p = *(group->handle) + var->offset;
switch (CFG_VAR_TYPE(var)) { @@ -220,6 +221,145 @@ int select_cfg_var(str *res, select_t *s, struct sip_msg *msg) memcpy(res, p, sizeof(str)); break;
+ default: + LOG(L_DBG, "DEBUG: select_cfg_var(): unsupported variable type: %d\n", + CFG_VAR_TYPE(var)); + return -1; } return 0; } + +/* fix-up function for read_cfg_var() + * + * return value: + * >0 - success + * 0 - the variable has not been declared yet, but it will be automatically + * fixed-up later. + * <0 - error + */ +int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle) +{ + cfg_group_t *group; + cfg_mapping_t *var; + str group_name, var_name; + + if (!gname || !vname || !read_handle) + return -1; + + group_name.s = gname; + group_name.len = strlen(gname); + var_name.s = vname; + var_name.len = strlen(vname); + + /* look-up the group and the variable */ + if (cfg_lookup_var(&group_name, &var_name, &group, &var)) { + if (cfg_shmized) { + LOG(L_ERR, "ERROR: read_cfg_var_fixup(): unknown variable: %.*s.%.*s\n", + group_name.len, group_name.s, + var_name.len, var_name.s); + return -1; + } + /* The variable was not found, add it to the non-fixed select list. + * So we act as if the fixup was successful, and we retry it later */ + if (cfg_new_select(&group_name, &var_name, + &read_handle->group, &read_handle->var)) + return -1; + + LOG(L_DBG, "DEBUG: read_cfg_var_fixup(): cfg read fixup is postponed: %.*s.%.*s\n", + group_name.len, group_name.s, + var_name.len, var_name.s); + + read_handle->group = NULL; + read_handle->var = NULL; + return 0; + } + + if (var->def->on_change_cb) { + /* fixup function is defined -- safer to return an error + than an incorrect value */ + LOG(L_ERR, "ERROR: read_cfg_var_fixup(): variable cannot be retrieved\n"); + return -1; + } + + read_handle->group = (void *)group; + read_handle->var = (void *)var; + return 1; +} + +/* read the value of a variable via a group and variable name previously fixed up + * Returns the type of the variable + */ +unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val) +{ + cfg_group_t *group; + cfg_mapping_t *var; + void *p; + static str s; + + if (!val || !read_handle || !read_handle->group || !read_handle->var) + return 0; + + group = (cfg_group_t *)(read_handle->group); + var = (cfg_mapping_t *)(read_handle->var); + + /* use the module's handle to access the variable, so the variables + are read from the local config */ + p = *(group->handle) + var->offset; + + switch (CFG_VAR_TYPE(var)) { + case CFG_VAR_INT: + *val = (void *)(long)*(int *)p; + break; + + case CFG_VAR_STRING: + *val = (void *)*(char **)p; + break; + + case CFG_VAR_STR: + memcpy(&s, p, sizeof(str)); + *val = (void *)&s; + break; + + case CFG_VAR_POINTER: + *val = *(void **)p; + break; + + } + return CFG_VAR_TYPE(var); +} + +/* wrapper function for read_cfg_var() -- convert the value to integer + * returns -1 on error, 0 on success + */ +int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val) +{ + unsigned int type; + void *v1, *v2; + + if ((type = read_cfg_var(read_handle, &v1)) == 0) + return -1; + + if (convert_val(type, v1, CFG_INPUT_INT, &v2)) + return -1; + + *val = (int)(long)(v2); + return 0; +} + +/* wrapper function for read_cfg_var() -- convert the value to str + * returns -1 on error, 0 on success + */ +int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val) +{ + unsigned int type; + void *v1, *v2; + + if ((type = read_cfg_var(read_handle, &v1)) == 0) + return -1; + + if (convert_val(type, v1, CFG_INPUT_STR, &v2)) + return -1; + + *val = *(str *)(v2); + return 0; +} diff --git a/cfg/cfg_select.h b/cfg/cfg_select.h index 9f9b186..6a03dd2 100644 --- a/cfg/cfg_select.h +++ b/cfg/cfg_select.h @@ -34,6 +34,11 @@
#include "../select.h"
+struct cfg_read_handle { + void *group; + void *var; +}; + /* free the list of not yet fixed selects */ void cfg_free_selects();
@@ -42,4 +47,23 @@ int cfg_fixup_selects();
int select_cfg_var(str *res, select_t *s, struct sip_msg *msg);
+/* fix-up function for read_cfg_var() + * + * return value: + * >0 - success + * 0 - the variable has not been declared yet, but it will be automatically + * fixed-up later. + * <0 - error + */ +int read_cfg_var_fixup(char *gname, char *vname, struct cfg_read_handle *read_handle); + +/* read the value of a variable via a group and variable name previously fixed up + * Returns the type of the variable + */ +unsigned int read_cfg_var(struct cfg_read_handle *read_handle, void **val); + +/* wrapper functions for read_cfg_var() -- convert the value to the requested format */ +int read_cfg_var_int(struct cfg_read_handle *read_handle, int *val); +int read_cfg_var_str(struct cfg_read_handle *read_handle, str *val); + #endif /* _CFG_SELECT_H */