mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-06 04:30:28 +00:00
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
This commit is contained in:
@@ -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].
|
||||
|
@@ -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);
|
||||
|
||||
@@ -2209,8 +2210,9 @@ 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));
|
||||
|
||||
@@ -2219,7 +2221,7 @@ static void register_group_feature(struct feature_group *fg, const char *exten,
|
||||
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,8 +2481,7 @@ 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 (!strcmp(fge->exten, code)) {
|
||||
if (operation) {
|
||||
res = fge->feature->operation(chan, peer, config, code, sense, fge->feature);
|
||||
}
|
||||
@@ -2489,10 +2491,14 @@ static int feature_interpret_helper(struct ast_channel *chan, struct ast_channel
|
||||
break;
|
||||
}
|
||||
res = AST_FEATURE_RETURN_PASSDIGITS;
|
||||
} else if (!strncmp(fge->exten, code, strlen(code))) {
|
||||
res = AST_FEATURE_RETURN_STOREDIGITS;
|
||||
}
|
||||
if (fge)
|
||||
}
|
||||
if (fge) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
AST_RWLIST_UNLOCK(&feature_groups);
|
||||
|
||||
@@ -2595,13 +2601,32 @@ 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);
|
||||
|
Reference in New Issue
Block a user