Module: sip-router
Branch: master
Commit: bcf3fff9389fc06a0fcc92f7e9875b185929987f
URL:
http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=bcf3fff…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)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 */