From d71d8ed99525f982cb3eaf988f8e8d78fd5bf527 Mon Sep 17 00:00:00 2001 From: Richard Mudgett <rmudgett@digium.com> Date: Wed, 9 May 2012 02:35:29 +0000 Subject: [PATCH] Keep answered FollowMe calls until call accepted or last step times out. git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@365856 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- UPGRADE.txt | 5 ++++ apps/app_followme.c | 54 +++++++++++++++++++++++++++++++----- configs/followme.conf.sample | 13 +++++---- 3 files changed, 59 insertions(+), 13 deletions(-) diff --git a/UPGRADE.txt b/UPGRADE.txt index adff551695..e5bbb6ae17 100644 --- a/UPGRADE.txt +++ b/UPGRADE.txt @@ -79,6 +79,11 @@ app_meetme: - The 'c' option (announce user count) will now work even if the 'q' (quiet) option is enabled. +app_followme: + - Answered outgoing calls no longer get cut off when the next step is started. + You now have until the last step times out to decide if you want to accept + the call or not before being disconnected. + SIP === - A new option "tonezone" for setting default tonezone for the channel driver diff --git a/apps/app_followme.c b/apps/app_followme.c index 4f98113add..04439e4bf3 100644 --- a/apps/app_followme.c +++ b/apps/app_followme.c @@ -190,6 +190,8 @@ struct findme_user { char dialarg[256]; /*! Collected digits to accept/decline the call. */ char yn[MAX_YN_STRING]; + /*! TRUE if the outgoing call is answered. */ + unsigned int answered:1; /*! TRUE if connected line information is available. */ unsigned int pending_connected_update:1; AST_LIST_ENTRY(findme_user) entry; @@ -550,12 +552,14 @@ static void clear_caller(struct findme_user *tmpuser) tmpuser->ochan = NULL; } -static void clear_calling_tree(struct findme_user_listptr *findme_user_list) +static void clear_unanswered_calls(struct findme_user_listptr *findme_user_list) { struct findme_user *tmpuser; AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) { - clear_caller(tmpuser); + if (!tmpuser->answered) { + clear_caller(tmpuser); + } } } @@ -704,8 +708,8 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us totalwait -= tmpto; wtd = to; if (totalwait <= 0) { - ast_verb(3, "We've hit our timeout for this step. Drop everyone and move on to the next one. %ld\n", totalwait); - clear_calling_tree(findme_user_list); + ast_verb(3, "We've hit our timeout for this step. Dropping unanswered calls and starting the next step.\n"); + clear_unanswered_calls(findme_user_list); return NULL; } if (winner) { @@ -743,6 +747,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us break; } ast_verb(3, "%s answered %s\n", ast_channel_name(winner), ast_channel_name(caller)); + tmpuser->answered = 1; /* If call has been answered, then the eventual hangup is likely to be normal hangup */ ast_channel_hangupcause_set(winner, AST_CAUSE_NORMAL_CLEARING); ast_channel_hangupcause_set(caller, AST_CAUSE_NORMAL_CLEARING); @@ -956,6 +961,19 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel ast_debug(2, "Number(s) %s timeout %ld\n", nm->number, nm->timeout); + /* + * Put all active outgoing channels into autoservice. + * + * This needs to be done because ast_exists_extension() may put + * the caller into autoservice. + */ + AST_LIST_TRAVERSE(&findme_user_list, tmpuser, entry) { + if (tmpuser->ochan) { + ast_autoservice_start(tmpuser->ochan); + } + } + + /* Create all new outgoing calls */ ast_copy_string(num, nm->number, sizeof(num)); for (number = num; number; number = rest) { struct ast_channel *outbound; @@ -1009,12 +1027,15 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel tmpuser->ochan = outbound; tmpuser->state = 0; + AST_LIST_INSERT_TAIL(&new_user_list, tmpuser, entry); + } + /* Start all new outgoing calls */ + AST_LIST_TRAVERSE_SAFE_BEGIN(&new_user_list, tmpuser, entry) { ast_verb(3, "calling Local/%s\n", tmpuser->dialarg); - if (!ast_call(tmpuser->ochan, tmpuser->dialarg, 0)) { - AST_LIST_INSERT_TAIL(&new_user_list, tmpuser, entry); - } else { + if (ast_call(tmpuser->ochan, tmpuser->dialarg, 0)) { ast_verb(3, "couldn't reach at this number.\n"); + AST_LIST_REMOVE_CURRENT(entry); /* Destroy this failed new outgoing call. */ ast_channel_lock(tmpuser->ochan); @@ -1025,6 +1046,17 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel destroy_calling_node(tmpuser); } } + AST_LIST_TRAVERSE_SAFE_END; + + /* Take all active outgoing channels out of autoservice. */ + AST_LIST_TRAVERSE_SAFE_BEGIN(&findme_user_list, tmpuser, entry) { + if (tmpuser->ochan && ast_autoservice_stop(tmpuser->ochan)) { + /* Existing outgoing call hungup. */ + AST_LIST_REMOVE_CURRENT(entry); + destroy_calling_node(tmpuser); + } + } + AST_LIST_TRAVERSE_SAFE_END; if (AST_LIST_EMPTY(&new_user_list)) { /* No new channels remain at this order level. If there were any at all. */ @@ -1036,6 +1068,14 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel winner = wait_for_winner(&findme_user_list, nm, caller, tpargs); if (!winner) { + /* Remove all dead outgoing nodes. */ + AST_LIST_TRAVERSE_SAFE_BEGIN(&findme_user_list, tmpuser, entry) { + if (!tmpuser->ochan) { + AST_LIST_REMOVE_CURRENT(entry); + destroy_calling_node(tmpuser); + } + } + AST_LIST_TRAVERSE_SAFE_END; continue; } diff --git a/configs/followme.conf.sample b/configs/followme.conf.sample index b11836a5cc..418ec582ea 100644 --- a/configs/followme.conf.sample +++ b/configs/followme.conf.sample @@ -40,17 +40,18 @@ context=>default ; The context to dial the numbers from number=>01233456,25 ; The a follow-me number to call. The format is: -; number=> <number to call[&2nd #[&3rd #]]> [, <timeout value in seconds> [, <order in follow-me>] ] +; number=> <number to call[&2nd #[&...]]>[,<timeout value in seconds>[,<order in follow-me>]] ; You can specify as many of these numbers as you like. They will be dialed in the ; order that you specify them in the config file OR as specified with the order field ; on the number prompt. As you can see from the example, forked dialing of multiple ; numbers in the same step is supported with this application if you'd like to dial ; multiple numbers in the same followme step. -; It's also important to note that the timeout value is not the same -; as the timeout value you would use in app_dial. This timeout value is the amount of -; time allowed between the time the dialing step starts and the callee makes a choice -; on whether to take the call or not. That being the case, you may want to account for -; this time, and make this timeout longer than a timeout you might specify in app_dial. +; +; The timeout value is the amount of time allowed between the time the dialing step +; starts and the callee answers. The callee then has until the timeout of the last +; step to make a choice on whether to take the call or not. That being the case, +; you may want to make the timeout on the last step longer to give enough time to +; make the choice to accept or not. takecall=>1 ; The keypress for the callee to take taking the current call. This can be ; a single digit or multiple digits. Default is the global default. -- GitLab