features: Add no answer option to Bridge.
Adds the n "no answer" option to the Bridge application so that answer supervision can not automatically be provided when Bridge is executed. Additionally, a mechanism (dialplan variable) is added to prevent bridge targets (typically the target of a masquerade) from answering the channel when they enter the bridge. ASTERISK-30223 #close Change-Id: I76f73fcd8e403bcd18f2abb40c658f537ac1ba6d
This commit is contained in:
parent
062cef0a85
commit
a2e418e495
|
@ -0,0 +1,5 @@
|
||||||
|
Subject: features
|
||||||
|
|
||||||
|
The Bridge application now has the n "no answer" option
|
||||||
|
that can be used to prevent the channel from being
|
||||||
|
automatically answered prior to bridging.
|
|
@ -164,6 +164,12 @@
|
||||||
</variable>
|
</variable>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="n">
|
||||||
|
<para>Do not answer the channel automatically before bridging.</para>
|
||||||
|
<para>Additionally, to prevent a bridged channel (the target of the Bridge application)
|
||||||
|
from answering, the <literal>BRIDGE_NOANSWER</literal> variable can be set to inhibit
|
||||||
|
answering.</para>
|
||||||
|
</option>
|
||||||
<option name="S(x)">
|
<option name="S(x)">
|
||||||
<para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
|
<para>Hang up the call after <replaceable>x</replaceable> seconds *after* the called party has answered the call.</para>
|
||||||
</option>
|
</option>
|
||||||
|
@ -525,7 +531,7 @@ static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config,
|
static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config,
|
||||||
struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features)
|
struct ast_bridge_features *chan_features, struct ast_bridge_features *peer_features, int noanswer)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
|
SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
|
||||||
|
@ -553,7 +559,10 @@ static int pre_bridge_setup(struct ast_channel *chan, struct ast_channel *peer,
|
||||||
|
|
||||||
res = 0;
|
res = 0;
|
||||||
|
|
||||||
if (ast_channel_state(chan) != AST_STATE_UP) {
|
if (noanswer) {
|
||||||
|
ast_debug(1, "Skipping answer on %s due to no answer directive\n", ast_channel_name(chan));
|
||||||
|
} else if (ast_channel_state(chan) != AST_STATE_UP) {
|
||||||
|
ast_debug(1, "Answering channel for bridge: %s\n", ast_channel_name(chan));
|
||||||
res = ast_raw_answer_with_stream_topology(chan, config->answer_topology);
|
res = ast_raw_answer_with_stream_topology(chan, config->answer_topology);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -627,6 +636,8 @@ int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *pee
|
||||||
struct ast_bridge *bridge;
|
struct ast_bridge *bridge;
|
||||||
struct ast_bridge_features chan_features;
|
struct ast_bridge_features chan_features;
|
||||||
struct ast_bridge_features *peer_features;
|
struct ast_bridge_features *peer_features;
|
||||||
|
const char *value;
|
||||||
|
int noanswer;
|
||||||
SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
|
SCOPE_TRACE(1, "%s Peer: %s\n", ast_channel_name(chan), ast_channel_name(peer));
|
||||||
|
|
||||||
/* Setup features. */
|
/* Setup features. */
|
||||||
|
@ -639,7 +650,12 @@ int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *pee
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features)) {
|
ast_channel_lock(chan);
|
||||||
|
value = pbx_builtin_getvar_helper(chan, "BRIDGE_NOANSWER");
|
||||||
|
noanswer = !ast_strlen_zero(value) ? 1 : 0;
|
||||||
|
ast_channel_unlock(chan);
|
||||||
|
|
||||||
|
if (pre_bridge_setup(chan, peer, config, &chan_features, peer_features, noanswer)) {
|
||||||
ast_bridge_features_destroy(peer_features);
|
ast_bridge_features_destroy(peer_features);
|
||||||
ast_bridge_features_cleanup(&chan_features);
|
ast_bridge_features_cleanup(&chan_features);
|
||||||
bridge_failed_peer_goto(chan, peer);
|
bridge_failed_peer_goto(chan, peer);
|
||||||
|
@ -848,6 +864,7 @@ enum {
|
||||||
OPT_CALLER_PARK = (1 << 10),
|
OPT_CALLER_PARK = (1 << 10),
|
||||||
OPT_CALLEE_KILL = (1 << 11),
|
OPT_CALLEE_KILL = (1 << 11),
|
||||||
OPT_CALLEE_GO_ON = (1 << 12),
|
OPT_CALLEE_GO_ON = (1 << 12),
|
||||||
|
OPT_NOANSWER = (1 << 13),
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
@ -866,6 +883,7 @@ AST_APP_OPTIONS(bridge_exec_options, BEGIN_OPTIONS
|
||||||
AST_APP_OPTION('k', OPT_CALLEE_PARK),
|
AST_APP_OPTION('k', OPT_CALLEE_PARK),
|
||||||
AST_APP_OPTION('K', OPT_CALLER_PARK),
|
AST_APP_OPTION('K', OPT_CALLER_PARK),
|
||||||
AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
|
AST_APP_OPTION_ARG('L', OPT_DURATION_LIMIT, OPT_ARG_DURATION_LIMIT),
|
||||||
|
AST_APP_OPTION('n', OPT_NOANSWER),
|
||||||
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
|
AST_APP_OPTION_ARG('S', OPT_DURATION_STOP, OPT_ARG_DURATION_STOP),
|
||||||
AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
|
AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
|
||||||
AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
|
AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
|
||||||
|
@ -1012,6 +1030,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
|
||||||
struct ast_bridge_features *peer_features;
|
struct ast_bridge_features *peer_features;
|
||||||
struct ast_bridge *bridge;
|
struct ast_bridge *bridge;
|
||||||
struct ast_features_xfer_config *xfer_cfg;
|
struct ast_features_xfer_config *xfer_cfg;
|
||||||
|
int noanswer;
|
||||||
|
|
||||||
AST_DECLARE_APP_ARGS(args,
|
AST_DECLARE_APP_ARGS(args,
|
||||||
AST_APP_ARG(dest_chan);
|
AST_APP_ARG(dest_chan);
|
||||||
|
@ -1066,6 +1085,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
|
||||||
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
|
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_PARKCALL);
|
||||||
if (ast_test_flag(&opts, OPT_CALLER_PARK))
|
if (ast_test_flag(&opts, OPT_CALLER_PARK))
|
||||||
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
|
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_PARKCALL);
|
||||||
|
noanswer = ast_test_flag(&opts, OPT_NOANSWER);
|
||||||
|
|
||||||
/* Setup after bridge goto location. */
|
/* Setup after bridge goto location. */
|
||||||
if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
|
if (ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
|
||||||
|
@ -1096,7 +1116,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pre_bridge_setup(chan, current_dest_chan, &bconfig, &chan_features, peer_features)) {
|
if (pre_bridge_setup(chan, current_dest_chan, &bconfig, &chan_features, peer_features, noanswer)) {
|
||||||
ast_bridge_features_destroy(peer_features);
|
ast_bridge_features_destroy(peer_features);
|
||||||
ast_bridge_features_cleanup(&chan_features);
|
ast_bridge_features_cleanup(&chan_features);
|
||||||
goto done;
|
goto done;
|
||||||
|
|
Loading…
Reference in New Issue