mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-19 11:42:27 +00:00
Update bridge_channel refactorings; export bridge_ symbol
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395295 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -1055,7 +1055,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_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
return;
|
||||
}
|
||||
res = ast_bridge_move(caller_bridge, bridge_channel->bridge, bridge_channel->chan,
|
||||
@@ -1063,7 +1063,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_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
return;
|
||||
}
|
||||
ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_ANSWER, NULL, 0);
|
||||
@@ -1159,13 +1159,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_leave_bridge(bridge_channel, AST_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_leave_bridge(bridge_channel, AST_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);
|
||||
@@ -1270,7 +1270,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_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1704,7 +1704,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_leave_bridge_nolock(logged, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
ast_bridge_channel_unlock(logged);
|
||||
}
|
||||
|
||||
@@ -1714,7 +1714,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_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
caller_abort_agent(agent);
|
||||
}
|
||||
|
||||
|
@@ -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_leave_bridge(bridge_channel, AST_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_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
|
||||
ast_test_suite_event_notify("BRIDGE_TIMELIMIT", "Channel1: %s", ast_channel_name(bridge_channel->chan));
|
||||
return -1;
|
||||
|
@@ -22,7 +22,20 @@
|
||||
* \file
|
||||
* \brief Bridging Channel API
|
||||
*
|
||||
* An API that act on a channel in a bridge
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* \author Joshua Colp <jcolp@digium.com>
|
||||
* \author Richard Mudgett <rmudgett@digium.com>
|
||||
@@ -48,8 +61,8 @@ enum ast_bridge_channel_state {
|
||||
AST_BRIDGE_CHANNEL_STATE_WAIT = 0,
|
||||
/*! Bridged channel was forced out and should be hung up (Bridge may dissolve.) */
|
||||
AST_BRIDGE_CHANNEL_STATE_END,
|
||||
/*! Bridged channel was forced out and should be hung up */
|
||||
AST_BRIDGE_CHANNEL_STATE_HANGUP,
|
||||
/*! Bridged channel was forced out. Don't dissolve the bridge regardless */
|
||||
AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE,
|
||||
};
|
||||
|
||||
enum ast_bridge_channel_thread_state {
|
||||
@@ -61,43 +74,6 @@ enum ast_bridge_channel_thread_state {
|
||||
AST_BRIDGE_CHANNEL_THREAD_FRAME,
|
||||
};
|
||||
|
||||
/*! \brief Actions that can be taken on a channel in a bridge */
|
||||
enum ast_bridge_action_type {
|
||||
/*! Bridged channel is to detect a feature hook */
|
||||
AST_BRIDGE_ACTION_FEATURE,
|
||||
/*! Bridged channel is to act on an interval hook */
|
||||
AST_BRIDGE_ACTION_INTERVAL,
|
||||
/*! Bridged channel is to send a DTMF stream out */
|
||||
AST_BRIDGE_ACTION_DTMF_STREAM,
|
||||
/*! Bridged channel is to indicate talking start */
|
||||
AST_BRIDGE_ACTION_TALKING_START,
|
||||
/*! Bridged channel is to indicate talking stop */
|
||||
AST_BRIDGE_ACTION_TALKING_STOP,
|
||||
/*! Bridge channel is to play the indicated sound file. */
|
||||
AST_BRIDGE_ACTION_PLAY_FILE,
|
||||
/*! Bridge channel is to run the indicated application. */
|
||||
AST_BRIDGE_ACTION_RUN_APP,
|
||||
/*! Bridge channel is to run the custom callback routine. */
|
||||
AST_BRIDGE_ACTION_CALLBACK,
|
||||
/*! Bridge channel is to get parked. */
|
||||
AST_BRIDGE_ACTION_PARK,
|
||||
/*! Bridge channel is to execute a blind transfer. */
|
||||
AST_BRIDGE_ACTION_BLIND_TRANSFER,
|
||||
/*! Bridge channel is to execute an attended transfer */
|
||||
AST_BRIDGE_ACTION_ATTENDED_TRANSFER,
|
||||
|
||||
/*
|
||||
* Bridge actions put after this comment must never be put onto
|
||||
* the bridge_channel wr_queue because they have other resources
|
||||
* that must be freed.
|
||||
*/
|
||||
|
||||
/*! Bridge reconfiguration deferred technology destruction. */
|
||||
AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY = 1000,
|
||||
/*! Bridge deferred dissolving. */
|
||||
AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
|
||||
};
|
||||
|
||||
struct ast_bridge;
|
||||
struct ast_bridge_tech_optimizations;
|
||||
|
||||
@@ -241,20 +217,40 @@ 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 Ask the bridged channel to leave the bridge it is currently in
|
||||
* \brief Set bridge channel state to leave bridge (if not leaving already).
|
||||
*
|
||||
* \param bridge_channel Channel to leave the bridge
|
||||
* \param bridge_channel Channel to change the state on
|
||||
* \param new_state The new state to place the channel into
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* \code
|
||||
* ast_bridge_channel_leave_bridge(bridge_channel, AST_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.
|
||||
*/
|
||||
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel);
|
||||
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
|
||||
|
||||
/*!
|
||||
* \brief Ask the bridged channel to leave the bridge it is currently in
|
||||
* \brief Set bridge channel state to leave bridge (if not leaving already).
|
||||
*
|
||||
* \param bridge_channel Channel to leave the bridge
|
||||
* \param bridge_channel Channel to change the state on
|
||||
* \param new_state The new state to place the channel into
|
||||
*
|
||||
* \note This function assumes the bridge_channel is locked.
|
||||
* Example usage:
|
||||
*
|
||||
* \code
|
||||
* ast_bridge_channel_leave_bridge(bridge_channel, AST_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.
|
||||
*/
|
||||
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel);
|
||||
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
|
||||
|
||||
/*!
|
||||
* \brief Write a frame to the specified bridge_channel.
|
||||
@@ -265,54 +261,9 @@ void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_ch
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*
|
||||
* \note This API call is meant for internal bridging operations.
|
||||
* \note BUGBUG This may get moved.
|
||||
*/
|
||||
int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr);
|
||||
|
||||
/*!
|
||||
* \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel Which channel work with.
|
||||
* \param action Type of bridge action frame.
|
||||
* \param data Frame payload data to pass.
|
||||
* \param datalen Frame payload data length to pass.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
typedef int (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
|
||||
|
||||
/*!
|
||||
* \brief Queue an action frame onto the bridge channel with data.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel Which channel to queue the frame onto.
|
||||
* \param action Type of bridge action frame.
|
||||
* \param data Frame payload data to pass.
|
||||
* \param datalen Frame payload data length to pass.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
|
||||
|
||||
/*!
|
||||
* \brief Write an action frame into the bridge with data.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel Which channel is putting the frame into the bridge.
|
||||
* \param action Type of bridge action frame.
|
||||
* \param data Frame payload data to pass.
|
||||
* \param datalen Frame payload data length to pass.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
|
||||
|
||||
/*!
|
||||
* \brief Queue a control frame onto the bridge channel with data.
|
||||
* \since 12.0.0
|
||||
@@ -569,6 +520,56 @@ void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channe
|
||||
*/
|
||||
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
|
||||
|
@@ -33,24 +33,59 @@
|
||||
#ifndef _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
|
||||
#define _ASTERISK_PRIVATE_BRIDGING_CHANNEL_H
|
||||
|
||||
struct blind_transfer_data {
|
||||
char exten[AST_MAX_EXTENSION];
|
||||
char context[AST_MAX_CONTEXT];
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Actions that can be taken on a channel in a bridge
|
||||
*/
|
||||
enum bridge_channel_action_type {
|
||||
/*! Bridged channel is to detect a feature hook */
|
||||
BRIDGE_CHANNEL_ACTION_FEATURE,
|
||||
/*! Bridged channel is to act on an interval hook */
|
||||
BRIDGE_CHANNEL_ACTION_INTERVAL,
|
||||
/*! Bridged channel is to send a DTMF stream out */
|
||||
BRIDGE_CHANNEL_ACTION_DTMF_STREAM,
|
||||
/*! Bridged channel is to indicate talking start */
|
||||
BRIDGE_CHANNEL_ACTION_TALKING_START,
|
||||
/*! Bridged channel is to indicate talking stop */
|
||||
BRIDGE_CHANNEL_ACTION_TALKING_STOP,
|
||||
/*! Bridge channel is to play the indicated sound file. */
|
||||
BRIDGE_CHANNEL_ACTION_PLAY_FILE,
|
||||
/*! Bridge channel is to run the indicated application. */
|
||||
BRIDGE_CHANNEL_ACTION_RUN_APP,
|
||||
/*! Bridge channel is to run the custom callback routine. */
|
||||
BRIDGE_CHANNEL_ACTION_CALLBACK,
|
||||
/*! Bridge channel is to get parked. */
|
||||
BRIDGE_CHANNEL_ACTION_PARK,
|
||||
/*! Bridge channel is to execute a blind transfer. */
|
||||
BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER,
|
||||
/*! Bridge channel is to execute an attended transfer */
|
||||
BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER,
|
||||
|
||||
/*
|
||||
* Bridge actions put after this comment must never be put onto
|
||||
* the bridge_channel wr_queue because they have other resources
|
||||
* that must be freed.
|
||||
*/
|
||||
|
||||
/*! Bridge reconfiguration deferred technology destruction. */
|
||||
BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY = 1000,
|
||||
/*! Bridge deferred dissolving. */
|
||||
BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING,
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Adjust the bridge_channel's bridge merge inhibit request count.
|
||||
* \internal
|
||||
* \brief Push the bridge channel into its specified bridge.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel What to operate on.
|
||||
* \param request Inhibit request increment.
|
||||
* (Positive to add requests. Negative to remove requests.)
|
||||
* \param bridge_channel Channel to push.
|
||||
*
|
||||
* \note This API call is meant for internal bridging operations.
|
||||
* \note On entry, bridge_channel->bridge is already locked.
|
||||
*
|
||||
* \retval bridge adjusted merge inhibit with reference count.
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on failure. The channel did not get pushed.
|
||||
*/
|
||||
struct ast_bridge *bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request);
|
||||
int bridge_channel_push(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
@@ -67,90 +102,57 @@ void bridge_channel_pull(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Push the bridge channel into its specified bridge.
|
||||
* \since 12.0.0
|
||||
* \brief Join the bridge_channel to the bridge
|
||||
*
|
||||
* \param bridge_channel Channel to push.
|
||||
* \param bridge_channel The Channel in the bridge
|
||||
*
|
||||
* \note On entry, bridge_channel->bridge is already locked.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on failure. The channel did not get pushed.
|
||||
* \note This API call starts the bridge_channel's processing of events while
|
||||
* it is in the bridge. It will return when the channel has been instructed to
|
||||
* leave the bridge.
|
||||
*/
|
||||
int bridge_channel_push(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
void bridge_channel_join(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Temporarily suspend a channel from a bridge, handing control over to some
|
||||
* other system
|
||||
*
|
||||
* \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);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Unsuspend a channel that was previously suspended
|
||||
*
|
||||
* \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);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Update the linkedids for all channels in a bridge
|
||||
* \since 12.0.0
|
||||
* \brief Queue a blind transfer action on a transferee bridge channel
|
||||
*
|
||||
* \param bridge_channel The channel joining the bridge
|
||||
* \param swap The channel being swapped out of the bridge. May be NULL.
|
||||
* This is only relevant for when a blind transfer is performed on a two-party
|
||||
* bridge. The transferee's bridge channel will have a blind transfer bridge
|
||||
* action queued onto it, resulting in the party being redirected to a new
|
||||
* destination
|
||||
*
|
||||
* \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
|
||||
* \param transferee The channel to have the action queued on
|
||||
* \param exten The destination extension for the transferee
|
||||
* \param context The destination context for the transferee
|
||||
* \param hook Frame hook to attach to transferee
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
void bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
|
||||
int bridge_channel_queue_blind_transfer(struct ast_channel *transferee,
|
||||
const char *exten, const char *context,
|
||||
transfer_channel_cb new_channel_cb, void *user_data);
|
||||
|
||||
/*!
|
||||
* \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 bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap);
|
||||
|
||||
|
||||
/*!
|
||||
* \brief Set bridge channel state to leave bridge (if not leaving already) with no lock.
|
||||
*
|
||||
* \param bridge_channel Channel to change the state on
|
||||
* \param new_state The new state to place the channel into
|
||||
*
|
||||
* \note This API call is only meant to be used within the
|
||||
* bridging module and hook callbacks to request the channel
|
||||
* exit the bridge.
|
||||
*
|
||||
* \note This function assumes the bridge_channel is locked.
|
||||
*/
|
||||
void ast_bridge_change_state_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
|
||||
|
||||
/*!
|
||||
* \brief Set bridge channel state to leave bridge (if not leaving already).
|
||||
*
|
||||
* \param bridge_channel Channel to change the state on
|
||||
* \param new_state The new state to place the channel into
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* \code
|
||||
* ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
* \endcode
|
||||
*
|
||||
* This places the channel pointed to by bridge_channel into the
|
||||
* state AST_BRIDGE_CHANNEL_STATE_HANGUP if it was
|
||||
* AST_BRIDGE_CHANNEL_STATE_WAIT before.
|
||||
*
|
||||
* \note This API call is only meant to be used within the
|
||||
* bridging module and hook callbacks to request the channel
|
||||
* exit the bridge.
|
||||
*/
|
||||
void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state);
|
||||
int bridge_channel_queue_attended_transfer(struct ast_channel *transferee,
|
||||
struct ast_channel *unbridged_chan);
|
||||
|
||||
#endif /* _ASTERISK_PRIVATE_BRIDGING_H */
|
||||
|
@@ -75,7 +75,7 @@ enum ast_bridge_builtin_feature {
|
||||
* how it was imparted.
|
||||
*
|
||||
* \note Joined channels exit the bridge with
|
||||
* AST_BRIDGE_CHANNEL_STATE_END.
|
||||
* AST_BRIDGE_CHANNEL_STATE_END_WITH_DISSOLVE.
|
||||
*/
|
||||
AST_BRIDGE_BUILTIN_HANGUP,
|
||||
/*!
|
||||
|
@@ -256,7 +256,7 @@ void bridge_dissolve(struct ast_bridge *bridge)
|
||||
struct ast_bridge_channel *bridge_channel;
|
||||
struct ast_frame action = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
.subclass.integer = AST_BRIDGE_ACTION_DEFERRED_DISSOLVING,
|
||||
.subclass.integer = BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING,
|
||||
};
|
||||
|
||||
if (bridge->dissolved) {
|
||||
@@ -268,7 +268,7 @@ void bridge_dissolve(struct ast_bridge *bridge)
|
||||
|
||||
/* BUGBUG need a cause code on the bridge for the later ejected channels. */
|
||||
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
|
||||
/* Must defer dissolving bridge because it is already locked. */
|
||||
@@ -518,12 +518,12 @@ static void bridge_action_bridge(struct ast_bridge *bridge, struct ast_frame *ac
|
||||
#endif
|
||||
|
||||
switch (action->subclass.integer) {
|
||||
case AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY:
|
||||
case BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY:
|
||||
ast_bridge_unlock(bridge);
|
||||
bridge_tech_deferred_destroy(bridge, action);
|
||||
ast_bridge_lock(bridge);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_DEFERRED_DISSOLVING:
|
||||
case BRIDGE_CHANNEL_ACTION_DEFERRED_DISSOLVING:
|
||||
ast_bridge_unlock(bridge);
|
||||
bridge->v_table->dissolving(bridge);
|
||||
ast_bridge_lock(bridge);
|
||||
@@ -999,7 +999,7 @@ static int smart_bridge_operation(struct ast_bridge *bridge)
|
||||
};
|
||||
struct ast_frame action = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
.subclass.integer = AST_BRIDGE_ACTION_DEFERRED_TECH_DESTROY,
|
||||
.subclass.integer = BRIDGE_CHANNEL_ACTION_DEFERRED_TECH_DESTROY,
|
||||
.data.ptr = &deferred_tech_destroy,
|
||||
.datalen = sizeof(deferred_tech_destroy),
|
||||
};
|
||||
@@ -2161,14 +2161,14 @@ enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge,
|
||||
ao2_ref(bridge, -1);
|
||||
}
|
||||
if (!bridge_channel) {
|
||||
state = AST_BRIDGE_CHANNEL_STATE_HANGUP;
|
||||
state = AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE;
|
||||
goto join_exit;
|
||||
}
|
||||
/* BUGBUG features cannot be NULL when passed in. When it is changed to allocated we can do like ast_bridge_impart() and allocate one. */
|
||||
ast_assert(features != NULL);
|
||||
if (!features) {
|
||||
ao2_ref(bridge_channel, -1);
|
||||
state = AST_BRIDGE_CHANNEL_STATE_HANGUP;
|
||||
state = AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE;
|
||||
goto join_exit;
|
||||
}
|
||||
if (tech_args) {
|
||||
@@ -2350,7 +2350,7 @@ int ast_bridge_depart(struct ast_channel *chan)
|
||||
* channel thread.
|
||||
*/
|
||||
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
|
||||
/* Wait for the depart thread to die */
|
||||
ast_debug(1, "Waiting for %p(%s) bridge thread to die.\n",
|
||||
@@ -2378,7 +2378,7 @@ int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
|
||||
ast_bridge_unlock(bridge);
|
||||
|
||||
@@ -2443,7 +2443,7 @@ void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridg
|
||||
if (kick_me) {
|
||||
for (idx = 0; idx < num_kick; ++idx) {
|
||||
if (bridge_channel == kick_me[idx]) {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2461,7 +2461,7 @@ void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridg
|
||||
bridge_channel_change_bridge(bridge_channel, dst_bridge);
|
||||
|
||||
if (bridge_channel_push(bridge_channel)) {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
}
|
||||
AST_LIST_TRAVERSE_SAFE_END;
|
||||
@@ -2475,7 +2475,7 @@ void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridg
|
||||
bridge_channel = kick_me[idx];
|
||||
ast_bridge_channel_lock(bridge_channel);
|
||||
if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
|
||||
ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
bridge_channel_pull(bridge_channel);
|
||||
}
|
||||
ast_bridge_channel_unlock(bridge_channel);
|
||||
@@ -2710,10 +2710,10 @@ int bridge_do_move(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bri
|
||||
bridge_channel_change_bridge(bridge_channel, orig_bridge);
|
||||
|
||||
if (bridge_channel_push(bridge_channel)) {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
} else {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
res = -1;
|
||||
}
|
||||
@@ -3111,7 +3111,7 @@ static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
|
||||
}
|
||||
other->swap = dst_bridge_channel->chan;
|
||||
if (!bridge_do_move(dst_bridge, other, 1, 1)) {
|
||||
ast_bridge_change_state(src_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(src_bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
res = -1;
|
||||
if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
|
||||
pvt->callbacks->optimization_finished(pvt);
|
||||
@@ -4567,71 +4567,6 @@ static struct ast_channel *get_transferee(struct ao2_container *channels, struct
|
||||
return transferee;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Queue a blind transfer action on a transferee bridge channel
|
||||
*
|
||||
* This is only relevant for when a blind transfer is performed on a two-party
|
||||
* bridge. The transferee's bridge channel will have a blind transfer bridge
|
||||
* action queued onto it, resulting in the party being redirected to a new
|
||||
* destination
|
||||
*
|
||||
* \param transferee The channel to have the action queued on
|
||||
* \param exten The destination extension for the transferee
|
||||
* \param context The destination context for the transferee
|
||||
* \param hook Frame hook to attach to transferee
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
static int bridge_channel_queue_blind_transfer(struct ast_channel *transferee,
|
||||
const char *exten, const char *context,
|
||||
transfer_channel_cb new_channel_cb, void *user_data)
|
||||
{
|
||||
RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
|
||||
struct blind_transfer_data blind_data;
|
||||
|
||||
ast_channel_lock(transferee);
|
||||
transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
|
||||
ast_channel_unlock(transferee);
|
||||
|
||||
if (!transferee_bridge_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_channel_cb) {
|
||||
new_channel_cb(transferee, user_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
|
||||
}
|
||||
|
||||
ast_copy_string(blind_data.exten, exten, sizeof(blind_data.exten));
|
||||
ast_copy_string(blind_data.context, context, sizeof(blind_data.context));
|
||||
|
||||
return ast_bridge_channel_queue_action_data(transferee_bridge_channel,
|
||||
AST_BRIDGE_ACTION_BLIND_TRANSFER, &blind_data, sizeof(blind_data));
|
||||
}
|
||||
|
||||
static int bridge_channel_queue_attended_transfer(struct ast_channel *transferee,
|
||||
struct ast_channel *unbridged_chan)
|
||||
{
|
||||
RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
|
||||
char unbridged_chan_name[AST_CHANNEL_NAME];
|
||||
|
||||
ast_channel_lock(transferee);
|
||||
transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
|
||||
ast_channel_unlock(transferee);
|
||||
|
||||
if (!transferee_bridge_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
|
||||
sizeof(unbridged_chan_name));
|
||||
|
||||
return ast_bridge_channel_queue_action_data(transferee_bridge_channel,
|
||||
AST_BRIDGE_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
|
||||
sizeof(unbridged_chan_name));
|
||||
}
|
||||
|
||||
enum try_parking_result {
|
||||
PARKING_SUCCESS,
|
||||
PARKING_FAILURE,
|
||||
@@ -4851,7 +4786,7 @@ static enum ast_transfer_result bridge_swap_attended_transfer(struct ast_bridge
|
||||
return AST_BRIDGE_TRANSFER_FAIL;
|
||||
}
|
||||
/* Must kick the source channel out of its bridge. */
|
||||
ast_bridge_change_state(source_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(source_bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
return AST_BRIDGE_TRANSFER_SUCCESS;
|
||||
} else {
|
||||
return AST_BRIDGE_TRANSFER_INVALID;
|
||||
|
@@ -285,7 +285,7 @@ static int basic_hangup_hook(struct ast_bridge *bridge, struct ast_bridge_channe
|
||||
}
|
||||
if (2 <= bridge_count) {
|
||||
/* Just allow this channel to leave the multi-party bridge. */
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
ast_bridge_unlock(bridge_channel->bridge);
|
||||
return 0;
|
||||
@@ -342,8 +342,8 @@ static int bridge_personality_normal_push(struct ast_bridge *self, struct ast_br
|
||||
return -1;
|
||||
}
|
||||
|
||||
bridge_channel_update_accountcodes(bridge_channel, swap);
|
||||
bridge_channel_update_linkedids(bridge_channel, swap);
|
||||
ast_bridge_channel_update_accountcodes(bridge_channel, swap);
|
||||
ast_bridge_channel_update_linkedids(bridge_channel, swap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2659,7 +2659,7 @@ static int feature_attended_transfer(struct ast_bridge *bridge, struct ast_bridg
|
||||
}
|
||||
|
||||
ast_bridge_channel_write_hold(bridge_channel, NULL);
|
||||
props->transferee_bridge = bridge_channel_merge_inhibit(bridge_channel, +1);
|
||||
props->transferee_bridge = ast_bridge_channel_merge_inhibit(bridge_channel, +1);
|
||||
|
||||
/* Grab the extension to transfer to */
|
||||
if (grab_transfer(bridge_channel->chan, exten, sizeof(exten), props->context)) {
|
||||
|
@@ -53,8 +53,21 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
|
||||
#include "asterisk/features_config.h"
|
||||
#include "asterisk/parking.h"
|
||||
|
||||
/*!
|
||||
* \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel Which channel work with.
|
||||
* \param action Type of bridge action frame.
|
||||
* \param data Frame payload data to pass.
|
||||
* \param datalen Frame payload data length to pass.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
typedef int (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen);
|
||||
|
||||
struct ast_bridge *bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request)
|
||||
struct ast_bridge *ast_bridge_channel_merge_inhibit(struct ast_bridge_channel *bridge_channel, int request)
|
||||
{
|
||||
struct ast_bridge *bridge;
|
||||
|
||||
@@ -98,31 +111,7 @@ static void bridge_channel_poke(struct ast_bridge_channel *bridge_channel)
|
||||
}
|
||||
}
|
||||
|
||||
void ast_bridge_change_state_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
|
||||
{
|
||||
/* BUGBUG need cause code for the bridge_channel leaving the bridge. */
|
||||
if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ast_debug(1, "Setting %p(%s) state from:%d to:%d\n",
|
||||
bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
|
||||
new_state);
|
||||
|
||||
/* Change the state on the bridge channel */
|
||||
bridge_channel->state = new_state;
|
||||
|
||||
bridge_channel_poke(bridge_channel);
|
||||
}
|
||||
|
||||
void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
|
||||
{
|
||||
ast_bridge_channel_lock(bridge_channel);
|
||||
ast_bridge_change_state_nolock(bridge_channel, new_state);
|
||||
ast_bridge_channel_unlock(bridge_channel);
|
||||
}
|
||||
|
||||
void bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
|
||||
void ast_bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
|
||||
{
|
||||
struct ast_bridge *bridge = bridge_channel->bridge;
|
||||
struct ast_bridge_channel *other = NULL;
|
||||
@@ -167,7 +156,7 @@ void bridge_channel_update_accountcodes(struct ast_bridge_channel *bridge_channe
|
||||
}
|
||||
}
|
||||
|
||||
void bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
|
||||
void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_channel, struct ast_bridge_channel *swap)
|
||||
{
|
||||
struct ast_bridge_channel *other = NULL;
|
||||
struct ast_bridge *bridge = bridge_channel->bridge;
|
||||
@@ -233,7 +222,19 @@ int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, st
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen)
|
||||
/*!
|
||||
* \brief Queue an action frame onto the bridge channel with data.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param bridge_channel Which channel to queue the frame onto.
|
||||
* \param action Type of bridge action frame.
|
||||
* \param data Frame payload data to pass.
|
||||
* \param datalen Frame payload data length to pass.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
static int ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
|
||||
{
|
||||
struct ast_frame frame = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
@@ -322,7 +323,7 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen)
|
||||
static int ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum bridge_channel_action_type action, const void *data, size_t datalen)
|
||||
{
|
||||
struct ast_frame frame = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
@@ -423,7 +424,7 @@ static void bridge_channel_handle_hangup(struct ast_bridge_channel *bridge_chann
|
||||
ao2_iterator_destroy(&iter);
|
||||
|
||||
/* Default hangup action. */
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
}
|
||||
|
||||
void ast_bridge_channel_run_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
|
||||
@@ -488,7 +489,7 @@ static int payload_helper_app(ast_bridge_channel_post_action_data post_it,
|
||||
strcpy(&app_data->app_name[app_data->moh_offset], moh_class);/* Safe */
|
||||
}
|
||||
|
||||
return post_it(bridge_channel, AST_BRIDGE_ACTION_RUN_APP, app_data, len_data);
|
||||
return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_RUN_APP, app_data, len_data);
|
||||
}
|
||||
|
||||
int ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
|
||||
@@ -573,7 +574,7 @@ static int payload_helper_playfile(ast_bridge_channel_post_action_data post_it,
|
||||
strcpy(&payload->playfile[payload->moh_offset], moh_class);/* Safe */
|
||||
}
|
||||
|
||||
return post_it(bridge_channel, AST_BRIDGE_ACTION_PLAY_FILE, payload, len_payload);
|
||||
return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PLAY_FILE, payload, len_payload);
|
||||
}
|
||||
|
||||
int ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_play_fn custom_play, const char *playfile, const char *moh_class)
|
||||
@@ -635,7 +636,7 @@ static int payload_helper_cb(ast_bridge_channel_post_action_data post_it,
|
||||
memcpy(cb_data->payload, payload, payload_size);/* Safe */
|
||||
}
|
||||
|
||||
return post_it(bridge_channel, AST_BRIDGE_ACTION_CALLBACK, cb_data, len_data);
|
||||
return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_CALLBACK, cb_data, len_data);
|
||||
}
|
||||
|
||||
int ast_bridge_channel_write_callback(struct ast_bridge_channel *bridge_channel, ast_bridge_custom_callback_fn callback, const void *payload, size_t payload_size)
|
||||
@@ -685,7 +686,7 @@ static int payload_helper_park(ast_bridge_channel_post_action_data post_it,
|
||||
strcpy(&payload->parkee_uuid[payload->app_data_offset], app_data);
|
||||
}
|
||||
|
||||
return post_it(bridge_channel, AST_BRIDGE_ACTION_PARK, payload, len_payload);
|
||||
return post_it(bridge_channel, BRIDGE_CHANNEL_ACTION_PARK, payload, len_payload);
|
||||
}
|
||||
|
||||
int ast_bridge_channel_write_park(struct ast_bridge_channel *bridge_channel, const char *parkee_uuid, const char *parker_uuid, const char *app_data)
|
||||
@@ -713,7 +714,7 @@ int ast_bridge_notify_talking(struct ast_bridge_channel *bridge_channel, int sta
|
||||
struct ast_frame action = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
.subclass.integer = started_talking
|
||||
? AST_BRIDGE_ACTION_TALKING_START : AST_BRIDGE_ACTION_TALKING_STOP,
|
||||
? BRIDGE_CHANNEL_ACTION_TALKING_START : BRIDGE_CHANNEL_ACTION_TALKING_STOP,
|
||||
};
|
||||
|
||||
return ast_bridge_channel_queue_frame(bridge_channel, &action);
|
||||
@@ -904,7 +905,7 @@ static void bridge_channel_interval(struct ast_bridge_channel *bridge_channel)
|
||||
static int bridge_channel_write_dtmf_stream(struct ast_bridge_channel *bridge_channel, const char *dtmf)
|
||||
{
|
||||
return ast_bridge_channel_write_action_data(bridge_channel,
|
||||
AST_BRIDGE_ACTION_DTMF_STREAM, dtmf, strlen(dtmf) + 1);
|
||||
BRIDGE_CHANNEL_ACTION_DTMF_STREAM, dtmf, strlen(dtmf) + 1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -1115,64 +1116,64 @@ static void bridge_channel_attended_transfer(struct ast_bridge_channel *bridge_c
|
||||
static void bridge_channel_handle_action(struct ast_bridge_channel *bridge_channel, struct ast_frame *action)
|
||||
{
|
||||
switch (action->subclass.integer) {
|
||||
case AST_BRIDGE_ACTION_INTERVAL:
|
||||
case BRIDGE_CHANNEL_ACTION_INTERVAL:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_interval(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_FEATURE:
|
||||
case BRIDGE_CHANNEL_ACTION_FEATURE:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_feature(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_DTMF_STREAM:
|
||||
case BRIDGE_CHANNEL_ACTION_DTMF_STREAM:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_dtmf_stream(bridge_channel, action->data.ptr);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_TALKING_START:
|
||||
case AST_BRIDGE_ACTION_TALKING_STOP:
|
||||
case BRIDGE_CHANNEL_ACTION_TALKING_START:
|
||||
case BRIDGE_CHANNEL_ACTION_TALKING_STOP:
|
||||
bridge_channel_talking(bridge_channel,
|
||||
action->subclass.integer == AST_BRIDGE_ACTION_TALKING_START);
|
||||
action->subclass.integer == BRIDGE_CHANNEL_ACTION_TALKING_START);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_PLAY_FILE:
|
||||
case BRIDGE_CHANNEL_ACTION_PLAY_FILE:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_playfile(bridge_channel, action->data.ptr);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_RUN_APP:
|
||||
case BRIDGE_CHANNEL_ACTION_RUN_APP:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_run_app(bridge_channel, action->data.ptr);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_CALLBACK:
|
||||
case BRIDGE_CHANNEL_ACTION_CALLBACK:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_do_callback(bridge_channel, action->data.ptr);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_PARK:
|
||||
case BRIDGE_CHANNEL_ACTION_PARK:
|
||||
bridge_channel_suspend(bridge_channel);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_park(bridge_channel, action->data.ptr);
|
||||
ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
|
||||
bridge_channel_unsuspend(bridge_channel);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_BLIND_TRANSFER:
|
||||
case BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER:
|
||||
bridge_channel_blind_transfer(bridge_channel, action->data.ptr);
|
||||
break;
|
||||
case AST_BRIDGE_ACTION_ATTENDED_TRANSFER:
|
||||
case BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER:
|
||||
bridge_channel_attended_transfer(bridge_channel, action->data.ptr);
|
||||
break;
|
||||
default:
|
||||
@@ -1350,7 +1351,7 @@ int bridge_channel_push(struct ast_bridge_channel *bridge_channel)
|
||||
|
||||
ast_bridge_publish_enter(bridge, bridge_channel->chan);
|
||||
if (swap) {
|
||||
ast_bridge_change_state(swap, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(swap, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
bridge_channel_pull(swap);
|
||||
}
|
||||
|
||||
@@ -1519,7 +1520,7 @@ static void bridge_channel_handle_interval(struct ast_bridge_channel *bridge_cha
|
||||
/* BUGBUG since this is now only run by the channel thread, there is no need to queue the action once this intervals become a first class wait item in bridge_channel_wait(). */
|
||||
struct ast_frame interval_action = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
.subclass.integer = AST_BRIDGE_ACTION_INTERVAL,
|
||||
.subclass.integer = BRIDGE_CHANNEL_ACTION_INTERVAL,
|
||||
};
|
||||
|
||||
ast_bridge_channel_queue_frame(bridge_channel, &interval_action);
|
||||
@@ -1544,7 +1545,7 @@ static struct ast_frame *bridge_handle_dtmf(struct ast_bridge_channel *bridge_ch
|
||||
if (hook) {
|
||||
struct ast_frame action = {
|
||||
.frametype = AST_FRAME_BRIDGE_ACTION,
|
||||
.subclass.integer = AST_BRIDGE_ACTION_FEATURE,
|
||||
.subclass.integer = BRIDGE_CHANNEL_ACTION_FEATURE,
|
||||
};
|
||||
|
||||
ast_frfree(frame);
|
||||
@@ -1769,7 +1770,7 @@ void bridge_channel_join(struct ast_bridge_channel *bridge_channel)
|
||||
}
|
||||
|
||||
if (bridge_channel_push(bridge_channel)) {
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
bridge_reconfigured(bridge_channel->bridge, 1);
|
||||
|
||||
@@ -1827,12 +1828,91 @@ void bridge_channel_join(struct ast_bridge_channel *bridge_channel)
|
||||
ast_bridge_channel_restore_formats(bridge_channel);
|
||||
}
|
||||
|
||||
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel)
|
||||
void ast_bridge_channel_leave_bridge(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
|
||||
{
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
ast_bridge_channel_lock(bridge_channel);
|
||||
ast_bridge_channel_leave_bridge_nolock(bridge_channel, new_state);
|
||||
ast_bridge_channel_unlock(bridge_channel);
|
||||
}
|
||||
|
||||
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel)
|
||||
void ast_bridge_channel_leave_bridge_nolock(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
|
||||
{
|
||||
ast_bridge_change_state_nolock(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
|
||||
/* BUGBUG need cause code for the bridge_channel leaving the bridge. */
|
||||
if (bridge_channel->state != AST_BRIDGE_CHANNEL_STATE_WAIT) {
|
||||
return;
|
||||
}
|
||||
|
||||
ast_debug(1, "Setting %p(%s) state from:%d to:%d\n",
|
||||
bridge_channel, ast_channel_name(bridge_channel->chan), bridge_channel->state,
|
||||
new_state);
|
||||
|
||||
/* Change the state on the bridge channel */
|
||||
bridge_channel->state = new_state;
|
||||
|
||||
bridge_channel_poke(bridge_channel);
|
||||
}
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Queue a blind transfer action on a transferee bridge channel
|
||||
*
|
||||
* This is only relevant for when a blind transfer is performed on a two-party
|
||||
* bridge. The transferee's bridge channel will have a blind transfer bridge
|
||||
* action queued onto it, resulting in the party being redirected to a new
|
||||
* destination
|
||||
*
|
||||
* \param transferee The channel to have the action queued on
|
||||
* \param exten The destination extension for the transferee
|
||||
* \param context The destination context for the transferee
|
||||
* \param hook Frame hook to attach to transferee
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error.
|
||||
*/
|
||||
int bridge_channel_queue_blind_transfer(struct ast_channel *transferee,
|
||||
const char *exten, const char *context,
|
||||
transfer_channel_cb new_channel_cb, void *user_data)
|
||||
{
|
||||
RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
|
||||
struct blind_transfer_data blind_data;
|
||||
|
||||
ast_channel_lock(transferee);
|
||||
transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
|
||||
ast_channel_unlock(transferee);
|
||||
|
||||
if (!transferee_bridge_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (new_channel_cb) {
|
||||
new_channel_cb(transferee, user_data, AST_BRIDGE_TRANSFER_SINGLE_PARTY);
|
||||
}
|
||||
|
||||
ast_copy_string(blind_data.exten, exten, sizeof(blind_data.exten));
|
||||
ast_copy_string(blind_data.context, context, sizeof(blind_data.context));
|
||||
|
||||
return ast_bridge_channel_queue_action_data(transferee_bridge_channel,
|
||||
BRIDGE_CHANNEL_ACTION_BLIND_TRANSFER, &blind_data, sizeof(blind_data));
|
||||
}
|
||||
|
||||
int bridge_channel_queue_attended_transfer(struct ast_channel *transferee,
|
||||
struct ast_channel *unbridged_chan)
|
||||
{
|
||||
RAII_VAR(struct ast_bridge_channel *, transferee_bridge_channel, NULL, ao2_cleanup);
|
||||
char unbridged_chan_name[AST_CHANNEL_NAME];
|
||||
|
||||
ast_channel_lock(transferee);
|
||||
transferee_bridge_channel = ast_channel_get_bridge_channel(transferee);
|
||||
ast_channel_unlock(transferee);
|
||||
|
||||
if (!transferee_bridge_channel) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ast_copy_string(unbridged_chan_name, ast_channel_name(unbridged_chan),
|
||||
sizeof(unbridged_chan_name));
|
||||
|
||||
return ast_bridge_channel_queue_action_data(transferee_bridge_channel,
|
||||
BRIDGE_CHANNEL_ACTION_ATTENDED_TRANSFER, unbridged_chan_name,
|
||||
sizeof(unbridged_chan_name));
|
||||
}
|
||||
|
@@ -404,7 +404,7 @@ static int parking_duration_callback(struct ast_bridge *bridge, struct ast_bridg
|
||||
user->resolution = PARK_TIMEOUT;
|
||||
ao2_unlock(user);
|
||||
|
||||
ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
|
||||
/* Set parking timeout channel variables */
|
||||
snprintf(parking_space, sizeof(parking_space), "%d", user->parking_space);
|
||||
@@ -492,14 +492,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_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_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_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
|
||||
ast_bridge_channel_leave_bridge(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user