summaryrefslogtreecommitdiff
path: root/main/bridge_channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/bridge_channel.c')
-rw-r--r--main/bridge_channel.c90
1 files changed, 63 insertions, 27 deletions
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index ac72c8bc2..5e359ff47 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -1510,6 +1510,51 @@ static void testsuite_notify_feature_success(struct ast_channel *chan, const cha
#endif /* TEST_FRAMEWORK */
}
+static int bridge_channel_feature_digit_add(
+ struct ast_bridge_channel *bridge_channel, int digit, size_t dtmf_len)
+{
+ if (dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1) {
+ /* Add the new digit to the DTMF string so we can do our matching */
+ bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit;
+ bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0';
+
+ ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n",
+ bridge_channel, ast_channel_name(bridge_channel->chan),
+ bridge_channel->dtmf_hook_state.collected);
+ }
+
+ return dtmf_len;
+}
+
+static unsigned int bridge_channel_feature_digit_timeout(struct ast_bridge_channel *bridge_channel)
+{
+ unsigned int digit_timeout;
+ struct ast_features_general_config *gen_cfg;
+
+ /* Determine interdigit timeout */
+ ast_channel_lock(bridge_channel->chan);
+ gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
+ ast_channel_unlock(bridge_channel->chan);
+
+ if (!gen_cfg) {
+ ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n");
+ return 3000; /* Pick a reasonable failsafe timeout in ms */
+ }
+
+ digit_timeout = gen_cfg->featuredigittimeout;
+ ao2_ref(gen_cfg, -1);
+
+ return digit_timeout;
+}
+
+void ast_bridge_channel_feature_digit_add(struct ast_bridge_channel *bridge_channel, int digit)
+{
+ if (digit) {
+ bridge_channel_feature_digit_add(
+ bridge_channel, digit, strlen(bridge_channel->dtmf_hook_state.collected));
+ }
+}
+
void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel, int digit)
{
struct ast_bridge_features *features = bridge_channel->features;
@@ -1527,17 +1572,10 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel,
}
if (digit) {
- /* There should always be room for the new digit. */
- ast_assert(dtmf_len < ARRAY_LEN(bridge_channel->dtmf_hook_state.collected) - 1);
-
- /* Add the new digit to the DTMF string so we can do our matching */
- bridge_channel->dtmf_hook_state.collected[dtmf_len++] = digit;
- bridge_channel->dtmf_hook_state.collected[dtmf_len] = '\0';
-
- ast_debug(1, "DTMF feature string on %p(%s) is now '%s'\n",
- bridge_channel, ast_channel_name(bridge_channel->chan),
- bridge_channel->dtmf_hook_state.collected);
+ dtmf_len = bridge_channel_feature_digit_add(bridge_channel, digit, dtmf_len);
+ }
+ while (digit) {
/* See if a DTMF feature hook matches or can match */
hook = ao2_find(features->dtmf_hooks, bridge_channel->dtmf_hook_state.collected,
OBJ_SEARCH_PARTIAL_KEY);
@@ -1545,25 +1583,12 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel,
ast_debug(1, "No DTMF feature hooks on %p(%s) match '%s'\n",
bridge_channel, ast_channel_name(bridge_channel->chan),
bridge_channel->dtmf_hook_state.collected);
+ break;
} else if (dtmf_len != strlen(hook->dtmf.code)) {
unsigned int digit_timeout;
- struct ast_features_general_config *gen_cfg;
-
/* Need more digits to match */
ao2_ref(hook, -1);
-
- /* Determine interdigit timeout */
- ast_channel_lock(bridge_channel->chan);
- gen_cfg = ast_get_chan_features_general_config(bridge_channel->chan);
- ast_channel_unlock(bridge_channel->chan);
- if (!gen_cfg) {
- ast_log(LOG_ERROR, "Unable to retrieve features configuration.\n");
- digit_timeout = 3000; /* Pick a reasonable failsafe timeout in ms */
- } else {
- digit_timeout = gen_cfg->featuredigittimeout;
- ao2_ref(gen_cfg, -1);
- }
-
+ digit_timeout = bridge_channel_feature_digit_timeout(bridge_channel);
bridge_channel->dtmf_hook_state.interdigit_timeout =
ast_tvadd(ast_tvnow(), ast_samp2tv(digit_timeout, 1000));
return;
@@ -1612,10 +1637,21 @@ void ast_bridge_channel_feature_digit(struct ast_bridge_channel *bridge_channel,
*/
if (bridge_channel->chan && ast_check_hangup_locked(bridge_channel->chan)) {
ast_bridge_channel_kick(bridge_channel, 0);
+ bridge_channel->dtmf_hook_state.collected[0] = '\0';
+ return;
+ }
+
+ /* if there is dtmf that has been collected then loop back through,
+ but set digit to -1 so it doesn't try to do an add since the dtmf
+ is already in the buffer */
+ dtmf_len = strlen(bridge_channel->dtmf_hook_state.collected);
+ if (!dtmf_len) {
+ return;
}
- return;
}
- } else {
+ }
+
+ if (!digit) {
ast_debug(1, "DTMF feature string collection on %p(%s) timed out\n",
bridge_channel, ast_channel_name(bridge_channel->chan));
}