diff options
author | Richard Mudgett <rmudgett@digium.com> | 2013-05-31 16:15:32 +0000 |
---|---|---|
committer | Richard Mudgett <rmudgett@digium.com> | 2013-05-31 16:15:32 +0000 |
commit | 680765d452f3c19ed6be54919503e8c7fad905ce (patch) | |
tree | 00ccd929bf1317f493de420cf29123985d384e88 /main | |
parent | ccc8cc5346f7f68f38b1749755777a33cd897f07 (diff) |
Remove ast_channel_bridge() and associated code called only by it.
* Added some more BUGBUG notes.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390291 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'main')
-rw-r--r-- | main/channel.c | 623 | ||||
-rw-r--r-- | main/channel_internal_api.c | 1 | ||||
-rw-r--r-- | main/manager.c | 1 |
3 files changed, 3 insertions, 622 deletions
diff --git a/main/channel.c b/main/channel.c index 190271321..1c2d6bf57 100644 --- a/main/channel.c +++ b/main/channel.c @@ -6655,6 +6655,7 @@ void ast_channel_set_linkgroup(struct ast_channel *chan, struct ast_channel *pee } } +#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) @@ -6690,6 +6691,7 @@ static void ast_set_owners_and_peers(struct ast_channel *chan1, ast_channel_peeraccount_set(chan1, ast_channel_accountcode(chan2)); } } +#endif //BUGBUG /*! * \internal @@ -7322,251 +7324,6 @@ struct ast_channel *ast_bridged_channel(struct ast_channel *chan) 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) { @@ -7577,382 +7334,6 @@ int ast_channel_early_bridge(struct ast_channel *c0, struct ast_channel *c1) 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 */ int ast_channel_setoption(struct ast_channel *chan, int option, void *data, int datalen, int block) { diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c index 87551f72f..ed45ddcfe 100644 --- a/main/channel_internal_api.c +++ b/main/channel_internal_api.c @@ -262,7 +262,6 @@ static void channel_data_add_flags(struct ast_data *tree, 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)); diff --git a/main/manager.c b/main/manager.c index 720a9396f..229b83b4e 100644 --- a/main/manager.c +++ b/main/manager.c @@ -4077,6 +4077,7 @@ static int action_atxfer(struct mansession *s, const struct message *m) pbx_builtin_setvar_helper(chan, "TRANSFER_CONTEXT", context); } +/* BUGBUG action_atxfer() is broken because the bridge DTMF hooks need both begin and end events to match correctly. */ for (feature_code = atxfer_feature->exten; feature_code && *feature_code; ++feature_code) { struct ast_frame f = { AST_FRAME_DTMF, .subclass.integer = *feature_code }; ast_queue_frame(chan, &f); |