Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 99b680c32a92d5d528b7b4375ed8c2974221bc45
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=99b680c…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 14 15:49:25 2010 +0200
cfg framework: error messages added
When a group instance is deleted while there are pending changes
to this instance which are not yet committed, the commit failed
without any error. An error message is added, and cfg_diff_next returns
also error in this case to let the drivers farther propagate the error.
---
cfg/cfg_ctx.c | 13 ++++++++++---
cfg/cfg_ctx.h | 13 +++++++++++--
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index 9413d75..534cf49 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -1027,8 +1027,11 @@ int cfg_commit(cfg_ctx_t *ctx)
group = changed->group;
if (!(CFG_GROUP_META(block, group)->array =
cfg_clone_array(CFG_GROUP_META(*cfg_global, group), group))
- )
+ ) {
+ LOG(L_ERR, "ERROR: cfg_set_now(): group array cannot be cloned for %.*s[%u]\n",
+ group->name_len, group->name, changed->group_id);
goto error;
+ }
replaced[replaced_num] = CFG_GROUP_META(*cfg_global, group)->array;
replaced_num++;
@@ -1318,6 +1321,10 @@ int cfg_diff_init(cfg_ctx_t *ctx,
/* return the pending changes that have not been
* committed yet
+ * return value:
+ * 1: valid value is found
+ * 0: no more changed value found
+ * -1: error occured
*/
int cfg_diff_next(void **h,
str *gname, unsigned int **gid, str *vname,
@@ -1348,7 +1355,7 @@ int cfg_diff_next(void **h,
} else {
if (!cfg_local) {
LOG(L_ERR, "ERROR: cfg_diff_next(): Local configuration is missing\n");
- return 0;
+ return -1;
}
group_inst = cfg_find_group(CFG_GROUP_META(cfg_local, changed->group),
changed->group->size,
@@ -1356,7 +1363,7 @@ int cfg_diff_next(void **h,
if (!group_inst) {
LOG(L_ERR, "ERROR: cfg_diff_next(): local group instance %.*s[%u] is not found\n",
changed->group->name_len, changed->group->name, changed->group_id);
- return 0;
+ return -1;
}
pval = (union cfg_var_value*)
(group_inst->vars + changed->var->offset);
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 1bfd348..8a0836e 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -157,19 +157,28 @@ int cfg_diff_init(cfg_ctx_t *ctx,
/*! \brief return the pending changes that have not been
* committed yet
+ * return value:
+ * 1: valid value is found
+ * 0: no more changed value found
+ * -1: error occured
+ *
*
* can be used as follows:
*
* void *handle;
* if (cfg_diff_init(ctx, &handle)) return -1
- * while (cfg_diff_next(&handle
+ * while ((err = cfg_diff_next(&handle
* &group_name, &group_id, &var_name,
* &old_val, &new_val
- * &val_type)
+ * &val_type)) > 0
* ) {
* ...
* }
* cfg_diff_release(ctx);
+ * if (err) {
+ * error occured, the changes cannot be retrieved
+ * ...
+ * }
*/
int cfg_diff_next(void **h,
str *gname, unsigned int **gid, str *vname,
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 8e1d174cc6ddcbdb573e2f6435ed2086d5b1c5ac
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=8e1d174…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Thu Sep 9 16:21:41 2010 +0200
cfg framework: group instances can be deleted + bugfix
- cfg_del_group_inst() is added which can be used to delete
the group instances apart from the default one.
- cfg_find_group_inst() used a wrong offset for shifting.
- The copies of the default variable needs to be updated even if the variable
is atomic.
---
cfg/cfg_ctx.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++----
cfg/cfg_ctx.h | 3 +
cfg/cfg_struct.c | 43 +++++++++++++++++++++-
cfg/cfg_struct.h | 7 +++
4 files changed, 151 insertions(+), 10 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index b0fa851..3ecc69e 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -274,10 +274,11 @@ static int cfg_update_defaults(cfg_group_meta_t *meta,
int i, clone_done=0;
cfg_group_inst_t *array, *ginst;
- array = meta->array;
+ if (!(array = meta->array))
+ return 0;
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)array
- + (sizeof(cfg_group_meta_t) + group->size - 1) * i);
+ + (sizeof(cfg_group_inst_t) + group->size - 1) * i);
if (!CFG_VAR_TEST(ginst, var)) {
/* The variable uses the default value, it needs to be rewritten. */
@@ -514,15 +515,15 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, unsigned int *group_id, str *va
it cannot be freed */
if (cfg_shmized) {
- if (!group_inst && block && CFG_GROUP_META(block, group)->array) {
- if (cfg_update_defaults(CFG_GROUP_META(block, group),
+ if (!group_inst) {
+ /* the default value is changed, the copies of this value
+ need to be also updated */
+ if (cfg_update_defaults(CFG_GROUP_META(block ? block : *cfg_global, group),
group, var, p,
- ((var->def->type & CFG_ATOMIC) == 0)) /* clone if needed */
- ) {
- LOG(L_ERR, "ERROR: cfg_set_now(): not enough shm memory\n");
+ block ? 1 : 0) /* clone if needed */
+ )
goto error;
- }
- if (CFG_GROUP_META(block, group)->array != CFG_GROUP_META(*cfg_global, group)->array)
+ if (block && (CFG_GROUP_META(block, group)->array != CFG_GROUP_META(*cfg_global, group)->array))
new_array = CFG_GROUP_META(block, group)->array;
}
@@ -1338,3 +1339,92 @@ error:
return -1;
}
+
+/* Delete an instance of a group */
+int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id)
+{
+ cfg_group_t *group;
+ cfg_block_t *block = NULL;
+ void **replaced = NULL;
+ cfg_group_inst_t *new_array = NULL, *group_inst;
+
+ /* verify the context even if we do not need it now
+ to make sure that a cfg driver has called the function
+ (very very weak security) */
+ if (!ctx) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): context is undefined\n");
+ return -1;
+ }
+
+ if (!cfg_shmized) {
+ /* It makes no sense to delete a group instance that has not
+ been created yet */
+ return -1;
+ }
+
+ if (!(group = cfg_lookup_group(group_name->s, group_name->len))) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): group not found\n");
+ return -1;
+ }
+
+ /* make sure that nobody else replaces the global config
+ while the new one is prepared */
+ CFG_WRITER_LOCK();
+ if (!(group_inst = cfg_find_group(CFG_GROUP_META(*cfg_global, group),
+ group->size,
+ group_id))
+ ) {
+ LOG(L_DBG, "DEBUG: cfg_del_group_inst(): the group instance does not exist\n");
+ goto error;
+ }
+
+ /* clone the global memory block because the additional array can be
+ replaced only together with the block. */
+ if (!(block = cfg_clone_global()))
+ goto error;
+
+ /* Remove the group instance from the array. */
+ if (cfg_collapse_array(CFG_GROUP_META(*cfg_global, group), group,
+ group_inst,
+ &new_array)
+ )
+ goto error;
+
+ CFG_GROUP_META(block, group)->array = new_array;
+ CFG_GROUP_META(block, group)->num--;
+
+ if (CFG_GROUP_META(*cfg_global, group)->array) {
+ /* prepare the array of the replaced strings,
+ and replaced group instances,
+ they will be freed when the old block is freed */
+ replaced = (void **)shm_malloc(sizeof(void *) * 2);
+ if (!replaced) {
+ LOG(L_ERR, "ERROR: cfg_del_group_inst(): not enough shm memory\n");
+ goto error;
+ }
+ replaced[0] = CFG_GROUP_META(*cfg_global, group)->array;
+ replaced[1] = NULL;
+ }
+ /* replace the global config with the new one */
+ cfg_install_global(block, replaced, NULL, NULL);
+ CFG_WRITER_UNLOCK();
+
+ LOG(L_INFO, "INFO: cfg_del_group_inst(): "
+ "group instance is deleted: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return 0;
+error:
+ CFG_WRITER_UNLOCK();
+ if (block) cfg_block_free(block);
+ if (new_array) shm_free(new_array);
+ if (replaced) shm_free(replaced);
+
+ LOG(L_ERR, "ERROR: cfg_add_group_inst(): "
+ "Failed to delete the group instance: %.*s[%u]\n",
+ group_name->len, group_name->s,
+ group_id);
+
+ return -1;
+}
diff --git a/cfg/cfg_ctx.h b/cfg/cfg_ctx.h
index 255911e..964e7f5 100644
--- a/cfg/cfg_ctx.h
+++ b/cfg/cfg_ctx.h
@@ -180,4 +180,7 @@ void cfg_diff_release(cfg_ctx_t *ctx);
/* Add a new instance to an existing group */
int cfg_add_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
+/* Delete an instance of a group */
+int cfg_del_group_inst(cfg_ctx_t *ctx, str *group_name, unsigned int group_id);
+
#endif /* _CFG_CTX_H */
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index 77d7cf5..9d5f008 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -645,6 +645,47 @@ cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
return new_array;
}
+/* Remove an instance from a group array.
+ * inst must point to an instance within meta->array.
+ * *_new_array is set to the newly allocated array. */
+int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ cfg_group_inst_t *inst,
+ cfg_group_inst_t **_new_array)
+{
+ cfg_group_inst_t *new_array, *old_array;
+ int inst_size, offset;
+
+ if (!meta->num)
+ return -1;
+
+ if (meta->num == 1) {
+ *_new_array = NULL;
+ return 0;
+ }
+
+ inst_size = sizeof(cfg_group_inst_t) + group->size - 1;
+ new_array = (cfg_group_inst_t *)shm_malloc(inst_size * (meta->num - 1));
+ if (!new_array) {
+ LOG(L_ERR, "ERROR: cfg_collapse_array(): not enough shm memory\n");
+ return -1;
+ }
+
+ old_array = meta->array;
+ offset = (char *)inst - (char *)old_array;
+ if (offset)
+ memcpy( new_array,
+ old_array,
+ offset);
+
+ if (meta->num * inst_size > offset + inst_size)
+ memcpy( (char *)new_array + offset,
+ (char *)old_array + offset + inst_size,
+ (meta->num - 1) * inst_size - offset);
+
+ *_new_array = new_array;
+ return 0;
+}
+
/* Find the group instance within the meta-data based on the group_id */
cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigned int group_id)
{
@@ -658,7 +699,7 @@ cfg_group_inst_t *cfg_find_group(cfg_group_meta_t *meta, int group_size, unsigne
TODO: improve */
for (i = 0; i < meta->num; i++) {
ginst = (cfg_group_inst_t *)((char *)meta->array
- + (sizeof(cfg_group_meta_t) + group_size - 1) * i);
+ + (sizeof(cfg_group_inst_t) + group_size - 1) * i);
if (ginst->id == group_id)
return ginst;
else if (ginst->id > group_id)
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index 65519e2..5f1fa0a 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -381,6 +381,13 @@ cfg_group_inst_t *cfg_extend_array(cfg_group_meta_t *meta, cfg_group_t *group,
unsigned int group_id,
cfg_group_inst_t **new_group);
+/* Remove an instance from a group array.
+ * inst must point to an instance within meta->array.
+ * *_new_array is set to the newly allocated array. */
+int cfg_collapse_array(cfg_group_meta_t *meta, cfg_group_t *group,
+ cfg_group_inst_t *inst,
+ cfg_group_inst_t **_new_array);
+
/* clones a string to shared memory */
int cfg_clone_str(str *src, str *dst);
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: ec5bc6bb857b9c285bd849f1112acaeaf8e2d13b
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=ec5bc6b…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 14 15:33:29 2010 +0200
cfg framework: support for group instances with delayed commits
cfg_set_delayed() and the related functions, commit, diff,... support
the additinal group instances from now.
The group instance must exist before cfg_set_delayed() is called, i.e.
the function does not create new instances.
---
cfg/cfg_ctx.c | 242 +++++++++++++++++++++++++++++++++++++++++++++++----------
cfg/cfg_ctx.h | 8 +-
2 files changed, 205 insertions(+), 45 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=ec5…
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: f845759d1422689ad37df695a6843f07fcd29197
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=f845759…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 14 15:53:06 2010 +0200
cfg_rpc: Support for cfg group instances added.
The RPC interface of the configuration framework is updated
to the latest core changes, i.e. the support for additional group
instances is introduced.
The syntax is backward compatible:
- To set the default value:
cfg.set_now_int/string group var value
cfg.set_delayed_int/string group var value
- To set a value within a specific instance:
cfg.set_now_int/string group[id] var value
cfg_set_delayed_int/string group[id] var value
"id" is the integer identifier of the group instance which needs to
be created with:
cfg.add_group_inst group[id]
The instance can also be deleted with:
cfg.del_group_inst group[id]
Note that the variables of a group instance take the default values
from the active configucation after the instance is created. When a
default value changes within a group, the group instance values are
also updated with the change unless the variable has been explicitly
set in the group instance.
---
modules/cfg_rpc/cfg_rpc.c | 146 +++++++++++++++++++++++++++++++++++++++++----
1 files changed, 135 insertions(+), 11 deletions(-)
diff --git a/modules/cfg_rpc/cfg_rpc.c b/modules/cfg_rpc/cfg_rpc.c
index ebd0451..f982d40 100644
--- a/modules/cfg_rpc/cfg_rpc.c
+++ b/modules/cfg_rpc/cfg_rpc.c
@@ -49,6 +49,40 @@ static int mod_init(void)
return 0;
}
+/* Set the group_id pointer based on the group string.
+ * The string is either "group_name", or "group_name[group_id]"
+ * *group_id is set to null in the former case.
+ * Warning: changes the group string
+ */
+static int get_group_id(str *group, unsigned int **group_id)
+{
+ static unsigned int id;
+ str s;
+
+ if (!group->s || (group->s[group->len-1] != ']')) {
+ *group_id = NULL;
+ return 0;
+ }
+
+ s.s = group->s + group->len - 2;
+ s.len = 0;
+ while ((s.s > group->s) && (*s.s != '[')) {
+ s.s--;
+ s.len++;
+ }
+ if (s.s == group->s) /* '[' not found */
+ return -1;
+ group->len = s.s - group->s;
+ s.s++;
+ if (!group->len || !s.len)
+ return -1;
+ if (str2int(&s, &id))
+ return -1;
+
+ *group_id = &id;
+ return 0;
+}
+
static const char* rpc_set_now_doc[2] = {
"Set the value of a configuration variable and commit the change immediately",
0
@@ -58,11 +92,17 @@ static void rpc_set_now_int(rpc_t* rpc, void* c)
{
str group, var;
int i;
+ unsigned int *group_id;
if (rpc->scan(c, "SSd", &group, &var, &i) < 3)
return;
- if (cfg_set_now_int(ctx, &group, &var, i)) {
+ if (get_group_id(&group, &group_id)) {
+ rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+ return;
+ }
+
+ if (cfg_set_now_int(ctx, &group, group_id, &var, i)) {
rpc->fault(c, 400, "Failed to set the variable");
return;
}
@@ -72,11 +112,17 @@ static void rpc_set_now_string(rpc_t* rpc, void* c)
{
str group, var;
char *ch;
+ unsigned int *group_id;
if (rpc->scan(c, "SSs", &group, &var, &ch) < 3)
return;
- if (cfg_set_now_string(ctx, &group, &var, ch)) {
+ if (get_group_id(&group, &group_id)) {
+ rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+ return;
+ }
+
+ if (cfg_set_now_string(ctx, &group, group_id, &var, ch)) {
rpc->fault(c, 400, "Failed to set the variable");
return;
}
@@ -91,11 +137,17 @@ static void rpc_set_delayed_int(rpc_t* rpc, void* c)
{
str group, var;
int i;
+ unsigned int *group_id;
if (rpc->scan(c, "SSd", &group, &var, &i) < 3)
return;
- if (cfg_set_delayed_int(ctx, &group, &var, i)) {
+ if (get_group_id(&group, &group_id)) {
+ rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+ return;
+ }
+
+ if (cfg_set_delayed_int(ctx, &group, group_id, &var, i)) {
rpc->fault(c, 400, "Failed to set the variable");
return;
}
@@ -105,11 +157,17 @@ static void rpc_set_delayed_string(rpc_t* rpc, void* c)
{
str group, var;
char *ch;
+ unsigned int *group_id;
if (rpc->scan(c, "SSs", &group, &var, &ch) < 3)
return;
- if (cfg_set_delayed_string(ctx, &group, &var, ch)) {
+ if (get_group_id(&group, &group_id)) {
+ rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+ return;
+ }
+
+ if (cfg_set_delayed_string(ctx, &group, group_id, &var, ch)) {
rpc->fault(c, 400, "Failed to set the variable");
return;
}
@@ -152,11 +210,17 @@ static void rpc_get(rpc_t* rpc, void* c)
void *val;
unsigned int val_type;
int ret;
+ unsigned int *group_id;
if (rpc->scan(c, "SS", &group, &var) < 2)
return;
- ret = cfg_get_by_name(ctx, &group, &var,
+ if (get_group_id(&group, &group_id)) {
+ rpc->fault(c, 400, "Wrong group syntax. Use either \"group\", or \"group[id]\"");
+ return;
+ }
+
+ ret = cfg_get_by_name(ctx, &group, group_id, &var,
&val, &val_type);
if (ret < 0) {
rpc->fault(c, 400, "Failed to get the variable");
@@ -249,24 +313,32 @@ static void rpc_diff(rpc_t* rpc, void* c)
{
void *h;
str gname, vname;
+ unsigned int *gid;
void *old_val, *new_val;
unsigned int val_type;
void *rpc_handle;
+ int err;
if (cfg_diff_init(ctx, &h)) {
rpc->fault(c, 400, "Failed to get the changes");
return;
}
- while(cfg_diff_next(&h,
- &gname, &vname,
+ while((err = cfg_diff_next(&h,
+ &gname, &gid, &vname,
&old_val, &new_val,
- &val_type)
+ &val_type)) > 0
) {
rpc->add(c, "{", &rpc_handle);
- rpc->struct_add(rpc_handle, "SS",
- "group name", &gname,
- "variable name", &vname);
+ if (gid)
+ rpc->struct_add(rpc_handle, "SdS",
+ "group name", &gname,
+ "group id", *gid,
+ "variable name", &vname);
+ else
+ rpc->struct_add(rpc_handle, "SS",
+ "group name", &gname,
+ "variable name", &vname);
switch (val_type) {
case CFG_VAR_INT:
@@ -294,6 +366,56 @@ static void rpc_diff(rpc_t* rpc, void* c)
}
}
cfg_diff_release(ctx);
+ if (err)
+ rpc->fault(c, 400, "Failed to get the changes");
+}
+
+static const char* rpc_add_group_inst_doc[2] = {
+ "Add a new instance to an existing configuration group",
+ 0
+};
+
+static void rpc_add_group_inst(rpc_t* rpc, void* c)
+{
+ str group;
+ unsigned int *group_id;
+
+ if (rpc->scan(c, "S", &group) < 1)
+ return;
+
+ if (get_group_id(&group, &group_id) || !group_id) {
+ rpc->fault(c, 400, "Wrong group syntax. Use \"group[id]\"");
+ return;
+ }
+
+ if (cfg_add_group_inst(ctx, &group, *group_id)) {
+ rpc->fault(c, 400, "Failed to add the group instance");
+ return;
+ }
+}
+
+static const char* rpc_del_group_inst_doc[2] = {
+ "Delte an instance of a configuration group",
+ 0
+};
+
+static void rpc_del_group_inst(rpc_t* rpc, void* c)
+{
+ str group;
+ unsigned int *group_id;
+
+ if (rpc->scan(c, "S", &group) < 1)
+ return;
+
+ if (get_group_id(&group, &group_id) || !group_id) {
+ rpc->fault(c, 400, "Wrong group syntax. Use \"group[id]\"");
+ return;
+ }
+
+ if (cfg_del_group_inst(ctx, &group, *group_id)) {
+ rpc->fault(c, 400, "Failed to delete the group instance");
+ return;
+ }
}
static rpc_export_t rpc_calls[] = {
@@ -307,6 +429,8 @@ static rpc_export_t rpc_calls[] = {
{"cfg.help", rpc_help, rpc_help_doc, 0},
{"cfg.list", rpc_list, rpc_list_doc, 0},
{"cfg.diff", rpc_diff, rpc_diff_doc, 0},
+ {"cfg.add_group_inst", rpc_add_group_inst, rpc_add_group_inst_doc, 0},
+ {"cfg.del_group_inst", rpc_del_group_inst, rpc_del_group_inst_doc, 0},
{0, 0, 0, 0}
};
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: b2efa6a116ebc89c8c6198a49fff176df745a2f5
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=b2efa6a…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Fri Sep 3 14:48:27 2010 +0200
cfg framework: group meta-data introduced
A new structure for meta-data is added to the variable block
before each group. This stucture will be a placeholder for the
multiple values of the same variable.
The meta-data indicates how many instances the group has excluding
the default instance, and will store the pointer to the array of
these instances.
---
cfg/cfg_ctx.c | 6 +++---
cfg/cfg_script.c | 8 ++++++++
cfg/cfg_struct.c | 40 +++++++++++++++++++++++++++++++++-------
cfg/cfg_struct.h | 30 +++++++++++++++++++++++++++---
4 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/cfg/cfg_ctx.c b/cfg/cfg_ctx.c
index 677a070..d2ea621 100644
--- a/cfg/cfg_ctx.c
+++ b/cfg/cfg_ctx.c
@@ -328,13 +328,13 @@ int cfg_set_now(cfg_ctx_t *ctx, str *group_name, str *var_name,
if (var->def->type & CFG_ATOMIC) {
/* atomic change is allowed, we can rewrite the value
directly in the global config */
- p = (*cfg_global)->vars+group->offset+var->offset;
+ p = (*cfg_global)->vars+group->var_offset+var->offset;
} else {
/* clone the memory block, and prepare the modification */
if (!(block = cfg_clone_global())) goto error;
- p = block->vars+group->offset+var->offset;
+ p = block->vars+group->var_offset+var->offset;
}
} else {
/* we are allowed to rewrite the value on-the-fly
@@ -786,7 +786,7 @@ int cfg_commit(cfg_ctx_t *ctx)
changed = changed->next
) {
p = block->vars
- + changed->group->offset
+ + changed->group->var_offset
+ changed->var->offset;
if ((CFG_VAR_TYPE(changed->var) == CFG_VAR_STRING)
diff --git a/cfg/cfg_script.c b/cfg/cfg_script.c
index a4ef236..e57fa2d 100644
--- a/cfg/cfg_script.c
+++ b/cfg/cfg_script.c
@@ -103,7 +103,15 @@ cfg_script_var_t *new_cfg_script_var(char *gname, char *vname, unsigned int type
LOG(L_ERR, "ERROR: new_cfg_script_var(): unsupported variable type\n");
return NULL;
}
+
group->num++;
+ if (group->num > CFG_MAX_VAR_NUM) {
+ LOG(L_ERR, "ERROR: new_cfg_script_var(): too many variables (%d) within a single group,"
+ " the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple"
+ " definitions.\n",
+ group->num, CFG_MAX_VAR_NUM);
+ return NULL;
+ }
var = (cfg_script_var_t *)pkg_malloc(sizeof(cfg_script_var_t));
if (!var) goto error;
diff --git a/cfg/cfg_struct.c b/cfg/cfg_struct.c
index f2f5bfe..18a8aca 100644
--- a/cfg/cfg_struct.c
+++ b/cfg/cfg_struct.c
@@ -42,7 +42,7 @@ cfg_block_t **cfg_global = NULL; /* pointer to the active cfg block */
cfg_block_t *cfg_local = NULL; /* per-process pointer to the active cfg block.
Updated only when the child process
finishes working on the SIP message */
-static int cfg_block_size = 0; /* size of the cfg block (constant) */
+static int cfg_block_size = 0; /* size of the cfg block including the meta-data (constant) */
gen_lock_t *cfg_global_lock = 0; /* protects *cfg_global */
gen_lock_t *cfg_writer_lock = 0; /* This lock makes sure that two processes do not
try to clone *cfg_global at the same time.
@@ -68,6 +68,14 @@ cfg_group_t *cfg_new_group(char *name, int name_len,
return NULL;
}
+ if (num > CFG_MAX_VAR_NUM) {
+ LOG(L_ERR, "ERROR: cfg_new_group(): too many variables (%d) within a single group,"
+ " the limit is %d. Increase CFG_MAX_VAR_NUM, or split the group into multiple"
+ " definitions.\n",
+ num, CFG_MAX_VAR_NUM);
+ return NULL;
+ }
+
group = (cfg_group_t *)pkg_malloc(sizeof(cfg_group_t)+name_len-1);
if (!group) {
LOG(L_ERR, "ERROR: cfg_new_group(): not enough memory\n");
@@ -162,13 +170,31 @@ int cfg_shmize(void)
if (!cfg_group) return 0;
/* Let us allocate one memory block that
- will contain all the variables */
+ * will contain all the variables + meta-data
+ * in the following form:
+ * |-----------|
+ * | meta-data | <- group A: meta_offset
+ * | variables | <- group A: var_offset
+ * |-----------|
+ * | meta-data | <- group B: meta_offset
+ * | variables | <- group B: var_offset
+ * |-----------|
+ * | ... |
+ * |-----------|
+ *
+ * The additional array for the multiple values
+ * of the same variable is linked to the meta-data.
+ */
for ( size=0, group = cfg_group;
group;
group=group->next
) {
size = ROUND_POINTER(size);
- group->offset = size;
+ group->meta_offset = size;
+ size += sizeof(cfg_group_meta_t);
+
+ size = ROUND_POINTER(size);
+ group->var_offset = size;
size += group->size;
}
@@ -190,19 +216,19 @@ int cfg_shmize(void)
if (cfg_shmize_strings(group)) goto error;
/* copy the values to the new block */
- memcpy(block->vars+group->offset, group->vars, group->size);
+ memcpy(block->vars+group->var_offset, group->vars, group->size);
} else {
/* The group was declared with NULL values,
* we have to fix it up.
* The fixup function takes care about the values,
* it fills up the block */
- if (cfg_script_fixup(group, block->vars+group->offset)) goto error;
+ if (cfg_script_fixup(group, block->vars+group->var_offset)) goto error;
/* Notify the drivers about the new config definition.
* Temporary set the group handle so that the drivers have a chance to
* overwrite the default values. The handle must be reset after this
* because the main process does not have a local configuration. */
- *(group->handle) = block->vars+group->offset;
+ *(group->handle) = block->vars+group->var_offset;
cfg_notify_drivers(group->name, group->name_len,
group->mapping->def);
*(group->handle) = NULL;
@@ -243,7 +269,7 @@ static void cfg_destory_groups(unsigned char *block)
(CFG_VAR_TYPE(&mapping[i]) == CFG_VAR_STR)) &&
mapping[i].flag & cfg_var_shmized) {
- old_string = *(char **)(block + group->offset + mapping[i].offset);
+ old_string = *(char **)(block + group->var_offset + mapping[i].offset);
if (old_string) shm_free(old_string);
}
diff --git a/cfg/cfg_struct.h b/cfg/cfg_struct.h
index c72573b..456e32b 100644
--- a/cfg/cfg_struct.h
+++ b/cfg/cfg_struct.h
@@ -36,6 +36,9 @@
#include "../compiler_opt.h"
#include "cfg.h"
+/*! \brief Maximum number of variables within a configuration group. */
+#define CFG_MAX_VAR_NUM 256
+
/*! \brief indicates that the variable has been already shmized */
#define cfg_var_shmized 1U
@@ -59,8 +62,10 @@ typedef struct _cfg_group {
shmized. */
int size; /*!< size of the memory block that has to be
allocated to store the values */
- int offset; /*!< offset of the group within the
- shmized memory block */
+ int meta_offset; /*!< offset of the group within the
+ shmized memory block for the meta_data */
+ int var_offset; /*!< offset of the group within the
+ shmized memory block for the variables */
void **handle; /*!< per-process handle that can be used
by the modules to access the variables.
It is registered when the group is created,
@@ -73,6 +78,25 @@ typedef struct _cfg_group {
char name[1];
} cfg_group_t;
+/*! \brief One instance of the cfg group variables which stores
+ * the additional values. These values can overwrite the default values. */
+typedef struct _cfg_group_inst {
+ unsigned int set[CFG_MAX_VAR_NUM/(sizeof(int)*8)];
+ /*!< Bitmap indicating whether or not a value is explicitely set
+ within this instance. If the value is not set,
+ then the default value is used, and copied into this instance. */
+ unsigned char vars[1]; /*!< block for the values */
+} cfg_group_inst_t;
+
+/*! \bried Meta-data which is stored before each variable group
+ * within the blob. This structure is used to handle the multivalue
+ * instances of the variables, i.e. manages the array for the
+ * additional values. */
+typedef struct _cfg_group_meta {
+ int num; /*!< Number of items in the array */
+ cfg_group_inst_t *array; /*!< Array of cfg groups with num number of items */
+} cfg_group_meta_t;
+
/*! \brief single memoy block that contains all the cfg values */
typedef struct _cfg_block {
atomic_t refcnt; /*!< reference counter,
@@ -242,7 +266,7 @@ static inline void cfg_update_local(int no_cbs)
group;
group = group->next
)
- *(group->handle) = cfg_local->vars + group->offset;
+ *(group->handle) = cfg_local->vars + group->var_offset;
if (unlikely(cfg_child_cb==CFG_NO_CHILD_CBS || no_cbs))
return;
Module: sip-router
Branch: tirpi/cfg_framework_multivalue
Commit: 6a44d0bd28c2cb896b9e53f7974d1bad88654c24
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6a44d0b…
Author: Miklos Tirpak <miklos(a)iptel.org>
Committer: Miklos Tirpak <miklos(a)iptel.org>
Date: Tue Sep 7 17:09:07 2010 +0200
cfg framework: cfg_set_now() supports the group instances
cfg_set_now() can write the variables within both
the default and the additional group instances.
If the additional variable is not explicitely set, then
the default value overwrites it.
Note: the group instance must exist before cfg_set_now() is called,
it is not created dynamicaly.
The function does not work yet before the config is shmized.
---
cfg/cfg.c | 1 +
cfg/cfg_ctx.c | 228 +++++++++++++++++++++++++++++++++++++++++++-----------
cfg/cfg_ctx.h | 22 ++++--
cfg/cfg_script.c | 1 +
cfg/cfg_script.h | 1 +
cfg/cfg_struct.c | 48 +++++++++++-
cfg/cfg_struct.h | 50 +++++++++++-
7 files changed, 293 insertions(+), 58 deletions(-)
Diff: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commitdiff;h=6a4…
Module: sip-router
Branch: master
Commit: 61b81832cb4eacc82b0c711c686f85c09e62be7c
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=61b8183…
Author: Marius Zbihlei <marius.zbihlei(a)1and1.ro>
Committer: Marius Zbihlei <marius.zbihlei(a)1and1.ro>
Date: Tue Sep 14 11:42:42 2010 +0300
Modules_k:usrloc Fixed syntax errors on documentation of modules.
---
modules_k/usrloc/README | 36 +++++++++++++++++---------------
modules_k/usrloc/doc/usrloc_admin.xml | 36 ++++++++++++++++----------------
2 files changed, 37 insertions(+), 35 deletions(-)
diff --git a/modules_k/usrloc/README b/modules_k/usrloc/README
index d6df0ea..f6fd5f7 100644
--- a/modules_k/usrloc/README
+++ b/modules_k/usrloc/README
@@ -199,26 +199,28 @@ Chapter 1. Admin Guide
1.1. Contact matching
How the contacts are matched (dor same AOR - Address of Record) is an
- important aspect of the usrloc modules, especialy in the context of NAT
- traversal - this raise mre problems since contacts from different
- phones of same users may overlap (if behind NATs with same
- configuration) or the re-register contact of same phone may be seen as
- a new one (due different binding via NAT).
+ important aspect of the usrloc module, especially in the context of NAT
+ traversal - this raises more problems since contacts from different
+ phones of the same user may overlap (if behind NATs with same
+ configuration) or the re-register contact of the same phone may be seen
+ as a new one (due different binding via NAT).
The SIP RFC 3261 publishes a matching algorithm based only on the
contact string with callid and cseq number extra checking (if callid is
- the same, it must have a higher cseq number, otherwise invalid). But as
- argumented above, this is not enough in NAT traversal context, so the
- Kamailio implementation of contact machting offers more algorithms:
- * contact based only - it strict RFC 3261 compiancy - the contact is
- matched as string and extra checked via callid and cseg (if callid
- is the same, it must have a higher cseq number, otherwise invalid).
- * contact and callid based - it an extension of the first case - the
- contact and callid must matched as string; the cseg must be higher
- than the previous one - so be careful how you deal with REGISTER
- retransmissions in this case.
- * contact and path based - it an extension of the first case - the
- contact and path must matched as string; the cseg must be higher
+ the same, it must have a higher cseq number, otherwise it is invalid).
+ But as argumented above, this is not enough in NAT traversal context,
+ so the Kamailio implementation of contact matching offers more
+ algorithms:
+ * contact based only - it is strict RFC 3261 compliancy - the contact
+ is matched as string and extra checked via callid and cseq (if
+ callid is the same, it must have a higher cseq number, otherwise it
+ is invalid).
+ * contact and callid based - it is an extension of the first case -
+ the contact and callid must be matched as string; the cseq must be
+ higher than the previous one - so be careful how you deal with
+ REGISTER retransmissions in this case.
+ * contact and path based - it is an extension of the first case - the
+ contact and path must be matched as string; the cseq must be higher
than the previous one - so be careful how you deal with REGISTER
retransmissions in this case.
diff --git a/modules_k/usrloc/doc/usrloc_admin.xml b/modules_k/usrloc/doc/usrloc_admin.xml
index 2b6d307..0b03fe2 100644
--- a/modules_k/usrloc/doc/usrloc_admin.xml
+++ b/modules_k/usrloc/doc/usrloc_admin.xml
@@ -24,43 +24,43 @@
<title>Contact matching</title>
<para>
How the contacts are matched (dor same AOR - Address of Record) is an
- important aspect of the usrloc modules, especialy in the context of NAT
- traversal - this raise mre problems since contacts from different
- phones of same users may overlap (if behind NATs with same
- configuration) or the re-register contact of same phone may be
+ important aspect of the usrloc module, especially in the context of NAT
+ traversal - this raises more problems since contacts from different
+ phones of the same user may overlap (if behind NATs with same
+ configuration) or the re-register contact of the same phone may be
seen as a new one (due different binding via NAT).
</para>
<para>
The SIP RFC 3261 publishes a matching algorithm based only on the
contact string with callid and cseq number extra checking (if callid
- is the same, it must have a higher cseq number, otherwise invalid).
+ is the same, it must have a higher cseq number, otherwise it is invalid).
But as argumented above, this is not enough in NAT traversal context,
- so the &kamailio; implementation of contact machting offers more algorithms:
+ so the &kamailio; implementation of contact matching offers more algorithms:
</para>
<itemizedlist>
<listitem>
<para>
- <emphasis>contact based only</emphasis> - it strict RFC 3261
- compiancy - the contact is matched as string and extra checked
- via callid and cseg (if callid is the same, it must have a
- higher cseq number, otherwise invalid).
+ <emphasis>contact based only</emphasis> - it is strict RFC 3261
+ compliancy - the contact is matched as string and extra checked
+ via callid and cseq (if callid is the same, it must have a
+ higher cseq number, otherwise it is invalid).
</para>
</listitem>
<listitem>
<para>
- <emphasis>contact and callid based</emphasis> - it an extension
- of the first case - the contact and callid must matched as
- string; the cseg must be higher than the previous one - so be
- careful how you deal with REGISTER retransmissions in this
+ <emphasis>contact and callid based</emphasis> - it is an extension
+ of the first case - the contact and callid must be matched as
+ string; the cseq must be higher than the previous one - so be
+ careful how you deal with REGISTER retransmissions in this
case.
</para>
</listitem>
<listitem>
<para>
- <emphasis>contact and path based</emphasis> - it an extension
- of the first case - the contact and path must matched as
- string; the cseg must be higher than the previous one - so be
- careful how you deal with REGISTER retransmissions in this
+ <emphasis>contact and path based</emphasis> - it is an extension
+ of the first case - the contact and path must be matched as
+ string; the cseq must be higher than the previous one - so be
+ careful how you deal with REGISTER retransmissions in this
case.
</para>
</listitem>
Module: sip-router
Branch: master
Commit: e017bd9c00a021c1f2fe0b69bb5382d69afd5e7d
URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=e017bd9…
Author: Ovidiu Sas <osas(a)voipembedded.com>
Committer: Ovidiu Sas <osas(a)voipembedded.com>
Date: Mon Sep 13 15:03:57 2010 -0400
modules_k/rtpproxy: fix crash related to SDP without ssession IP
- when the IP address is provided only in the SDP stream description
and not in the SDP session description, the rtpproxy module was crashing
due to wrong check of the IP address length.
- thanks to Daniel Constantin Mierla for reporting and investigating this.
---
modules_k/rtpproxy/rtpproxy.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/modules_k/rtpproxy/rtpproxy.c b/modules_k/rtpproxy/rtpproxy.c
index f526581..daee003 100644
--- a/modules_k/rtpproxy/rtpproxy.c
+++ b/modules_k/rtpproxy/rtpproxy.c
@@ -2074,7 +2074,7 @@ force_rtp_proxy(struct sip_msg* msg, char* str1, char* str2, int offer)
sdp_stream = get_sdp_stream(msg, sdp_session_num, sdp_stream_num);
if(!sdp_stream) break;
- if (sdp_stream->ip_addr.s && !sdp_stream->ip_addr.len) {
+ if (sdp_stream->ip_addr.s && sdp_stream->ip_addr.len>0) {
oldip = sdp_stream->ip_addr;
pf = sdp_stream->pf;
} else {