[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r387795 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Mon May 6 19:00:58 CDT 2013
Author: rmudgett
Date: Mon May 6 19:00:56 2013
New Revision: 387795
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=387795
Log:
Setup the ;2 local channel to join a bridge or masquerade into a channel on ast_call().
Still to do:
* Move channels/chan_local.c to main/core_local.c and make it not dynamically loadable.
Modified:
team/rmudgett/bridge_phase/channels/chan_local.c
team/rmudgett/bridge_phase/include/asterisk/core_local.h
Modified: team/rmudgett/bridge_phase/channels/chan_local.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/channels/chan_local.c?view=diff&rev=387795&r1=387794&r2=387795
==============================================================================
--- team/rmudgett/bridge_phase/channels/chan_local.c (original)
+++ team/rmudgett/bridge_phase/channels/chan_local.c Mon May 6 19:00:56 2013
@@ -110,6 +110,24 @@
.setoption = ast_unreal_setoption,
};
+/*! What to do with the ;2 channel when ast_call() happens. */
+enum local_call_action {
+ /* The ast_call() will run dialplan on the ;2 channel. */
+ LOCAL_CALL_ACTION_DIALPLAN,
+ /* The ast_call() will impart the ;2 channel into a bridge. */
+ LOCAL_CALL_ACTION_BRIDGE,
+ /* The ast_call() will masquerade the ;2 channel into a channel. */
+ LOCAL_CALL_ACTION_MASQUERADE,
+};
+
+/*! Join a bridge on ast_call() parameters. */
+struct local_bridge {
+ /*! Bridge to join. */
+ struct ast_bridge *join;
+ /*! Channel to swap with when joining bridge. */
+ struct ast_channel *swap;
+};
+
/*!
* \brief the local pvt structure for all channels
*
@@ -120,8 +138,19 @@
struct ast_local_pvt {
/*! Unreal channel driver base class values. */
struct ast_unreal_pvt base;
- char context[AST_MAX_CONTEXT]; /*!< Context to call */
- char exten[AST_MAX_EXTENSION]; /*!< Extension to call */
+ /*! Additional action arguments */
+ union {
+ /*! Make ;2 join a bridge on ast_call(). */
+ struct local_bridge bridge;
+ /*! Make ;2 masquerade into this channel on ast_call(). */
+ struct ast_channel *masq;
+ } action;
+ /*! What to do with the ;2 channel on ast_call(). */
+ enum local_call_action type;
+ /*! Context to call */
+ char context[AST_MAX_CONTEXT];
+ /*! Extension to call */
+ char exten[AST_MAX_EXTENSION];
};
void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
@@ -601,7 +630,7 @@
ao2_lock(p);
/*
* Block -1 stop tones events if we are to be optimized out. We
- * don't need a flurry of these events on a unreal channel chain
+ * don't need a flurry of these events on an unreal channel chain
* when initially connected to slow the optimization process.
*/
if (0 <= condition || ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION)) {
@@ -819,9 +848,78 @@
ao2_unlock(p);
}
-/* BUGBUG need to create ast_local_setup_bridge(). */
-/* BUGBUG need to create ast_local_setup_masquerade(). */
-/* BUGBUG need to create ast_local_setup_dialplan(). */
+int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap)
+{
+ struct ast_local_pvt *p;
+ struct ast_local_pvt *found;
+ int res = -1;
+
+ /* Sanity checks. */
+ if (!ast || !bridge) {
+ return -1;
+ }
+
+ ast_channel_lock(ast);
+ p = ast_channel_tech_pvt(ast);
+ ast_channel_unlock(ast);
+
+ found = p ? ao2_find(locals, p, 0) : NULL;
+ if (found) {
+ ao2_lock(found);
+ if (found->type == LOCAL_CALL_ACTION_DIALPLAN
+ && found->base.owner
+ && found->base.chan
+ && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
+ ao2_ref(bridge, +1);
+ if (swap) {
+ ast_channel_ref(swap);
+ }
+ found->type = LOCAL_CALL_ACTION_BRIDGE;
+ found->action.bridge.join = bridge;
+ found->action.bridge.swap = swap;
+ res = 0;
+ }
+ ao2_unlock(found);
+ ao2_ref(found, -1);
+ }
+
+ return res;
+}
+
+int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq)
+{
+ struct ast_local_pvt *p;
+ struct ast_local_pvt *found;
+ int res = -1;
+
+ /* Sanity checks. */
+ if (!ast || !masq) {
+ return -1;
+ }
+
+ ast_channel_lock(ast);
+ p = ast_channel_tech_pvt(ast);
+ ast_channel_unlock(ast);
+
+ found = p ? ao2_find(locals, p, 0) : NULL;
+ if (found) {
+ ao2_lock(found);
+ if (found->type == LOCAL_CALL_ACTION_DIALPLAN
+ && found->base.owner
+ && found->base.chan
+ && !ast_test_flag(&found->base, AST_UNREAL_CARETAKER_THREAD)) {
+ ast_channel_ref(masq);
+ found->type = LOCAL_CALL_ACTION_MASQUERADE;
+ found->action.masq = masq;
+ res = 0;
+ }
+ ao2_unlock(found);
+ ao2_ref(found, -1);
+ }
+
+ return res;
+}
+
/*! \brief Initiate new call, part of PBX interface
* dest is the dial string */
static int local_call(struct ast_channel *ast, const char *dest, int timeout)
@@ -882,20 +980,45 @@
}
ast_channel_unlock(chan);
- if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
- ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
- p->exten, p->context);
- res = -1;
- } else {
+ res = -1;
+ switch (p->type) {
+ case LOCAL_CALL_ACTION_DIALPLAN:
+ if (!ast_exists_extension(NULL, p->context, p->exten, 1, chan_cid)) {
+ ast_log(LOG_NOTICE, "No such extension/context %s@%s while calling Local channel\n",
+ p->exten, p->context);
+ } else {
+ local_bridge_event(p);
+
+ /* Start switch on sub channel */
+ res = ast_pbx_start(chan);
+ }
+ break;
+ case LOCAL_CALL_ACTION_BRIDGE:
local_bridge_event(p);
-
- /* Start switch on sub channel */
- res = ast_pbx_start(chan);
+ ast_answer(chan);
+ res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap,
+ NULL, 1);
+ ao2_ref(p->action.bridge.join, -1);
+ p->action.bridge.join = NULL;
+ ao2_cleanup(p->action.bridge.swap);
+ p->action.bridge.swap = NULL;
+ break;
+ case LOCAL_CALL_ACTION_MASQUERADE:
+ local_bridge_event(p);
+ ast_answer(chan);
+ res = ast_channel_masquerade(p->action.masq, chan);
if (!res) {
- ao2_lock(p);
- ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
- ao2_unlock(p);
- }
+ ast_do_masquerade(p->action.masq);
+ /* Chan is now an orphaned zombie. Destroy it. */
+ ast_hangup(chan);
+ }
+ p->action.masq = ast_channel_unref(p->action.masq);
+ break;
+ }
+ if (!res) {
+ ao2_lock(p);
+ ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
+ ao2_unlock(p);
}
/* we already unlocked them, clear them here so the cleanup label won't touch them. */
@@ -914,8 +1037,10 @@
ast_channel_unref(chan);
}
- /* owner is supposed to be == to ast, if it
- * is, don't unlock it because ast must exit locked */
+ /*
+ * owner is supposed to be == to ast, if it is, don't unlock it
+ * because ast must exit locked
+ */
if (owner) {
if (owner != ast) {
ast_channel_unlock(owner);
@@ -1083,6 +1208,17 @@
{
struct ast_local_pvt *doomed = vdoomed;
+ switch (doomed->type) {
+ case LOCAL_CALL_ACTION_DIALPLAN:
+ break;
+ case LOCAL_CALL_ACTION_BRIDGE:
+ ao2_cleanup(doomed->action.bridge.join);
+ ao2_cleanup(doomed->action.bridge.swap);
+ break;
+ case LOCAL_CALL_ACTION_MASQUERADE:
+ ao2_cleanup(doomed->action.masq);
+ break;
+ }
ast_unreal_destructor(&doomed->base);
}
Modified: team/rmudgett/bridge_phase/include/asterisk/core_local.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/core_local.h?view=diff&rev=387795&r1=387794&r2=387795
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/core_local.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/core_local.h Mon May 6 19:00:56 2013
@@ -168,6 +168,31 @@
*/
struct ast_channel *ast_local_get_peer(struct ast_channel *ast);
+/*!
+ * \brief Setup the outgoing local channel to join a bridge on ast_call().
+ * \since 12.0.0
+ *
+ * \param ast Either channel of a local channel pair.
+ * \param bridge Bridge to join.
+ * \param swap Channel to swap with when joining.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int ast_local_setup_bridge(struct ast_channel *ast, struct ast_bridge *bridge, struct ast_channel *swap);
+
+/*!
+ * \brief Setup the outgoing local channel to masquerade into a channel on ast_call().
+ * \since 12.0.0
+ *
+ * \param ast Either channel of a local channel pair.
+ * \param masq Channel to masquerade into.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+int ast_local_setup_masquerade(struct ast_channel *ast, struct ast_channel *masq);
+
/* ------------------------------------------------------------------- */
#if defined(__cplusplus) || defined(c_plusplus)
More information about the asterisk-commits
mailing list