mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-03 11:11:05 +00:00
Make DTMF attended transfer support feature-complete.
This greatly modifies the operation of DTMF attended transfers so that the full range of options from features.conf applies. In addition, a new option has been added that allows for a transferer to switch between bridges during a transfer before completing the transfer. (closes issue ASTERISK-21543) reported by Matt Jordan Review: https://reviewboard.asterisk.org/r/2654 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395151 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -396,6 +396,8 @@ struct ast_bridge_methods {
|
||||
struct ast_bridge {
|
||||
/*! Bridge virtual method table. */
|
||||
const struct ast_bridge_methods *v_table;
|
||||
/*! "Personality" currently exhibited by bridge subclass */
|
||||
void *personality;
|
||||
/*! Immutable bridge UUID. */
|
||||
char uniqueid[AST_UUID_STR_LEN];
|
||||
/*! Bridge technology that is handling the bridge */
|
||||
@@ -1785,6 +1787,16 @@ struct ast_channel *ast_bridge_peer_nolock(struct ast_bridge *bridge, struct ast
|
||||
*/
|
||||
struct ast_channel *ast_bridge_peer(struct ast_bridge *bridge, struct ast_channel *chan);
|
||||
|
||||
/*!
|
||||
* \brief Remove marked bridge channel feature hooks.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param features Bridge features structure
|
||||
* \param flags Determinator for whether hook is removed.
|
||||
*
|
||||
* \return Nothing
|
||||
*/
|
||||
void ast_bridge_features_remove(struct ast_bridge_features *features, enum ast_bridge_hook_remove_flags flags);
|
||||
#if defined(__cplusplus) || defined(c_plusplus)
|
||||
}
|
||||
#endif
|
||||
|
@@ -183,6 +183,8 @@ struct ast_bridge_hook_timer {
|
||||
enum ast_bridge_hook_remove_flags {
|
||||
/*! The hook is removed when the channel is pulled from the bridge. */
|
||||
AST_BRIDGE_HOOK_REMOVE_ON_PULL = (1 << 0),
|
||||
/*! The hook is removed when the bridge's personality changes. */
|
||||
AST_BRIDGE_HOOK_REMOVE_ON_PERSONALITY_CHANGE = (1 << 1),
|
||||
};
|
||||
|
||||
/* BUGBUG Need to be able to selectively remove DTMF, hangup, and interval hooks. */
|
||||
@@ -265,6 +267,8 @@ struct ast_bridge_features_attended_transfer {
|
||||
char threeway[MAXIMUM_DTMF_FEATURE_STRING];
|
||||
/*! DTMF string used to complete the transfer (If not empty.) */
|
||||
char complete[MAXIMUM_DTMF_FEATURE_STRING];
|
||||
/*! DTMF string used to swap bridged targets (If not empty.) */
|
||||
char swap[MAXIMUM_DTMF_FEATURE_STRING];
|
||||
};
|
||||
|
||||
enum ast_bridge_features_monitor {
|
||||
|
88
include/asterisk/bridging_internal.h
Normal file
88
include/asterisk/bridging_internal.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Asterisk -- An open source telephony toolkit.
|
||||
*
|
||||
* Copyright (C) 2013 Digium, Inc.
|
||||
*
|
||||
* Mark Michelson <mmichelson@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 Private Bridging API
|
||||
*
|
||||
* \author Mark Michelson <mmichelson@digium.com>
|
||||
*
|
||||
* See Also:
|
||||
* \arg \ref AstCREDITS
|
||||
*/
|
||||
|
||||
#ifndef _ASTERISK_PRIVATE_BRIDGING_H
|
||||
#define _ASTERISK_PRIVATE_BRIDGING_H
|
||||
|
||||
struct ast_bridge;
|
||||
struct ast_bridge_channel;
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Move a bridge channel from one bridge to another.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param dst_bridge Destination bridge of bridge channel move.
|
||||
* \param bridge_channel Channel moving from one bridge to another.
|
||||
* \param attempt_recovery TRUE if failure attempts to push channel back into original bridge.
|
||||
* \param optimized Indicates whether the move is part of an unreal channel optimization.
|
||||
*
|
||||
* \note The dst_bridge and bridge_channel->bridge are assumed already locked.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on failure.
|
||||
*/
|
||||
int bridge_move_do(struct ast_bridge *dst_bridge, struct ast_bridge_channel *bridge_channel,
|
||||
int attempt_recovery, unsigned int optimized);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Do the merge of two bridges.
|
||||
* \since 12.0.0
|
||||
*
|
||||
* \param dst_bridge Destination bridge of merge.
|
||||
* \param src_bridge Source bridge of merge.
|
||||
* \param kick_me Array of channels to kick from the bridges.
|
||||
* \param num_kick Number of channels in the kick_me array.
|
||||
* \param optimized Indicates whether the merge is part of an unreal channel optimization.
|
||||
*
|
||||
* \return Nothing
|
||||
*
|
||||
* \note The two bridges are assumed already locked.
|
||||
*
|
||||
* This moves the channels in src_bridge into the bridge pointed
|
||||
* to by dst_bridge.
|
||||
*/
|
||||
void bridge_merge_do(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge,
|
||||
struct ast_bridge_channel **kick_me, unsigned int num_kick, unsigned int optimized);
|
||||
|
||||
/*!
|
||||
* \internal
|
||||
* \brief Helper function to find a bridge channel given a channel.
|
||||
*
|
||||
* \param bridge What to search
|
||||
* \param chan What to search for.
|
||||
*
|
||||
* \note On entry, bridge is already locked.
|
||||
*
|
||||
* \retval bridge_channel if channel is in the bridge.
|
||||
* \retval NULL if not in bridge.
|
||||
*/
|
||||
struct ast_bridge_channel *find_bridge_channel(struct ast_bridge *bridge, struct ast_channel *chan);
|
||||
|
||||
#endif /* _ASTERISK_PRIVATE_BRIDGING_H */
|
@@ -63,6 +63,37 @@ void ast_channel_remove_bridge_role(struct ast_channel *chan, const char *role_n
|
||||
*/
|
||||
int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *role_name, const char *option, const char *value);
|
||||
|
||||
/*!
|
||||
* \brief Check if a role exists on a channel
|
||||
*
|
||||
* \param channel The channel to check
|
||||
* \param role_name The name of the role to search for
|
||||
*
|
||||
* \retval 0 The requested role does not exist on the channel
|
||||
* \retval 1 The requested role exists on the channel
|
||||
*
|
||||
* This is an alternative to \ref ast_bridge_channel_has_role that is useful if bridge
|
||||
* roles have not yet been established on a channel's bridge_channel. A possible example of
|
||||
* when this could be used is in a bridge v_table's push() callback.
|
||||
*/
|
||||
int ast_channel_has_role(struct ast_channel *channel, const char *role_name);
|
||||
|
||||
/*!
|
||||
* \brief Retrieve the value of a requested role option from a channel
|
||||
*
|
||||
* \param channel The channel to retrieve the requested option from
|
||||
* \param role_name The role to which the option belongs
|
||||
* \param option The name of the option to retrieve
|
||||
*
|
||||
* \retval NULL The option does not exist
|
||||
* \retval non-NULL The value of the option
|
||||
*
|
||||
* This is an alternative to \ref ast_bridge_channel_get_role_option that is useful if bridge
|
||||
* roles have not yet been esstablished on a channel's bridge_channel. A possible example of
|
||||
* when this could be used is in a bridge v_table's push() callback.
|
||||
*/
|
||||
const char *ast_channel_get_role_option(struct ast_channel *channel, const char *role_name, const char *option);
|
||||
|
||||
/*!
|
||||
* \brief Check to see if a bridge channel inherited a specific role from its channel
|
||||
*
|
||||
@@ -72,7 +103,7 @@ int ast_channel_set_bridge_role_option(struct ast_channel *channel, const char *
|
||||
* \retval 0 The bridge channel does not have the requested role
|
||||
* \retval 1 The bridge channel does have the requested role
|
||||
*
|
||||
* \note Before a bridge_channel can effectively check roles against a bridge, ast_bridge_roles_bridge_channel_establish_roles
|
||||
* \note Before a bridge_channel can effectively check roles against a bridge, ast_bridge_channel_establish_roles
|
||||
* should be called on the bridge_channel so that roles and their respective role options can be copied from the channel
|
||||
* datastore into the bridge_channel roles list. Otherwise this function will just return 0 because the list will be NULL.
|
||||
*/
|
||||
@@ -88,10 +119,10 @@ int ast_bridge_channel_has_role(struct ast_bridge_channel *bridge_channel, const
|
||||
* \retval NULL If either the role does not exist on the bridge_channel or the role does exist but the option has not been set
|
||||
* \retval The value of the option
|
||||
*
|
||||
* \note See ast_bridge_roles_channel_set_role_option note about the need to call ast_bridge_roles_bridge_channel_establish_roles.
|
||||
* \note See ast_channel_set_role_option note about the need to call ast_bridge_channel_establish_roles.
|
||||
*
|
||||
* \note The returned character pointer is only valid as long as the bridge_channel is guaranteed to be alive and hasn't had
|
||||
* ast_bridge_roles_bridge_channel_clear_roles called against it (as this will free all roles and role options in the bridge
|
||||
* ast_bridge_channel_clear_roles called against it (as this will free all roles and role options in the bridge
|
||||
* channel). If you need this value after one of these destruction events occurs, you must make a local copy while it is
|
||||
* still valid.
|
||||
*/
|
||||
@@ -119,12 +150,12 @@ int ast_bridge_channel_establish_roles(struct ast_bridge_channel *bridge_channel
|
||||
* \param bridge_channel the bridge channel that we are scrubbing
|
||||
*
|
||||
* \details
|
||||
* If roles are already established on a bridge channel, ast_bridge_roles_bridge_channel_establish_roles will fail unconditionally
|
||||
* If roles are already established on a bridge channel, ast_bridge_channel_establish_roles will fail unconditionally
|
||||
* without changing any roles. In order to update a bridge channel's roles, they must first be cleared from the bridge channel using
|
||||
* this function.
|
||||
*
|
||||
* \note
|
||||
* ast_bridge_roles_bridge_channel_clear_roles also serves as the destructor for the role list of a bridge channel.
|
||||
* ast_bridge_channel_clear_roles also serves as the destructor for the role list of a bridge channel.
|
||||
*/
|
||||
void ast_bridge_channel_clear_roles(struct ast_bridge_channel *bridge_channel);
|
||||
|
||||
|
@@ -66,6 +66,8 @@ struct ast_features_xfer_config {
|
||||
AST_STRING_FIELD(atxfercomplete);
|
||||
/*! DTMF sequence used to turn an attempted atxfer into a three-way call */
|
||||
AST_STRING_FIELD(atxferthreeway);
|
||||
/*! DTMF sequence used to swap which party the transferer is talking to */
|
||||
AST_STRING_FIELD(atxferswap);
|
||||
);
|
||||
/*! Milliseconds allowed between digit presses when dialing transfer destination */
|
||||
unsigned int transferdigittimeout;
|
||||
|
@@ -256,6 +256,8 @@ enum ast_attended_transfer_dest_type {
|
||||
AST_ATTENDED_TRANSFER_DEST_APP,
|
||||
/*! The transfer results in both bridges remaining with a local channel linking them */
|
||||
AST_ATTENDED_TRANSFER_DEST_LINK,
|
||||
/*! The transfer results in a threeway call between transferer, transferee, and transfer target */
|
||||
AST_ATTENDED_TRANSFER_DEST_THREEWAY,
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -279,6 +281,8 @@ struct ast_attended_transfer_message {
|
||||
char app[AST_MAX_APP];
|
||||
/*! Pair of local channels linking the bridges. Applicable for AST_ATTENDED_TRANSFER_DEST_LINK */
|
||||
struct ast_channel_snapshot *links[2];
|
||||
/*! Transferer channel and bridge that survived the transition to a threeway call. Applicable for AST_ATTENDED_TRANSFER_DEST_THREEWAY */
|
||||
struct ast_bridge_channel_snapshot_pair threeway;
|
||||
} dest;
|
||||
};
|
||||
|
||||
@@ -328,6 +332,25 @@ void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast
|
||||
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
|
||||
struct ast_bridge *final_bridge);
|
||||
|
||||
/*!
|
||||
* \since 12
|
||||
* \brief Publish an attended transfer that results in a threeway call.
|
||||
*
|
||||
* Publish an \ref ast_attended_transfer_message with the dest_type set to
|
||||
* \c AST_ATTENDED_TRANSFER_DEST_THREEWAY. Like with \ref ast_bridge_publish_attended_transfer_bridge_merge,
|
||||
* this results from merging two bridges together. The difference is that a
|
||||
* transferer channel survives the bridge merge
|
||||
*
|
||||
* \param is_external Indicates if the transfer was initiated externally
|
||||
* \param result The result of the transfer.
|
||||
* \param transferee The bridge between the transferer and transferees as well as the transferer channel from that bridge
|
||||
* \param target The bridge between the transferer and transfer targets as well as the transferer channel from that bridge
|
||||
* \param final_pair The bridge that the parties end up in, and the transferer channel that is in this bridge.
|
||||
*/
|
||||
void ast_bridge_publish_attended_transfer_threeway(int is_external, enum ast_transfer_result result,
|
||||
struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
|
||||
struct ast_bridge_channel_pair *final_pair);
|
||||
|
||||
/*!
|
||||
* \since 12
|
||||
* \brief Publish an attended transfer that results in an application being run
|
||||
|
Reference in New Issue
Block a user