summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Bryant <russell@russellbryant.com>2010-07-09 21:57:21 +0000
committerRussell Bryant <russell@russellbryant.com>2010-07-09 21:57:21 +0000
commitb4ba8548e188a36c5c2d296f11692f895d05d0d9 (patch)
tree36b50fe00ce72e314ce5e5ef44a3a1d3f9948b5b
parent7b1e28c6a138c68e0526ddfb86ee2b1c37354e01 (diff)
Fix some issues related to dynamic feature groups in features.conf.
The bridge handling code did not properly consider feature groups when setting parameters that would affect whether or not a native bridge would be attempted. If DYNAMIC_FEATURES only include a feature group, a native bridge would occur that may prevent features from working. Fix a bug in verbose output that would show the key mapping as empty if it was using the default mapping and not a custom mapping in the feature group. Add feature groups to the output of "features show". Adjust the feature execution logic to match that of the logic when executing a feature that was not configured through a feature group. Update features.conf.sample to show that an '=' is still required if using the default key mapping from [applicationmap]. Finally, clean up a little bit of formatting to better coform to coding guidelines while in the area. (closes issue #17589) Reported by: lmadsen Patches: issue_17589.rev4.txt uploaded by russell (license 2) Tested by: russell, lmadsen git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@275424 65c4cc65-6c06-0410-ace0-fbb531ad65f3
-rw-r--r--configs/features.conf.sample13
-rw-r--r--main/features.c83
2 files changed, 71 insertions, 25 deletions
diff --git a/configs/features.conf.sample b/configs/features.conf.sample
index 1fd9c0485..84a0ee06c 100644
--- a/configs/features.conf.sample
+++ b/configs/features.conf.sample
@@ -93,6 +93,7 @@ context => parkedcalls ; Which context parked calls are in (default parking lot
;<FeatureName> => <DTMF_sequence>,<ActivateOn>[/<ActivatedBy>],<Application>[,<AppArguments>[,MOH_Class]]
;<FeatureName> => <DTMF_sequence>,<ActivateOn>[/<ActivatedBy>],<Application>[,"<AppArguments>"[,MOH_Class]]
;<FeatureName> => <DTMF_sequence>,<ActivateOn>[/<ActivatedBy>],<Application>([<AppArguments>])[,MOH_Class]
+
;
; FeatureName -> This is the name of the feature used in when setting the
; DYNAMIC_FEATURES variable to enable usage of this feature.
@@ -140,11 +141,13 @@ context => parkedcalls ; Which context parked calls are in (default parking lot
;unpauseMonitor => #3,self/callee,UnPauseMonitor ;Allow the callee to unpause monitoring
; ;on their channel
-; GROUPS
-; Groups are groupings of features defined in [applicationmap]
-; that can have their own key mappings.
+; Dynamic Feature Groups:
+; Dynamic feature groups are groupings of features defined in [applicationmap]
+; that can have their own custom key mappings. To give a channel access to a dynamic
+; feature group, add the group name to the value of the DYNAMIC_FEATURES variable.
;
; example:
; [myGroupName] ; defines the group named myGroupName
-; testfeature => #9 ; associates testfeature with the group and the keycode #9
-; pauseMonitor ; associates pauseMonitor with the group and the keycode
+; testfeature => #9 ; associates testfeature with the group and the keycode '#9'.
+; pauseMonitor => ; associates pauseMonitor with the group and uses the keycode specified
+; ; in the [applicationmap].
diff --git a/main/features.c b/main/features.c
index 1f1da2967..798e86111 100644
--- a/main/features.c
+++ b/main/features.c
@@ -2165,7 +2165,7 @@ void ast_register_feature(struct ast_call_feature *feature)
* Add new feature group to the feature group list insert at head of list.
* \note This function MUST be called while feature_groups is locked.
*/
-static struct feature_group* register_group(const char *fgname)
+static struct feature_group *register_group(const char *fgname)
{
struct feature_group *fg;
@@ -2174,8 +2174,9 @@ static struct feature_group* register_group(const char *fgname)
return NULL;
}
- if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128)))
+ if (!(fg = ast_calloc_with_stringfields(1, struct feature_group, 128))) {
return NULL;
+ }
ast_string_field_set(fg, gname, fgname);
@@ -2195,7 +2196,7 @@ static struct feature_group* register_group(const char *fgname)
* Check fg and feature specified, add feature to list
* \note This function MUST be called while feature_groups is locked.
*/
-static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
+static void register_group_feature(struct feature_group *fg, const char *exten, struct ast_call_feature *feature)
{
struct feature_group_exten *fge;
@@ -2209,17 +2210,18 @@ static void register_group_feature(struct feature_group *fg, const char *exten,
return;
}
- if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128)))
+ if (!(fge = ast_calloc_with_stringfields(1, struct feature_group_exten, 128))) {
return;
+ }
ast_string_field_set(fge, exten, S_OR(exten, feature->exten));
fge->feature = feature;
- AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
+ AST_LIST_INSERT_HEAD(&fg->features, fge, entry);
ast_verb(2, "Registered feature '%s' for group '%s' at exten '%s'\n",
- feature->sname, fg->gname, exten);
+ feature->sname, fg->gname, fge->exten);
}
void ast_unregister_feature(struct ast_call_feature *feature)
@@ -2286,7 +2288,8 @@ static void ast_unregister_groups(void)
* \retval feature group on success.
* \retval NULL on failure.
*/
-static struct feature_group *find_group(const char *name) {
+static struct feature_group *find_group(const char *name)
+{
struct feature_group *fg = NULL;
AST_LIST_TRAVERSE(&feature_groups, fg, entry) {
@@ -2478,20 +2481,23 @@ static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel
if (fg) {
AST_LIST_TRAVERSE(&fg->features, fge, entry) {
- if (strcasecmp(fge->exten, code))
- continue;
- if (operation) {
- res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
- }
- memcpy(feature, fge->feature, sizeof(feature));
- if (res != AST_FEATURE_RETURN_KEEPTRYING) {
- AST_RWLIST_UNLOCK(&feature_groups);
- break;
+ if (!strcmp(fge->exten, code)) {
+ if (operation) {
+ res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
+ }
+ memcpy(feature, fge->feature, sizeof(feature));
+ if (res != AST_FEATURE_RETURN_KEEPTRYING) {
+ AST_RWLIST_UNLOCK(&feature_groups);
+ break;
+ }
+ res = AST_FEATURE_RETURN_PASSDIGITS;
+ } else if (!strncmp(fge->exten, code, strlen(code))) {
+ res = AST_FEATURE_RETURN_STOREDIGITS;
}
- res = AST_FEATURE_RETURN_PASSDIGITS;
}
- if (fge)
+ if (fge) {
break;
+ }
}
AST_RWLIST_UNLOCK(&feature_groups);
@@ -2595,12 +2601,31 @@ static void set_config_flags(struct ast_channel *chan, struct ast_channel *peer,
/* while we have a feature */
while ((tok = strsep(&tmp, "#"))) {
+ struct feature_group *fg;
+
+ AST_RWLIST_RDLOCK(&feature_groups);
+ AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
+ struct feature_group_exten *fge;
+
+ AST_LIST_TRAVERSE(&fg->features, fge, entry) {
+ if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLER)) {
+ ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
+ }
+ if (ast_test_flag(fge->feature, AST_FEATURE_FLAG_BYCALLEE)) {
+ ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
+ }
+ }
+ }
+ AST_RWLIST_UNLOCK(&feature_groups);
+
AST_RWLIST_RDLOCK(&feature_list);
if ((feature = find_dynamic_feature(tok)) && ast_test_flag(feature, AST_FEATURE_FLAG_NEEDSDTMF)) {
- if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER))
+ if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLER)) {
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_0);
- if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE))
+ }
+ if (ast_test_flag(feature, AST_FEATURE_FLAG_BYCALLEE)) {
ast_set_flag(config, AST_BRIDGE_DTMF_CHANNEL_1);
+ }
}
AST_RWLIST_UNLOCK(&feature_list);
}
@@ -4651,6 +4676,24 @@ static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cl
AST_RWLIST_UNLOCK(&feature_list);
}
+ ast_cli(a->fd, "\nFeature Groups:\n");
+ ast_cli(a->fd, "---------------\n");
+ if (AST_RWLIST_EMPTY(&feature_groups)) {
+ ast_cli(a->fd, "(none)\n");
+ } else {
+ struct feature_group *fg;
+ struct feature_group_exten *fge;
+
+ AST_RWLIST_RDLOCK(&feature_groups);
+ AST_RWLIST_TRAVERSE(&feature_groups, fg, entry) {
+ ast_cli(a->fd, "===> Group: %s\n", fg->gname);
+ AST_LIST_TRAVERSE(&fg->features, fge, entry) {
+ ast_cli(a->fd, "===> --> %s (%s)\n", fge->feature->sname, fge->exten);
+ }
+ }
+ AST_RWLIST_UNLOCK(&feature_groups);
+ }
+
iter = ao2_iterator_init(parkinglots, 0);
while ((curlot = ao2_iterator_next(&iter))) {
ast_cli(a->fd, "\nCall parking (Parking lot: %s)\n", curlot->name);