summaryrefslogtreecommitdiff
path: root/main/channel.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2013-08-23 18:33:36 +0000
committerRichard Mudgett <rmudgett@digium.com>2013-08-23 18:33:36 +0000
commit6ebfac8e70b0863fd96ee4fe6ca4b254696fe9c4 (patch)
treedf6a91c733cc32ae5179493b800384824dcdcfa3 /main/channel.c
parent31ab4866275aa28f6ec9fe7ce166b4f86f8ecf24 (diff)
Handle DTMF and hold wrapup when a channel leaves the bridging system.
DTMF start/end and hold/unhold events have state because a DTMF begin event and hold event must be ended by something. The following cases need to be handled when a channel is moved around in the system. * When a channel leaves a bridge it may owe a DTMF end event to the bridge. * When a channel leaves a bridge it may owe an UNHOLD event to the bridge. (This case is explicitly ignored because things like transfers need explicit control over this.) * When a channel leaves the bridging system it may need to simulate a DTMF end event to the channel. * When a channel leaves the bridging system it may need to simulate an UNHOLD event to the channel. The patch also fixes the following: * Fixes playing a file and restarting MOH using the latest MOH class used. (closes issue ASTERISK-22043) Reported by: Matt Jordan Review: https://reviewboard.asterisk.org/r/2791/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@397577 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main/channel.c')
-rw-r--r--main/channel.c38
1 files changed, 35 insertions, 3 deletions
diff --git a/main/channel.c b/main/channel.c
index 1abed5e94..f085d31e8 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -941,6 +941,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
/* Initial state */
ast_channel_state_set(tmp, state);
+ ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD);
ast_channel_streamid_set(tmp, -1);
@@ -1072,6 +1073,8 @@ struct ast_channel *ast_dummy_channel_alloc(void)
ast_channel_epfd_set(tmp, -1);
#endif
+ ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD);
+
ast_channel_internal_setup_topics(tmp);
headp = ast_channel_varshead(tmp);
@@ -4453,7 +4456,6 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
ast_channel_connected(chan));
}
break;
-
case AST_CONTROL_REDIRECTING:
{
struct ast_party_redirecting redirecting;
@@ -4466,7 +4468,10 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
ast_party_redirecting_free(&redirecting);
}
break;
-
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+ ast_channel_hold_state_set(chan, condition);
+ break;
default:
break;
}
@@ -6376,6 +6381,7 @@ void ast_do_masquerade(struct ast_channel *original)
int origstate;
int visible_indication;
int clone_was_zombie = 0;/*!< TRUE if the clonechan was a zombie before the masquerade. */
+ int clone_hold_state;
struct ast_frame *current;
const struct ast_channel_tech *t;
void *t_pvt;
@@ -6478,6 +6484,8 @@ void ast_do_masquerade(struct ast_channel *original)
free_translation(clonechan);
free_translation(original);
+ clone_hold_state = ast_channel_hold_state(clonechan);
+
/* Save the current DTMF digit being sent if any. */
clone_sending_dtmf_digit = ast_channel_sending_dtmf_digit(clonechan);
clone_sending_dtmf_tv = ast_channel_sending_dtmf_tv(clonechan);
@@ -6712,6 +6720,11 @@ void ast_do_masquerade(struct ast_channel *original)
ast_bridge_notify_masquerade(original);
+ if (clone_hold_state == AST_CONTROL_HOLD) {
+ ast_debug(1, "Channel %s simulating UNHOLD for masquerade.\n",
+ ast_channel_name(original));
+ ast_indicate(original, AST_CONTROL_UNHOLD);
+ }
if (clone_sending_dtmf_digit) {
/*
* The clonechan was sending a DTMF digit that was not completed
@@ -6731,7 +6744,23 @@ void ast_do_masquerade(struct ast_channel *original)
* (RINGING, CONGESTION, etc.)
*/
if (visible_indication) {
- ast_indicate(original, visible_indication);
+ if (visible_indication == AST_CONTROL_HOLD) {
+ const char *latest_musicclass;
+ int len;
+
+ ast_channel_lock(original);
+ latest_musicclass = ast_strdupa(ast_channel_latest_musicclass(original));
+ ast_channel_unlock(original);
+ if (ast_strlen_zero(latest_musicclass)) {
+ latest_musicclass = NULL;
+ len = 0;
+ } else {
+ len = strlen(latest_musicclass) + 1;
+ }
+ ast_indicate_data(original, visible_indication, latest_musicclass, len);
+ } else {
+ ast_indicate(original, visible_indication);
+ }
}
ast_channel_lock(original);
@@ -10390,6 +10419,9 @@ void ast_channel_end_dtmf(struct ast_channel *chan, char digit, struct timeval s
}
duration = ast_tvdiff_ms(ast_tvnow(), start);
+ if (duration < option_dtmfminduration) {
+ duration = option_dtmfminduration;
+ }
ast_senddigit_end(chan, digit, duration);
ast_log(LOG_DTMF, "DTMF end '%c' simulated on %s due to %s, duration %ld ms\n",
digit, ast_channel_name(chan), why, duration);