[svn-commits] mjordan: trunk r393801 - in /trunk: ./ include/asterisk/ main/

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Jul 8 09:26:45 CDT 2013


Author: mjordan
Date: Mon Jul  8 09:26:40 2013
New Revision: 393801

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393801
Log:
Create Local channel messages on the Stasis message bus and produce AMI events

This patch does the following:

* It adds a virtual table of callbacks to core_unreal. These callbacks can be
  supplied by concrete implementations of "unreal" channel drivers, which lets
  the unreal channel driver call specific functionality when it performs some
  action. Currently, this is done to notify implementations when an
  optimization operation has begun, and when an optimization operation has
  succeeded.

* It adds Stasis-Core messages for Local channel bridging and Local channel
  optimization. Local channel optimization is now two events: a Begin and an
  End. Some consumers of Stasis-Core may want to know when an operation is
  beginning so that they can 'prepare' their information; others will be more
  concerned about when the operation has completed, so that they can 'fix up'
  information. Stasis-Core allows for both, as does AMI.

Review: https://reviewboard.asterisk.org/r/2552


Modified:
    trunk/CHANGES
    trunk/include/asterisk/bridging.h
    trunk/include/asterisk/core_local.h
    trunk/include/asterisk/core_unreal.h
    trunk/main/bridging.c
    trunk/main/core_local.c
    trunk/main/core_unreal.c

Modified: trunk/CHANGES
URL: http://svnview.digium.com/svn/asterisk/trunk/CHANGES?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/CHANGES (original)
+++ trunk/CHANGES Mon Jul  8 09:26:40 2013
@@ -269,6 +269,17 @@
  * "ChannelUpdate" events have been removed.
 
  * AMI events now contain a SystemName field, if available.
+
+ * Local channel optimization is now conveyed in two events:
+   LocalOptimizationBegin and LocalOptimizationEnd. The Begin event is sent
+   when the Local channel driver begins attempting to optimize itself out of
+   the media path; the End event is sent after the channel halves have
+   successfully optimized themselves out of the media path.
+
+ * Local channel information in events is now prefixed with "LocalOne" and
+   "LocalTwo". This replaces the suffix of "1" and "2" for the two halves of
+   the Local channel. This affects the LocalBridge, LocalOptimizationBegin,
+   and LocalOptimizationEnd events.
 
 AGI (Asterisk Gateway Interface)
 ------------------

Modified: trunk/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/bridging.h?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/include/asterisk/bridging.h (original)
+++ trunk/include/asterisk/bridging.h Mon Jul  8 09:26:40 2013
@@ -870,19 +870,23 @@
  */
 int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan);
 
+struct ast_unreal_pvt;
+
 /*!
  * \brief Check and optimize out the unreal channels between bridges.
  * \since 12.0.0
  *
  * \param chan Unreal channel writing a frame into the channel driver.
  * \param peer Other unreal channel in the pair.
+ * \param pvt Private data provided by an implementation of the unreal driver that
+ * contains the callbacks that should be called when optimization begins/ends
  *
  * \note It is assumed that chan is already locked.
  *
  * \retval 0 if unreal channels were not optimized out.
  * \retval non-zero if unreal channels were optimized out.
  */
-int ast_bridge_unreal_optimized_out(struct ast_channel *chan, struct ast_channel *peer);
+int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt);
 
 /*!
  * \brief Tells, if optimization is allowed, how the optimization would be performed

Modified: trunk/include/asterisk/core_local.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/core_local.h?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/include/asterisk/core_local.h (original)
+++ trunk/include/asterisk/core_local.h Mon Jul  8 09:26:40 2013
@@ -37,6 +37,7 @@
 struct ast_channel;
 struct ast_bridge;
 struct ast_bridge_features;
+struct stasis_message_type;
 
 /* ------------------------------------------------------------------- */
 
@@ -91,6 +92,44 @@
 
 /* ------------------------------------------------------------------- */
 
+/*!
+ * \brief Message type for when two local channel halves are bridged together
+ * \since 12.0.0
+ *
+ * \note Payloads for the \ref ast_local_bridge_type are a \ref ast_multi_channel_blob.
+ * Roles for the channels in the \ref ast_multi_channel_blob are "1" and "2", reflecting
+ * the two halves. Unlike most other bridges, the 'bridge' between two local channels is
+ * not part of the bridge framework; as such, the message simply references the two local
+ * channel halves that are now bridged.
+ *
+ * \retval A \ref stasis message type
+ */
+struct stasis_message_type *ast_local_bridge_type(void);
+
+/*!
+ * \brief Message type for when a local channel optimization begins
+ * \since 12.0.0
+ *
+ * \note Payloads for the \ref ast_local_optimization_begin_type are a
+ * \ref ast_multi_channel_blob. Roles for the channels in the \ref ast_multi_channel_blob
+ * are "1" and "2", reflecting the two halves.
+ *
+ * \retval A \ref stasis message type
+ */
+struct stasis_message_type *ast_local_optimization_begin_type(void);
+
+/*!
+ * \brief Message type for when a local channel optimization completes
+ * \since 12.0.0
+ *
+ * \note Payloads for the \ref ast_local_optimization_end_type are a
+ * \ref ast_multi_channel_blob. Roles for the channels in the \ref ast_multi_channel_blob
+ * are "1" and "2", reflecting the two halves.
+ *
+ * \retval A \ref stasis message type
+ */
+struct stasis_message_type *ast_local_optimization_end_type(void);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif

Modified: trunk/include/asterisk/core_unreal.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/core_unreal.h?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/include/asterisk/core_unreal.h (original)
+++ trunk/include/asterisk/core_unreal.h Mon Jul  8 09:26:40 2013
@@ -43,6 +43,30 @@
 
 /* ------------------------------------------------------------------- */
 
+struct ast_unreal_pvt;
+
+/*!
+ * \brief Callbacks that can be provided by concrete implementations of the unreal
+ * channel driver that will be called when events occur in the unreal layer
+ */
+struct ast_unreal_pvt_callbacks {
+	/*!
+	 * \brief Called when an optimization attempt has started
+	 * \note p is locked when this callback is called
+	 * \param p The \ref ast_unreal_pvt object
+	 */
+	void (* const optimization_started)(struct ast_unreal_pvt *p);
+
+	/*!
+	 * \brief Called when an optimization attempt completed successfully
+	 * \note p is locked when this callback is called
+	 * \param p The \ref ast_unreal_pvt object
+	 * \param success Non-zero if the optimization succeeded, zero if the optimization
+	 * met with fatal and permanent error
+	 */
+	void (* const optimization_finished)(struct ast_unreal_pvt *p);
+};
+
 /*!
  * \brief The base pvt structure for local channel derivatives.
  *
@@ -51,11 +75,12 @@
  * ast_chan owner -> ast_unreal_pvt -> ast_chan chan
  */
 struct ast_unreal_pvt {
-	struct ast_channel *owner;      /*!< Master Channel - ;1 side */
-	struct ast_channel *chan;       /*!< Outbound channel - ;2 side */
-	struct ast_format_cap *reqcap;  /*!< Requested format capabilities */
-	struct ast_jb_conf jb_conf;     /*!< jitterbuffer configuration */
-	unsigned int flags;             /*!< Private option flags */
+	struct ast_unreal_pvt_callbacks *callbacks; /*!< Event callbacks */
+	struct ast_channel *owner;                  /*!< Master Channel - ;1 side */
+	struct ast_channel *chan;                   /*!< Outbound channel - ;2 side */
+	struct ast_format_cap *reqcap;              /*!< Requested format capabilities */
+	struct ast_jb_conf jb_conf;                 /*!< jitterbuffer configuration */
+	unsigned int flags;                         /*!< Private option flags */
 	/*! Base name of the unreal channels.  exten at context or other name. */
 	char name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
 };
@@ -65,6 +90,7 @@
 #define AST_UNREAL_CARETAKER_THREAD (1 << 0) /*!< The ;2 side launched a PBX, was pushed into a bridge, or was masqueraded into an application. */
 #define AST_UNREAL_NO_OPTIMIZATION  (1 << 1) /*!< Do not optimize out the unreal channels */
 #define AST_UNREAL_MOH_INTERCEPT    (1 << 2) /*!< Intercept and act on hold/unhold control frames */
+#define AST_UNREAL_OPTIMIZE_BEGUN   (1 << 3) /*!< Indicates that an optimization attempt has been started */
 
 /*!
  * \brief Send an unreal pvt in with no locks held and get all locks

Modified: trunk/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/bridging.c?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/main/bridging.c (original)
+++ trunk/main/bridging.c Mon Jul  8 09:26:40 2013
@@ -61,6 +61,7 @@
 #include "asterisk/cli.h"
 #include "asterisk/parking.h"
 #include "asterisk/core_local.h"
+#include "asterisk/core_unreal.h"
 #include "asterisk/features_config.h"
 
 /*! All bridges container. */
@@ -628,6 +629,12 @@
 	ast_debug(1, "Bridge %s: pulling %p(%s)\n",
 		bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan));
 
+	ast_verb(3, "Channel %s left '%s' %s-bridge <%s>\n",
+		ast_channel_name(bridge_channel->chan),
+		bridge->technology->name,
+		bridge->v_table->name,
+		bridge->uniqueid);
+
 /* BUGBUG This is where incoming HOLD/UNHOLD memory should write UNHOLD into bridge. (if not local optimizing) */
 /* BUGBUG This is where incoming DTMF begin/end memory should write DTMF end into bridge. (if not local optimizing) */
 	if (!bridge_channel->just_joined) {
@@ -713,6 +720,16 @@
 	if (!bridge_channel->suspended) {
 		++bridge->num_active;
 	}
+
+	ast_verb(3, "Channel %s %s%s%s '%s' %s-bridge <%s>\n",
+		ast_channel_name(bridge_channel->chan),
+		swap ? "swapped with " : "joined",
+		swap ? ast_channel_name(swap->chan) : "",
+		swap ? " into" : "",
+		bridge->technology->name,
+		bridge->v_table->name,
+		bridge->uniqueid);
+
 	ast_bridge_publish_enter(bridge, bridge_channel->chan);
 	if (swap) {
 		ast_bridge_change_state(swap, AST_BRIDGE_CHANNEL_STATE_HANGUP);
@@ -1895,7 +1912,7 @@
 	 * must not release the bridge lock until we have installed the
 	 * new bridge technology.
 	 */
-	ast_debug(1, "Bridge %s: switching %s technology to %s\n",
+	ast_verb(4, "Bridge %s: switching from %s technology to %s\n",
 		bridge->uniqueid, old_technology->name, new_technology->name);
 
 	/*
@@ -4644,14 +4661,17 @@
  * \param chan_bridge_channel
  * \param peer_bridge
  * \param peer_bridge_channel
+ * \param pvt Unreal data containing callbacks to call if the optimization actually
+ * happens
  *
  * \retval 1 if unreal channels failed to optimize out.
  * \retval 0 if unreal channels were not optimized out.
  * \retval -1 if unreal channels were optimized out.
  */
-static int check_swap_optimize_out(struct ast_bridge *chan_bridge,
+static int try_swap_optimize_out(struct ast_bridge *chan_bridge,
 	struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
-	struct ast_bridge_channel *peer_bridge_channel)
+	struct ast_bridge_channel *peer_bridge_channel,
+	struct ast_unreal_pvt *pvt)
 {
 	struct ast_bridge *dst_bridge;
 	struct ast_bridge_channel *dst_bridge_channel;
@@ -4696,10 +4716,18 @@
 			ast_channel_name(dst_bridge_channel->chan),
 			ast_channel_name(other->chan));
 
+		if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
+				&& pvt->callbacks->optimization_started) {
+			pvt->callbacks->optimization_started(pvt);
+			ast_set_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN);
+		}
 		other->swap = dst_bridge_channel->chan;
 		if (!bridge_move_do(dst_bridge, other, 1)) {
 			ast_bridge_change_state(src_bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
 			res = -1;
+			if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
+				pvt->callbacks->optimization_finished(pvt);
+			}
 		}
 	}
 	return res;
@@ -4761,13 +4789,16 @@
  * \param chan_bridge_channel
  * \param peer_bridge
  * \param peer_bridge_channel
+ * \param pvt Unreal data containing callbacks to call if the optimization actually
+ * happens
  *
  * \retval 0 if unreal channels were not optimized out.
  * \retval -1 if unreal channels were optimized out.
  */
-static int check_merge_optimize_out(struct ast_bridge *chan_bridge,
+static int try_merge_optimize_out(struct ast_bridge *chan_bridge,
 	struct ast_bridge_channel *chan_bridge_channel, struct ast_bridge *peer_bridge,
-	struct ast_bridge_channel *peer_bridge_channel)
+	struct ast_bridge_channel *peer_bridge_channel,
+	struct ast_unreal_pvt *pvt)
 {
 	struct merge_direction merge;
 	struct ast_bridge_channel *kick_me[] = {
@@ -4798,12 +4829,20 @@
 		ast_channel_name(chan_bridge_channel->chan),
 		ast_channel_name(peer_bridge_channel->chan));
 
+	if (pvt && !ast_test_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN) && pvt->callbacks
+			&& pvt->callbacks->optimization_started) {
+		pvt->callbacks->optimization_started(pvt);
+		ast_set_flag(pvt, AST_UNREAL_OPTIMIZE_BEGUN);
+	}
 	bridge_merge_do(merge.dest, merge.src, kick_me, ARRAY_LEN(kick_me));
+	if (pvt && pvt->callbacks && pvt->callbacks->optimization_finished) {
+		pvt->callbacks->optimization_finished(pvt);
+	}
 
 	return -1;
 }
 
-int ast_bridge_unreal_optimized_out(struct ast_channel *chan, struct ast_channel *peer)
+int ast_bridge_unreal_optimize_out(struct ast_channel *chan, struct ast_channel *peer, struct ast_unreal_pvt *pvt)
 {
 	struct ast_bridge *chan_bridge;
 	struct ast_bridge *peer_bridge;
@@ -4821,11 +4860,11 @@
 	if (peer_bridge) {
 		peer_bridge_channel = ast_channel_internal_bridge_channel(peer);
 
-		res = check_swap_optimize_out(chan_bridge, chan_bridge_channel,
-			peer_bridge, peer_bridge_channel);
+		res = try_swap_optimize_out(chan_bridge, chan_bridge_channel,
+			peer_bridge, peer_bridge_channel, pvt);
 		if (!res) {
-			res = check_merge_optimize_out(chan_bridge, chan_bridge_channel,
-				peer_bridge, peer_bridge_channel);
+			res = try_merge_optimize_out(chan_bridge, chan_bridge_channel,
+				peer_bridge, peer_bridge_channel, pvt);
 		} else if (0 < res) {
 			res = 0;
 		}

Modified: trunk/main/core_local.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/core_local.c?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/main/core_local.c (original)
+++ trunk/main/core_local.c Mon Jul  8 09:26:40 2013
@@ -46,6 +46,8 @@
 #include "asterisk/bridging.h"
 #include "asterisk/core_unreal.h"
 #include "asterisk/core_local.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_channels.h"
 #include "asterisk/_private.h"
 #include "asterisk/stasis_channels.h"
 
@@ -161,6 +163,34 @@
 			</syntax>
 		</managerEventInstance>
 	</managerEvent>
+	<managerEvent language="en_US" name="LocalOptimizationBegin">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when two halves of a Local Channel begin to optimize
+			themselves out of the media path.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='LocalBridge']/managerEventInstance/syntax/parameter[contains(@name, 'LocalOne')])" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='LocalBridge']/managerEventInstance/syntax/parameter[contains(@name, 'LocalTwo')])" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">LocalOptimizationEnd</ref>
+				<ref type="manager">LocalOptimizeAway</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="LocalOptimizationEnd">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when two halves of a Local Channel have finished optimizing
+			themselves out of the media path.</synopsis>
+			<syntax>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='LocalBridge']/managerEventInstance/syntax/parameter[contains(@name, 'LocalOne')])" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='LocalBridge']/managerEventInstance/syntax/parameter[contains(@name, 'LocalTwo')])" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">LocalOptimizationBegin</ref>
+				<ref type="manager">LocalOptimizeAway</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
  ***/
 
 static const char tdesc[] = "Local Proxy Channel Driver";
@@ -171,6 +201,30 @@
 static int local_call(struct ast_channel *ast, const char *dest, int timeout);
 static int local_hangup(struct ast_channel *ast);
 static int local_devicestate(const char *data);
+static void local_optimization_started_cb(struct ast_unreal_pvt *base);
+static void local_optimization_finished_cb(struct ast_unreal_pvt *base);
+
+static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *msg);
+
+/*!
+ * @{ \brief Define local channel message types.
+ */
+STASIS_MESSAGE_TYPE_DEFN(ast_local_bridge_type,
+	.to_ami = local_message_to_ami,
+	);
+STASIS_MESSAGE_TYPE_DEFN(ast_local_optimization_begin_type,
+	.to_ami = local_message_to_ami,
+	);
+STASIS_MESSAGE_TYPE_DEFN(ast_local_optimization_end_type,
+	.to_ami = local_message_to_ami,
+	);
+/*! @} */
+
+/*! \brief Callbacks from the unreal core when channel optimization occurs */
+struct ast_unreal_pvt_callbacks local_unreal_callbacks = {
+	.optimization_started = local_optimization_started_cb,
+	.optimization_finished = local_optimization_finished_cb,
+};
 
 /* PBX interface structure for channel registration */
 static struct ast_channel_tech local_tech = {
@@ -326,59 +380,115 @@
 	return res;
 }
 
-static struct ast_manager_event_blob *local_bridge_to_ami(struct stasis_message *msg)
-{
-	RAII_VAR(struct ast_str *, channel_one_string, NULL, ast_free);
-	RAII_VAR(struct ast_str *, channel_two_string, NULL, ast_free);
-	struct ast_multi_channel_blob *obj = stasis_message_data(msg);
-	struct ast_json *blob, *context, *exten, *optimize;
-	struct ast_channel_snapshot *chan_one, *chan_two;
-
-	chan_one = ast_multi_channel_blob_get_channel(obj, "1");
-	chan_two = ast_multi_channel_blob_get_channel(obj, "2");
-	blob = ast_multi_channel_blob_get_json(obj);
-
-	channel_one_string = ast_manager_build_channel_state_string_prefix(chan_one, "LocalOne");
-	if (!channel_one_string) {
+static void publish_local_optimization(struct local_pvt *p, int complete)
+{
+	RAII_VAR(struct ast_multi_channel_blob *, payload, NULL, ao2_cleanup);
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, blob, ast_json_null(), ast_json_unref);
+	RAII_VAR(struct ast_channel_snapshot *, local_one_snapshot, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_channel_snapshot *, local_two_snapshot, NULL, ao2_cleanup);
+
+	if (!blob) {
+		return;
+	}
+
+	local_one_snapshot = ast_channel_snapshot_create(p->base.owner);
+	if (!local_one_snapshot) {
+		return;
+	}
+
+	local_two_snapshot = ast_channel_snapshot_create(p->base.chan);
+	if (!local_two_snapshot) {
+		return;
+	}
+
+	payload = ast_multi_channel_blob_create(blob);
+	if (!payload) {
+		return;
+	}
+	ast_multi_channel_blob_add_channel(payload, "1", local_one_snapshot);
+	ast_multi_channel_blob_add_channel(payload, "2", local_two_snapshot);
+
+	msg = stasis_message_create(
+			complete ? ast_local_optimization_end_type() : ast_local_optimization_begin_type(),
+			payload);
+	if (!msg) {
+		return;
+	}
+
+	stasis_publish(ast_channel_topic(p->base.owner), msg);
+
+}
+
+/*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_started_cb */
+static void local_optimization_started_cb(struct ast_unreal_pvt *base)
+{
+	struct local_pvt *p = (struct local_pvt *)base;
+	publish_local_optimization(p, 0);
+}
+
+/*! \brief Callback for \ref ast_unreal_pvt_callbacks \ref optimization_finished_cb */
+static void local_optimization_finished_cb(struct ast_unreal_pvt *base)
+{
+	struct local_pvt *p = (struct local_pvt *)base;
+	publish_local_optimization(p, 1);
+}
+
+static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message *message)
+{
+	struct ast_multi_channel_blob *obj = stasis_message_data(message);
+	struct ast_json *blob = ast_multi_channel_blob_get_json(obj);
+	struct ast_channel_snapshot *local_snapshot_one;
+	struct ast_channel_snapshot *local_snapshot_two;
+	RAII_VAR(struct ast_str *, local_channel_one, NULL, ast_free);
+	RAII_VAR(struct ast_str *, local_channel_two, NULL, ast_free);
+	struct ast_str *event_buffer = ast_str_alloca(128);
+	const char *event;
+
+	local_snapshot_one = ast_multi_channel_blob_get_channel(obj, "1");
+	local_snapshot_two = ast_multi_channel_blob_get_channel(obj, "2");
+	if (!local_snapshot_one || !local_snapshot_two) {
 		return NULL;
 	}
 
-	channel_two_string = ast_manager_build_channel_state_string_prefix(chan_two, "LocalTwo");
-	if (!channel_two_string) {
+	local_channel_one = ast_manager_build_channel_state_string_prefix(local_snapshot_one, "LocalOne");
+	local_channel_two = ast_manager_build_channel_state_string_prefix(local_snapshot_two, "LocalTwo");
+	if (!local_channel_one || !local_channel_two) {
 		return NULL;
 	}
 
-	context = ast_json_object_get(blob, "context");
-	exten = ast_json_object_get(blob, "exten");
-	optimize = ast_json_object_get(blob, "optimize");
-
-	return ast_manager_event_blob_create(EVENT_FLAG_CALL, "LocalBridge",
+	if (stasis_message_type(message) == ast_local_optimization_begin_type()) {
+		event = "LocalOptimizationBegin";
+	} else if (stasis_message_type(message) == ast_local_optimization_end_type()) {
+		event = "LocalOptimizationEnd";
+	} else if (stasis_message_type(message) == ast_local_bridge_type()) {
+		event = "LocalBridge";
+		ast_str_append(&event_buffer, 0, "Context: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "context")));
+		ast_str_append(&event_buffer, 0, "Exten: %s\r\n", ast_json_string_get(ast_json_object_get(blob, "exten")));
+		ast_str_append(&event_buffer, 0, "LocalOptimization: %s\r\n", ast_json_is_true(ast_json_object_get(blob, "can_optimize")) ? "Yes" : "No");
+	} else {
+		return NULL;
+	}
+
+	return ast_manager_event_blob_create(EVENT_FLAG_CALL, event,
 		"%s"
 		"%s"
-		"Context: %s\r\n"
-		"Exten: %s\r\n"
-		"LocalOptimization: %s\r\n",
-		ast_str_buffer(channel_one_string),
-		ast_str_buffer(channel_two_string),
-		ast_json_string_get(context),
-		ast_json_string_get(exten),
-		ast_json_is_true(optimize) ? "Yes" : "No");
-}
-
-STASIS_MESSAGE_TYPE_DEFN_LOCAL(local_bridge_type,
-	.to_ami = local_bridge_to_ami,
-	);
+		"%s",
+		ast_str_buffer(local_channel_one),
+		ast_str_buffer(local_channel_two),
+		ast_str_buffer(event_buffer));
+}
 
 /*!
  * \internal
- * \brief Post the LocalBridge AMI event.
+ * \brief Post the \ref ast_local_bridge_type \ref stasis message
  * \since 12.0.0
  *
- * \param p local_pvt to raise the bridge event.
+ * \param p local_pvt to raise the local bridge message
  *
  * \return Nothing
  */
-static void local_bridge_event(struct local_pvt *p)
+static void publish_local_bridge_message(struct local_pvt *p)
 {
 	RAII_VAR(struct ast_multi_channel_blob *, multi_blob, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
@@ -390,7 +500,7 @@
 	blob = ast_json_pack("{s: s, s: s, s: b}",
 		"context", p->context,
 		"exten", p->exten,
-		"optimize", ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
+		"can_optimize", !ast_test_flag(&p->base, AST_UNREAL_NO_OPTIMIZATION));
 	if (!blob) {
 		return;
 	}
@@ -413,7 +523,7 @@
 	ast_multi_channel_blob_add_channel(multi_blob, "1", one_snapshot);
 	ast_multi_channel_blob_add_channel(multi_blob, "2", two_snapshot);
 
-	msg = stasis_message_create(local_bridge_type(), multi_blob);
+	msg = stasis_message_create(ast_local_bridge_type(), multi_blob);
 	if (!msg) {
 		return;
 	}
@@ -564,14 +674,14 @@
 			ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
 				p->exten, p->context);
 		} else {
-			local_bridge_event(p);
+			publish_local_bridge_message(p);
 
 			/* Start switch on sub channel */
 			res = ast_pbx_start(chan);
 		}
 		break;
 	case LOCAL_CALL_ACTION_BRIDGE:
-		local_bridge_event(p);
+		publish_local_bridge_message(p);
 		ast_answer(chan);
 		res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
 			p->action.bridge.features, 1);
@@ -582,7 +692,7 @@
 		p->action.bridge.features = NULL;
 		break;
 	case LOCAL_CALL_ACTION_MASQUERADE:
-		local_bridge_event(p);
+		publish_local_bridge_message(p);
 		ast_answer(chan);
 		res = ast_channel_move(p->action.masq, chan);
 		if (!res) {
@@ -699,6 +809,7 @@
 	if (!pvt) {
 		return NULL;
 	}
+	pvt->base.callbacks = &local_unreal_callbacks;
 
 	parse = ast_strdupa(data);
 
@@ -883,12 +994,24 @@
 	locals = NULL;
 
 	ast_format_cap_destroy(local_tech.capabilities);
-	STASIS_MESSAGE_TYPE_CLEANUP(local_bridge_type);
+
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_begin_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_optimization_end_type);
+	STASIS_MESSAGE_TYPE_CLEANUP(ast_local_bridge_type);
 }
 
 int ast_local_init(void)
 {
-	if (STASIS_MESSAGE_TYPE_INIT(local_bridge_type)) {
+
+	if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_begin_type)) {
+		return -1;
+	}
+
+	if (STASIS_MESSAGE_TYPE_INIT(ast_local_optimization_end_type)) {
+		return -1;
+	}
+
+	if (STASIS_MESSAGE_TYPE_INIT(ast_local_bridge_type)) {
 		return -1;
 	}
 

Modified: trunk/main/core_unreal.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/core_unreal.c?view=diff&rev=393801&r1=393800&r2=393801
==============================================================================
--- trunk/main/core_unreal.c (original)
+++ trunk/main/core_unreal.c Mon Jul  8 09:26:40 2013
@@ -281,18 +281,20 @@
  */
 static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
 {
+	int res = 0;
+
 	/* Do a few conditional checks early on just to see if this optimization is possible */
 	if (ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION) || !p->chan || !p->owner) {
-		return 0;
-	}
+		return res;
+	}
+
 	if (ast == p->owner) {
-		return ast_bridge_unreal_optimized_out(p->owner, p->chan);
-	}
-	if (ast == p->chan) {
-		return ast_bridge_unreal_optimized_out(p->chan, p->owner);
-	}
-	/* ast is not valid to optimize. */
-	return 0;
+		res = ast_bridge_unreal_optimize_out(p->owner, p->chan, p);
+	} else if (ast == p->chan) {
+		res = ast_bridge_unreal_optimize_out(p->chan, p->owner, p);
+	}
+
+	return res;
 }
 
 struct ast_frame  *ast_unreal_read(struct ast_channel *ast)




More information about the svn-commits mailing list