|
|
|
@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
|
|
|
|
#include "asterisk/utils.h"
|
|
|
|
|
#include "asterisk/app.h"
|
|
|
|
|
#include "asterisk/astobj2.h"
|
|
|
|
|
#include "asterisk/astdb.h"
|
|
|
|
|
|
|
|
|
|
static struct ao2_container *group_container = NULL;
|
|
|
|
|
|
|
|
|
@ -94,13 +95,18 @@ static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data,
|
|
|
|
|
struct group_entry *entry;
|
|
|
|
|
size_t bufused = 0;
|
|
|
|
|
int trunc_warning = 0;
|
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
|
|
if (!grhead) {
|
|
|
|
|
if (!ast_strlen_zero(cmd)) {
|
|
|
|
|
ast_log(LOG_WARNING, "No such dialgroup '%s'\n", data);
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
i = ao2_iterator_init(grhead->entries, 0);
|
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
|
|
|
|
|
i = ao2_iterator_init(grhead->entries, OBJ_POINTER);
|
|
|
|
|
while ((entry = ao2_iterator_next(&i))) {
|
|
|
|
|
int tmp = strlen(entry->name);
|
|
|
|
|
/* Ensure that we copy only complete names, not partials */
|
|
|
|
@ -109,10 +115,43 @@ static int dialgroup_read(struct ast_channel *chan, const char *cmd, char *data,
|
|
|
|
|
buf[bufused++] = '&';
|
|
|
|
|
ast_copy_string(buf + bufused, entry->name, len - bufused);
|
|
|
|
|
bufused += tmp;
|
|
|
|
|
} else if (trunc_warning++ == 0)
|
|
|
|
|
} else if (trunc_warning++ == 0) {
|
|
|
|
|
if (!ast_strlen_zero(cmd)) {
|
|
|
|
|
ast_log(LOG_WARNING, "Dialgroup '%s' is too large. Truncating list.\n", data);
|
|
|
|
|
} else {
|
|
|
|
|
res = 1;
|
|
|
|
|
ao2_ref(entry, -1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ao2_ref(entry, -1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int dialgroup_refreshdb(struct ast_channel *chan, const char *cdialgroup)
|
|
|
|
|
{
|
|
|
|
|
int len = 500, res = 0;
|
|
|
|
|
char *buf = NULL;
|
|
|
|
|
char *dialgroup = ast_strdupa(cdialgroup);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
len *= 2;
|
|
|
|
|
buf = ast_realloc(buf, len);
|
|
|
|
|
|
|
|
|
|
if ((res = dialgroup_read(chan, "", dialgroup, buf, len)) < 0) {
|
|
|
|
|
ast_free(buf);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} while (res == 1);
|
|
|
|
|
|
|
|
|
|
if (ast_strlen_zero(buf)) {
|
|
|
|
|
ast_db_del("dialgroup", cdialgroup);
|
|
|
|
|
} else {
|
|
|
|
|
ast_db_put("dialgroup", cdialgroup, buf);
|
|
|
|
|
}
|
|
|
|
|
ast_free(buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -120,7 +159,7 @@ static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data
|
|
|
|
|
{
|
|
|
|
|
struct group *grhead;
|
|
|
|
|
struct group_entry *entry;
|
|
|
|
|
int j;
|
|
|
|
|
int j, needrefresh = 1;
|
|
|
|
|
AST_DECLARE_APP_ARGS(args,
|
|
|
|
|
AST_APP_ARG(group);
|
|
|
|
|
AST_APP_ARG(op);
|
|
|
|
@ -133,7 +172,7 @@ static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data
|
|
|
|
|
AST_STANDARD_APP_ARGS(args, data);
|
|
|
|
|
AST_NONSTANDARD_APP_ARGS(inter, value, '&');
|
|
|
|
|
|
|
|
|
|
if (!(grhead = ao2_find(group_container, data, 0))) {
|
|
|
|
|
if (!(grhead = ao2_find(group_container, args.group, 0))) {
|
|
|
|
|
/* Create group */
|
|
|
|
|
grhead = ao2_alloc(sizeof(*grhead), group_destroy);
|
|
|
|
|
if (!grhead)
|
|
|
|
@ -153,27 +192,40 @@ static int dialgroup_write(struct ast_channel *chan, const char *cmd, char *data
|
|
|
|
|
|
|
|
|
|
/* Remove all existing */
|
|
|
|
|
ao2_ref(grhead->entries, -1);
|
|
|
|
|
if (!(grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn)))
|
|
|
|
|
if (!(grhead->entries = ao2_container_alloc(37, entry_hash_fn, entry_cmp_fn))) {
|
|
|
|
|
ao2_unlink(group_container, grhead);
|
|
|
|
|
ao2_ref(grhead, -1);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (strcasecmp(args.op, "add") == 0) {
|
|
|
|
|
for (j = 0; j < inter.argc; j++) {
|
|
|
|
|
if ((entry = ao2_alloc(sizeof(*entry), NULL))) {
|
|
|
|
|
ast_copy_string(entry->name, inter.faces[j], sizeof(entry->name));
|
|
|
|
|
ao2_link(grhead->entries, entry);
|
|
|
|
|
} else
|
|
|
|
|
ao2_ref(entry, -1);
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "Unable to add '%s' to dialgroup '%s'\n", inter.faces[j], grhead->name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if (strncasecmp(args.op, "del", 3) == 0) {
|
|
|
|
|
for (j = 0; j < inter.argc; j++) {
|
|
|
|
|
if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK)))
|
|
|
|
|
if ((entry = ao2_find(grhead->entries, inter.faces[j], OBJ_UNLINK))) {
|
|
|
|
|
ao2_ref(entry, -1);
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_WARNING, "Interface '%s' not found in dialgroup '%s'\n", inter.faces[j], grhead->name);
|
|
|
|
|
}
|
|
|
|
|
} else
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ast_log(LOG_ERROR, "Unrecognized operation: %s\n", args.op);
|
|
|
|
|
needrefresh = 0;
|
|
|
|
|
}
|
|
|
|
|
ao2_ref(grhead, -1);
|
|
|
|
|
|
|
|
|
|
if (needrefresh) {
|
|
|
|
|
dialgroup_refreshdb(chan, args.group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -211,10 +263,25 @@ static int unload_module(void)
|
|
|
|
|
|
|
|
|
|
static int load_module(void)
|
|
|
|
|
{
|
|
|
|
|
if ((group_container = ao2_container_alloc(37, group_hash_fn, group_cmp_fn)))
|
|
|
|
|
struct ast_db_entry *dbtree, *tmp;
|
|
|
|
|
char groupname[AST_MAX_EXTENSION], *ptr;
|
|
|
|
|
|
|
|
|
|
if ((group_container = ao2_container_alloc(37, group_hash_fn, group_cmp_fn))) {
|
|
|
|
|
/* Refresh groups from astdb */
|
|
|
|
|
if ((dbtree = ast_db_gettree("dialgroup", NULL))) {
|
|
|
|
|
for (tmp = dbtree; tmp; tmp = tmp->next) {
|
|
|
|
|
ast_copy_string(groupname, tmp->key, sizeof(groupname));
|
|
|
|
|
if ((ptr = strrchr(groupname, '/'))) {
|
|
|
|
|
ptr++;
|
|
|
|
|
dialgroup_write(NULL, "", ptr, tmp->data);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ast_db_freetree(dbtree);
|
|
|
|
|
}
|
|
|
|
|
return ast_custom_function_register(&dialgroup_function);
|
|
|
|
|
else
|
|
|
|
|
} else {
|
|
|
|
|
return AST_MODULE_LOAD_DECLINE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Dialgroup dialplan function");
|
|
|
|
|