Move after bridge callbacks into their own file

One more major refactoring to go.


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395367 65c4cc65-6c06-0410-ace0-fbb531ad65f3
changes/78/78/1
Matthew Jordan 12 years ago
parent 71609d58aa
commit 9d8a5ceb02

@ -43,6 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/bridging.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_basic.h"
#include "asterisk/bridging_after.h"
#include "asterisk/config_options.h"
#include "asterisk/features_config.h"
#include "asterisk/astobj2.h"
@ -1055,7 +1056,7 @@ static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, stru
if (!caller_bridge) {
/* Reset agent. */
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
return;
}
res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
@ -1063,7 +1064,7 @@ static void agent_connect_caller(struct ast_bridge_channel *bridge_channel, stru
if (res) {
/* Reset agent. */
ast_bridge_destroy(caller_bridge);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
return;
}
ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_ANSWER, NULL, 0);
@ -1159,13 +1160,13 @@ static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bri
if (deferred_logoff) {
ast_debug(1, "Agent %s: Deferred logoff.\n", agent->username);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
} else if (probation_timedout) {
ast_debug(1, "Agent %s: Login complete.\n", agent->username);
agent_devstate_changed(agent->username);
} else if (ack_timedout) {
ast_debug(1, "Agent %s: Ack call timeout.\n", agent->username);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
} else if (wrapup_timedout) {
ast_debug(1, "Agent %s: Wrapup timeout. Ready for new call.\n", agent->username);
agent_devstate_changed(agent->username);
@ -1175,7 +1176,7 @@ static int bridge_agent_hold_heartbeat(struct ast_bridge *bridge, struct ast_bri
}
static void agent_after_bridge_cb(struct ast_channel *chan, void *data);
static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason reason, void *data);
static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data);
/*!
* \internal
@ -1252,7 +1253,7 @@ static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_cha
}
if (swap) {
res = ast_after_bridge_callback_set(chan, agent_after_bridge_cb,
res = ast_bridge_set_after_callback(chan, agent_after_bridge_cb,
agent_after_bridge_cb_failed, chan);
if (res) {
ast_channel_remove_bridge_role(chan, "holding_participant");
@ -1270,7 +1271,7 @@ static int bridge_agent_hold_push(struct ast_bridge *self, struct ast_bridge_cha
* agent will have some slightly different behavior in corner
* cases.
*/
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
return 0;
}
@ -1620,7 +1621,7 @@ static void agent_after_bridge_cb(struct ast_channel *chan, void *data)
ao2_ref(agent, -1);
}
static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason reason, void *data)
static void agent_after_bridge_cb_failed(enum ast_bridge_after_cb_reason reason, void *data)
{
struct ast_channel *chan = data;
struct agent_pvt *agent;
@ -1631,7 +1632,7 @@ static void agent_after_bridge_cb_failed(enum ast_after_bridge_cb_reason reason,
}
ast_log(LOG_WARNING, "Agent %s: Forced logout. Lost control of %s because: %s\n",
agent->username, ast_channel_name(chan),
ast_after_bridge_cb_reason_string(reason));
ast_bridge_after_cb_reason_string(reason));
agent_lock(agent);
agent_logout(agent);
ao2_ref(agent, -1);
@ -1704,7 +1705,7 @@ static void caller_abort_agent(struct agent_pvt *agent)
}
/* Kick the agent out of the holding bridge to reset it. */
ast_bridge_channel_leave_bridge_nolock(logged, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge_nolock(logged, BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_unlock(logged);
}
@ -1714,7 +1715,7 @@ static int caller_safety_timeout(struct ast_bridge *bridge, struct ast_bridge_ch
if (agent->state == AGENT_STATE_CALL_PRESENT) {
ast_verb(3, "Agent '%s' did not respond. Safety timeout.\n", agent->username);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
caller_abort_agent(agent);
}

@ -67,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/dial.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_after.h"
#include "asterisk/features_config.h"
/*** DOCUMENTATION
@ -201,7 +202,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<argument name="exten" required="false" />
<argument name="priority" required="true" />
<para>If the call is answered, transfer the calling party to
the specified <replaceable>priority</replaceable> and the called party to the specified
the specified <replaceable>priority</replaceable> and the called party to the specified
<replaceable>priority</replaceable> plus one.</para>
<note>
<para>You cannot use any additional action post answer options in conjunction with this option.</para>
@ -290,7 +291,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<argument name="arg" multiple="true">
<para>Macro arguments</para>
</argument>
<para>Execute the specified <replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel
<para>Execute the specified <replaceable>macro</replaceable> for the <emphasis>called</emphasis> channel
before connecting to the calling channel. Arguments can be specified to the Macro
using <literal>^</literal> as a delimiter. The macro can set the variable
<variable>MACRO_RESULT</variable> to specify the following actions after the macro is
@ -332,7 +333,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>With <replaceable>delete</replaceable> set to <literal>1</literal>, the introduction will
always be deleted.</para>
</argument>
<para>This option is a modifier for the call screening/privacy mode. (See the
<para>This option is a modifier for the call screening/privacy mode. (See the
<literal>p</literal> and <literal>P</literal> options.) It specifies
that no introductions are to be saved in the <directory>priv-callerintros</directory>
directory.</para>
@ -353,7 +354,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<argument name="mode">
<para>With <replaceable>mode</replaceable> either not specified or set to <literal>1</literal>,
the originator hanging up will cause the phone to ring back immediately.</para>
<para>With <replaceable>mode</replaceable> set to <literal>2</literal>, when the operator
<para>With <replaceable>mode</replaceable> set to <literal>2</literal>, when the operator
flashes the trunk, it will ring their phone back.</para>
</argument>
<para>Enables <emphasis>operator services</emphasis> mode. This option only
@ -1071,7 +1072,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in,
/* If we are calling a single channel, and not providing ringback or music, */
/* then, make them compatible for in-band tone purpose */
if (ast_channel_make_compatible(outgoing->chan, in) < 0) {
/* If these channels can not be made compatible,
/* If these channels can not be made compatible,
* there is no point in continuing. The bridge
* will just fail if it gets that far.
*/
@ -1765,7 +1766,7 @@ static int do_privacy(struct ast_channel *chan, struct ast_channel *peer,
/*! \page DialPrivacy Dial Privacy scripts
* \par priv-callee-options script:
* \li Dial 1 if you wish this caller to reach you directly in the future,
* \li Dial 1 if you wish this caller to reach you directly in the future,
* and immediately connect to their incoming call.
* \li Dial 2 if you wish to send this caller to voicemail now and forevermore.
* \li Dial 3 to send this caller to the torture menus, now and forevermore.
@ -1891,7 +1892,7 @@ static int setup_privacy_args(struct privacy_args *pa,
} else if (ast_test_flag64(opts, OPT_SCREEN_NOCALLERID) && strncmp(pa->privcid, "NOCALLERID", 10) == 0) {
ast_verb(3, "CallerID blank; N option set; Screening should happen; dbval is %d\n", pa->privdb_val);
}
if (pa->privdb_val == AST_PRIVACY_DENY) {
ast_verb(3, "Privacy DB reports PRIVACY_DENY for this callerid. Dial reports unavailable\n");
ast_copy_string(pa->status, "NOANSWER", sizeof(pa->status));
@ -2021,14 +2022,14 @@ static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_ch
ast_channel_lock(chan);
context = ast_strdupa(ast_channel_context(chan));
ast_channel_unlock(chan);
ast_after_bridge_set_h(peer, context);
ast_bridge_set_after_h(peer, context);
} else if (ast_test_flag64(opts, OPT_CALLEE_GO_ON)) {
ast_channel_lock(chan);
context = ast_strdupa(ast_channel_context(chan));
extension = ast_strdupa(ast_channel_exten(chan));
priority = ast_channel_priority(chan);
ast_channel_unlock(chan);
ast_after_bridge_set_go_on(peer, context, extension, priority,
ast_bridge_set_after_go_on(peer, context, extension, priority,
opt_args[OPT_ARG_CALLEE_GO_ON]);
}
}
@ -2444,7 +2445,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* We are on the only destination. */
ast_rtp_instance_early_bridge_make_compatible(tc, chan);
}
/* Inherit specially named variables from parent channel */
ast_channel_inherit_variables(chan, tc);
ast_channel_datastore_inherit(chan, tc);
@ -2698,7 +2699,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
/* If appropriate, log that we have a destination channel and set the answer time */
if (ast_channel_name(peer))
pbx_builtin_setvar_helper(chan, "DIALEDPEERNAME", ast_channel_name(peer));
ast_channel_lock(peer);
number = pbx_builtin_getvar_helper(peer, "DIALEDPEERNUMBER");
if (ast_strlen_zero(number)) {
@ -2967,7 +2968,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
ast_channel_hangupcause_set(chan, ast_channel_hangupcause(peer));
}
setup_peer_after_bridge_goto(chan, peer, &opts, opt_args);
if (ast_after_bridge_goto_setup(peer)
if (ast_bridge_setup_after_goto(peer)
|| ast_pbx_start(peer)) {
ast_autoservice_chan_hangup_peer(chan, peer);
}
@ -2997,7 +2998,7 @@ static int dial_exec_full(struct ast_channel *chan, const char *data, struct ast
config.end_bridge_callback = end_bridge_callback;
config.end_bridge_callback_data = chan;
config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
if (moh) {
moh = 0;
ast_moh_stop(chan);

@ -109,6 +109,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_channels.h"
#include "asterisk/stasis_message_router.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_after.h"
/* Define, to debug reference counts on queues, without debugging reference counts on queue members */
/* #define REF_DEBUG_ONLY_QUEUES */
@ -5293,7 +5294,7 @@ static void setup_peer_after_bridge_goto(struct ast_channel *chan, struct ast_ch
extension = ast_strdupa(ast_channel_exten(chan));
priority = ast_channel_priority(chan);
ast_channel_unlock(chan);
ast_after_bridge_set_go_on(peer, context, extension, priority,
ast_bridge_set_after_go_on(peer, context, extension, priority,
opt_args[OPT_ARG_CALLEE_GO_ON]);
}
}

@ -483,7 +483,7 @@ static int feature_hangup(struct ast_bridge *bridge, struct ast_bridge_channel *
* bridge_channel to force the channel out of the bridge and the
* core takes care of the rest.
*/
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
return 0;
}

@ -58,7 +58,7 @@ static int bridge_features_duration_callback(struct ast_bridge *bridge, struct a
ast_stream_and_wait(bridge_channel->chan, limits->duration_sound, AST_DIGIT_NONE);
}
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s", ast_channel_name(bridge_channel->chan));
return -1;
@ -114,7 +114,7 @@ static int bridge_features_connect_callback(struct ast_bridge *bridge, struct as
{
struct ast_bridge_features_limits *limits = hook_pvt;
if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
if (bridge_channel->state != BRIDGE_CHANNEL_STATE_WAIT) {
return -1;
}
@ -126,7 +126,7 @@ static int bridge_features_warning_callback(struct ast_bridge *bridge, struct as
{
struct ast_bridge_features_limits *limits = hook_pvt;
if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
/* If we aren't in the wait state, something more important than this warning is happening and we should skip it. */
limits_interval_playback(bridge, bridge_channel, limits, limits->warning_sound);
}

@ -576,7 +576,7 @@ static void softmix_bridge_write_voice(struct ast_bridge *bridge, struct ast_bri
ast_mutex_unlock(&sc->lock);
if (update_talking != -1) {
ast_bridge_notify_talking(bridge_channel, update_talking);
ast_bridge_channel_notify_talking(bridge_channel, update_talking);
}
}

@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stringfields.h"
#include "asterisk/global_datastores.h"
#include "asterisk/bridging_basic.h"
#include "asterisk/bridging_after.h"
/*** DOCUMENTATION
<function name="CHANNELS" language="en_US">
@ -531,7 +532,7 @@ static int func_channel_read(struct ast_channel *chan, const char *function,
locked_copy_string(chan, buf, ast_print_namedgroups(&tmp_str, ast_channel_named_pickupgroups(chan)), len);
} else if (!strcasecmp(data, "after_bridge_goto")) {
ast_after_bridge_goto_read(chan, buf, len);
ast_bridge_read_after_goto(chan, buf, len);
} else if (!strcasecmp(data, "amaflags")) {
ast_channel_lock(chan);
snprintf(buf, len, "%d", ast_channel_amaflags(chan));
@ -575,9 +576,9 @@ static int func_channel_write_real(struct ast_channel *chan, const char *functio
locked_string_field_set(chan, userfield, value);
else if (!strcasecmp(data, "after_bridge_goto")) {
if (ast_strlen_zero(value)) {
ast_after_bridge_goto_discard(chan);
ast_bridge_discard_after_goto(chan);
} else {
ast_after_bridge_set_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
ast_bridge_set_after_go_on(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan), value);
}
} else if (!strcasecmp(data, "amaflags")) {
ast_channel_lock(chan);

@ -447,7 +447,7 @@ void ast_bridge_notify_masquerade(struct ast_channel *chan);
* If channel specific features are enabled a pointer to the features structure
* can be specified in the features parameter.
*/
enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge,
enum bridge_channel_state ast_bridge_join(struct ast_bridge *bridge,
struct ast_channel *chan,
struct ast_channel *swap,
struct ast_bridge_features *features,
@ -884,202 +884,6 @@ enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
*/
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee,
struct ast_channel *to_transfer_target);
/*!
* \brief Set channel to goto specific location after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Context to goto after bridge.
* \param exten Exten to goto after bridge.
* \param priority Priority to goto after bridge.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* \return Nothing
*/
void ast_after_bridge_set_goto(struct ast_channel *chan, const char *context, const char *exten, int priority);
/*!
* \brief Set channel to run the h exten after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Context to goto after bridge.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* \return Nothing
*/
void ast_after_bridge_set_h(struct ast_channel *chan, const char *context);
/*!
* \brief Set channel to go on in the dialplan after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Current context of the caller channel.
* \param exten Current exten of the caller channel.
* \param priority Current priority of the caller channel
* \param parseable_goto User specified goto string from dialplan.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* If parseable_goto then use the given context/exten/priority
* as the relative position for the parseable_goto.
* Else goto the given context/exten/priority+1.
*
* \return Nothing
*/
void ast_after_bridge_set_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto);
/*!
* \brief Setup any after bridge goto location to begin execution.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
*
* \note chan is locked by this function.
*
* \details Pull off any after bridge goto location datastore and
* setup for dialplan execution there.
*
* \retval 0 on success. The goto location is set for a PBX to run it.
* \retval non-zero on error or no goto location.
*
* \note If the after bridge goto is set to run an h exten it is
* run here immediately.
*/
int ast_after_bridge_goto_setup(struct ast_channel *chan);
/*!
* \brief Run a PBX on any after bridge goto location.
* \since 12.0.0
*
* \param chan Channel to execute after bridge goto location.
*
* \note chan is locked by this function.
*
* \details Pull off any after bridge goto location datastore
* and run a PBX at that location.
*
* \note On return, the chan pointer is no longer valid because
* the channel has hung up.
*
* \return Nothing
*/
void ast_after_bridge_goto_run(struct ast_channel *chan);
/*!
* \brief Discard channel after bridge goto location.
* \since 12.0.0
*
* \param chan Channel to discard after bridge goto location.
*
* \note chan is locked by this function.
*
* \return Nothing
*/
void ast_after_bridge_goto_discard(struct ast_channel *chan);
/*!
* \brief Read after bridge goto if it exists
* \since 12.0.0
*
* \param chan Channel to read the after bridge goto parseable goto string from
* \param buffer Buffer to write the after bridge goto data to
* \param buf_size size of the buffer being written to
*/
void ast_after_bridge_goto_read(struct ast_channel *chan, char *buffer, size_t buf_size);
/*! Reason the the after bridge callback will not be called. */
enum ast_after_bridge_cb_reason {
/*! The datastore is being destroyed. Likely due to hangup. (Enum value must be zero.) */
AST_AFTER_BRIDGE_CB_REASON_DESTROY,
/*! Something else replaced the callback with another. */
AST_AFTER_BRIDGE_CB_REASON_REPLACED,
/*! The callback was removed because of a masquerade. (fixup) */
AST_AFTER_BRIDGE_CB_REASON_MASQUERADE,
/*! The channel was departed from the bridge. */
AST_AFTER_BRIDGE_CB_REASON_DEPART,
/*! Was explicitly removed by external code. */
AST_AFTER_BRIDGE_CB_REASON_REMOVED,
};
/*!
* \brief After bridge callback failed.
* \since 12.0.0
*
* \param reason Reason callback is failing.
* \param data Extra data what setup the callback wanted to pass.
*
* \note Called when the channel leaves the bridging system or
* is destroyed.
*
* \return Nothing
*/
typedef void (*ast_after_bridge_cb_failed)(enum ast_after_bridge_cb_reason reason, void *data);
/*!
* \brief After bridge callback function.
* \since 12.0.0
*
* \param chan Channel just leaving bridging system.
* \param data Extra data what setup the callback wanted to pass.
*
* \return Nothing
*/
typedef void (*ast_after_bridge_cb)(struct ast_channel *chan, void *data);
/*!
* \brief Discard channel after bridge callback.
* \since 12.0.0
*
* \param chan Channel to discard after bridge callback.
* \param reason Why are we doing this.
*
* \note chan is locked by this function.
*
* \return Nothing
*/
void ast_after_bridge_callback_discard(struct ast_channel *chan, enum ast_after_bridge_cb_reason reason);
/*!
* \brief Setup an after bridge callback for when the channel leaves the bridging system.
* \since 12.0.0
*
* \param chan Channel to setup an after bridge callback on.
* \param callback Function to call when the channel leaves the bridging system.
* \param failed Function to call when it will not be calling the callback.
* \param data Extra data to pass with the callback.
*
* \note chan is locked by this function.
*
* \note failed is called when the channel leaves the bridging
* system or is destroyed.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_after_bridge_callback_set(struct ast_channel *chan, ast_after_bridge_cb callback, ast_after_bridge_cb_failed failed, void *data);
/*!
* \brief Get a string representation of an after bridge callback reason
* \since 12.0.0
*
* \param reason The reason to interpret to a string
* \retval NULL Unrecognized reason
* \retval non-NULL String representation of reason
*/
const char *ast_after_bridge_cb_reason_string(enum ast_after_bridge_cb_reason reason);
/*!
* \brief Get a container of all channels in the bridge

@ -0,0 +1,244 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2013 Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief After Bridge Execution API
*
* \author Richard Mudgett <rmudgett@digium.com>
*
* See Also:
* \arg \ref AstCREDITS
*/
#ifndef _ASTERISK_BRIDGING_AFTER_H
#define _ASTERISK_BRIDGING_AFTER_H
#if defined(__cplusplus) || defined(c_plusplus)
extern "C" {
#endif
/*! Reason the the after bridge callback will not be called. */
enum ast_bridge_after_cb_reason {
/*! The datastore is being destroyed. Likely due to hangup. (Enum value must be zero.) */
AST_BRIDGE_AFTER_CB_REASON_DESTROY,
/*! Something else replaced the callback with another. */
AST_BRIDGE_AFTER_CB_REASON_REPLACED,
/*! The callback was removed because of a masquerade. (fixup) */
AST_BRIDGE_AFTER_CB_REASON_MASQUERADE,
/*! The channel was departed from the bridge. */
AST_BRIDGE_AFTER_CB_REASON_DEPART,
/*! Was explicitly removed by external code. */
AST_BRIDGE_AFTER_CB_REASON_REMOVED,
};
/*!
* \brief Set channel to goto specific location after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Context to goto after bridge.
* \param exten Exten to goto after bridge.
* \param priority Priority to goto after bridge.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* \return Nothing
*/
void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority);
/*!
* \brief Set channel to run the h exten after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Context to goto after bridge.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* \return Nothing
*/
void ast_bridge_set_after_h(struct ast_channel *chan, const char *context);
/*!
* \brief Set channel to go on in the dialplan after the bridge.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param context Current context of the caller channel.
* \param exten Current exten of the caller channel.
* \param priority Current priority of the caller channel
* \param parseable_goto User specified goto string from dialplan.
*
* \note chan is locked by this function.
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* If parseable_goto then use the given context/exten/priority
* as the relative position for the parseable_goto.
* Else goto the given context/exten/priority+1.
*
* \return Nothing
*/
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto);
/*!
* \brief Setup any after bridge goto location to begin execution.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
*
* \note chan is locked by this function.
*
* \details Pull off any after bridge goto location datastore and
* setup for dialplan execution there.
*
* \retval 0 on success. The goto location is set for a PBX to run it.
* \retval non-zero on error or no goto location.
*
* \note If the after bridge goto is set to run an h exten it is
* run here immediately.
*/
int ast_bridge_setup_after_goto(struct ast_channel *chan);
/*!
* \brief Run any after bridge callback.
* \since 12.0.0
*
* \param chan Channel to run after bridge callback.
*
* \return Nothing
*/
void ast_bridge_run_after_callback(struct ast_channel *chan);
/*!
* \brief Run discarding any after bridge callbacks.
* \since 12.0.0
*
* \param chan Channel to run after bridge callback.
*
* \return Nothing
*/
void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason);
/*!
* \brief Run a PBX on any after bridge goto location.
* \since 12.0.0
*
* \param chan Channel to execute after bridge goto location.
*
* \note chan is locked by this function.
*
* \details Pull off any after bridge goto location datastore
* and run a PBX at that location.
*
* \note On return, the chan pointer is no longer valid because
* the channel has hung up.
*
* \return Nothing
*/
void ast_bridge_run_after_goto(struct ast_channel *chan);
/*!
* \brief Discard channel after bridge goto location.
* \since 12.0.0
*
* \param chan Channel to discard after bridge goto location.
*
* \note chan is locked by this function.
*
* \return Nothing
*/
void ast_bridge_discard_after_goto(struct ast_channel *chan);
/*!
* \brief Read after bridge goto if it exists
* \since 12.0.0
*
* \param chan Channel to read the after bridge goto parseable goto string from
* \param buffer Buffer to write the after bridge goto data to
* \param buf_size size of the buffer being written to
*/
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size);
/*!
* \brief After bridge callback failed.
* \since 12.0.0
*
* \param reason Reason callback is failing.
* \param data Extra data what setup the callback wanted to pass.
*
* \note Called when the channel leaves the bridging system or
* is destroyed.
*
* \return Nothing
*/
typedef void (*ast_bridge_after_cb_failed)(enum ast_bridge_after_cb_reason reason, void *data);
/*!
* \brief After bridge callback function.
* \since 12.0.0
*
* \param chan Channel just leaving bridging system.
* \param data Extra data what setup the callback wanted to pass.
*
* \return Nothing
*/
typedef void (*ast_bridge_after_cb)(struct ast_channel *chan, void *data);
/*!
* \brief Setup an after bridge callback for when the channel leaves the bridging system.
* \since 12.0.0
*
* \param chan Channel to setup an after bridge callback on.
* \param callback Function to call when the channel leaves the bridging system.
* \param failed Function to call when it will not be calling the callback.
* \param data Extra data to pass with the callback.
*
* \note chan is locked by this function.
*
* \note failed is called when the channel leaves the bridging
* system or is destroyed.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data);
/*!
* \brief Get a string representation of an after bridge callback reason
* \since 12.0.0
*
* \param reason The reason to interpret to a string
* \retval NULL Unrecognized reason
* \retval non-NULL String representation of reason
*/
const char *ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
#endif /* _ASTERISK_BRIDGING_H */

@ -20,29 +20,29 @@
/*!
* \file
* \brief Bridging Channel API
* \page AstBridgeChannel Bridging Channel API
*
* An API that act on a channel in a bridge. Note that while the
* \ref ast_bridge_channel is owned by a channel, it should only be used
* by members of the bridging system. The only places where this API should
* be used is:
* - The \ref AstBridging API itself
* - Bridge mixing technologies
* - Bridge sub-classes
* \arg \ref AstBridging API itself
* \arg Bridge mixing technologies
* \arg Bridge sub-classes
*
* In general, anywhere else it is unsafe to use this API. Care should be
* taken when using this API to ensure that the locking order remains
* correct. The locking order must be:
* - The \ref ast_bridge
* - The \ref ast_bridge_channel
* - The \ref ast_channel
* \arg The \ref \c ast_bridge
* \arg The \ref \c ast_bridge_channel
* \arg The \ref \c ast_channel
*
* \author Joshua Colp <jcolp@digium.com>
* \author Richard Mudgett <rmudgett@digium.com>
* \author Matt Jordan <mjordan@digium.com>
*
* See Also:
* \ref bridging.h
* \arg \ref AstBridging
* \arg \ref AstCREDITS
*/
@ -56,22 +56,22 @@ extern "C" {
#include "asterisk/bridging_technology.h"
/*! \brief State information about a bridged channel */
enum ast_bridge_channel_state {
enum bridge_channel_state {
/*! Waiting for a signal (Channel in the bridge) */
AST_BRIDGE_CHANNEL_STATE_WAIT = 0,
BRIDGE_CHANNEL_STATE_WAIT = 0,
/*! Bridged channel was forced out and should be hung up (Bridge may dissolve.) */
AST_BRIDGE_CHANNEL_STATE_END,
BRIDGE_CHANNEL_STATE_END,
/*! Bridged channel was forced out. Don't dissolve the bridge regardless */
AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
};
enum ast_bridge_channel_thread_state {
enum bridge_channel_thread_state {
/*! Bridge channel thread is idle/waiting. */
AST_BRIDGE_CHANNEL_THREAD_IDLE,
BRIDGE_CHANNEL_THREAD_IDLE,
/*! Bridge channel thread is writing a normal/simple frame. */
AST_BRIDGE_CHANNEL_THREAD_SIMPLE,
BRIDGE_CHANNEL_THREAD_SIMPLE,
/*! Bridge channel thread is processing a frame. */
AST_BRIDGE_CHANNEL_THREAD_FRAME,
BRIDGE_CHANNEL_THREAD_FRAME,
};
struct ast_bridge;
@ -85,7 +85,7 @@ struct ast_bridge_channel {
/*! Condition, used if we want to wake up a thread waiting on the bridged channel */
ast_cond_t cond;
/*! Current bridged channel state */
enum ast_bridge_channel_state state;
enum bridge_channel_state state;
/*! Asterisk channel participating in the bridge */
struct ast_channel *chan;
/*! Asterisk channel we are swapping with (if swapping) */
@ -154,7 +154,7 @@ struct ast_bridge_channel {
*
* \note Needs to be atomically settable.
*/
enum ast_bridge_channel_thread_state activity;
enum bridge_channel_thread_state activity;
};
/*!
@ -216,6 +216,24 @@ static inline void _ast_bridge_channel_unlock(struct ast_bridge_channel *bridge_
*/
void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Lets the bridging indicate when a bridge channel has stopped or started talking.
*
* \note All DSP functionality on the bridge has been pushed down to the lowest possible
* layer, which in this case is the specific bridging technology being used. Since it
* is necessary for the knowledge of which channels are talking to make its way up to the
* application, this function has been created to allow the bridging technology to communicate
* that information with the bridging core.
*
* \param bridge_channel The bridge channel that has either started or stopped talking.
* \param started_talking set to 1 when this indicates the channel has started talking set to 0
* when this indicates the channel has stopped talking.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_channel_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already).
*
@ -225,14 +243,14 @@ void ast_bridge_channel_lock_bridge(struct ast_bridge_channel *bridge_channel);
* Example usage:
*
* \code
* ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
* ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
* \endcode
*
* This places the channel pointed to by bridge_channel into the
* state AST_BRIDGE_CHANNEL_STATE_END if it was
* AST_BRIDGE_CHANNEL_STATE_WAIT before.
* state BRIDGE_CHANNEL_STATE_END if it was
* BRIDGE_CHANNEL_STATE_WAIT before.
*/
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state);
/*!
* \brief Set bridge channel state to leave bridge (if not leaving already).
@ -243,14 +261,82 @@ void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel,
* Example usage:
*
* \code
* ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
* ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END);
* \endcode
*
* This places the channel pointed to by bridge_channel into the
* state AST_BRIDGE_CHANNEL_STATE_END if it was
* AST_BRIDGE_CHANNEL_STATE_WAIT before.
* state BRIDGE_CHANNEL_STATE_END if it was
* BRIDGE_CHANNEL_STATE_WAIT before.
*/
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum bridge_channel_state new_state);
/*!
* \brief Get the peer bridge channel of a two party bridge.
* \since 12.0.0
*
* \param bridge_channel What to get the peer of.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \note This is an internal bridge function.
*
* \retval peer on success.
* \retval NULL no peer channel.
*/
struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_internal_join
* \since 12.0.0
*
* \param bridge_channel Channel to restore
*/
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Adjust the bridge_channel's bridge merge inhibit request count.
* \since 12.0.0
*
* \param bridge_channel What to operate on.
* \param request Inhibit request increment.
* (Positive to add requests. Negative to remove requests.)
*
* \note This API call is meant for internal bridging operations.
*
* \retval bridge adjusted merge inhibit with reference count.
*/
struct ast_bridge *ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request);
/*!
* \internal
* \brief Update the linkedids for all channels in a bridge
* \since 12.0.0
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_internal_push operation, typically by a sub-class of a bridge
*/
void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \internal
* \brief Update the accountcodes for a channel entering a bridge
* \since 12.0.0
*
* This function updates the accountcode and peeraccount on channels in two-party
* bridges. In multi-party bridges, peeraccount is not set - it doesn't make much sense -
* however accountcode propagation will still occur if the channel joining has an
* accountcode.
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_internal_push operation, typically by a sub-class of a bridge
*/
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \brief Write a frame to the specified bridge_channel.
@ -497,79 +583,6 @@ int ast_bridge_channel_queue_callback(struct ast_bridge_channel *bridge_channel,
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid,
const char *parker_uuid, const char *app_data);
/*!
* \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_join
* \since 12.0.0
*
* \param bridge_channel Channel to restore
*/
void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel);
/*!
* \brief Get the peer bridge channel of a two party bridge.
* \since 12.0.0
*
* \param bridge_channel What to get the peer of.
*
* \note On entry, bridge_channel->bridge is already locked.
*
* \note This is an internal bridge function.
*
* \retval peer on success.
* \retval NULL no peer channel.
*/
struct ast_bridge_channel *ast_bridge_channel_peer(struct ast_bridge_channel *bridge_channel);
struct blind_transfer_data {
char exten[AST_MAX_EXTENSION];
char context[AST_MAX_CONTEXT];
};
/*!
* \brief Adjust the bridge_channel's bridge merge inhibit request count.
* \since 12.0.0
*
* \param bridge_channel What to operate on.
* \param request Inhibit request increment.
* (Positive to add requests. Negative to remove requests.)
*
* \note This API call is meant for internal bridging operations.
*
* \retval bridge adjusted merge inhibit with reference count.
*/
struct ast_bridge *ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request);
/*!
* \internal
* \brief Update the linkedids for all channels in a bridge
* \since 12.0.0
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_push operation, typically by a sub-class of a bridge
*/
void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
/*!
* \internal
* \brief Update the accountcodes for a channel entering a bridge
* \since 12.0.0
*
* This function updates the accountcode and peeraccount on channels in two-party
* bridges. In multi-party bridges, peeraccount is not set - it doesn't make much sense -
* however accountcode propagation will still occur if the channel joining has an
* accountcode.
*
* \param bridge_channel The channel joining the bridge
* \param swap The channel being swapped out of the bridge. May be NULL.
*
* \note The bridge must be locked prior to calling this function. This should be called
* during a \ref bridge_channel_push operation, typically by a sub-class of a bridge
*/
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif

@ -16,6 +16,9 @@
* at the top of the source tree.
*/
#ifndef _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
#define _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
/*!
* \file
* \brief Private Bridging Channel API
@ -23,16 +26,14 @@
* \author Matt Jordan <mjordan@digium.com>
*
* A private API to manipulate channels in a bridge. These can be called on a channel in
* a bridge by the bridging API, but should not be called by external consumers of the
* Bridging API.
* a bridge by \ref bridging.c. These functions should not be called elsewhere, including
* by other members of the Bridging API.
*
* See Also:
* \arg \ref AstCREDITS
* \arg \ref Ast
*/
#ifndef _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
#define _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
/*!
* \internal
* \brief Actions that can be taken on a channel in a bridge
@ -71,6 +72,18 @@ enum bridge_channel_action_type {
BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING,
};
/*!
* \internal
* \brief Allocate a new ao2 ref counted bridge_channel
* \since 12.0.0
*
* \param bridge The bridge to make the bridge_channel for
*
* \retval NULL on error
* \retval ao2 ref counted object on success
*/
struct ast_bridge_channel *bridge_channel_internal_alloc(struct ast_bridge *bridge);
/*!
* \internal
* \brief Push the bridge channel into its specified bridge.
@ -83,7 +96,7 @@ enum bridge_channel_action_type {
* \retval 0 on success.
* \retval -1 on failure. The channel did not get pushed.
*/
int bridge_channel_push(struct ast_bridge_channel *bridge_channel);
int bridge_channel_internal_push(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
@ -96,7 +109,7 @@ int bridge_channel_push(struct ast_bridge_channel *bridge_channel);
*
* \return Nothing
*/
void bridge_channel_pull(struct ast_bridge_channel *bridge_channel);
void bridge_channel_internal_pull(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
@ -108,7 +121,7 @@ void bridge_channel_pull(struct ast_bridge_channel *bridge_channel);
* it is in the bridge. It will return when the channel has been instructed to
* leave the bridge.
*/
void bridge_channel_join(struct ast_bridge_channel *bridge_channel);
void bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
@ -118,7 +131,7 @@ void bridge_channel_join(struct ast_bridge_channel *bridge_channel);
* \param bridge_channel The channel in the bridge
* \note This function assumes that \ref bridge_channel is already locked
*/
void bridge_channel_suspend_nolock(struct ast_bridge_channel *bridge_channel);
void bridge_channel_internal_suspend_nolock(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
@ -127,7 +140,7 @@ void bridge_channel_suspend_nolock(struct ast_bridge_channel *bridge_channel);
* \param bridge_channel The channel in the bridge
* \note This function assumes that \ref bridge_channel is already locked
*/
void bridge_channel_unsuspend_nolock(struct ast_bridge_channel *bridge_channel);
void bridge_channel_internal_unsuspend_nolock(struct ast_bridge_channel *bridge_channel);
/*!
* \internal
@ -146,11 +159,35 @@ void bridge_channel_unsuspend_nolock(struct ast_bridge_channel *bridge_channel);
* \retval 0 on success.
* \retval -1 on error.
*/
int bridge_channel_queue_blind_transfer(struct ast_channel *transferee,
int bridge_channel_internal_queue_blind_transfer(struct ast_channel *transferee,
const char *exten, const char *context,
transfer_channel_cb new_channel_cb, void *user_data);
int bridge_channel_queue_attended_transfer(struct ast_channel *transferee,
/*!
* \internal
* \brief Queue an attended transfer action on a transferee bridge channel
*
* This is only relevant for when an attended transfer is performed on a two-party
* bridge. The transferee's bridge channel will have an attended transfer bridge
* action queued onto it.
*
* \param transferee The channel to have the action queued on
* \param unbridged_chan The unbridged channel who is the target of the attended
* transfer
*
* \retval 0 on success.
* \retval -1 on error.
*/
int bridge_channel_internal_queue_attended_transfer(struct ast_channel *transferee,
struct ast_channel *unbridged_chan);
/*!
* \internal
* \brief Return whether or not the bridge_channel would allow optimization
*
* \retval 0 if optimization is not allowed
* \retval non-zero if optimization is allowed
*/
int bridge_channel_internal_allows_optimization(struct ast_bridge_channel *bridge_channel);
#endif /* _ASTERISK_PRIVATE_BRIDGING_H */

@ -16,7 +16,8 @@
* at the top of the source tree.
*/
/*! \file
/*!
* \file
* \brief Channel Bridging API
* \author Joshua Colp <jcolp@digium.com>
*/
@ -75,7 +76,7 @@ enum ast_bridge_builtin_feature {
* how it was imparted.
*
* \note Joined channels exit the bridge with
* AST_BRIDGE_CHANNEL_STATE_END_WITH_DISSOLVE.
* BRIDGE_CHANNEL_STATE_END_WITH_DISSOLVE.
*/
AST_BRIDGE_BUILTIN_HANGUP,
/*!

@ -180,8 +180,8 @@ void bridge_merge_inhibit_nolock(struct ast_bridge *bridge, int request);
* \param colp_update Whether to perform COLP updates.
*
* \details
* After a series of bridge_channel_push and
* bridge_channel_pull calls, you need to call this function
* After a series of bridge_channel_internal_push and
* bridge_channel_internal_pull calls, you need to call this function
* to cause the bridge to complete restructuring for the change
* in the channel makeup of the bridge.
*

@ -202,24 +202,6 @@ int __ast_bridge_technology_register(struct ast_bridge_technology *technology, s
*/
int ast_bridge_technology_unregister(struct ast_bridge_technology *technology);
/*!
* \brief Lets the bridging indicate when a bridge channel has stopped or started talking.
*
* \note All DSP functionality on the bridge has been pushed down to the lowest possible
* layer, which in this case is the specific bridging technology being used. Since it
* is necessary for the knowledge of which channels are talking to make its way up to the
* application, this function has been created to allow the bridging technology to communicate
* that information with the bridging core.
*
* \param bridge_channel The bridge channel that has either started or stopped talking.
* \param started_talking set to 1 when this indicates the channel has started talking set to 0
* when this indicates the channel has stopped talking.
*
* \retval 0 on success.
* \retval -1 on error.
*/
int ast_bridge_notify_talking(struct ast_bridge_channel *bridge_channel, int started_talking);
/*!
* \brief Suspend a bridge technology from consideration
*

File diff suppressed because it is too large Load Diff

@ -0,0 +1,640 @@
/*
* Asterisk -- An open source telephony toolkit.
*
* Copyright (C) 2007 - 2009, Digium, Inc.
*
* Richard Mudgett <rmudgett@digium.com>
*
* See http://www.asterisk.org for more information about
* the Asterisk project. Please do not directly contact
* any of the maintainers of this project for assistance;
* the project provides a web site, mailing lists and IRC
* channels for your use.
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*!
* \file
* \brief After Bridge Execution API
*
* \author Richard Mudgett <rmudgett@digium.com>
*
* See Also:
* \arg \ref AstCREDITS
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/bridging_after.h"
struct after_bridge_cb_node {
/*! Next list node. */
AST_LIST_ENTRY(after_bridge_cb_node) list;
/*! Desired callback function. */
ast_bridge_after_cb callback;
/*! After bridge callback will not be called and destroy any resources data may contain. */
ast_bridge_after_cb_failed failed;
/*! Extra data to pass to the callback. */
void *data;
/*! Reason the after bridge callback failed. */
enum ast_bridge_after_cb_reason reason;
};
struct after_bridge_cb_ds {
/*! After bridge callbacks container. */
AST_LIST_HEAD(, after_bridge_cb_node) callbacks;
};
/*!
* \internal
* \brief Indicate after bridge callback failed.
* \since 12.0.0
*
* \param node After bridge callback node.
*
* \return Nothing
*/
static void after_bridge_cb_failed(struct after_bridge_cb_node *node)
{
if (node->failed) {
node->failed(node->reason, node->data);
node->failed = NULL;
}
}
/*!
* \internal
* \brief Run discarding any after bridge callbacks.
* \since 12.0.0
*
* \param after_bridge After bridge callback container process.
* \param reason Why are we doing this.
*
* \return Nothing
*/
static void after_bridge_cb_run_discard(struct after_bridge_cb_ds *after_bridge, enum ast_bridge_after_cb_reason reason)
{
struct after_bridge_cb_node *node;
for (;;) {
AST_LIST_LOCK(&after_bridge->callbacks);
node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
AST_LIST_UNLOCK(&after_bridge->callbacks);
if (!node) {
break;
}
if (!node->reason) {
node->reason = reason;
}
after_bridge_cb_failed(node);
ast_free(node);
}
}
/*!
* \internal
* \brief Destroy the after bridge callback datastore.
* \since 12.0.0
*
* \param data After bridge callback data to destroy.
*
* \return Nothing
*/
static void after_bridge_cb_destroy(void *data)
{
struct after_bridge_cb_ds *after_bridge = data;
after_bridge_cb_run_discard(after_bridge, AST_BRIDGE_AFTER_CB_REASON_DESTROY);
AST_LIST_HEAD_DESTROY(&after_bridge->callbacks);
ast_free(after_bridge);
}
static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan);
/*!
* \internal
* \brief Fixup the after bridge callback datastore.
* \since 12.0.0
*
* \param data After bridge callback data to fixup.
* \param old_chan The datastore is moving from this channel.
* \param new_chan The datastore is moving to this channel.
*
* \return Nothing
*/
static void after_bridge_cb_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
struct after_bridge_cb_ds *after_bridge;
struct after_bridge_cb_node *node;
after_bridge = after_bridge_cb_find(new_chan);
if (!after_bridge) {
return;
}
AST_LIST_LOCK(&after_bridge->callbacks);
node = AST_LIST_LAST(&after_bridge->callbacks);
if (node && !node->reason) {
node->reason = AST_BRIDGE_AFTER_CB_REASON_MASQUERADE;
}
AST_LIST_UNLOCK(&after_bridge->callbacks);
}
static const struct ast_datastore_info after_bridge_cb_info = {
.type = "after-bridge-cb",
.destroy = after_bridge_cb_destroy,
.chan_fixup = after_bridge_cb_fixup,
};
/*!
* \internal
* \brief Find an after bridge callback datastore container.
* \since 12.0.0
*
* \param chan Channel to find the after bridge callback container on.
*
* \retval after_bridge datastore container on success.
* \retval NULL on error.
*/
static struct after_bridge_cb_ds *after_bridge_cb_find(struct ast_channel *chan)
{
struct ast_datastore *datastore;
SCOPED_CHANNELLOCK(lock, chan);
datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
if (!datastore) {
return NULL;
}
return datastore->data;
}
/*!
* \internal
* \brief Setup/create an after bridge callback datastore container.
* \since 12.0.0
*
* \param chan Channel to setup/create the after bridge callback container on.
*
* \retval after_bridge datastore container on success.
* \retval NULL on error.
*/
static struct after_bridge_cb_ds *after_bridge_cb_setup(struct ast_channel *chan)
{
struct ast_datastore *datastore;
struct after_bridge_cb_ds *after_bridge;
SCOPED_CHANNELLOCK(lock, chan);
datastore = ast_channel_datastore_find(chan, &after_bridge_cb_info, NULL);
if (datastore) {
return datastore->data;
}
/* Create a new datastore. */
datastore = ast_datastore_alloc(&after_bridge_cb_info, NULL);
if (!datastore) {
return NULL;
}
after_bridge = ast_calloc(1, sizeof(*after_bridge));
if (!after_bridge) {
ast_datastore_free(datastore);
return NULL;
}
AST_LIST_HEAD_INIT(&after_bridge->callbacks);
datastore->data = after_bridge;
ast_channel_datastore_add(chan, datastore);
return datastore->data;
}
void ast_bridge_run_after_callback(struct ast_channel *chan)
{
struct after_bridge_cb_ds *after_bridge;
struct after_bridge_cb_node *node;
after_bridge = after_bridge_cb_find(chan);
if (!after_bridge) {
return;
}
for (;;) {
AST_LIST_LOCK(&after_bridge->callbacks);
node = AST_LIST_REMOVE_HEAD(&after_bridge->callbacks, list);
AST_LIST_UNLOCK(&after_bridge->callbacks);
if (!node) {
break;
}
if (node->reason) {
after_bridge_cb_failed(node);
} else {
node->failed = NULL;
node->callback(chan, node->data);
}
ast_free(node);
}
}
void ast_bridge_discard_after_callback(struct ast_channel *chan, enum ast_bridge_after_cb_reason reason)
{
struct after_bridge_cb_ds *after_bridge;
after_bridge = after_bridge_cb_find(chan);
if (!after_bridge) {
return;
}
after_bridge_cb_run_discard(after_bridge, reason);
}
int ast_bridge_set_after_callback(struct ast_channel *chan, ast_bridge_after_cb callback, ast_bridge_after_cb_failed failed, void *data)
{
struct after_bridge_cb_ds *after_bridge;
struct after_bridge_cb_node *new_node;
struct after_bridge_cb_node *last_node;
/* Sanity checks. */
ast_assert(chan != NULL);
if (!chan || !callback) {
return -1;
}
after_bridge = after_bridge_cb_setup(chan);
if (!after_bridge) {
return -1;
}
/* Create a new callback node. */
new_node = ast_calloc(1, sizeof(*new_node));
if (!new_node) {
return -1;
}
new_node->callback = callback;
new_node->failed = failed;
new_node->data = data;
/* Put it in the container disabling any previously active one. */
AST_LIST_LOCK(&after_bridge->callbacks);
last_node = AST_LIST_LAST(&after_bridge->callbacks);
if (last_node && !last_node->reason) {
last_node->reason = AST_BRIDGE_AFTER_CB_REASON_REPLACED;
}
AST_LIST_INSERT_TAIL(&after_bridge->callbacks, new_node, list);
AST_LIST_UNLOCK(&after_bridge->callbacks);
return 0;
}
const char *reason_strings[] = {
[AST_BRIDGE_AFTER_CB_REASON_DESTROY] = "Channel destroyed (hungup)",
[AST_BRIDGE_AFTER_CB_REASON_REPLACED] = "Callback was replaced",
[AST_BRIDGE_AFTER_CB_REASON_MASQUERADE] = "Channel masqueraded",
[AST_BRIDGE_AFTER_CB_REASON_DEPART] = "Channel was departed from bridge",
[AST_BRIDGE_AFTER_CB_REASON_REMOVED] = "Callback was removed",
};
const char *ast_bridge_after_cb_reason_string(enum ast_bridge_after_cb_reason reason)
{
if (reason < AST_BRIDGE_AFTER_CB_REASON_DESTROY
|| AST_BRIDGE_AFTER_CB_REASON_REMOVED < reason
|| !reason_strings[reason]) {
return "Unknown";
}
return reason_strings[reason];
}
struct after_bridge_goto_ds {
/*! Goto string that can be parsed by ast_parseable_goto(). */
const char *parseable_goto;
/*! Specific goto context or default context for parseable_goto. */
const char *context;
/*! Specific goto exten or default exten for parseable_goto. */
const char *exten;
/*! Specific goto priority or default priority for parseable_goto. */
int priority;
/*! TRUE if the peer should run the h exten. */
unsigned int run_h_exten:1;
/*! Specific goto location */
unsigned int specific:1;
};
/*!
* \internal
* \brief Destroy the after bridge goto datastore.
* \since 12.0.0
*
* \param data After bridge goto data to destroy.
*
* \return Nothing
*/
static void after_bridge_goto_destroy(void *data)
{
struct after_bridge_goto_ds *after_bridge = data;
ast_free((char *) after_bridge->parseable_goto);
ast_free((char *) after_bridge->context);
ast_free((char *) after_bridge->exten);
}
/*!
* \internal
* \brief Fixup the after bridge goto datastore.
* \since 12.0.0
*
* \param data After bridge goto data to fixup.
* \param old_chan The datastore is moving from this channel.
* \param new_chan The datastore is moving to this channel.
*
* \return Nothing
*/
static void after_bridge_goto_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
{
/* There can be only one. Discard any already on the new channel. */
ast_bridge_discard_after_goto(new_chan);
}
static const struct ast_datastore_info after_bridge_goto_info = {
.type = "after-bridge-goto",
.destroy = after_bridge_goto_destroy,
.chan_fixup = after_bridge_goto_fixup,
};
/*!
* \internal
* \brief Remove channel goto location after the bridge and return it.
* \since 12.0.0
*
* \param chan Channel to remove after bridge goto location.
*
* \retval datastore on success.
* \retval NULL on error or not found.
*/
static struct ast_datastore *after_bridge_goto_remove(struct ast_channel *chan)
{
struct ast_datastore *datastore;
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
if (datastore && ast_channel_datastore_remove(chan, datastore)) {
datastore = NULL;
}
ast_channel_unlock(chan);
return datastore;
}
void ast_bridge_discard_after_goto(struct ast_channel *chan)
{
struct ast_datastore *datastore;
datastore = after_bridge_goto_remove(chan);
if (datastore) {
ast_datastore_free(datastore);
}
}
void ast_bridge_read_after_goto(struct ast_channel *chan, char *buffer, size_t buf_size)
{
struct ast_datastore *datastore;
struct after_bridge_goto_ds *after_bridge;
char *current_pos = buffer;
size_t remaining_size = buf_size;
SCOPED_CHANNELLOCK(lock, chan);
datastore = ast_channel_datastore_find(chan, &after_bridge_goto_info, NULL);
if (!datastore) {
buffer[0] = '\0';
return;
}
after_bridge = datastore->data;
if (after_bridge->parseable_goto) {
snprintf(buffer, buf_size, "%s", after_bridge->parseable_goto);
return;
}
if (!ast_strlen_zero(after_bridge->context)) {
snprintf(current_pos, remaining_size, "%s,", after_bridge->context);
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
}
if (after_bridge->run_h_exten) {
snprintf(current_pos, remaining_size, "h,");
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
} else if (!ast_strlen_zero(after_bridge->exten)) {
snprintf(current_pos, remaining_size, "%s,", after_bridge->exten);
remaining_size = remaining_size - strlen(current_pos);
current_pos += strlen(current_pos);
}
snprintf(current_pos, remaining_size, "%d", after_bridge->priority);
}
int ast_bridge_setup_after_goto(struct ast_channel *chan)
{
struct ast_datastore *datastore;
struct after_bridge_goto_ds *after_bridge;
int goto_failed = -1;
/* Determine if we are going to setup a dialplan location and where. */
if (ast_channel_softhangup_internal_flag(chan) & AST_SOFTHANGUP_ASYNCGOTO) {
/* An async goto has already setup a location. */
ast_channel_clear_softhangup(chan, AST_SOFTHANGUP_ASYNCGOTO);
if (!ast_check_hangup(chan)) {
goto_failed = 0;
}
return goto_failed;
}
/* Get after bridge goto datastore. */
datastore = after_bridge_goto_remove(chan);
if (!datastore) {
return goto_failed;
}
after_bridge = datastore->data;
if (after_bridge->run_h_exten) {
if (ast_exists_extension(chan, after_bridge->context, "h", 1,
S_COR(ast_channel_caller(chan)->id.number.valid,
ast_channel_caller(chan)->id.number.str, NULL))) {
ast_debug(1, "Running after bridge goto h exten %s,h,1\n",
ast_channel_context(chan));
ast_pbx_h_exten_run(chan, after_bridge->context);
}
} else if (!ast_check_hangup(chan)) {
if (after_bridge->specific) {
goto_failed = ast_explicit_goto(chan, after_bridge->context,
after_bridge->exten, after_bridge->priority);
} else if (!ast_strlen_zero(after_bridge->parseable_goto)) {
char *context;
char *exten;
int priority;
/* Option F(x) for Bridge(), Dial(), and Queue() */
/* Save current dialplan location in case of failure. */
context = ast_strdupa(ast_channel_context(chan));
exten = ast_strdupa(ast_channel_exten(chan));
priority = ast_channel_priority(chan);
/* Set current dialplan position to default dialplan position */
ast_explicit_goto(chan, after_bridge->context, after_bridge->exten,
after_bridge->priority);
/* Then perform the goto */
goto_failed = ast_parseable_goto(chan, after_bridge->parseable_goto);
if (goto_failed) {
/* Restore original dialplan location. */
ast_channel_context_set(chan, context);
ast_channel_exten_set(chan, exten);
ast_channel_priority_set(chan, priority);
}
} else {
/* Option F() for Bridge(), Dial(), and Queue() */
goto_failed = ast_goto_if_exists(chan, after_bridge->context,
after_bridge->exten, after_bridge->priority + 1);
}
if (!goto_failed) {
if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
}
ast_debug(1, "Setup after bridge goto location to %s,%s,%d.\n",
ast_channel_context(chan),
ast_channel_exten(chan),
ast_channel_priority(chan));
}
}
/* Discard after bridge goto datastore. */
ast_datastore_free(datastore);
return goto_failed;
}
void ast_bridge_run_after_goto(struct ast_channel *chan)
{
int goto_failed;
goto_failed = ast_bridge_setup_after_goto(chan);
if (goto_failed || ast_pbx_run(chan)) {
ast_hangup(chan);
}
}
/*!
* \internal
* \brief Set after bridge goto location of channel.
* \since 12.0.0
*
* \param chan Channel to setup after bridge goto location.
* \param run_h_exten TRUE if the h exten should be run.
* \param specific TRUE if the context/exten/priority is exactly specified.
* \param context Context to goto after bridge.
* \param exten Exten to goto after bridge. (Could be NULL if run_h_exten)
* \param priority Priority to goto after bridge.
* \param parseable_goto User specified goto string. (Could be NULL)
*
* \details Add a channel datastore to setup the goto location
* when the channel leaves the bridge and run a PBX from there.
*
* If run_h_exten then execute the h exten found in the given context.
* Else if specific then goto the given context/exten/priority.
* Else if parseable_goto then use the given context/exten/priority
* as the relative position for the parseable_goto.
* Else goto the given context/exten/priority+1.
*
* \return Nothing
*/
static void __after_bridge_set_goto(struct ast_channel *chan, int run_h_exten, int specific, const char *context, const char *exten, int priority, const char *parseable_goto)
{
struct ast_datastore *datastore;
struct after_bridge_goto_ds *after_bridge;
/* Sanity checks. */
ast_assert(chan != NULL);
if (!chan) {
return;
}
if (run_h_exten) {
ast_assert(run_h_exten && context);
if (!context) {
return;
}
} else {
ast_assert(context && exten && 0 < priority);
if (!context || !exten || priority < 1) {
return;
}
}
/* Create a new datastore. */
datastore = ast_datastore_alloc(&after_bridge_goto_info, NULL);
if (!datastore) {
return;
}
after_bridge = ast_calloc(1, sizeof(*after_bridge));
if (!after_bridge) {
ast_datastore_free(datastore);
return;
}
/* Initialize it. */
after_bridge->parseable_goto = ast_strdup(parseable_goto);
after_bridge->context = ast_strdup(context);
after_bridge->exten = ast_strdup(exten);
after_bridge->priority = priority;
after_bridge->run_h_exten = run_h_exten ? 1 : 0;
after_bridge->specific = specific ? 1 : 0;
datastore->data = after_bridge;
if ((parseable_goto && !after_bridge->parseable_goto)
|| (context && !after_bridge->context)
|| (exten && !after_bridge->exten)) {
ast_datastore_free(datastore);
return;
}
/* Put it on the channel replacing any existing one. */
ast_channel_lock(chan);
ast_bridge_discard_after_goto(chan);
ast_channel_datastore_add(chan, datastore);
ast_channel_unlock(chan);
}
void ast_bridge_set_after_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
{
__after_bridge_set_goto(chan, 0, 1, context, exten, priority, NULL);
}
void ast_bridge_set_after_h(struct ast_channel *chan, const char *context)
{
__after_bridge_set_goto(chan, 1, 0, context, NULL, 1, NULL);
}
void ast_bridge_set_after_go_on(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *parseable_goto)
{
char *p_goto;
if (!ast_strlen_zero(parseable_goto)) {
p_goto = ast_strdupa(parseable_goto);
ast_replace_subargument_delimiter(p_goto);
} else {
p_goto = NULL;
}
__after_bridge_set_goto(chan, 0, 0, context, exten, priority, p_goto);
}

@ -36,13 +36,13 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/linkedlists.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_basic.h"
#include "asterisk/bridging_after.h"
#include "asterisk/astobj2.h"
#include "asterisk/features_config.h"
#include "asterisk/pbx.h"
#include "asterisk/file.h"
#include "asterisk/app.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_channel_internal.h"
#include "asterisk/dial.h"
#include "asterisk/stasis_bridging.h"
@ -279,13 +279,13 @@ static int basic_hangup_hook(struct ast_bridge *bridge, struct ast_bridge_channe
ast_bridge_channel_lock_bridge(bridge_channel);
AST_LIST_TRAVERSE(&bridge->channels, iter, entry) {
if (iter != bridge_channel && iter->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
if (iter != bridge_channel && iter->state == BRIDGE_CHANNEL_STATE_WAIT) {
++bridge_count;
}
}
if (2 <= bridge_count) {
/* Just allow this channel to leave the multi-party bridge. */
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
}
ast_bridge_unlock(bridge_channel->bridge);
return 0;
@ -2300,7 +2300,7 @@ static int bridge_personality_atxfer_push(struct ast_bridge *self, struct ast_br
static void transfer_pull(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel, struct attended_transfer_properties *props)
{
if (self->num_channels > 1 || bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
if (self->num_channels > 1 || bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) {
return;
}
@ -2794,13 +2794,13 @@ static int feature_blind_transfer(struct ast_bridge *bridge, struct ast_bridge_c
if (!ast_strlen_zero(goto_on_blindxfr)) {
ast_debug(1, "After transfer, transferer %s goes to %s\n",
ast_channel_name(bridge_channel->chan), goto_on_blindxfr);
ast_after_bridge_set_go_on(bridge_channel->chan, NULL, NULL, 0, goto_on_blindxfr);
ast_bridge_set_after_go_on(bridge_channel->chan, NULL, NULL, 0, goto_on_blindxfr);
}
if (ast_bridge_transfer_blind(0, bridge_channel->chan, exten, context, blind_transfer_cb,
bridge_channel->chan) != AST_BRIDGE_TRANSFER_SUCCESS &&
!ast_strlen_zero(goto_on_blindxfr)) {
ast_after_bridge_goto_discard(bridge_channel->chan);
ast_bridge_discard_after_goto(bridge_channel->chan);
}
return 0;

File diff suppressed because it is too large Load Diff

@ -73,6 +73,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_basic.h"
#include "asterisk/bridging_after.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_channels.h"
#include "asterisk/features_config.h"
@ -839,15 +840,15 @@ static void *bridge_call_thread(void *data)
}
if (tobj->return_to_pbx) {
ast_after_bridge_set_goto(tobj->chan, ast_channel_context(tobj->chan),
ast_bridge_set_after_goto(tobj->chan, ast_channel_context(tobj->chan),
ast_channel_exten(tobj->chan), ast_channel_priority(tobj->chan));
ast_after_bridge_set_goto(tobj->peer, ast_channel_context(tobj->peer),
ast_bridge_set_after_goto(tobj->peer, ast_channel_context(tobj->peer),
ast_channel_exten(tobj->peer), ast_channel_priority(tobj->peer));
}
ast_bridge_call(tobj->chan, tobj->peer, &tobj->bconfig);
ast_after_bridge_goto_run(tobj->chan);
ast_bridge_run_after_goto(tobj->chan);
ast_free(tobj);
@ -3544,7 +3545,7 @@ static void bridge_check_monitor(struct ast_channel *chan, struct ast_channel *p
*/
static void bridge_failed_peer_goto(struct ast_channel *chan, struct ast_channel *peer)
{
if (ast_after_bridge_goto_setup(peer)
if (ast_bridge_setup_after_goto(peer)
|| ast_pbx_start(peer)) {
ast_autoservice_chan_hangup_peer(chan, peer);
}
@ -4399,7 +4400,7 @@ static int action_bridge(struct mansession *s, const struct message *m)
return 0;
}
ast_after_bridge_set_go_on(chana, chana_context, chana_exten, chana_priority, NULL);
ast_bridge_set_after_go_on(chana, chana_context, chana_exten, chana_priority, NULL);
if (ast_bridge_add_channel(bridge, chana, NULL, playtone & PLAYTONE_CHANNEL1, xfer_cfg_a ? xfer_cfg_a->xfersound : NULL)) {
snprintf(buf, sizeof(buf), "Unable to add Channel1 to bridge: %s", ast_channel_name(chana));
astman_send_error(s, m, buf);
@ -4407,7 +4408,7 @@ static int action_bridge(struct mansession *s, const struct message *m)
return 0;
}
ast_after_bridge_set_go_on(chanb, chanb_context, chanb_exten, chanb_priority, NULL);
ast_bridge_set_after_go_on(chanb, chanb_context, chanb_exten, chanb_priority, NULL);
if (ast_bridge_add_channel(bridge, chanb, NULL, playtone & PLAYTONE_CHANNEL2, xfer_cfg_b ? xfer_cfg_b->xfersound : NULL)) {
snprintf(buf, sizeof(buf), "Unable to add Channel2 to bridge: %s", ast_channel_name(chanb));
astman_send_error(s, m, buf);
@ -5046,7 +5047,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
extension = ast_strdupa(ast_channel_exten(chan));
priority = ast_channel_priority(chan);
ast_channel_unlock(chan);
ast_after_bridge_set_go_on(current_dest_chan, context, extension, priority,
ast_bridge_set_after_go_on(current_dest_chan, context, extension, priority,
opt_args[OPT_ARG_CALLEE_GO_ON]);
} else if (!ast_test_flag(&opts, OPT_CALLEE_KILL)) {
ast_channel_lock(current_dest_chan);
@ -5054,7 +5055,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data)
extension = ast_strdupa(ast_channel_exten(current_dest_chan));
priority = ast_channel_priority(current_dest_chan);
ast_channel_unlock(current_dest_chan);
ast_after_bridge_set_goto(current_dest_chan, context, extension, priority);
ast_bridge_set_after_goto(current_dest_chan, context, extension, priority);
}
if (ast_bridge_features_init(&chan_features)) {

@ -34,7 +34,6 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/bridging.h"
#include "asterisk/bridging_internal.h"
#include "asterisk/bridging_channel_internal.h"
#include "asterisk/bridging_channel.h"
#include "asterisk/bridging_features.h"
#include "asterisk/features.h"
@ -404,7 +403,7 @@ static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridg
user->resolution = PARK_TIMEOUT;
ao2_unlock(user);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
/* Set parking timeout channel variables */
snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
@ -492,14 +491,14 @@ void say_parking_space(struct ast_bridge_channel *bridge_channel, const char *pa
if (sscanf(payload, "%u %u", &hangup_after, &numeric_value) != 2) {
/* If say_parking_space is called with a non-numeric string, we have a problem. */
ast_assert(0);
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
return;
}
ast_say_digits(bridge_channel->chan, numeric_value, "", ast_channel_language(bridge_channel->chan));
if (hangup_after) {
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
ast_bridge_channel_leave_bridge(bridge_channel, BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
}
}

Loading…
Cancel
Save