[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r390108 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed May 29 20:11:43 CDT 2013
Author: rmudgett
Date: Wed May 29 20:11:39 2013
New Revision: 390108
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=390108
Log:
Bridge API: Update BRIDGEPEER and BRIDGEPVTCALLID.
* Deleted a bunch of unused old bridge code.
Modified:
team/rmudgett/bridge_phase/include/asterisk/channel.h
team/rmudgett/bridge_phase/main/bridging.c
team/rmudgett/bridge_phase/main/channel.c
team/rmudgett/bridge_phase/main/channel_internal_api.c
team/rmudgett/bridge_phase/main/features.c
Modified: team/rmudgett/bridge_phase/include/asterisk/channel.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/include/asterisk/channel.h?view=diff&rev=390108&r1=390107&r2=390108
==============================================================================
--- team/rmudgett/bridge_phase/include/asterisk/channel.h (original)
+++ team/rmudgett/bridge_phase/include/asterisk/channel.h Wed May 29 20:11:39 2013
@@ -872,8 +872,6 @@
AST_FLAG_MOH = (1 << 6),
/*! This channel is spying on another channel */
AST_FLAG_SPYING = (1 << 7),
- /*! This channel is in a native bridge */
- AST_FLAG_NBRIDGE = (1 << 8),
/*! the channel is in an auto-incrementing dialplan processor,
* so when ->priority is set, it will get incremented before
* finding the next priority to run */
@@ -927,7 +925,6 @@
AST_FEATURE_AUTOMON = (1 << 4),
AST_FEATURE_PARKCALL = (1 << 5),
AST_FEATURE_AUTOMIXMON = (1 << 6),
- AST_FEATURE_WARNING_ACTIVE = (1 << 8),
};
/*! \brief bridge configuration */
@@ -2015,21 +2012,6 @@
* \return Returns 0 on success and -1 if it could not be done
*/
int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1);
-
-/*!
- * \brief Bridge two channels together
- * \param c0 first channel to bridge
- * \param c1 second channel to bridge
- * \param config config for the channels
- * \param fo destination frame(?)
- * \param rc destination channel(?)
- * \details
- * Bridge two channels (c0 and c1) together. If an important frame occurs, we return that frame in
- * *rf (remember, it could be NULL) and which channel (0 or 1) in rc
- */
-/* int ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc); */
-int ast_channel_bridge(struct ast_channel *c0,struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc);
/*!
* \brief Weird function made for call transfers
Modified: team/rmudgett/bridge_phase/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/bridging.c?view=diff&rev=390108&r1=390107&r2=390108
==============================================================================
--- team/rmudgett/bridge_phase/main/bridging.c (original)
+++ team/rmudgett/bridge_phase/main/bridging.c Wed May 29 20:11:39 2013
@@ -1724,7 +1724,7 @@
*
* \return Nothing
*/
-static void handle_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
+static void check_bridge_play_sound(struct ast_bridge_channel *bridge_channel)
{
const char *play_file;
@@ -1745,7 +1745,7 @@
/*!
* \internal
- * \brief Handle any BRIDGE_PLAY_SOUND channel variables in the bridge.
+ * \brief Check for any BRIDGE_PLAY_SOUND channel variables in the bridge.
* \since 12.0.0
*
* \param bridge What to operate on.
@@ -1754,12 +1754,213 @@
*
* \return Nothing
*/
-static void handle_bridge_play_sounds(struct ast_bridge *bridge)
+static void check_bridge_play_sounds(struct ast_bridge *bridge)
{
struct ast_bridge_channel *bridge_channel;
AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
- handle_bridge_play_sound(bridge_channel);
+ check_bridge_play_sound(bridge_channel);
+ }
+}
+
+static void update_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
+{
+ pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
+ pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
+}
+
+/*!
+ * \internal
+ * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a 2 party bridge.
+ * \since 12.0.0
+ *
+ * \param c0 Party of the first part.
+ * \param c1 Party of the second part.
+ *
+ * \note On entry, the bridge is already locked.
+ * \note The bridge is expected to have exactly two parties.
+ *
+ * \return Nothing
+ */
+static void set_bridge_peer_vars_2party(struct ast_channel *c0, struct ast_channel *c1)
+{
+ const char *c0_name;
+ const char *c1_name;
+ const char *c0_pvtid = NULL;
+ const char *c1_pvtid = NULL;
+#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid) \
+ do { \
+ name = ast_strdupa(ast_channel_name(chan)); \
+ if (ast_channel_tech(chan)->get_pvt_uniqueid) { \
+ pvtid = ast_strdupa(ast_channel_tech(chan)->get_pvt_uniqueid(chan)); \
+ } \
+ } while (0)
+
+ ast_channel_lock(c1);
+ UPDATE_BRIDGE_VARS_GET(c1, c1_name, c1_pvtid);
+ ast_channel_unlock(c1);
+
+ ast_channel_lock(c0);
+ update_bridge_vars_set(c0, c1_name, c1_pvtid);
+ UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
+ ast_channel_unlock(c0);
+
+ ast_channel_lock(c1);
+ update_bridge_vars_set(c1, c0_name, c0_pvtid);
+ ast_channel_unlock(c1);
+}
+
+/*!
+ * \internal
+ * \brief Fill the BRIDGEPEER value buffer with a comma separated list of channel names.
+ * \since 12.0.0
+ *
+ * \param buf Buffer to fill. Is guaranteed to be large enough.
+ * \param cur_idx Which index into names[] to skip.
+ * \param names Channel names to put in the buffer.
+ * \param num_names Number of names in the array.
+ *
+ * \return Nothing
+ */
+static void fill_bridgepeer_buf(char *buf, unsigned int cur_idx, const char *names[], unsigned int num_names)
+{
+ int need_separator = 0;
+ unsigned int idx;
+ const char *src;
+ char *pos;
+
+ pos = buf;
+ for (idx = 0; idx < num_names; ++idx) {
+ if (idx == cur_idx) {
+ continue;
+ }
+
+ if (need_separator) {
+ *pos++ = ',';
+ }
+ need_separator = 1;
+
+ /* Copy name into buffer. */
+ src = names[idx];
+ while (*src) {
+ *pos++ = *src++;
+ }
+ }
+ *pos = '\0';
+}
+
+/*!
+ * \internal
+ * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a multi-party bridge.
+ * \since 12.0.0
+ *
+ * \param bridge What to operate on.
+ *
+ * \note On entry, the bridge is already locked.
+ * \note The bridge is expected to have more than two parties.
+ *
+ * \return Nothing
+ */
+static void set_bridge_peer_vars_multiparty(struct ast_bridge *bridge)
+{
+/*
+ * Set a maximum number of channel names for the BRIDGEPEER
+ * list. The plus one is for the current channel which is not
+ * put in the list.
+ */
+#define MAX_BRIDGEPEER_CHANS (2 + 1)//BUGBUG
+//#define MAX_BRIDGEPEER_CHANS (10 + 1)
+
+ unsigned int idx;
+ unsigned int num_names;
+ unsigned int len;
+ const char **names;
+ char *buf;
+ struct ast_bridge_channel *bridge_channel;
+
+ /* Get first MAX_BRIDGEPEER_CHANS channel names. */
+ num_names = MIN(bridge->num_channels, MAX_BRIDGEPEER_CHANS);
+ names = ast_alloca(num_names * sizeof(*names));
+ idx = 0;
+ AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
+ if (num_names <= idx) {
+ break;
+ }
+ ast_channel_lock(bridge_channel->chan);
+ names[idx++] = ast_strdupa(ast_channel_name(bridge_channel->chan));
+ ast_channel_unlock(bridge_channel->chan);
+ }
+
+ /* Determine maximum buf size needed. */
+ len = num_names;
+ for (idx = 0; idx < num_names; ++idx) {
+ len += strlen(names[idx]);
+ }
+ buf = ast_alloca(len);
+
+ /* Set the bridge channel variables. */
+ idx = 0;
+ buf[0] = '\0';
+ AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
+ if (idx < num_names) {
+ fill_bridgepeer_buf(buf, idx, names, num_names);
+ }
+ ++idx;
+
+ ast_channel_lock(bridge_channel->chan);
+ast_log(LOG_NOTICE, "BUGBUG Chan %s: BRIDGEPEER=%s\n", ast_channel_name(bridge_channel->chan), buf);
+ update_bridge_vars_set(bridge_channel->chan, buf, NULL);
+ ast_channel_unlock(bridge_channel->chan);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in a holding bridge.
+ * \since 12.0.0
+ *
+ * \param bridge What to operate on.
+ *
+ * \note On entry, the bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void set_bridge_peer_vars_holding(struct ast_bridge *bridge)
+{
+ struct ast_bridge_channel *bridge_channel;
+
+ AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
+ ast_channel_lock(bridge_channel->chan);
+ update_bridge_vars_set(bridge_channel->chan, NULL, NULL);
+ ast_channel_unlock(bridge_channel->chan);
+ }
+}
+
+/*!
+ * \internal
+ * \brief Set BRIDGEPEER and BRIDGEPVTCALLID channel variables in the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge What to operate on.
+ *
+ * \note On entry, the bridge is already locked.
+ *
+ * \return Nothing
+ */
+static void set_bridge_peer_vars(struct ast_bridge *bridge)
+{
+ if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_HOLDING) {
+ set_bridge_peer_vars_holding(bridge);
+ return;
+ }
+ if (bridge->num_channels < 2) {
+ return;
+ }
+ if (bridge->num_channels == 2) {
+ set_bridge_peer_vars_2party(AST_LIST_FIRST(&bridge->channels)->chan,
+ AST_LIST_LAST(&bridge->channels)->chan);
+ } else {
+ set_bridge_peer_vars_multiparty(bridge);
}
}
@@ -1797,7 +1998,8 @@
if (bridge->dissolved) {
return;
}
- handle_bridge_play_sounds(bridge);
+ check_bridge_play_sounds(bridge);
+ set_bridge_peer_vars(bridge);
}
/*!
Modified: team/rmudgett/bridge_phase/main/channel.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/channel.c?view=diff&rev=390108&r1=390107&r2=390108
==============================================================================
--- team/rmudgett/bridge_phase/main/channel.c (original)
+++ team/rmudgett/bridge_phase/main/channel.c Wed May 29 20:11:39 2013
@@ -6669,6 +6669,7 @@
}
}
+#if 0 //BUGBUG setting up peeraccount needs to be removed.
/* copy accountcode and peeraccount across during a link */
static void ast_set_owners_and_peers(struct ast_channel *chan1,
struct ast_channel *chan2)
@@ -6704,6 +6705,7 @@
ast_channel_peeraccount_set(chan1, ast_channel_accountcode(chan2));
}
}
+#endif //BUGBUG
/*!
* \internal
@@ -7336,251 +7338,6 @@
return NULL;
}
-static void bridge_playfile(struct ast_channel *chan, struct ast_channel *peer, const char *sound, int remain)
-{
- int check;
-
- check = ast_autoservice_start(peer);
- if (check) {
- return;
- }
-
- if (!strcmp(sound, "timeleft")) { /* Queue support */
- int min = 0;
- int sec = 0;
-
- if (remain > 0) {
- if (remain / 60 > 1) {
- min = remain / 60;
- sec = remain % 60;
- } else {
- sec = remain;
- }
- }
-
- ast_stream_and_wait(chan, "vm-youhave", "");
- if (min) {
- ast_say_number(chan, min, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
- ast_stream_and_wait(chan, "queue-minutes", "");
- }
- if (sec) {
- ast_say_number(chan, sec, AST_DIGIT_ANY, ast_channel_language(chan), NULL);
- ast_stream_and_wait(chan, "queue-seconds", "");
- }
- } else {
- ast_stream_and_wait(chan, sound, "");
- }
-
- ast_autoservice_stop(peer);
-}
-
-static enum ast_bridge_result ast_generic_bridge(struct ast_channel *c0, struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo,
- struct ast_channel **rc)
-{
- /* Copy voice back and forth between the two channels. */
- struct ast_channel *cs[3];
- struct ast_frame *f;
- enum ast_bridge_result res = AST_BRIDGE_COMPLETE;
- struct ast_format_cap *o0nativeformats;
- struct ast_format_cap *o1nativeformats;
- int watch_c0_dtmf;
- int watch_c1_dtmf;
- void *pvt0, *pvt1;
- /* Indicates whether a frame was queued into a jitterbuffer */
- int frame_put_in_jb = 0;
- int jb_in_use;
- int to;
-
- o0nativeformats = ast_format_cap_dup(ast_channel_nativeformats(c0));
- o1nativeformats = ast_format_cap_dup(ast_channel_nativeformats(c1));
-
- if (!o0nativeformats || !o1nativeformats) {
- ast_format_cap_destroy(o0nativeformats); /* NULL safe */
- ast_format_cap_destroy(o1nativeformats); /* NULL safe */
- return AST_BRIDGE_FAILED;
- }
-
- cs[0] = c0;
- cs[1] = c1;
- pvt0 = ast_channel_tech_pvt(c0);
- pvt1 = ast_channel_tech_pvt(c1);
- watch_c0_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_0;
- watch_c1_dtmf = config->flags & AST_BRIDGE_DTMF_CHANNEL_1;
-
- /* Check the need of a jitterbuffer for each channel */
- jb_in_use = ast_jb_do_usecheck(c0, c1);
- if (jb_in_use)
- ast_jb_empty_and_reset(c0, c1);
-
- ast_poll_channel_add(c0, c1);
-
- if (config->feature_timer > 0 && ast_tvzero(config->nexteventts)) {
- /* nexteventts is not set when the bridge is not scheduled to
- * break, so calculate when the bridge should possibly break
- * if a partial feature match timed out */
- config->nexteventts = ast_tvadd(ast_tvnow(), ast_samp2tv(config->feature_timer, 1000));
- }
-
- for (;;) {
- struct ast_channel *who, *other;
-
- if ((ast_channel_tech_pvt(c0) != pvt0) || (ast_channel_tech_pvt(c1) != pvt1) ||
- (!ast_format_cap_identical(o0nativeformats, ast_channel_nativeformats(c0))) ||
- (!ast_format_cap_identical(o1nativeformats, ast_channel_nativeformats(c1)))) {
- /* Check for Masquerade, codec changes, etc */
- res = AST_BRIDGE_RETRY;
- break;
- }
- if (!ast_tvzero(config->nexteventts)) {
- to = ast_tvdiff_ms(config->nexteventts, ast_tvnow());
- if (to <= 0) {
- if (config->feature_timer) {
- /* feature timer expired - make sure we do not play warning */
- ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
- /* Indicate a feature timeout. */
- res = AST_BRIDGE_RETRY;
- } else if (config->timelimit
- && !ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
- /* generic bridge ending to play warning */
- ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
- res = AST_BRIDGE_RETRY;
- } else {
- res = AST_BRIDGE_COMPLETE;
- }
- break;
- }
- } else {
- to = -1;
- }
- /* Calculate the appropriate max sleep interval - in general, this is the time,
- left to the closest jb delivery moment */
- if (jb_in_use)
- to = ast_jb_get_when_to_wakeup(c0, c1, to);
- who = ast_waitfor_n(cs, 2, &to);
- if (!who) {
- /* No frame received within the specified timeout - check if we have to deliver now */
- if (jb_in_use)
- ast_jb_get_and_deliver(c0, c1);
- if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */
- if (ast_channel_softhangup_internal_flag(c0) & AST_SOFTHANGUP_UNBRIDGE) {
- ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE);
- }
- if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
- ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
- }
- ast_channel_lock_both(c0, c1);
- ast_channel_internal_bridged_channel_set(c0, c1);
- ast_channel_internal_bridged_channel_set(c1, c0);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- }
- continue;
- }
- f = ast_read(who);
- if (!f) {
- *fo = NULL;
- *rc = who;
- ast_debug(1, "Didn't get a frame from channel: %s\n", ast_channel_name(who));
- break;
- }
-
- other = (who == c0) ? c1 : c0; /* the 'other' channel */
- /* Try add the frame info the who's bridged channel jitterbuff */
- if (jb_in_use)
- frame_put_in_jb = !ast_jb_put(other, f);
-
- if ((f->frametype == AST_FRAME_CONTROL) && !(config->flags & AST_BRIDGE_IGNORE_SIGS)) {
- int bridge_exit = 0;
-
- switch (f->subclass.integer) {
- case AST_CONTROL_PVT_CAUSE_CODE:
- case AST_CONTROL_AOC:
- case AST_CONTROL_MCID:
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
- break;
- case AST_CONTROL_REDIRECTING:
- if (ast_channel_redirecting_sub(who, other, f, 1) &&
- ast_channel_redirecting_macro(who, other, f, other == c0, 1)) {
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
- }
- break;
- case AST_CONTROL_CONNECTED_LINE:
- if (ast_channel_connected_line_sub(who, other, f, 1) &&
- ast_channel_connected_line_macro(who, other, f, other == c0, 1)) {
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
- }
- break;
- case AST_CONTROL_HOLD:
- case AST_CONTROL_UNHOLD:
- case AST_CONTROL_VIDUPDATE:
- case AST_CONTROL_SRCUPDATE:
- case AST_CONTROL_SRCCHANGE:
- case AST_CONTROL_T38_PARAMETERS:
- ast_indicate_data(other, f->subclass.integer, f->data.ptr, f->datalen);
- if (jb_in_use) {
- ast_jb_empty_and_reset(c0, c1);
- }
- break;
- default:
- *fo = f;
- *rc = who;
- bridge_exit = 1;
- ast_debug(1, "Got a FRAME_CONTROL (%d) frame on channel %s\n", f->subclass.integer, ast_channel_name(who));
- break;
- }
- if (bridge_exit)
- break;
- }
- if ((f->frametype == AST_FRAME_VOICE) ||
- (f->frametype == AST_FRAME_DTMF_BEGIN) ||
- (f->frametype == AST_FRAME_DTMF) ||
- (f->frametype == AST_FRAME_VIDEO) ||
- (f->frametype == AST_FRAME_IMAGE) ||
- (f->frametype == AST_FRAME_HTML) ||
- (f->frametype == AST_FRAME_MODEM) ||
- (f->frametype == AST_FRAME_TEXT)) {
- /* monitored dtmf causes exit from bridge */
- int monitored_source = (who == c0) ? watch_c0_dtmf : watch_c1_dtmf;
-
- if (monitored_source &&
- (f->frametype == AST_FRAME_DTMF_END ||
- f->frametype == AST_FRAME_DTMF_BEGIN)) {
- *fo = f;
- *rc = who;
- ast_debug(1, "Got DTMF %s on channel (%s)\n",
- f->frametype == AST_FRAME_DTMF_END ? "end" : "begin",
- ast_channel_name(who));
-
- break;
- }
- /* Write immediately frames, not passed through jb */
- if (!frame_put_in_jb)
- ast_write(other, f);
-
- /* Check if we have to deliver now */
- if (jb_in_use)
- ast_jb_get_and_deliver(c0, c1);
- }
- /* XXX do we want to pass on also frames not matched above ? */
- ast_frfree(f);
-
-#ifndef HAVE_EPOLL
- /* Swap who gets priority */
- cs[2] = cs[0];
- cs[0] = cs[1];
- cs[1] = cs[2];
-#endif
- }
-
- ast_poll_channel_del(c0, c1);
-
- ast_format_cap_destroy(o0nativeformats);
- ast_format_cap_destroy(o1nativeformats);
-
- return res;
-}
-
/*! \brief Bridge two channels together (early) */
int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1)
{
@@ -7589,382 +7346,6 @@
return -1;
return ast_channel_tech(c0)->early_bridge(c0, c1);
-}
-
-/*! \brief Send manager event for bridge link and unlink events.
- * \param onoff Link/Unlinked
- * \param type 1 for core, 2 for native
- * \param c0 first channel in bridge
- * \param c1 second channel in bridge
-*/
-static void manager_bridge_event(int onoff, int type, struct ast_channel *c0, struct ast_channel *c1)
-{
- struct ast_channel *chans[2] = { c0, c1 };
- /*** DOCUMENTATION
- <managerEventInstance>
- <synopsis>Raised when a bridge changes between two channels.</synopsis>
- <syntax>
- <parameter name="Bridgestate">
- <enumlist>
- <enum name="Link"/>
- <enum name="Unlink"/>
- </enumlist>
- </parameter>
- <parameter name="Bridgetype">
- <enumlist>
- <enum name="core"/>
- <enum name="native"/>
- </enumlist>
- </parameter>
- </syntax>
- </managerEventInstance>
- ***/
- ast_manager_event_multichan(EVENT_FLAG_CALL, "Bridge", 2, chans,
- "Bridgestate: %s\r\n"
- "Bridgetype: %s\r\n"
- "Channel1: %s\r\n"
- "Channel2: %s\r\n"
- "Uniqueid1: %s\r\n"
- "Uniqueid2: %s\r\n"
- "CallerID1: %s\r\n"
- "CallerID2: %s\r\n",
- onoff ? "Link" : "Unlink",
- type == 1 ? "core" : "native",
- ast_channel_name(c0), ast_channel_name(c1),
- ast_channel_uniqueid(c0), ast_channel_uniqueid(c1),
- S_COR(ast_channel_caller(c0)->id.number.valid, ast_channel_caller(c0)->id.number.str, ""),
- S_COR(ast_channel_caller(c1)->id.number.valid, ast_channel_caller(c1)->id.number.str, ""));
-}
-
-static void update_bridge_vars_set(struct ast_channel *chan, const char *name, const char *pvtid)
-{
- if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BRIDGEPEER"))) {
- pbx_builtin_setvar_helper(chan, "BRIDGEPEER", name);
- }
- if (pvtid) {
- pbx_builtin_setvar_helper(chan, "BRIDGEPVTCALLID", pvtid);
- }
-}
-
-static void update_bridge_vars(struct ast_channel *c0, struct ast_channel *c1)
-{
- const char *c0_name;
- const char *c1_name;
- const char *c0_pvtid = NULL;
- const char *c1_pvtid = NULL;
-#define UPDATE_BRIDGE_VARS_GET(chan, name, pvtid) \
- do { \
- name = ast_strdupa(ast_channel_name(chan)); \
- if (ast_channel_tech(chan)->get_pvt_uniqueid) { \
- pvtid = ast_strdupa(ast_channel_tech(chan)->get_pvt_uniqueid(chan)); \
- } \
- } while (0)
-
- ast_channel_lock(c1);
- UPDATE_BRIDGE_VARS_GET(c1, c1_name, c1_pvtid);
- ast_channel_unlock(c1);
-
- ast_channel_lock(c0);
- update_bridge_vars_set(c0, c1_name, c1_pvtid);
- UPDATE_BRIDGE_VARS_GET(c0, c0_name, c0_pvtid);
- ast_channel_unlock(c0);
-
- ast_channel_lock(c1);
- update_bridge_vars_set(c1, c0_name, c0_pvtid);
- ast_channel_unlock(c1);
-}
-
-static void bridge_play_sounds(struct ast_channel *c0, struct ast_channel *c1)
-{
- const char *s, *sound;
-
- /* See if we need to play an audio file to any side of the bridge */
-
- ast_channel_lock(c0);
- if ((s = pbx_builtin_getvar_helper(c0, "BRIDGE_PLAY_SOUND"))) {
- sound = ast_strdupa(s);
- ast_channel_unlock(c0);
- bridge_playfile(c0, c1, sound, 0);
- pbx_builtin_setvar_helper(c0, "BRIDGE_PLAY_SOUND", NULL);
- } else {
- ast_channel_unlock(c0);
- }
-
- ast_channel_lock(c1);
- if ((s = pbx_builtin_getvar_helper(c1, "BRIDGE_PLAY_SOUND"))) {
- sound = ast_strdupa(s);
- ast_channel_unlock(c1);
- bridge_playfile(c1, c0, sound, 0);
- pbx_builtin_setvar_helper(c1, "BRIDGE_PLAY_SOUND", NULL);
- } else {
- ast_channel_unlock(c1);
- }
-}
-
-/* BUGBUG ast_channel_bridge() and anything that only it calls will be removed. */
-/*! \brief Bridge two channels together */
-enum ast_bridge_result ast_channel_bridge(struct ast_channel *c0, struct ast_channel *c1,
- struct ast_bridge_config *config, struct ast_frame **fo, struct ast_channel **rc)
-{
- enum ast_bridge_result res;
- struct ast_format_cap *o0nativeformats;
- struct ast_format_cap *o1nativeformats;
- long time_left_ms=0;
- char caller_warning = 0;
- char callee_warning = 0;
-
- *fo = NULL;
-
- if (ast_channel_internal_bridged_channel(c0)) {
- ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
- ast_channel_name(c0), ast_channel_name(ast_channel_internal_bridged_channel(c0)));
- return AST_BRIDGE_FAILED;
- }
- if (ast_channel_internal_bridged_channel(c1)) {
- ast_log(LOG_WARNING, "%s is already in a bridge with %s\n",
- ast_channel_name(c1), ast_channel_name(ast_channel_internal_bridged_channel(c1)));
- return AST_BRIDGE_FAILED;
- }
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(ast_channel_flags(c0), AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
- ast_test_flag(ast_channel_flags(c1), AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1))
- return AST_BRIDGE_FAILED;
-
- o0nativeformats = ast_format_cap_dup(ast_channel_nativeformats(c0));
- o1nativeformats = ast_format_cap_dup(ast_channel_nativeformats(c1));
- if (!o0nativeformats || !o1nativeformats) {
- ast_format_cap_destroy(o0nativeformats);
- ast_format_cap_destroy(o1nativeformats);
- ast_log(LOG_WARNING, "failed to copy native formats\n");
- return AST_BRIDGE_FAILED;
- }
-
- caller_warning = ast_test_flag(&config->features_caller, AST_FEATURE_PLAY_WARNING);
- callee_warning = ast_test_flag(&config->features_callee, AST_FEATURE_PLAY_WARNING);
-
- if (ast_tvzero(config->start_time)) {
- config->start_time = ast_tvnow();
- if (config->start_sound) {
- if (caller_warning) {
- bridge_playfile(c0, c1, config->start_sound, config->timelimit / 1000);
- }
- if (callee_warning) {
- bridge_playfile(c1, c0, config->start_sound, config->timelimit / 1000);
- }
- }
- }
-
- /* Keep track of bridge */
- ast_channel_lock_both(c0, c1);
- ast_channel_internal_bridged_channel_set(c0, c1);
- ast_channel_internal_bridged_channel_set(c1, c0);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
-
- ast_set_owners_and_peers(c0, c1);
-
- if (config->feature_timer && !ast_tvzero(config->nexteventts)) {
- config->nexteventts = ast_tvadd(config->feature_start_time, ast_samp2tv(config->feature_timer, 1000));
- } else if (config->timelimit) {
- time_left_ms = config->timelimit - ast_tvdiff_ms(ast_tvnow(), config->start_time);
- config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
- if ((caller_warning || callee_warning) && config->play_warning) {
- long next_warn = config->play_warning;
- if (time_left_ms < config->play_warning && config->warning_freq > 0) {
- /* At least one warning was played, which means we are returning after feature */
- long warns_passed = (config->play_warning - time_left_ms) / config->warning_freq;
- /* It is 'warns_passed * warning_freq' NOT '(warns_passed + 1) * warning_freq',
- because nexteventts will be updated once again in the 'if (!to)' block */
- next_warn = config->play_warning - warns_passed * config->warning_freq;
- }
- config->nexteventts = ast_tvsub(config->nexteventts, ast_samp2tv(next_warn, 1000));
- }
- } else {
- config->nexteventts = ast_tv(0, 0);
- }
-
- if (!ast_channel_tech(c0)->send_digit_begin)
- ast_set_flag(ast_channel_flags(c1), AST_FLAG_END_DTMF_ONLY);
- if (!ast_channel_tech(c1)->send_digit_begin)
- ast_set_flag(ast_channel_flags(c0), AST_FLAG_END_DTMF_ONLY);
- manager_bridge_event(1, 1, c0, c1);
-
- /* Before we enter in and bridge these two together tell them both the source of audio has changed */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
-
- for (/* ever */;;) {
- struct timeval now = { 0, };
- int to;
-
- if (!ast_tvzero(config->nexteventts)) {
- now = ast_tvnow();
- to = ast_tvdiff_ms(config->nexteventts, now);
- if (to <= 0) {
- if (!config->timelimit) {
- res = AST_BRIDGE_COMPLETE;
- break;
- }
- to = 0;
- }
- } else {
- to = -1;
- }
-
- if (config->timelimit) {
- time_left_ms = config->timelimit - ast_tvdiff_ms(now, config->start_time);
- if (time_left_ms < to)
- to = time_left_ms;
-
- if (time_left_ms <= 0) {
- if (caller_warning && config->end_sound)
- bridge_playfile(c0, c1, config->end_sound, 0);
- if (callee_warning && config->end_sound)
- bridge_playfile(c1, c0, config->end_sound, 0);
- *fo = NULL;
- res = AST_BRIDGE_COMPLETE;
- ast_test_suite_event_notify("BRIDGE_TIMELIMIT",
- "Channel1: %s\r\n"
- "Channel2: %s",
- ast_channel_name(c0), ast_channel_name(c1));
- break;
- }
-
- if (!to) {
- if (time_left_ms >= 5000 && config->warning_sound && config->play_warning && ast_test_flag(config, AST_FEATURE_WARNING_ACTIVE)) {
- int t = (time_left_ms + 500) / 1000; /* round to nearest second */
- if (caller_warning)
- bridge_playfile(c0, c1, config->warning_sound, t);
- if (callee_warning)
- bridge_playfile(c1, c0, config->warning_sound, t);
- }
-
- if (config->warning_freq && (time_left_ms > (config->warning_freq + 5000))) {
- config->nexteventts = ast_tvadd(config->nexteventts, ast_samp2tv(config->warning_freq, 1000));
- } else {
- config->nexteventts = ast_tvadd(config->start_time, ast_samp2tv(config->timelimit, 1000));
- }
- }
- ast_clear_flag(config, AST_FEATURE_WARNING_ACTIVE);
- }
-
- if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */
- if (ast_channel_softhangup_internal_flag(c0) & AST_SOFTHANGUP_UNBRIDGE) {
- ast_channel_clear_softhangup(c0, AST_SOFTHANGUP_UNBRIDGE);
- }
- if (ast_channel_softhangup_internal_flag(c1) & AST_SOFTHANGUP_UNBRIDGE) {
- ast_channel_clear_softhangup(c1, AST_SOFTHANGUP_UNBRIDGE);
- }
- ast_channel_lock_both(c0, c1);
- ast_channel_internal_bridged_channel_set(c0, c1);
- ast_channel_internal_bridged_channel_set(c1, c0);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
- }
-
- /* Stop if we're a zombie or need a soft hangup */
- if (ast_test_flag(ast_channel_flags(c0), AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c0) ||
- ast_test_flag(ast_channel_flags(c1), AST_FLAG_ZOMBIE) || ast_check_hangup_locked(c1)) {
- *fo = NULL;
- res = AST_BRIDGE_COMPLETE;
- ast_debug(1, "Bridge stops because we're zombie or need a soft hangup: c0=%s, c1=%s, flags: %s,%s,%s,%s\n",
- ast_channel_name(c0), ast_channel_name(c1),
- ast_test_flag(ast_channel_flags(c0), AST_FLAG_ZOMBIE) ? "Yes" : "No",
- ast_check_hangup(c0) ? "Yes" : "No",
- ast_test_flag(ast_channel_flags(c1), AST_FLAG_ZOMBIE) ? "Yes" : "No",
- ast_check_hangup(c1) ? "Yes" : "No");
- break;
- }
-
- update_bridge_vars(c0, c1);
-
- bridge_play_sounds(c0, c1);
-
- if (ast_channel_tech(c0)->bridge &&
- /* if < 1 ms remains use generic bridging for accurate timing */
- (!config->timelimit || to > 1000 || to == 0) &&
- (ast_channel_tech(c0)->bridge == ast_channel_tech(c1)->bridge) &&
- !ast_channel_monitor(c0) && !ast_channel_monitor(c1) &&
- !ast_channel_audiohooks(c0) && !ast_channel_audiohooks(c1) &&
- ast_framehook_list_is_empty(ast_channel_framehooks(c0)) && ast_framehook_list_is_empty(ast_channel_framehooks(c1)) &&
- !ast_channel_masq(c0) && !ast_channel_masqr(c0) && !ast_channel_masq(c1) && !ast_channel_masqr(c1)) {
- int timeoutms = to - 1000 > 0 ? to - 1000 : to;
-
- /* Looks like they share a bridge method and nothing else is in the way */
- ast_set_flag(ast_channel_flags(c0), AST_FLAG_NBRIDGE);
- ast_set_flag(ast_channel_flags(c1), AST_FLAG_NBRIDGE);
- res = ast_channel_tech(c0)->bridge(c0, c1, config->flags, fo, rc, timeoutms);
- ast_clear_flag(ast_channel_flags(c0), AST_FLAG_NBRIDGE);
- ast_clear_flag(ast_channel_flags(c1), AST_FLAG_NBRIDGE);
- if (res == AST_BRIDGE_COMPLETE) {
- ast_debug(1, "Returning from native bridge, channels: %s, %s\n", ast_channel_name(c0), ast_channel_name(c1));
-
- if ((ast_channel_softhangup_internal_flag(c0) | ast_channel_softhangup_internal_flag(c1)) & AST_SOFTHANGUP_UNBRIDGE) {/* Bit operators are intentional. */
- ast_debug(1, "Unbridge signal received. Ending native bridge.\n");
- continue;
- }
- break;
- }
- switch (res) {
- case AST_BRIDGE_RETRY:
- if (config->play_warning) {
- ast_set_flag(config, AST_FEATURE_WARNING_ACTIVE);
- }
- continue;
- default:
- ast_verb(3, "Native bridging %s and %s ended\n", ast_channel_name(c0), ast_channel_name(c1));
- /* fallthrough */
- case AST_BRIDGE_FAILED_NOWARN:
- break;
- }
- }
-
- if (((ast_format_cmp(ast_channel_readformat(c1), ast_channel_writeformat(c0)) == AST_FORMAT_CMP_NOT_EQUAL) ||
- (ast_format_cmp(ast_channel_readformat(c0), ast_channel_writeformat(c1)) == AST_FORMAT_CMP_NOT_EQUAL) ||
- !ast_format_cap_identical(ast_channel_nativeformats(c0), o0nativeformats) ||
- !ast_format_cap_identical(ast_channel_nativeformats(c1), o1nativeformats)) &&
- !(ast_channel_generator(c0) || ast_channel_generator(c1))) {
- if (ast_channel_make_compatible(c0, c1)) {
- ast_log(LOG_WARNING, "Can't make %s and %s compatible\n", ast_channel_name(c0), ast_channel_name(c1));
- res = AST_BRIDGE_FAILED;
- break;
- }
-
- ast_format_cap_copy(o0nativeformats, ast_channel_nativeformats(c0));
- ast_format_cap_copy(o1nativeformats, ast_channel_nativeformats(c1));
- }
-
- update_bridge_vars(c0, c1);
-
- res = ast_generic_bridge(c0, c1, config, fo, rc);
- if (res != AST_BRIDGE_RETRY) {
- break;
- } else if (config->feature_timer) {
- /* feature timer expired but has not been updated, sending to ast_bridge_call to do so */
- break;
- }
- }
-
- ast_clear_flag(ast_channel_flags(c0), AST_FLAG_END_DTMF_ONLY);
- ast_clear_flag(ast_channel_flags(c1), AST_FLAG_END_DTMF_ONLY);
-
- /* Now that we have broken the bridge the source will change yet again */
- ast_indicate(c0, AST_CONTROL_SRCUPDATE);
- ast_indicate(c1, AST_CONTROL_SRCUPDATE);
-
- ast_channel_lock_both(c0, c1);
- ast_channel_internal_bridged_channel_set(c0, NULL);
- ast_channel_internal_bridged_channel_set(c1, NULL);
- ast_channel_unlock(c0);
- ast_channel_unlock(c1);
-
- manager_bridge_event(0, 1, c0, c1);
- ast_debug(1, "Bridge stops bridging channels %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
-
- ast_format_cap_destroy(o0nativeformats);
- ast_format_cap_destroy(o1nativeformats);
- return res;
}
/*! \brief Sets an option on a channel */
Modified: team/rmudgett/bridge_phase/main/channel_internal_api.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/channel_internal_api.c?view=diff&rev=390108&r1=390107&r2=390108
==============================================================================
--- team/rmudgett/bridge_phase/main/channel_internal_api.c (original)
+++ team/rmudgett/bridge_phase/main/channel_internal_api.c Wed May 29 20:11:39 2013
@@ -262,7 +262,6 @@
ast_data_add_bool(tree, "EXCEPTION", ast_test_flag(ast_channel_flags(chan), AST_FLAG_EXCEPTION));
ast_data_add_bool(tree, "MOH", ast_test_flag(ast_channel_flags(chan), AST_FLAG_MOH));
ast_data_add_bool(tree, "SPYING", ast_test_flag(ast_channel_flags(chan), AST_FLAG_SPYING));
- ast_data_add_bool(tree, "NBRIDGE", ast_test_flag(ast_channel_flags(chan), AST_FLAG_NBRIDGE));
ast_data_add_bool(tree, "IN_AUTOLOOP", ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP));
ast_data_add_bool(tree, "OUTGOING", ast_test_flag(ast_channel_flags(chan), AST_FLAG_OUTGOING));
ast_data_add_bool(tree, "IN_DTMF", ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_DTMF));
Modified: team/rmudgett/bridge_phase/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/main/features.c?view=diff&rev=390108&r1=390107&r2=390108
==============================================================================
--- team/rmudgett/bridge_phase/main/features.c (original)
+++ team/rmudgett/bridge_phase/main/features.c Wed May 29 20:11:39 2013
@@ -4315,10 +4315,6 @@
{
int res;
-/* BUGBUG these channel vars may need to be made dynamic so they update when transfers happen. */
- pbx_builtin_setvar_helper(chan, "BRIDGEPEER", ast_channel_name(peer));
- pbx_builtin_setvar_helper(peer, "BRIDGEPEER", ast_channel_name(chan));
-
set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES"));
add_features_datastores(chan, peer, config);
More information about the asterisk-commits
mailing list