[asterisk-commits] mmichelson: branch mmichelson/transfer r386326 - in /team/mmichelson/transfer...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon Apr 22 16:01:42 CDT 2013
Author: mmichelson
Date: Mon Apr 22 16:01:38 2013
New Revision: 386326
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=386326
Log:
Implement a naive blind transfer.
I call it "naive" because I wrote this in the way that I think it needs
to work. This might work just fine, or it might totally fail! Neat!
Currently, the frame hook that is passed in is unused.
Modified:
team/mmichelson/transfer/include/asterisk/bridging.h
team/mmichelson/transfer/include/asterisk/bridging_features.h
team/mmichelson/transfer/main/bridging.c
Modified: team/mmichelson/transfer/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/include/asterisk/bridging.h?view=diff&rev=386326&r1=386325&r2=386326
==============================================================================
--- team/mmichelson/transfer/include/asterisk/bridging.h (original)
+++ team/mmichelson/transfer/include/asterisk/bridging.h Mon Apr 22 16:01:38 2013
@@ -1214,13 +1214,13 @@
enum ast_transfer_result {
/*! The transfer completed successfully */
- AST_TRANSFER_SUCCESS,
+ AST_BRIDGE_TRANSFER_SUCCESS,
/*! A bridge involved does not permit transferring */
- AST_TRANSFER_NOT_PERMITTED,
+ AST_BRIDGE_TRANSFER_NOT_PERMITTED,
/*! The current bridge setup makes transferring an invalid operation */
- AST_TRANSFER_INVALID,
+ AST_BRIDGE_TRANSFER_INVALID,
/*! The transfer operation failed for a miscellaneous reason */
- AST_TRANSFER_FAIL,
+ AST_BRIDGE_TRANSFER_FAIL,
};
/*!
@@ -1242,7 +1242,7 @@
* \return The success or failure result of the blind transfer
*/
enum ast_transfer_result ast_bridge_blind_transfer(struct ast_channel *transferer,
- const char *exten, const char *context, struct ast_framehook *hook)
+ const char *exten, const char *context, struct ast_framehook *hook);
/*!
* \brief Attended transfer
@@ -1262,7 +1262,7 @@
* \return The success or failure of the attended transfer
*/
enum ast_transfer_result ast_bridge_attended_transfer(struct ast_channel *to_transferee,
- struct ast_channel *to_transfer_target, struct ast_framehook *hook)
+ struct ast_channel *to_transfer_target, struct ast_framehook *hook);
/*!
* \brief Set channel to goto specific location after the bridge.
* \since 12.0.0
Modified: team/mmichelson/transfer/include/asterisk/bridging_features.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/include/asterisk/bridging_features.h?view=diff&rev=386326&r1=386325&r2=386326
==============================================================================
--- team/mmichelson/transfer/include/asterisk/bridging_features.h (original)
+++ team/mmichelson/transfer/include/asterisk/bridging_features.h Mon Apr 22 16:01:38 2013
@@ -42,6 +42,10 @@
AST_BRIDGE_FLAG_MERGE_INHIBIT_TO = (1 << 4),
/*! Bridge channels can be moved to another bridge only by masquerade (ConfBridge) */
AST_BRIDGE_FLAG_MASQUERADE_ONLY = (1 << 5),
+ /*! Bridge does not allow transfers of channels out */
+ AST_BRIDGE_FLAG_TRANSFER_PROHIBITED = (1 << 6),
+ /*! Bridge transfers require transfer of entire bridge rather than individual channels */
+ AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY = (1 << 7),
};
/*! \brief Flags used for per bridge channel features */
Modified: team/mmichelson/transfer/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/transfer/main/bridging.c?view=diff&rev=386326&r1=386325&r2=386326
==============================================================================
--- team/mmichelson/transfer/main/bridging.c (original)
+++ team/mmichelson/transfer/main/bridging.c Mon Apr 22 16:01:38 2013
@@ -4189,32 +4189,108 @@
ast_bridge_unlock(bridge);
}
+/*!
+ * \internal
+ * \brief Accomplish a transfer by swapping a Local channel with an existing channel
+ *
+ * This, in a sense, blind transfers an entire bridge to an extension and context. It
+ * works by creating a local channel to dial out and swapping the called local channel
+ * with the transferring channel. By doing so, all participants in the bridge are
+ * privy to the goings-on of the blind transfer.
+ *
+ * While this means of transferring would work for both two-party and multi-party
+ * bridges, this method is only used for multi-party bridges since this method would
+ * be less efficient for two-party bridges.
+ *
+ * \param transferer The channel performing a transfer
+ * \param bridge The bridge where the transfer is being performed
+ * \param exten The destination extension for the blind transfer
+ * \param context The destination context for the blind transfer
+ * \return The success or failure of the operation
+ */
+static enum ast_transfer_result local_channel_swap_transfer(struct ast_channel *transferer,
+ struct ast_bridge *bridge, const char *exten, const char *context)
+{
+ struct ast_channel *local;
+ char chan_name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
+ int cause;
+
+ snprintf(chan_name, sizeof(chan_name), "%s@%s\n", exten, context);
+ local = ast_request("Local", ast_channel_nativeformats(transferer),
+ transferer, chan_name, &cause);
+ if (!local) {
+ return AST_BRIDGE_TRANSFER_FAIL;
+ }
+ if (ast_call(local, chan_name, 0)) {
+ ast_hangup(local);
+ return AST_BRIDGE_TRANSFER_FAIL;
+ }
+ if (ast_bridge_impart(bridge, local, transferer, NULL, 1)) {
+ ast_hangup(local);
+ return AST_BRIDGE_TRANSFER_FAIL;
+ }
+ return AST_BRIDGE_TRANSFER_SUCCESS;
+}
+
enum ast_transfer_result ast_bridge_blind_transfer(struct ast_channel *transferer,
const char *exten, const char *context, struct ast_framehook *hook)
{
- /* First, ensure that the transferer is actually in a bridge. If not, return AST_TRANSFER_INVALID.
- * Second, ensure that the bridge the transferer is in is capable of transfers. If not, return AST_TRANSFER_NOT_PERMITTED
- * Third, check if the bridge in use requires transferring the bridge.
- * If the bridge requires it, then perform the local channel swap method of blind transferring
- * If the bridge does not require it, then check the number of bridged participants.
- * If there is only one participant, then use an ast_async_goto() on the bridged participant
- * If there are multiple participants, then perform the local channel swap method of blind transferring
- * If any of the steps above fails, then return AST_TRANSFER_FAIL
- * Otherwise, return AST_TRANSFER_SUCCESS.
+ RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
+ struct ast_channel *bridged_channel;
+ int do_bridge_transfer;
+ int transfer_prohibited;
+
+ ast_channel_lock(transferer);
+ bridge = ast_channel_internal_bridge(transferer);
+ if (!bridge) {
+ ast_channel_unlock(transferer);
+ return AST_BRIDGE_TRANSFER_INVALID;
+ }
+ ao2_ref(bridge, +1);
+ ast_channel_unlock(transferer);
+
+ ast_bridge_lock(bridge);
+ transfer_prohibited = ast_test_flag(&bridge->feature_flags,
+ AST_BRIDGE_FLAG_TRANSFER_PROHIBITED);
+ do_bridge_transfer = ast_test_flag(&bridge->feature_flags,
+ AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY) ||
+ bridge->num_channels > 2;
+ ast_bridge_unlock(bridge);
+
+ if (transfer_prohibited) {
+ return AST_BRIDGE_TRANSFER_NOT_PERMITTED;
+ }
+
+ if (do_bridge_transfer) {
+ return local_channel_swap_transfer(transferer, bridge, exten, context);
+ }
+
+ ast_channel_lock(transferer);
+ bridged_channel = ast_bridged_channel(transferer);
+ if (!bridged_channel) {
+ ast_channel_unlock(transferer);
+ return AST_BRIDGE_TRANSFER_FAIL;
+ }
+ ast_channel_ref(bridged_channel);
+ ast_channel_unlock(transferer);
+
+ /* XXX I don't know if the ast_bridge_remove() call is necessary
+ * here since ast_async_goto will set the AST_SOFTHANGUP_GOTO flag
+ * on the channel that is being redirected
*/
-
- /* XXX STUB */
- return AST_TRANSFER_SUCCESS;
+ ast_bridge_remove(bridge, bridged_channel);
+ return ast_async_goto(bridged_channel, context, exten, 1) == 0 ?
+ AST_BRIDGE_TRANSFER_SUCCESS : AST_BRIDGE_TRANSFER_FAIL;
}
enum ast_transfer_result ast_bridge_attended_transfer(struct ast_channel *to_transferee,
struct ast_channel *to_transfer_target, struct ast_framehook *hook)
{
- /* First, check the validity of scenario. If invalid, return AST_TRANSFER_INVALID. The following are invalid:
+ /* First, check the validity of scenario. If invalid, return AST_BRIDGE_TRANSFER_INVALID. The following are invalid:
* 1) atxfer of an unbridged call to an unbridged call
* 2) atxfer of an unbridged call to a multi-party (n > 2) bridge
* 3) atxfer of a multi-party (n > 2) bridge to an unbridged call
- * Second, check that the bridge(s) involved allows transfers. If not, return AST_TRANSFER_NOT_PERMITTED.
+ * Second, check that the bridge(s) involved allows transfers. If not, return AST_BRIDGE_TRANSFER_NOT_PERMITTED.
* Third, break into different scenarios for different bridge situations:
* If both channels are bridged, perform a bridge merge. Direction of the merge is TBD.
* If channel A is bridged, and channel B is not (e.g. transferring to IVR or blond transfer)
@@ -4228,7 +4304,7 @@
*/
/* XXX STUB */
- return AST_TRANSFER_SUCCESS;
+ return AST_BRIDGE_TRANSFER_SUCCESS;
}
/*!
More information about the asterisk-commits
mailing list