[asterisk-commits] mmichelson: branch group/issue8824 r167604 - /team/group/issue8824/main/
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jan 7 17:17:36 CST 2009
Author: mmichelson
Date: Wed Jan 7 17:17:35 2009
New Revision: 167604
URL: http://svn.digium.com/view/asterisk?view=rev&rev=167604
Log:
Make attended transfers show correct connected line information for all parties
involved
Modified:
team/group/issue8824/main/features.c
Modified: team/group/issue8824/main/features.c
URL: http://svn.digium.com/view/asterisk/team/group/issue8824/main/features.c?view=diff&rev=167604&r1=167603&r2=167604
==============================================================================
--- team/group/issue8824/main/features.c (original)
+++ team/group/issue8824/main/features.c Wed Jan 7 17:17:35 2009
@@ -1284,7 +1284,7 @@
struct ast_bridge_config bconfig;
struct ast_frame *f;
int l;
- struct ast_party_connected_line connected_line;
+ struct ast_party_connected_line connected_line = {{0,},};
ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
set_peers(&transferer, &transferee, peer, chan, sense);
@@ -1367,6 +1367,15 @@
memset(&bconfig,0,sizeof(struct ast_bridge_config));
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
+ /* We need to get the transferer's connected line information copied
+ * at this point because he is likely to hang up during the bridge with
+ * newchan. This info will be used down below before bridging the
+ * transferee and newchan
+ *
+ * As a result, we need to be sure to free this data before returning
+ * or overwriting it.
+ */
+ ast_party_connected_line_copy(&connected_line, &transferer->connected);
res = ast_bridge_call(transferer, newchan, &bconfig);
if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
ast_hangup(newchan);
@@ -1374,10 +1383,12 @@
ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
finishup(transferee);
transferer->_softhangup = 0;
+ ast_party_connected_line_free(&connected_line);
return AST_FEATURE_RETURN_SUCCESS;
}
if (check_compat(transferee, newchan)) {
finishup(transferee);
+ ast_party_connected_line_free(&connected_line);
return -1;
}
ast_indicate(transferee, AST_CONTROL_UNHOLD);
@@ -1388,8 +1399,125 @@
|| ast_check_hangup(transferee)
|| ast_check_hangup(newchan)) {
ast_hangup(newchan);
+ ast_party_connected_line_free(&connected_line);
return -1;
}
+ xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
+ if (!xferchan) {
+ ast_hangup(newchan);
+ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+ /* Make formats okay */
+ xferchan->visible_indication = transferer->visible_indication;
+ xferchan->readformat = transferee->readformat;
+ xferchan->writeformat = transferee->writeformat;
+ ast_channel_masquerade(xferchan, transferee);
+ ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
+ xferchan->_state = AST_STATE_UP;
+ ast_clear_flag(xferchan, AST_FLAGS_ALL);
+ xferchan->_softhangup = 0;
+ if ((f = ast_read(xferchan)))
+ ast_frfree(f);
+ newchan->_state = AST_STATE_UP;
+ ast_clear_flag(newchan, AST_FLAGS_ALL);
+ newchan->_softhangup = 0;
+ if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
+ ast_hangup(xferchan);
+ ast_hangup(newchan);
+ ast_party_connected_line_free(&connected_line);
+ return -1;
+ }
+ tobj->chan = newchan;
+ tobj->peer = xferchan;
+ tobj->bconfig = *config;
+
+ if (tobj->bconfig.end_bridge_callback_data_fixup) {
+ tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
+ }
+
+ /* Due to a limitation regarding when callerID is set on a Local channel,
+ * we use the transferer's connected line information here.
+ */
+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_connected_line_update(xferchan, &connected_line);
+ /* We need to free the allocated information in connected_line before overwriting
+ * the info with the callerid of xferchan. Otherwise, there would be a memory leak
+ */
+ ast_party_connected_line_free(&connected_line);
+ ast_party_connected_line_collect_caller(&connected_line, &xferchan->cid);
+ connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
+ ast_connected_line_update(newchan, &connected_line);
+
+ if (ast_stream_and_wait(newchan, xfersound, ""))
+ ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
+ ast_bridge_call_thread_launch(tobj);
+ return -1; /* XXX meaning the channel is bridged ? */
+ } else if (!ast_check_hangup(transferee)) {
+ /* act as blind transfer */
+ if (ast_autoservice_stop(transferee) < 0) {
+ ast_hangup(newchan);
+ return -1;
+ }
+
+ if (!newchan) {
+ unsigned int tries = 0;
+ char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
+
+ transferer_tech = strsep(&transferer_name, "/");
+ transferer_name = strsep(&transferer_name, "-");
+
+ if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
+ ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
+ if (ast_stream_and_wait(transferee, "beeperr", ""))
+ return -1;
+ return AST_FEATURE_RETURN_SUCCESS;
+ }
+
+ ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
+ newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
+ transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+ while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
+ /* Trying to transfer again */
+ ast_autoservice_start(transferee);
+ ast_indicate(transferee, AST_CONTROL_HOLD);
+
+ newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
+ xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
+ if (ast_autoservice_stop(transferee) < 0) {
+ if (newchan)
+ ast_hangup(newchan);
+ return -1;
+ }
+ if (!newchan) {
+ /* Transfer failed, sleeping */
+ ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
+ ast_safe_sleep(transferee, atxferloopdelay);
+ ast_debug(1, "Trying to callback...\n");
+ newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
+ transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
+ }
+ tries++;
+ }
+ }
+ if (!newchan)
+ return -1;
+
+ /* newchan is up, we should prepare transferee and bridge them */
+ if (check_compat(transferee, newchan)) {
+ finishup(transferee);
+ return -1;
+ }
+ ast_indicate(transferee, AST_CONTROL_UNHOLD);
+
+ if ((ast_waitfordigit(transferee, 100) < 0)
+ || (ast_waitfordigit(newchan, 100) < 0)
+ || ast_check_hangup(transferee)
+ || ast_check_hangup(newchan)) {
+ ast_hangup(newchan);
+ return -1;
+ }
+
xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
if (!xferchan) {
ast_hangup(newchan);
@@ -1417,114 +1545,6 @@
tobj->chan = newchan;
tobj->peer = xferchan;
tobj->bconfig = *config;
-
- if (tobj->bconfig.end_bridge_callback_data_fixup) {
- tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
- }
-
- ast_party_connected_line_collect_caller(&connected_line, &newchan->cid);
- connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_connected_line_update(xferchan, &connected_line);
- ast_party_connected_line_collect_caller(&connected_line, &xferchan->cid);
- connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
- ast_connected_line_update(newchan, &connected_line);
-
- if (ast_stream_and_wait(newchan, xfersound, ""))
- ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
- ast_bridge_call_thread_launch(tobj);
- return -1; /* XXX meaning the channel is bridged ? */
- } else if (!ast_check_hangup(transferee)) {
- /* act as blind transfer */
- if (ast_autoservice_stop(transferee) < 0) {
- ast_hangup(newchan);
- return -1;
- }
-
- if (!newchan) {
- unsigned int tries = 0;
- char *transferer_tech, *transferer_name = ast_strdupa(transferer->name);
-
- transferer_tech = strsep(&transferer_name, "/");
- transferer_name = strsep(&transferer_name, "-");
-
- if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
- ast_log(LOG_WARNING, "Transferer has invalid channel name: '%s'\n", transferer->name);
- if (ast_stream_and_wait(transferee, "beeperr", ""))
- return -1;
- return AST_FEATURE_RETURN_SUCCESS;
- }
-
- ast_log(LOG_NOTICE, "We're trying to call %s/%s\n", transferer_tech, transferer_name);
- newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
- transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
- while (!newchan && !atxferdropcall && tries < atxfercallbackretries) {
- /* Trying to transfer again */
- ast_autoservice_start(transferee);
- ast_indicate(transferee, AST_CONTROL_HOLD);
-
- newchan = ast_feature_request_and_dial(transferer, transferee, "Local", ast_best_codec(transferer->nativeformats),
- xferto, atxfernoanswertimeout, &outstate, transferer->cid.cid_num, transferer->cid.cid_name, 1, transferer->language);
- if (ast_autoservice_stop(transferee) < 0) {
- if (newchan)
- ast_hangup(newchan);
- return -1;
- }
- if (!newchan) {
- /* Transfer failed, sleeping */
- ast_debug(1, "Sleeping for %d ms before callback.\n", atxferloopdelay);
- ast_safe_sleep(transferee, atxferloopdelay);
- ast_debug(1, "Trying to callback...\n");
- newchan = ast_feature_request_and_dial(transferee, NULL, transferer_tech, ast_best_codec(transferee->nativeformats),
- transferer_name, atxfernoanswertimeout, &outstate, transferee->cid.cid_num, transferee->cid.cid_name, 0, transferer->language);
- }
- tries++;
- }
- }
- if (!newchan)
- return -1;
-
- /* newchan is up, we should prepare transferee and bridge them */
- if (check_compat(transferee, newchan)) {
- finishup(transferee);
- return -1;
- }
- ast_indicate(transferee, AST_CONTROL_UNHOLD);
-
- if ((ast_waitfordigit(transferee, 100) < 0)
- || (ast_waitfordigit(newchan, 100) < 0)
- || ast_check_hangup(transferee)
- || ast_check_hangup(newchan)) {
- ast_hangup(newchan);
- return -1;
- }
-
- xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", 0, "Transfered/%s", transferee->name);
- if (!xferchan) {
- ast_hangup(newchan);
- return -1;
- }
- /* Make formats okay */
- xferchan->visible_indication = transferer->visible_indication;
- xferchan->readformat = transferee->readformat;
- xferchan->writeformat = transferee->writeformat;
- ast_channel_masquerade(xferchan, transferee);
- ast_explicit_goto(xferchan, transferee->context, transferee->exten, transferee->priority);
- xferchan->_state = AST_STATE_UP;
- ast_clear_flag(xferchan, AST_FLAGS_ALL);
- xferchan->_softhangup = 0;
- if ((f = ast_read(xferchan)))
- ast_frfree(f);
- newchan->_state = AST_STATE_UP;
- ast_clear_flag(newchan, AST_FLAGS_ALL);
- newchan->_softhangup = 0;
- if (!(tobj = ast_calloc(1, sizeof(*tobj)))) {
- ast_hangup(xferchan);
- ast_hangup(newchan);
- return -1;
- }
- tobj->chan = newchan;
- tobj->peer = xferchan;
- tobj->bconfig = *config;
if (tobj->bconfig.end_bridge_callback_data_fixup) {
tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
@@ -2028,6 +2048,8 @@
ast_channel_inherit_variables(caller, chan);
pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller->name);
+ ast_copy_caller_to_connected(&chan->connected, &caller->cid);
+
if (ast_call(chan, data, timeout)) {
ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, (char *)data);
goto done;
More information about the asterisk-commits
mailing list