diff --git a/UPGRADE.txt b/UPGRADE.txt index adff55169510a9c2e52df3d68b5bf6acd7fd209a..e5bbb6ae170352c3afd541ac50482b9834344297 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 4f98113add4830b5e9bf681d0b4356ef49d7b86b..04439e4bf30d998da30c875216339704db1b6208 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 b11836a5cc36366352e04441cb01c94decf63113..418ec582ea312d667a7e5152441bed1204cfa856 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.