[svn-commits] mmichelson: branch mmichelson/rls-notify r420362 - in /team/mmichelson/rls-no...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Aug 7 13:36:42 CDT 2014


Author: mmichelson
Date: Thu Aug  7 13:36:35 2014
New Revision: 420362

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=420362
Log:
Resolve conflict and reset automerge.


Added:
    team/mmichelson/rls-notify/include/asterisk/res_pjsip_outbound_publish.h
      - copied unchanged from r420359, team/group/rls/include/asterisk/res_pjsip_outbound_publish.h
    team/mmichelson/rls-notify/res/res_pjsip_outbound_publish.c
      - copied unchanged from r420359, team/group/rls/res/res_pjsip_outbound_publish.c
    team/mmichelson/rls-notify/res/res_pjsip_outbound_publish.exports.in
      - copied unchanged from r420359, team/group/rls/res/res_pjsip_outbound_publish.exports.in
    team/mmichelson/rls-notify/res/res_pjsip_publish_asterisk.c
      - copied unchanged from r420359, team/group/rls/res/res_pjsip_publish_asterisk.c
Modified:
    team/mmichelson/rls-notify/   (props changed)
    team/mmichelson/rls-notify/apps/app_queue.c
    team/mmichelson/rls-notify/include/asterisk/bridge_features.h
    team/mmichelson/rls-notify/include/asterisk/datastore.h
    team/mmichelson/rls-notify/include/asterisk/res_pjsip_pubsub.h
    team/mmichelson/rls-notify/include/asterisk/stasis_app.h
    team/mmichelson/rls-notify/include/asterisk/stasis_bridges.h
    team/mmichelson/rls-notify/main/bridge.c
    team/mmichelson/rls-notify/main/bridge_basic.c
    team/mmichelson/rls-notify/main/cel.c
    team/mmichelson/rls-notify/main/channel.c
    team/mmichelson/rls-notify/main/pbx.c
    team/mmichelson/rls-notify/main/stasis_bridges.c
    team/mmichelson/rls-notify/res/ari/ari_model_validators.c
    team/mmichelson/rls-notify/res/ari/ari_model_validators.h
    team/mmichelson/rls-notify/res/res_pjsip_pubsub.c
    team/mmichelson/rls-notify/res/res_pjsip_pubsub.exports.in
    team/mmichelson/rls-notify/res/res_stasis.c
    team/mmichelson/rls-notify/res/stasis/app.c
    team/mmichelson/rls-notify/res/stasis/app.h
    team/mmichelson/rls-notify/res/stasis/command.c
    team/mmichelson/rls-notify/res/stasis/command.h
    team/mmichelson/rls-notify/res/stasis/control.c
    team/mmichelson/rls-notify/res/stasis/control.h
    team/mmichelson/rls-notify/res/stasis/stasis_bridge.c
    team/mmichelson/rls-notify/rest-api/api-docs/events.json
    team/mmichelson/rls-notify/tests/test_cel.c

Propchange: team/mmichelson/rls-notify/
------------------------------------------------------------------------------
    automerge = *

Propchange: team/mmichelson/rls-notify/
------------------------------------------------------------------------------
Binary property 'branch-12-merged' - no diff available.

Propchange: team/mmichelson/rls-notify/
------------------------------------------------------------------------------
--- rls-notify-integrated (original)
+++ rls-notify-integrated Thu Aug  7 13:36:35 2014
@@ -1,1 +1,1 @@
-/team/group/rls:1-420331
+/team/group/rls:1-420361

Propchange: team/mmichelson/rls-notify/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Thu Aug  7 13:36:35 2014
@@ -1,1 +1,1 @@
-/trunk:1-420292
+/trunk:1-420358

Modified: team/mmichelson/rls-notify/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/apps/app_queue.c?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/apps/app_queue.c (original)
+++ team/mmichelson/rls-notify/apps/app_queue.c Thu Aug  7 13:36:35 2014
@@ -5551,6 +5551,7 @@
 		ast_str_set(&transfer_str, 0, "BRIDGE|%s", atxfer_msg->dest.bridge);
 		break;
 	case AST_ATTENDED_TRANSFER_DEST_APP:
+	case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
 		ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);
 		break;
 	case AST_ATTENDED_TRANSFER_DEST_LINK:
@@ -5619,10 +5620,7 @@
 		struct stasis_message *msg)
 {
 	struct queue_stasis_data *queue_data = userdata;
-	struct ast_bridge_blob *blind_blob = stasis_message_data(msg);
-	struct ast_json *result_blob;
-	struct ast_json *exten_blob;
-	struct ast_json *context_blob;
+	struct ast_blind_transfer_message *transfer_msg = stasis_message_data(msg);
 	const char *exten;
 	const char *context;
 	RAII_VAR(struct ast_channel_snapshot *, caller_snapshot, NULL, ao2_cleanup);
@@ -5632,19 +5630,14 @@
 		return;
 	}
 
-	result_blob = ast_json_object_get(blind_blob->blob, "result");
-	if (!result_blob) {
+	if (transfer_msg->result != AST_BRIDGE_TRANSFER_SUCCESS) {
 		return;
 	}
 
-	if (ast_json_integer_get(result_blob) != AST_BRIDGE_TRANSFER_SUCCESS) {
-		return;
-	}
-
 	ao2_lock(queue_data);
 
 	if (ast_strlen_zero(queue_data->bridge_uniqueid) ||
-			strcmp(queue_data->bridge_uniqueid, blind_blob->bridge->uniqueid)) {
+			strcmp(queue_data->bridge_uniqueid, transfer_msg->to_transferee.bridge_snapshot->uniqueid)) {
 		ao2_unlock(queue_data);
 		return;
 	}
@@ -5654,10 +5647,8 @@
 
 	ao2_unlock(queue_data);
 
-	exten_blob = ast_json_object_get(blind_blob->blob, "exten");
-	exten = exten_blob ? ast_json_string_get(exten_blob) : "<unknown>";
-	context_blob = ast_json_object_get(blind_blob->blob, "context");
-	context = context_blob ? ast_json_string_get(context_blob) : "<unknown>";
+	exten = transfer_msg->exten;
+	context = transfer_msg->context;
 
 	ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
 	ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,

Modified: team/mmichelson/rls-notify/include/asterisk/bridge_features.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/include/asterisk/bridge_features.h?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/include/asterisk/bridge_features.h (original)
+++ team/mmichelson/rls-notify/include/asterisk/bridge_features.h Thu Aug  7 13:36:35 2014
@@ -157,6 +157,25 @@
  */
 typedef int (*ast_bridge_talking_indicate_callback)(struct ast_bridge_channel *bridge_channel, void *hook_pvt, int talking);
 
+/*!
+ * \brief Move indicator callback
+ *
+ * \details
+ * This callback can be registered with the bridge channel in order
+ * to be notified when the bridge channel is being moved from one
+ * bridge to another.
+ *
+ * \param bridge_channel The channel executing the feature
+ * \param hook_pvt Private data passed in when the hook was created
+ * \param src The bridge from which the bridge channel is moving
+ * \param dst The bridge into which the bridge channel is moving
+ *
+ * \retval 0 Keep the callback hook.
+ * \retval -1 Remove the callback hook.
+ */
+typedef int (*ast_bridge_move_indicate_callback)(struct ast_bridge_channel *bridge_channel,
+		void *hook_pvt, struct ast_bridge *src, struct ast_bridge *dst);
+
 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),
@@ -173,6 +192,7 @@
 	AST_BRIDGE_HOOK_TYPE_JOIN,
 	AST_BRIDGE_HOOK_TYPE_LEAVE,
 	AST_BRIDGE_HOOK_TYPE_TALK,
+	AST_BRIDGE_HOOK_TYPE_MOVE,
 };
 
 /*! \brief Structure that is the essence of a feature hook. */
@@ -621,6 +641,37 @@
 	enum ast_bridge_hook_remove_flags remove_flags);
 
 /*!
+ * \brief Attach a bridge channel move detection hook to a bridge features structure
+ *
+ * \param features Bridge features structure
+ * \param callback Function to execute upon activation
+ * \param hook_pvt Unique data
+ * \param destructor Optional destructor callback for hook_pvt data
+ * \param remove_flags Dictates what situations the hook should be removed.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure (The caller must cleanup any hook_pvt resources.)
+ *
+ * Example usage:
+ *
+ * \code
+ * struct ast_bridge_features features;
+ * ast_bridge_features_init(&features);
+ * ast_bridge_move_hook(&features, move_callback, NULL, NULL, 0);
+ * \endcode
+ *
+ * This makes the bridging core call \ref callback when a
+ * channel is moved from one bridge to another.  A
+ * pointer to useful data may be provided to the hook_pvt
+ * parameter.
+ */
+int ast_bridge_move_hook(struct ast_bridge_features *features,
+	ast_bridge_move_indicate_callback callback,
+	void *hook_pvt,
+	ast_bridge_hook_pvt_destructor destructor,
+	enum ast_bridge_hook_remove_flags remove_flags);
+
+/*!
  * \brief Enable a built in feature on a bridge features structure
  *
  * \param features Bridge features structure

Modified: team/mmichelson/rls-notify/include/asterisk/datastore.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/include/asterisk/datastore.h?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/include/asterisk/datastore.h (original)
+++ team/mmichelson/rls-notify/include/asterisk/datastore.h Thu Aug  7 13:36:35 2014
@@ -34,7 +34,7 @@
 	void (*destroy)(void *data);		/*!< Destroy function */
 
 	/*!
-	 * \brief Fix up channel references
+	 * \brief Fix up channel references on the masquerading channel
 	 *
 	 * \arg data The datastore data
 	 * \arg old_chan The old channel owning the datastore
@@ -48,6 +48,20 @@
 	 * \return nothing.
 	 */
 	void (*chan_fixup)(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
+
+	/*!
+	 * \brief Fix up channel references on the channel being masqueraded into
+	 *
+	 * \arg data The datastore data
+	 * \arg old_chan The old channel owning the datastore
+	 * \arg new_chan The new channel owning the datastore
+	 *
+	 * This is the same as the above callback, except it is called for the channel
+	 * being masqueraded into instead of the channel that is masquerading.
+	 *
+	 * \return nothing.
+	 */
+	void (*chan_breakdown)(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
 };
 
 /*! \brief Structure for a data store object */

Modified: team/mmichelson/rls-notify/include/asterisk/res_pjsip_pubsub.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/include/asterisk/res_pjsip_pubsub.h?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/include/asterisk/res_pjsip_pubsub.h (original)
+++ team/mmichelson/rls-notify/include/asterisk/res_pjsip_pubsub.h Thu Aug  7 13:36:35 2014
@@ -58,9 +58,10 @@
 	 *
 	 * \param endpoint The endpoint from whom the PUBLISH arrived.
 	 * \param resource The resource whose state is being published.
+	 * \param event_configuration The name of the event type configuration to use for this resource.
 	 * \return Response code for the incoming PUBLISH
 	 */
-	int (*new_publication)(struct ast_sip_endpoint *endpoint, const char *resource);
+	int (*new_publication)(struct ast_sip_endpoint *endpoint, const char *resource, const char *event_configuration);
 	/*!
 	 * \brief Called when a publication has reached its expiration.
 	 */
@@ -97,6 +98,22 @@
  * \retval non-NULL The associated endpoint
  */
 struct ast_sip_endpoint *ast_sip_publication_get_endpoint(struct ast_sip_publication *pub);
+
+/*!
+ * \brief Given a publication, get the resource the publication is to
+ *
+ * \param pub The publication
+ * \return The resource
+ */
+const char *ast_sip_publication_get_resource(const struct ast_sip_publication *pub);
+
+/*!
+ * \brief Given a publication, get the configuration name for the event type in use
+ *
+ * \param pub The publication
+ * \return The configuration name
+ */
+const char *ast_sip_publication_get_event_configuration(const struct ast_sip_publication *pub);
 
 /*!
  * \brief Register a publish handler

Modified: team/mmichelson/rls-notify/include/asterisk/stasis_app.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/include/asterisk/stasis_app.h?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/include/asterisk/stasis_app.h (original)
+++ team/mmichelson/rls-notify/include/asterisk/stasis_app.h Thu Aug  7 13:36:35 2014
@@ -799,6 +799,28 @@
  */
 struct stasis_message_sanitizer *stasis_app_get_sanitizer(void);
 
+/*!
+ * \brief Stasis message type for a StasisEnd event
+ */
+struct stasis_message_type *ast_stasis_end_message_type(void);
+
+/*!
+ * \brief Indicate that this channel has had a StasisEnd published for it
+ *
+ * \param The channel that is exiting Stasis.
+ */
+void stasis_app_channel_set_stasis_end_published(struct ast_channel *chan);
+
+/*!
+ * \brief Has this channel had a StasisEnd published on it?
+ *
+ * \param chan The channel upon which the query rests.
+ *
+ * \retval 0 No
+ * \retval 1 Yes
+ */
+int stasis_app_channel_is_stasis_end_published(struct ast_channel *chan);
+
 /*! @} */
 
 #endif /* _ASTERISK_STASIS_APP_H */

Modified: team/mmichelson/rls-notify/include/asterisk/stasis_bridges.h
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/include/asterisk/stasis_bridges.h?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/include/asterisk/stasis_bridges.h (original)
+++ team/mmichelson/rls-notify/include/asterisk/stasis_bridges.h Thu Aug  7 13:36:35 2014
@@ -285,6 +285,24 @@
 struct stasis_message_type *ast_blind_transfer_type(void);
 
 /*!
+ * \brief Message published during a blind transfer
+ */
+struct ast_blind_transfer_message {
+	/*! Result of the transfer */
+	enum ast_transfer_result result;
+	/*! True if the transfer was initiated by an external source (i.e. not DTMF-initiated) */
+	int is_external;
+	/*! Transferer and its bridge */
+	struct ast_bridge_channel_snapshot_pair to_transferee;
+	/*! Destination context */
+	char context[AST_MAX_CONTEXT];
+	/*! Destination extension */
+	char exten[AST_MAX_EXTENSION];
+	/*! Transferee channel. NULL if there were multiple transferee channels */
+	struct ast_channel_snapshot *transferee;
+};
+
+/*!
  * \brief Publish a blind transfer event
  *
  * \pre Bridges involved are locked. Channels involved are not locked.
@@ -294,9 +312,11 @@
  * \param to_transferee The bridge between the transferer and transferee plus the transferer channel
  * \param context The destination context for the blind transfer
  * \param exten The destination extension for the blind transfer
+ * \param transferee_channel If a single channel is being transferred, this is it. If multiple parties are being transferred, this is NULL.
  */
 void ast_bridge_publish_blind_transfer(int is_external, enum ast_transfer_result result,
-		struct ast_bridge_channel_pair *to_transferee, const char *context, const char *exten);
+		struct ast_bridge_channel_pair *to_transferee, const char *context, const char *exten,
+		struct ast_channel *transferee_channel);
 
 enum ast_attended_transfer_dest_type {
 	/*! The transfer failed, so there is no appropriate final state */
@@ -305,6 +325,8 @@
 	AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE,
 	/*! The transfer results in a channel or bridge running an application */
 	AST_ATTENDED_TRANSFER_DEST_APP,
+	/*! The transfer results in a channel or bridge running an application via a local channel */
+	AST_ATTENDED_TRANSFER_DEST_LOCAL_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 */
@@ -323,6 +345,12 @@
 	struct ast_bridge_channel_snapshot_pair to_transferee;
 	/*! Bridge between transferer <-> transfer target and the transferer channel in that bridge. May be NULL */
 	struct ast_bridge_channel_snapshot_pair to_transfer_target;
+	/*! Local channel connecting transferee bridge to application */
+	struct ast_channel_snapshot *replace_channel;
+	/*! Transferee channel. Will be NULL if there were multiple channels transferred. */
+	struct ast_channel_snapshot *transferee;
+	/*! Transfer target channel. Will be NULL if there were multiple channels targeted. */
+	struct ast_channel_snapshot *target;
 	/*! Indicates the final state of the transfer */
 	enum ast_attended_transfer_dest_type dest_type;
 	union {
@@ -358,9 +386,12 @@
  * \param result The result of the transfer. Will always be a type of failure.
  * \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 transferee_channel If a single channel is being transferred, this is it. If multiple parties are being transferred, this is NULL.
+ * \param target_channel If a single channel is being transferred to, this is it. If multiple parties are being transferred to, this is NULL.
  */
 void ast_bridge_publish_attended_transfer_fail(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 *transferee, struct ast_bridge_channel_pair *target,
+		struct ast_channel *transferee_channel, struct ast_channel *target_channel);
 
 /*!
  * \since 12
@@ -382,10 +413,13 @@
  * \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_bridge The bridge that the parties end up in. Will be a bridge from the transferee or target pair.
+ * \param transferee_channel If a single channel is being transferred, this is it. If multiple parties are being transferred, this is NULL.
+ * \param target_channel If a single channel is being transferred to, this is it. If multiple parties are being transferred to, this is NULL.
  */
 void ast_bridge_publish_attended_transfer_bridge_merge(int is_external, enum ast_transfer_result result,
 		struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
-		struct ast_bridge *final_bridge);
+		struct ast_bridge *final_bridge, struct ast_channel *transferee_channel,
+		struct ast_channel *target_channel);
 
 /*!
  * \since 12
@@ -403,10 +437,13 @@
  * \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.
+ * \param transferee_channel If a single channel is being transferred, this is it. If multiple parties are being transferred, this is NULL.
+ * \param target_channel If a single channel is being transferred to, this is it. If multiple parties are being transferred to, this is NULL.
  */
 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);
+		struct ast_bridge_channel_pair *final_pair, struct ast_channel *transferee_channel,
+		struct ast_channel *target_channel);
 
 /*!
  * \since 12
@@ -423,13 +460,23 @@
  *
  * \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 dest_app The application that the channel or bridge is running upon transfer completion.
+ * \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 replace_channel The channel that will be replacing the transferee bridge
+ *        transferer channel when a local channel is involved
+ * \param dest_app The application that the channel or bridge is running upon transfer
+ *        completion.
+ * \param transferee_channel If a single channel is being transferred, this is it.
+ *        If multiple parties are being transferred, this is NULL.
+ * \param target_channel If a single channel is being transferred to, this is it.
+ *        If multiple parties are being transferred to, this is NULL.
  */
 void ast_bridge_publish_attended_transfer_app(int is_external, enum ast_transfer_result result,
 		struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
-		const char *dest_app);
+		struct ast_channel *replace_channel, const char *dest_app,
+		struct ast_channel *transferee_channel, struct ast_channel *target_channel);
 
 /*!
  * \since 12
@@ -451,10 +498,13 @@
  * \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 locals The local channels linking the bridges together.
+ * \param transferee_channel If a single channel is being transferred, this is it. If multiple parties are being transferred, this is NULL.
+ * \param target_channel If a single channel is being transferred to, this is it. If multiple parties are being transferred to, this is NULL.
  */
 void ast_bridge_publish_attended_transfer_link(int is_external, enum ast_transfer_result result,
 		struct ast_bridge_channel_pair *transferee, struct ast_bridge_channel_pair *target,
-		struct ast_channel *locals[2]);
+		struct ast_channel *locals[2], struct ast_channel *transferee_channel,
+		struct ast_channel *target_channel);
 
 /*!
  * \brief Returns the most recent snapshot for the bridge.

Modified: team/mmichelson/rls-notify/main/bridge.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/main/bridge.c?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/main/bridge.c (original)
+++ team/mmichelson/rls-notify/main/bridge.c Thu Aug  7 13:36:35 2014
@@ -1825,6 +1825,32 @@
 	ao2_ref(old_bridge, -1);
 }
 
+static void bridge_channel_moving(struct ast_bridge_channel *bridge_channel, struct ast_bridge *src, struct ast_bridge *dst)
+{
+	struct ast_bridge_features *features = bridge_channel->features;
+	struct ast_bridge_hook *hook;
+	struct ao2_iterator iter;
+
+	/* Run any moving hooks. */
+	iter = ao2_iterator_init(features->other_hooks, 0);
+	for (; (hook = ao2_iterator_next(&iter)); ao2_ref(hook, -1)) {
+		int remove_me;
+		ast_bridge_move_indicate_callback move_cb;
+
+		if (hook->type != AST_BRIDGE_HOOK_TYPE_MOVE) {
+			continue;
+		}
+		move_cb = (ast_bridge_move_indicate_callback) hook->callback;
+		remove_me = move_cb(bridge_channel, hook->hook_pvt, src, dst);
+		if (remove_me) {
+			ast_debug(1, "Move detection hook %p is being removed from %p(%s)\n",
+				hook, bridge_channel, ast_channel_name(bridge_channel->chan));
+			ao2_unlink(features->other_hooks, hook);
+		}
+	}
+	ao2_iterator_destroy(&iter);
+}
+
 void bridge_do_merge(struct ast_bridge *dst_bridge, struct ast_bridge *src_bridge, struct ast_bridge_channel **kick_me, unsigned int num_kick,
 	unsigned int optimized)
 {
@@ -1872,6 +1898,8 @@
 			 */
 			continue;
 		}
+
+		bridge_channel_moving(bridge_channel, bridge_channel->bridge, dst_bridge);
 
 		/* Point to new bridge.*/
 		bridge_channel_change_bridge(bridge_channel, dst_bridge);
@@ -2122,6 +2150,8 @@
 	ao2_ref(orig_bridge, +1);/* Keep a ref in case the push fails. */
 	bridge_channel_change_bridge(bridge_channel, dst_bridge);
 
+	bridge_channel_moving(bridge_channel, orig_bridge, dst_bridge);
+
 	if (bridge_channel_internal_push(bridge_channel)) {
 		/* Try to put the channel back into the original bridge. */
 		ast_bridge_features_remove(bridge_channel->features,
@@ -3089,6 +3119,18 @@
 		AST_BRIDGE_HOOK_TYPE_TALK);
 }
 
+int ast_bridge_move_hook(struct ast_bridge_features *features,
+	ast_bridge_move_indicate_callback callback,
+	void *hook_pvt,
+	ast_bridge_hook_pvt_destructor destructor,
+	enum ast_bridge_hook_remove_flags remove_flags)
+{
+	ast_bridge_hook_callback hook_cb = (ast_bridge_hook_callback) callback;
+
+	return bridge_other_hook(features, hook_cb, hook_pvt, destructor, remove_flags,
+		AST_BRIDGE_HOOK_TYPE_MOVE);
+}
+
 int ast_bridge_interval_hook(struct ast_bridge_features *features,
 	enum ast_bridge_hook_timer_option flags,
 	unsigned int interval,
@@ -3828,14 +3870,55 @@
 	struct ast_bridge_channel_pair to_transferee;
 	/* The bridge between the transferer and transfer target, and the transferer channel in this bridge */
 	struct ast_bridge_channel_pair to_transfer_target;
+	/* The Local;1 that will replace the transferee bridge transferer channel */
+	struct ast_channel *replace_channel;
+	/* The transferee channel. NULL if there is no transferee channel or if multiple parties are transferred */
+	struct ast_channel *transferee_channel;
+	/* The transfer target channel. NULL if there is no transfer target channel or if multiple parties are transferred */
+	struct ast_channel *target_channel;
 };
+
+/*!
+ * \internal
+ * \brief Get the transferee channel
+ *
+ * This is only applicable to cases where a transfer is occurring on a
+ * two-party bridge. The channels container passed in is expected to only
+ * contain two channels, the transferer and the transferee. The transferer
+ * channel is passed in as a parameter to ensure we don't return it as
+ * the transferee channel.
+ *
+ * \param channels A two-channel container containing the transferer and transferee
+ * \param transferer The party that is transfering the call
+ * \return The party that is being transferred
+ */
+static struct ast_channel *get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
+{
+	struct ao2_iterator channel_iter;
+	struct ast_channel *transferee;
+
+	for (channel_iter = ao2_iterator_init(channels, 0);
+			(transferee = ao2_iterator_next(&channel_iter));
+			ao2_cleanup(transferee)) {
+		if (transferee != transferer) {
+			break;
+		}
+	}
+
+	ao2_iterator_destroy(&channel_iter);
+	return transferee;
+}
+
 
 static void stasis_publish_data_cleanup(struct stasis_attended_transfer_publish_data *publication)
 {
 	ast_channel_unref(publication->to_transferee.channel);
 	ast_channel_unref(publication->to_transfer_target.channel);
+	ast_channel_cleanup(publication->transferee_channel);
+	ast_channel_cleanup(publication->target_channel);
 	ao2_cleanup(publication->to_transferee.bridge);
 	ao2_cleanup(publication->to_transfer_target.bridge);
+	ao2_cleanup(publication->replace_channel);
 }
 
 /*!
@@ -3865,6 +3948,9 @@
 		ao2_ref(to_target_bridge, +1);
 		publication->to_transfer_target.bridge = to_target_bridge;
 	}
+
+	publication->transferee_channel = ast_bridge_peer(to_transferee_bridge, to_transferee);
+	publication->target_channel = ast_bridge_peer(to_target_bridge, to_transfer_target);
 }
 
 /*
@@ -3878,7 +3964,8 @@
 		struct ast_bridge *final_bridge)
 {
 	ast_bridge_publish_attended_transfer_bridge_merge(1, AST_BRIDGE_TRANSFER_SUCCESS,
-			&publication->to_transferee, &publication->to_transfer_target, final_bridge);
+			&publication->to_transferee, &publication->to_transfer_target, final_bridge,
+			publication->transferee_channel, publication->target_channel);
 }
 
 /*
@@ -3892,7 +3979,9 @@
 		const char *app)
 {
 	ast_bridge_publish_attended_transfer_app(1, AST_BRIDGE_TRANSFER_SUCCESS,
-			&publication->to_transferee, &publication->to_transfer_target, app);
+			&publication->to_transferee, &publication->to_transfer_target,
+			publication->replace_channel, app,
+			publication->transferee_channel, publication->target_channel);
 }
 
 /*
@@ -3909,7 +3998,8 @@
 	struct ast_channel *locals[2] = { local_channel1, local_channel2 };
 
 	ast_bridge_publish_attended_transfer_link(1, AST_BRIDGE_TRANSFER_SUCCESS,
-			&publication->to_transferee, &publication->to_transfer_target, locals);
+			&publication->to_transferee, &publication->to_transfer_target, locals,
+			publication->transferee_channel, publication->target_channel);
 }
 
 /*
@@ -3923,7 +4013,8 @@
 		enum ast_transfer_result result)
 {
 	ast_bridge_publish_attended_transfer_fail(1, result, &publication->to_transferee,
-			&publication->to_transfer_target);
+			&publication->to_transfer_target, publication->transferee_channel,
+			publication->target_channel);
 }
 
 /*!
@@ -3987,9 +4078,12 @@
 		return AST_BRIDGE_TRANSFER_FAIL;
 	}
 
+	/* Get a ref for use later since this one is being stolen */
+	ao2_ref(local_chan, +1);
 	if (ast_bridge_impart(bridge1, local_chan, chan1, NULL,
 		AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
 		ast_hangup(local_chan);
+		ao2_cleanup(local_chan);
 		return AST_BRIDGE_TRANSFER_FAIL;
 	}
 
@@ -4005,40 +4099,12 @@
 		publish_attended_transfer_link(publication,
 				local_chan, local_chan2);
 	} else {
+		publication->replace_channel = ao2_bump(local_chan);
 		publish_attended_transfer_app(publication, app);
 	}
+
+	ao2_cleanup(local_chan);
 	return AST_BRIDGE_TRANSFER_SUCCESS;
-}
-
-/*!
- * \internal
- * \brief Get the transferee channel
- *
- * This is only applicable to cases where a transfer is occurring on a
- * two-party bridge. The channels container passed in is expected to only
- * contain two channels, the transferer and the transferee. The transferer
- * channel is passed in as a parameter to ensure we don't return it as
- * the transferee channel.
- *
- * \param channels A two-channel container containing the transferer and transferee
- * \param transferer The party that is transfering the call
- * \return The party that is being transferred
- */
-static struct ast_channel *get_transferee(struct ao2_container *channels, struct ast_channel *transferer)
-{
-	struct ao2_iterator channel_iter;
-	struct ast_channel *transferee;
-
-	for (channel_iter = ao2_iterator_init(channels, 0);
-			(transferee = ao2_iterator_next(&channel_iter));
-			ao2_cleanup(transferee)) {
-		if (transferee != transferer) {
-			break;
-		}
-	}
-
-	ao2_iterator_destroy(&channel_iter);
-	return transferee;
 }
 
 static enum ast_transfer_result try_parking(struct ast_channel *transferer,
@@ -4142,7 +4208,7 @@
 
 static void publish_blind_transfer(int is_external, enum ast_transfer_result result,
 		struct ast_channel *transferer, struct ast_bridge *bridge,
-		const char *context, const char *exten)
+		const char *context, const char *exten, struct ast_channel *transferee_channel)
 {
 	struct ast_bridge_channel_pair pair;
 	pair.channel = transferer;
@@ -4150,7 +4216,7 @@
 	if (bridge) {
 		ast_bridge_lock(bridge);
 	}
-	ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten);
+	ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten, transferee_channel);
 	if (bridge) {
 		ast_bridge_unlock(bridge);
 	}
@@ -4174,6 +4240,9 @@
 		transfer_result = AST_BRIDGE_TRANSFER_INVALID;
 		goto publish;
 	}
+
+	transferee = ast_bridge_peer(bridge, transferer);
+
 	ast_channel_lock(transferer);
 	bridge_channel = ast_channel_get_bridge_channel(transferer);
 	ast_channel_unlock(transferer);
@@ -4235,7 +4304,6 @@
 
 	/* Reaching this portion means that we're dealing with a two-party bridge */
 
-	transferee = get_transferee(channels, transferer);
 	if (!transferee) {
 		transfer_result = AST_BRIDGE_TRANSFER_FAIL;
 		goto publish;
@@ -4251,7 +4319,7 @@
 	transfer_result = AST_BRIDGE_TRANSFER_SUCCESS;
 
 publish:
-	publish_blind_transfer(is_external, transfer_result, transferer, bridge, context, exten);
+	publish_blind_transfer(is_external, transfer_result, transferer, bridge, context, exten, transferee);
 	return transfer_result;
 }
 

Modified: team/mmichelson/rls-notify/main/bridge_basic.c
URL: http://svnview.digium.com/svn/asterisk/team/mmichelson/rls-notify/main/bridge_basic.c?view=diff&rev=420362&r1=420361&r2=420362
==============================================================================
--- team/mmichelson/rls-notify/main/bridge_basic.c (original)
+++ team/mmichelson/rls-notify/main/bridge_basic.c Thu Aug  7 13:36:35 2014
@@ -1526,9 +1526,85 @@
 }
 
 /*!
+ * \brief Get a desired transfer party for a bridge the transferer is not in.
+ *
+ * \param bridge The bridge to get the party from. May be NULL.
+ * \param[out] party The lone channel in the bridge. Will be set NULL if bridge is NULL or multiple parties are present.
+ */
+static void get_transfer_party_non_transferer_bridge(struct ast_bridge *bridge,
+		struct ast_channel **party)
+{
+	if (bridge && bridge->num_channels == 1) {
+		*party = ast_channel_ref(AST_LIST_FIRST(&bridge->channels)->chan);
+	} else {
+		*party = NULL;
+	}
+}
+
+/*!
+ * \brief Get the transferee and transfer target when the transferer is in a bridge with
+ * one of the desired parties.
+ *
+ * \param transferer_bridge The bridge the transferer is in
+ * \param other_bridge The bridge the transferer is not in. May be NULL.
+ * \param transferer The transferer party
+ * \param[out] transferer_peer The party that is in the bridge with the transferer
+ * \param[out] other_party The party that is in the other_bridge
+ */
+static void get_transfer_parties_transferer_bridge(struct ast_bridge *transferer_bridge,
+		struct ast_bridge *other_bridge, struct ast_channel *transferer,
+		struct ast_channel **transferer_peer, struct ast_channel **other_party)
+{
+	*transferer_peer = ast_bridge_peer(transferer_bridge, transferer);
+	get_transfer_party_non_transferer_bridge(other_bridge, other_party);
+}
+
+/*!
+ * \brief determine transferee and transfer target for an attended transfer
+ *
+ * In builtin attended transfers, there is a single transferer channel that jumps between
+ * the two bridges involved. At the time the attended transfer occurs, the transferer could
+ * be in either bridge, so determining the parties is a bit more complex than normal.
+ *
+ * The method used here is to determine which of the two bridges the transferer is in, and
+ * grabbing the peer from that bridge. The other bridge, if it only has a single channel in it,
+ * has the other desired channel.
+ *
+ * \param transferer The channel performing the transfer
+ * \param transferee_bridge The bridge that the transferee is in
+ * \param target_bridge The bridge that the transfer target is in
+ * \param[out] transferee The transferee channel
+ * \param[out] transfer_target The transfer target channel
+ */
+static void get_transfer_parties(struct ast_channel *transferer, struct ast_bridge *transferee_bridge,
+		struct ast_bridge *target_bridge, struct ast_channel **transferee,
+		struct ast_channel **transfer_target)
+{
+	struct ast_bridge *transferer_bridge;
+
+	ast_channel_lock(transferer);
+	transferer_bridge = ast_channel_get_bridge(transferer);
+	ast_channel_unlock(transferer);
+
+	if (transferer_bridge == transferee_bridge) {
+		get_transfer_parties_transferer_bridge(transferee_bridge, target_bridge,
+				transferer, transferee, transfer_target);
+	} else if (transferer_bridge == target_bridge) {
+		get_transfer_parties_transferer_bridge(target_bridge, transferee_bridge,
+				transferer, transfer_target, transferee);
+	} else {
+		get_transfer_party_non_transferer_bridge(transferee_bridge, transferee);
+		get_transfer_party_non_transferer_bridge(target_bridge, transfer_target);
+	}
+
+	ao2_cleanup(transferer_bridge);
+}
+
+/*!
  * \brief Send a stasis publication for a successful attended transfer
  */
-static void publish_transfer_success(struct attended_transfer_properties *props)
+static void publish_transfer_success(struct attended_transfer_properties *props,
+		struct ast_channel *transferee_channel, struct ast_channel *target_channel)
 {
 	struct ast_bridge_channel_pair transferee = {
 		.channel = props->transferer,
@@ -1548,7 +1624,8 @@
 	}
 
 	ast_bridge_publish_attended_transfer_bridge_merge(0, AST_BRIDGE_TRANSFER_SUCCESS,
-			&transferee, &transfer_target, props->transferee_bridge);
+			&transferee, &transfer_target, props->transferee_bridge, transferee_channel,
+			target_channel);
 
 	if (transferee.bridge) {
 		ast_bridge_unlock(transferee.bridge);
@@ -1561,7 +1638,8 @@
 /*!
  * \brief Send a stasis publication for an attended transfer that ends in a threeway call
  */
-static void publish_transfer_threeway(struct attended_transfer_properties *props)
+static void publish_transfer_threeway(struct attended_transfer_properties *props,
+		struct ast_channel *transferee_channel, struct ast_channel *target_channel)
 {
 	struct ast_bridge_channel_pair transferee = {
 		.channel = props->transferer,
@@ -1585,7 +1663,8 @@
 	}
 
 	ast_bridge_publish_attended_transfer_threeway(0, AST_BRIDGE_TRANSFER_SUCCESS,
-			&transferee, &transfer_target, &threeway);
+			&transferee, &transfer_target, &threeway, transferee_channel,
+			target_channel);
 
 	if (transferee.bridge) {
 		ast_bridge_unlock(transferee.bridge);
@@ -1608,6 +1687,8 @@
 		.channel = props->transferer,
 		.bridge = props->target_bridge,
 	};
+	struct ast_channel *transferee_channel;
+	struct ast_channel *target_channel;
 
 	if (transferee.bridge && transfer_target.bridge) {
 		ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
@@ -1617,8 +1698,12 @@
 		ast_bridge_lock(transfer_target.bridge);
 	}
 
+	get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
+			&transferee_channel, &target_channel);
 	ast_bridge_publish_attended_transfer_fail(0, AST_BRIDGE_TRANSFER_FAIL,
-			&transferee, &transfer_target);
+			&transferee, &transfer_target, transferee_channel, target_channel);
+	ast_channel_cleanup(transferee_channel);
+	ast_channel_cleanup(target_channel);
 
 	if (transferee.bridge) {
 		ast_bridge_unlock(transferee.bridge);
@@ -2072,11 +2157,18 @@
 
 static int threeway_enter(struct attended_transfer_properties *props)
 {
+	struct ast_channel *transferee_channel;
+	struct ast_channel *target_channel;
+
+	get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
+			&transferee_channel, &target_channel);
 	bridge_merge(props->transferee_bridge, props->target_bridge, NULL, 0);
 	play_sound(props->transfer_target, props->xfersound);
 	play_sound(props->transferer, props->xfersound);
-	publish_transfer_threeway(props);
-
+	publish_transfer_threeway(props, transferee_channel, target_channel);
+
+	ast_channel_cleanup(transferee_channel);
+	ast_channel_cleanup(target_channel);
 	return 0;
 }
 
@@ -2178,17 +2270,33 @@
 
 static int complete_enter(struct attended_transfer_properties *props)
 {
+	struct ast_channel *transferee_channel;
+	struct ast_channel *target_channel;
+
+	get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
+			&transferee_channel, &target_channel);
 	bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
 	play_sound(props->transfer_target, props->xfersound);
-	publish_transfer_success(props);
+	publish_transfer_success(props, transferee_channel, target_channel);
+
+	ast_channel_cleanup(transferee_channel);
+	ast_channel_cleanup(target_channel);
 	return 0;
 }
 
 static int blond_enter(struct attended_transfer_properties *props)
 {
+	struct ast_channel *transferee_channel;
+	struct ast_channel *target_channel;
+
+	get_transfer_parties(props->transferer, props->transferee_bridge, props->target_bridge,
+			&transferee_channel, &target_channel);
 	bridge_merge(props->transferee_bridge, props->target_bridge, &props->transferer, 1);
 	ringing(props->transfer_target);
-	publish_transfer_success(props);
+	publish_transfer_success(props, transferee_channel, target_channel);
+

[... 2365 lines stripped ...]



More information about the svn-commits mailing list