Allow disconnect feature before a call is bridged

feature.conf has a disconnect option.  By default this option is set to '*', but it could be anything.  If a user wishes to disconnect a call before the other side answers, only '*' will work, regardless if the disconnect option is set to something else.  This is because features are unavailable until bridging takes place.  The default disconnect option, '*', was hardcoded in app_dial, which doesn't make any sense from a user perspective since they may expect it to be something different.  This patch allows features to be detected from outside of the bridge, but not operated on.  In this case, the disconnect feature can be detected before briding and handled outside of features.c.

(closes issue #11583)
Reported by: sobomax
Patches:
	patch-apps__app_dial.c uploaded by sobomax (license 359)
	11583.latest-patch uploaded by murf (license 17)
	detect_disconnect.diff uploaded by dvossel (license 671)
Tested by: sobomax, dvossel
Review: http://reviewboard.digium.com/r/195/






git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@183126 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
David Vossel
2009-03-19 16:15:16 +00:00
parent 661c6384ad
commit dd17912d68
4 changed files with 140 additions and 42 deletions

View File

@@ -383,6 +383,7 @@ static int onedigit_goto(struct ast_channel *chan, const char *context, char ext
return 0;
}
static int detect_disconnect(struct ast_channel *chan, char code, char *featurecode, int len);
static const char *get_cid_name(char *name, int namelen, struct ast_channel *chan)
{
@@ -417,7 +418,9 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
struct ast_channel *peer = NULL;
/* single is set if only one destination is enabled */
int single = outgoing && !outgoing->next && !ast_test_flag(outgoing, OPT_MUSICBACK | OPT_RINGBACK);
char featurecode[FEATURE_MAX_LEN + 1] = { 0, };
if (single) {
/* Turn off hold music, etc */
ast_deactivate_generator(in);
@@ -742,10 +745,10 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
}
}
if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) &&
(f->subclass == '*')) { /* hmm it it not guaranteed to be '*' anymore. */
if (ast_test_flag(peerflags, OPT_CALLER_HANGUP) &&
detect_disconnect(in, f->subclass, featurecode, sizeof(featurecode))) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass);
ast_verbose(VERBOSE_PREFIX_3 "User requested call disconnect.\n");
*to=0;
ast_cdr_noanswer(in->cdr);
strcpy(status, "CANCEL");
@@ -786,6 +789,34 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct dial_l
return peer;
}
static int detect_disconnect(struct ast_channel *chan, char code, char *featurecode, int len)
{
struct ast_flags features = { AST_FEATURE_DISCONNECT }; /* only concerned with disconnect feature */
struct ast_call_feature feature;
char *tmp;
int res;
if ((strlen(featurecode)) < (len - 2)) {
tmp = &featurecode[strlen(featurecode)];
tmp[0] = code;
tmp[1] = '\0';
} else {
featurecode[0] = 0;
return -1; /* no room in featurecode buffer */
}
res = ast_feature_detect(chan, &features, featurecode, &feature);
if (res != FEATURE_RETURN_STOREDIGITS) {
featurecode[0] = '\0';
}
if (feature.feature_mask & AST_FEATURE_DISCONNECT) {
return 1;
}
return 0;
}
static void replace_macro_delimiter(char *s)
{
for (; *s; s++)