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
This commit is contained in:
Richard Mudgett
2012-05-09 02:35:29 +00:00
parent a689a5776e
commit d71d8ed995
3 changed files with 59 additions and 13 deletions

View File

@@ -79,6 +79,11 @@ app_meetme:
- The 'c' option (announce user count) will now work even if the 'q' (quiet) - The 'c' option (announce user count) will now work even if the 'q' (quiet)
option is enabled. 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 SIP
=== ===
- A new option "tonezone" for setting default tonezone for the channel driver - A new option "tonezone" for setting default tonezone for the channel driver

View File

@@ -190,6 +190,8 @@ struct findme_user {
char dialarg[256]; char dialarg[256];
/*! Collected digits to accept/decline the call. */ /*! Collected digits to accept/decline the call. */
char yn[MAX_YN_STRING]; char yn[MAX_YN_STRING];
/*! TRUE if the outgoing call is answered. */
unsigned int answered:1;
/*! TRUE if connected line information is available. */ /*! TRUE if connected line information is available. */
unsigned int pending_connected_update:1; unsigned int pending_connected_update:1;
AST_LIST_ENTRY(findme_user) entry; AST_LIST_ENTRY(findme_user) entry;
@@ -550,14 +552,16 @@ static void clear_caller(struct findme_user *tmpuser)
tmpuser->ochan = NULL; 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; struct findme_user *tmpuser;
AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) { AST_LIST_TRAVERSE(findme_user_list, tmpuser, entry) {
if (!tmpuser->answered) {
clear_caller(tmpuser); clear_caller(tmpuser);
} }
} }
}
static void destroy_calling_node(struct findme_user *node) static void destroy_calling_node(struct findme_user *node)
{ {
@@ -704,8 +708,8 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
totalwait -= tmpto; totalwait -= tmpto;
wtd = to; wtd = to;
if (totalwait <= 0) { 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); ast_verb(3, "We've hit our timeout for this step. Dropping unanswered calls and starting the next step.\n");
clear_calling_tree(findme_user_list); clear_unanswered_calls(findme_user_list);
return NULL; return NULL;
} }
if (winner) { if (winner) {
@@ -743,6 +747,7 @@ static struct ast_channel *wait_for_winner(struct findme_user_listptr *findme_us
break; break;
} }
ast_verb(3, "%s answered %s\n", ast_channel_name(winner), ast_channel_name(caller)); 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 */ /* 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(winner, AST_CAUSE_NORMAL_CLEARING);
ast_channel_hangupcause_set(caller, 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); 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)); ast_copy_string(num, nm->number, sizeof(num));
for (number = num; number; number = rest) { for (number = num; number; number = rest) {
struct ast_channel *outbound; struct ast_channel *outbound;
@@ -1009,12 +1027,15 @@ static struct ast_channel *findmeexec(struct fm_args *tpargs, struct ast_channel
tmpuser->ochan = outbound; tmpuser->ochan = outbound;
tmpuser->state = 0; tmpuser->state = 0;
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); AST_LIST_INSERT_TAIL(&new_user_list, tmpuser, entry);
} else { }
/* 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_verb(3, "couldn't reach at this number.\n"); ast_verb(3, "couldn't reach at this number.\n");
AST_LIST_REMOVE_CURRENT(entry);
/* Destroy this failed new outgoing call. */ /* Destroy this failed new outgoing call. */
ast_channel_lock(tmpuser->ochan); 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); 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)) { if (AST_LIST_EMPTY(&new_user_list)) {
/* No new channels remain at this order level. If there were any at all. */ /* 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); winner = wait_for_winner(&findme_user_list, nm, caller, tpargs);
if (!winner) { 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; continue;
} }

View File

@@ -40,17 +40,18 @@ context=>default
; The context to dial the numbers from ; The context to dial the numbers from
number=>01233456,25 number=>01233456,25
; The a follow-me number to call. The format is: ; 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 ; 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 ; 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 ; 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 ; numbers in the same step is supported with this application if you'd like to dial
; multiple numbers in the same followme step. ; 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 ; The timeout value is the amount of time allowed between the time the dialing step
; time allowed between the time the dialing step starts and the callee makes a choice ; starts and the callee answers. The callee then has until the timeout of the last
; on whether to take the call or not. That being the case, you may want to account for ; step to make a choice on whether to take the call or not. That being the case,
; this time, and make this timeout longer than a timeout you might specify in app_dial. ; 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 takecall=>1
; The keypress for the callee to take taking the current call. This can be ; 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. ; a single digit or multiple digits. Default is the global default.