diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet master/app.c groupcount_extensions/app.c --- master/app.c 2004-10-03 10:10:45 -07:00 +++ groupcount_extensions/app.c 2004-10-03 09:36:34 -07:00 @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -961,3 +963,109 @@ return res; } +/* Channel group core functions */ + +int ast_app_group_split_group(char *data, char *group, int group_max, char *category, int category_max) +{ + int res=0; + char tmp[256] = ""; + char *grp=NULL, *cat=NULL; + + if (data && !ast_strlen_zero(data)) { + strncpy(tmp, data, sizeof(tmp) - 1); + grp = tmp; + cat = strchr(tmp, '@'); + if (cat) { + *cat = '\0'; + cat++; + } + } + + if (grp && !ast_strlen_zero(grp)) + strncpy(group, grp, group_max -1); + else + res = -1; + + if (cat) + snprintf(category, category_max, "%s_%s", GROUP_CATEGORY_PREFIX, cat); + else + strncpy(category, GROUP_CATEGORY_PREFIX, category_max - 1); + + return res; +} + +int ast_app_group_set_channel(struct ast_channel *chan, char *data) +{ + int res=0; + char group[80] = ""; + char category[80] = ""; + + if (!ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category))) { + pbx_builtin_setvar_helper(chan, category, group); + } else + res = -1; + + return res; +} + +int ast_app_group_get_count(char *group, char *category) +{ + struct ast_channel *chan; + int count = 0; + char *test; + char cat[80] = ""; + + if (category && !ast_strlen_zero(category)) { + strncpy(cat, category, sizeof(cat) - 1); + } else { + strncpy(cat, GROUP_CATEGORY_PREFIX, sizeof(cat) - 1); + } + + if (group && !ast_strlen_zero(group)) { + chan = ast_channel_walk_locked(NULL); + while(chan) { + test = pbx_builtin_getvar_helper(chan, cat); + if (test && !strcasecmp(test, group)) + count++; + ast_mutex_unlock(&chan->lock); + chan = ast_channel_walk_locked(chan); + } + } + + return count; +} + +int ast_app_group_match_get_count(char *groupmatch, char *category) +{ + regex_t regexbuf; + struct ast_channel *chan; + int count = 0; + char *test; + char cat[80] = ""; + + if (!groupmatch || ast_strlen_zero(groupmatch)) + return 0; + + /* if regex compilation fails, return zero matches */ + if (regcomp(®exbuf, groupmatch, REG_EXTENDED | REG_NOSUB)) + return 0; + + if (category && !ast_strlen_zero(category)) { + strncpy(cat, category, sizeof(cat) - 1); + } else { + strncpy(cat, GROUP_CATEGORY_PREFIX, sizeof(cat) - 1); + } + + chan = ast_channel_walk_locked(NULL); + while(chan) { + test = pbx_builtin_getvar_helper(chan, cat); + if (test && !regexec(®exbuf, test, 0, NULL, 0)) + count++; + ast_mutex_unlock(&chan->lock); + chan = ast_channel_walk_locked(chan); + } + + regfree(®exbuf); + + return count; +} diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet master/apps/app_groupcount.c groupcount_extensions/apps/app_groupcount.c --- master/apps/app_groupcount.c 2004-10-03 10:10:45 -07:00 +++ groupcount_extensions/apps/app_groupcount.c 2004-10-03 09:36:34 -07:00 @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include #include @@ -22,125 +24,73 @@ #include #include #include +#include +#include -static char *tdesc = "Group Management Routines"; +STANDARD_LOCAL_USER; -static char *app_group_count = "GetGroupCount"; -static char *app_group_set = "SetGroup"; -static char *app_group_check = "CheckGroup"; +LOCAL_USER_DECL; -static char *group_count_synopsis = "GetGroupCount([groupname][@category])"; -static char *group_set_synopsis = "SetGroup(groupname[@category])"; -static char *group_check_synopsis = "CheckGroup(max[@category])"; +static int group_count_exec(struct ast_channel *chan, void *data) +{ + int res = 0; + int count; + struct localuser *u; + char group[80] = ""; + char category[80] = ""; + char ret[80] = ""; + char *grp; -static char *group_count_descrip = -"GetGroupCount([group][@category])\n" -" Calculates the group count for the specified group, or uses\n" -"the current channel's group if not specifed (and non-empty).\n" -"Stores result in GROUPCOUNT. Always returns 0.\n"; + LOCAL_USER_ADD(u); -static char *group_set_descrip = -"SetGroup(group)\n" -" Sets the channel group to the specified value. Equivalent to\n" -"SetVar(GROUP=group). Always returns 0.\n"; + ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)); -static char *group_check_descrip = -"CheckGroup(max)\n" -" Checks that the current number of total channels in the\n" -"current channel's group does not exceed 'max'. If the number\n" -"does not exceed 'max', we continue to the next step. If the\n" -"number does in fact exceed max, if priority n+101 exists, then\n" -"execution continues at that step, otherwise -1 is returned.\n"; - -STANDARD_LOCAL_USER; + if (ast_strlen_zero(group)) { + grp = pbx_builtin_getvar_helper(chan, category); + strncpy(group, grp, sizeof(group) - 1); + } -LOCAL_USER_DECL; + count = ast_app_group_get_count(group, category); + snprintf(ret, sizeof(ret), "%d", count); + pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret); -#define DEFAULT_CATEGORY "GROUP" + LOCAL_USER_REMOVE(u); -static int group_get_count(char *group, char *category) -{ - struct ast_channel *chan; - int count = 0; - char *test; - if (group && !ast_strlen_zero(group)) { - chan = ast_channel_walk_locked(NULL); - while(chan) { - test = pbx_builtin_getvar_helper(chan, category); - if (test && !strcasecmp(test, group)) - count++; - ast_mutex_unlock(&chan->lock); - chan = ast_channel_walk_locked(chan); - } - } - return count; + return res; } -static int group_count_exec(struct ast_channel *chan, void *data) +static int group_match_count_exec(struct ast_channel *chan, void *data) { - int res=0; + int res = 0; int count; struct localuser *u; - char *group=NULL; - char *cat = NULL; - char ret[80]=""; - char tmp[256]=""; + char group[80] = ""; + char category[80] = ""; + char ret[80] = ""; LOCAL_USER_ADD(u); - /* Check and parse arguments */ - if (data && !ast_strlen_zero(data)) { - strncpy(tmp, data, sizeof(tmp) - 1); - group = tmp; - cat = strchr(tmp, '@'); - if (cat) { - *cat = '\0'; - cat++; - } - } - if (cat) - snprintf(ret, sizeof(ret), "GROUP_%s", cat); - else - strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1); + ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)); - if (!group || ast_strlen_zero(group)) { - group = pbx_builtin_getvar_helper(chan, ret); + if (!ast_strlen_zero(group)) { + count = ast_app_group_match_get_count(group, category); + snprintf(ret, sizeof(ret), "%d", count); + pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret); } - count = group_get_count(group, ret); - snprintf(ret, sizeof(ret), "%d", count); - pbx_builtin_setvar_helper(chan, "GROUPCOUNT", ret); + LOCAL_USER_REMOVE(u); + return res; } static int group_set_exec(struct ast_channel *chan, void *data) { - int res=0; + int res = 0; struct localuser *u; - char ret[80] = ""; - char tmp[256] = ""; - char *cat=NULL, *group=NULL; LOCAL_USER_ADD(u); - /* Check and parse arguments */ - if (data && !ast_strlen_zero(data)) { - strncpy(tmp, data, sizeof(tmp) - 1); - group = tmp; - cat = strchr(tmp, '@'); - if (cat) { - *cat = '\0'; - cat++; - } - } - if (cat) - snprintf(ret, sizeof(ret), "GROUP_%s", cat); - else - strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1); - - if (group && !ast_strlen_zero(group)) { - pbx_builtin_setvar_helper(chan, ret, group); - } else + if (ast_app_group_set_channel(chan, data)) ast_log(LOG_WARNING, "SetGroup requires an argument (group name)\n"); LOCAL_USER_REMOVE(u); @@ -149,51 +99,139 @@ static int group_check_exec(struct ast_channel *chan, void *data) { - int res=0; + int res = 0; int max, count; struct localuser *u; - char ret[80] = ""; - char tmp[256] = ""; - char *cat, *group; + char limit[80]=""; + char category[80]=""; LOCAL_USER_ADD(u); - if (data && !ast_strlen_zero(data)) { - strncpy(tmp, data, sizeof(tmp) - 1); - group = tmp; - cat = strchr(tmp, '@'); - if (cat) { - *cat = '\0'; - cat++; - } - if ((sscanf((char *)tmp, "%i", &max) == 1) && (max > -1)) { - if (cat) - snprintf(ret, sizeof(ret), "GROUP_%s", cat); + if (!data || ast_strlen_zero(data)) { + ast_log(LOG_WARNING, "CheckGroup requires an argument(max[@category])\n"); + return res; + } + + ast_app_group_split_group(data, limit, sizeof(limit), category, sizeof(category)); + + if ((sscanf(limit, "%i", &max) == 1) && (max > -1)) { + count = ast_app_group_get_count(pbx_builtin_getvar_helper(chan, category), category); + if (count > max) { + if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) + chan->priority += 100; else - strncpy(ret, DEFAULT_CATEGORY, sizeof(ret) - 1); - - count = group_get_count(pbx_builtin_getvar_helper(chan, ret), ret); - if (count > max) { - if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) - chan->priority += 100; - else - res = -1; - } - } else - ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n"); + res = -1; + } } else - ast_log(LOG_WARNING, "CheckGroup requires an argument(max)\n"); + ast_log(LOG_WARNING, "CheckGroup requires a positive integer argument (max)\n"); + LOCAL_USER_REMOVE(u); return res; } +static int group_show_channels(int fd, int argc, char *argv[]) +{ +#define FORMAT_STRING "%-25s %-20s %-20s\n" + + struct ast_channel *c = NULL; + int numchans = 0; + struct ast_var_t *current; + struct varshead *headp; + regex_t regexbuf; + int havepattern = 0; + + if (argc < 3 || argc > 4) + return RESULT_SHOWUSAGE; + + if (argc == 4) { + if (regcomp(®exbuf, argv[3], REG_EXTENDED | REG_NOSUB)) + return RESULT_SHOWUSAGE; + havepattern = 1; + } + + c = ast_channel_walk_locked(NULL); + ast_cli(fd, FORMAT_STRING, "Channel", "Group", "Category"); + while(c) { + headp=&c->varshead; + AST_LIST_TRAVERSE(headp,current,entries) { + if (!strncmp(ast_var_name(current), GROUP_CATEGORY_PREFIX "_", strlen(GROUP_CATEGORY_PREFIX) + 1)) { + if (!havepattern || !regexec(®exbuf, ast_var_value(current), 0, NULL, 0)) { + ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), + (ast_var_name(current) + strlen(GROUP_CATEGORY_PREFIX) + 1)); + numchans++; + } + } else if (!strcmp(ast_var_name(current), GROUP_CATEGORY_PREFIX)) { + if (!havepattern || !regexec(®exbuf, ast_var_value(current), 0, NULL, 0)) { + ast_cli(fd, FORMAT_STRING, c->name, ast_var_value(current), "(default)"); + numchans++; + } + } + } + numchans++; + ast_mutex_unlock(&c->lock); + c = ast_channel_walk_locked(c); + } + + if (havepattern) + regfree(®exbuf); + + ast_cli(fd, "%d active channel(s)\n", numchans); + return RESULT_SUCCESS; +} + +static char *tdesc = "Group Management Routines"; + +static char *app_group_count = "GetGroupCount"; +static char *app_group_set = "SetGroup"; +static char *app_group_check = "CheckGroup"; +static char *app_group_match_count = "GetGroupMatchCount"; + +static char *group_count_synopsis = "GetGroupCount([groupname][@category])"; +static char *group_set_synopsis = "SetGroup(groupname[@category])"; +static char *group_check_synopsis = "CheckGroup(max[@category])"; +static char *group_match_count_synopsis = "GetGroupMatchCount(groupmatch[@category])"; + +static char *group_count_descrip = +"GetGroupCount([group][@category])\n" +" Calculates the group count for the specified group, or uses\n" +"the current channel's group if not specifed (and non-empty).\n" +"Stores result in GROUPCOUNT. Always returns 0.\n"; + +static char *group_set_descrip = +"SetGroup(group)\n" +" Sets the channel group to the specified value. Equivalent to\n" +"SetVar(GROUP=group). Always returns 0.\n"; + +static char *group_check_descrip = +"CheckGroup(max[@category])\n" +" Checks that the current number of total channels in the\n" +"current channel's group does not exceed 'max'. If the number\n" +"does not exceed 'max', we continue to the next step. If the\n" +"number does in fact exceed max, if priority n+101 exists, then\n" +"execution continues at that step, otherwise -1 is returned.\n"; + +static char *group_match_count_descrip = +"GetGroupMatchCount(groupmatch[@category])\n" +" Calculates the group count for all groups that match the specified\n" +"pattern. Uses standard regular expression matching (see regex(7)).\n" +"Stores result in GROUPCOUNT. Always returns 0.\n"; + +static char show_channels_usage[] = +"Usage: group show channels [pattern]\n" +" Lists all currently active channels with channel group(s) specified.\n Optional regular expression pattern is matched to group names for each channel.\n"; + +static struct ast_cli_entry cli_show_channels = + { { "group", "show", "channels", NULL }, group_show_channels, "Show active channels with group(s)", show_channels_usage}; + int unload_module(void) { int res; STANDARD_HANGUP_LOCALUSERS; + ast_cli_unregister(&cli_show_channels); res = ast_unregister_application(app_group_count); res |= ast_unregister_application(app_group_set); res |= ast_unregister_application(app_group_check); + res |= ast_unregister_application(app_group_match_count); return res; } @@ -203,6 +241,8 @@ res = ast_register_application(app_group_count, group_count_exec, group_count_synopsis, group_count_descrip); res |= ast_register_application(app_group_set, group_set_exec, group_set_synopsis, group_set_descrip); res |= ast_register_application(app_group_check, group_check_exec, group_check_synopsis, group_check_descrip); + res |= ast_register_application(app_group_match_count, group_match_count_exec, group_match_count_synopsis, group_match_count_descrip); + ast_cli_register(&cli_show_channels); return res; } diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet master/include/asterisk/app.h groupcount_extensions/include/asterisk/app.h --- master/include/asterisk/app.h 2004-10-03 10:10:45 -07:00 +++ groupcount_extensions/include/asterisk/app.h 2004-10-03 09:36:34 -07:00 @@ -68,6 +68,20 @@ // permitted silence time in milliseconds of 'maxsilence' under 'silencethreshold' or use '-1' for either or both parameters for defaults. int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime_sec, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence_ms); +#define GROUP_CATEGORY_PREFIX "GROUP" + +//! Split a group string into group and category, returning a default category if none is provided. +int ast_app_group_split_group(char *data, char *group, int group_max, char *category, int category_max); + +//! Set the group for a channel, splitting the provided data into group and category, if specified. +int ast_app_group_set_channel(struct ast_channel *chan, char *data); + +//! Get the current channel count of the specified group and category. +int ast_app_group_get_count(char *group, char *category); + +//! Get the current channel count of all groups that match the specified pattern and category. +int ast_app_group_match_get_count(char *groupmatch, char *category); + #if defined(__cplusplus) || defined(c_plusplus) } #endif