summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES11
-rw-r--r--include/asterisk/bridging.h6
-rw-r--r--include/asterisk/core_local.h39
-rw-r--r--include/asterisk/core_unreal.h36
-rw-r--r--main/bridging.c59
-rw-r--r--main/core_local.c205
-rw-r--r--main/core_unreal.c16
7 files changed, 308 insertions, 64 deletions
diff --git a/CHANGES b/CHANGES
index 037001daf..5819d7098 100644
--- a/CHANGES
+++ b/CHANGES
@@ -270,6 +270,17 @@ AMI (Asterisk Manager Interface)
* 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)
------------------
* The manager event AGIExec has been split into AGIExecStart and AGIExecEnd.
diff --git a/include/asterisk/bridging.h b/include/asterisk/bridging.h
index e03bfd0cd..08d0023e5 100644
--- a/include/asterisk/bridging.h
+++ b/include/asterisk/bridging.h
@@ -870,19 +870,23 @@ int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan);
*/
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
diff --git a/include/asterisk/core_local.h b/include/asterisk/core_local.h
index 693c93b46..491112d2b 100644
--- a/include/asterisk/core_local.h
+++ b/include/asterisk/core_local.h
@@ -37,6 +37,7 @@ extern "C" {
struct ast_channel;
struct ast_bridge;
struct ast_bridge_features;
+struct stasis_message_type;
/* ------------------------------------------------------------------- */
@@ -91,6 +92,44 @@ int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq
/* ------------------------------------------------------------------- */
+/*!
+ * \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
diff --git a/include/asterisk/core_unreal.h b/include/asterisk/core_unreal.h
index 7cb68f162..a6e98895a 100644
--- a/include/asterisk/core_unreal.h
+++ b/include/asterisk/core_unreal.h
@@ -43,6 +43,30 @@ struct ast_callid;
/* ------------------------------------------------------------------- */
+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 @@ struct ast_callid;
* 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@context or other name. */
char name[AST_MAX_EXTENSION + AST_MAX_CONTEXT + 2];
};
@@ -65,6 +90,7 @@ struct ast_unreal_pvt {
#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
diff --git a/main/bridging.c b/main/bridging.c
index 1dc8b6ea3..d01a66ad7 100644
--- a/main/bridging.c
+++ b/main/bridging.c
@@ -61,6 +61,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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 @@ static void bridge_channel_pull(struct ast_bridge_channel *bridge_channel)
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 @@ static int bridge_channel_push(struct ast_bridge_channel *bridge_channel)
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 @@ static int smart_bridge_operation(struct ast_bridge *bridge)
* 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 @@ static enum bridge_allow_swap bridges_allow_swap_optimization(struct ast_bridge
* \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 @@ static int check_swap_optimize_out(struct ast_bridge *chan_bridge,
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 @@ static enum bridge_allow_merge bridges_allow_merge_optimization(struct ast_bridg
* \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 @@ static int check_merge_optimize_out(struct ast_bridge *chan_bridge,
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 @@ int ast_bridge_unreal_optimized_out(struct ast_channel *chan, struct ast_channel
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;
}
diff --git a/main/core_local.c b/main/core_local.c
index 16abc428c..b35e03110 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -46,6 +46,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#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 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
</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 struct ast_channel *local_request(const char *type, struct ast_format_cap
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 @@ static int local_devicestate(const char *data)
return res;
}
-static struct ast_manager_event_blob *local_bridge_to_ami(struct stasis_message *msg)
+static void publish_local_optimization(struct local_pvt *p, int complete)
{
- 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) {
+ 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");
+ 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, "LocalBridge",
+ 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");
+ "%s",
+ ast_str_buffer(local_channel_one),
+ ast_str_buffer(local_channel_two),
+ ast_str_buffer(event_buffer));
}
-STASIS_MESSAGE_TYPE_DEFN_LOCAL(local_bridge_type,
- .to_ami = local_bridge_to_ami,
- );
-
/*!
* \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 @@ static void local_bridge_event(struct local_pvt *p)
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 @@ static void local_bridge_event(struct local_pvt *p)
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 @@ static int local_call(struct ast_channel *ast, const char *dest, int timeout)
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 @@ static int local_call(struct ast_channel *ast, const char *dest, int timeout)
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 @@ static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *ca
if (!pvt) {
return NULL;
}
+ pvt->base.callbacks = &local_unreal_callbacks;
parse = ast_strdupa(data);
@@ -883,12 +994,24 @@ static void local_shutdown(void)
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;
}
diff --git a/main/core_unreal.c b/main/core_unreal.c
index d5e588111..71d0f6c8f 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -281,18 +281,20 @@ int ast_unreal_answer(struct ast_channel *ast)
*/
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);
+ 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);
}
- if (ast == p->chan) {
- return ast_bridge_unreal_optimized_out(p->chan, p->owner);
- }
- /* ast is not valid to optimize. */
- return 0;
+
+ return res;
}
struct ast_frame *ast_unreal_read(struct ast_channel *ast)