simplify the flow of builtin_atxfer().

There is still a lot of similarity with builtin_blindtransfer()
which should be removed by definining functions for the common
pieces of code (eg in the first part).



git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@21097 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.4
Luigi Rizzo 20 years ago
parent 177b8e9143
commit 51743a4aea

@ -444,7 +444,7 @@ static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *pee
char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL; char *caller_chan_id = NULL, *callee_chan_id = NULL, *args = NULL, *touch_filename = NULL;
int x = 0; int x = 0;
size_t len; size_t len;
struct ast_channel *caller_chan = NULL, *callee_chan = NULL; struct ast_channel *caller_chan, *callee_chan;
if (!monitor_ok) { if (!monitor_ok) {
ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n"); ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
@ -574,9 +574,9 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
if (res < 0) { if (res < 0) {
finishup(transferee); finishup(transferee);
return -1; /* error ? */ return -1; /* error ? */
} else if (res > 0) { /* If they've typed a digit already, handle it */
xferto[0] = (char) res;
} }
if (res > 0) /* If they've typed a digit already, handle it */
xferto[0] = (char) res;
ast_stopstream(transferer); ast_stopstream(transferer);
res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout); res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, transferdigittimeout);
@ -634,18 +634,31 @@ static int builtin_blindtransfer(struct ast_channel *chan, struct ast_channel *p
return FEATURE_RETURN_SUCCESS; return FEATURE_RETURN_SUCCESS;
} }
static int check_compat(struct ast_channel *c, struct ast_channel *newchan)
{
if (ast_channel_make_compatible(c, newchan) < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n",
c->name, newchan->name);
ast_hangup(newchan);
return -1;
}
return 0;
}
static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense) static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense)
{ {
struct ast_channel *transferer; struct ast_channel *transferer;
struct ast_channel *transferee; struct ast_channel *transferee;
struct ast_channel *newchan, *xferchan=NULL;
int outstate=0;
struct ast_bridge_config bconfig;
const char *transferer_real_context; const char *transferer_real_context;
char xferto[256],dialstr[265]; char xferto[256];
int res; int res;
struct ast_frame *f = NULL; int outstate=0;
struct ast_channel *newchan;
struct ast_channel *xferchan;
struct ast_bridge_thread_obj *tobj; struct ast_bridge_thread_obj *tobj;
struct ast_bridge_config bconfig;
struct ast_frame *f;
int l;
if (option_debug) if (option_debug)
ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense); ast_log(LOG_DEBUG, "Executing Attended Transfer %s, %s (sense=%d) \n", chan->name, peer->name, sense);
@ -661,7 +674,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
if (res < 0) { if (res < 0) {
finishup(transferee); finishup(transferee);
return res; return res;
} else if (res > 0) /* If they've typed a digit already, handle it */ }
if (res > 0) /* If they've typed a digit already, handle it */
xferto[0] = (char) res; xferto[0] = (char) res;
/* this is specific of atxfer */ /* this is specific of atxfer */
@ -677,16 +691,20 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
return -1; return -1;
return FEATURE_RETURN_SUCCESS; return FEATURE_RETURN_SUCCESS;
} }
/* valid extension, res == 1 */ /* valid extension, res == 1 */
{ if (!ast_exists_extension(transferer, transferer_real_context, xferto, 1, transferer->cid.cid_num)) {
if (!ast_exists_extension(transferer, transferer_real_context,xferto, 1, transferer->cid.cid_num)) {
ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context); ast_log(LOG_WARNING, "Extension %s does not exist in context %s\n",xferto,transferer_real_context);
finishup(transferee); finishup(transferee);
if (stream_and_wait(transferer, "beeperr", transferer->language, "")) if (stream_and_wait(transferer, "beeperr", transferer->language, ""))
return -1; return -1;
} else { return FEATURE_RETURN_SUCCESS;
snprintf(dialstr, sizeof(dialstr), "%s@%s/n", xferto, transferer_real_context); }
newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats), dialstr, 15000, &outstate, transferer->cid.cid_num, transferer->cid.cid_name);
l = strlen(xferto);
snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context); /* append context */
newchan = ast_feature_request_and_dial(transferer, "Local", ast_best_codec(transferer->nativeformats),
xferto, 15000, &outstate, transferer->cid.cid_num, transferer->cid.cid_name);
ast_indicate(transferer, -1); ast_indicate(transferer, -1);
if (!newchan) { if (!newchan) {
finishup(transferee); finishup(transferee);
@ -696,23 +714,15 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
return -1; return -1;
return FEATURE_RETURN_SUCCESS; return FEATURE_RETURN_SUCCESS;
} }
{
res = ast_channel_make_compatible(transferer, newchan); if (check_compat(transferer, newchan))
if (res < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferer->name, newchan->name);
ast_hangup(newchan);
return -1; return -1;
}
memset(&bconfig,0,sizeof(struct ast_bridge_config)); memset(&bconfig,0,sizeof(struct ast_bridge_config));
ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT); ast_set_flag(&(bconfig.features_caller), AST_FEATURE_DISCONNECT);
ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT); ast_set_flag(&(bconfig.features_callee), AST_FEATURE_DISCONNECT);
res = ast_bridge_call(transferer,newchan,&bconfig); res = ast_bridge_call(transferer, newchan, &bconfig);
if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) { if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) {
ast_hangup(newchan); ast_hangup(newchan);
if (f) {
ast_frfree(f);
f = NULL;
}
if (stream_and_wait(transferer, xfersound, transferer->language, "")) if (stream_and_wait(transferer, xfersound, transferer->language, ""))
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
finishup(transferee); finishup(transferee);
@ -720,13 +730,8 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
return FEATURE_RETURN_SUCCESS; return FEATURE_RETURN_SUCCESS;
} }
res = ast_channel_make_compatible(transferee, newchan); if (check_compat(transferee, newchan))
if (res < 0) {
ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", transferee->name, newchan->name);
ast_hangup(newchan);
return -1; return -1;
}
ast_moh_stop(transferee); ast_moh_stop(transferee);
@ -736,11 +741,14 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
|| ast_check_hangup(transferee) || ast_check_hangup(transferee)
|| ast_check_hangup(newchan)) { || ast_check_hangup(newchan)) {
ast_hangup(newchan); ast_hangup(newchan);
res = -1;
return -1; return -1;
} }
if ((xferchan = ast_channel_alloc(0))) { xferchan = ast_channel_alloc(0);
if (!xferchan) {
ast_hangup(newchan);
return -1;
}
ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name); ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name);
/* Make formats okay */ /* Make formats okay */
xferchan->readformat = transferee->readformat; xferchan->readformat = transferee->readformat;
@ -751,21 +759,19 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
ast_clear_flag(xferchan, AST_FLAGS_ALL); ast_clear_flag(xferchan, AST_FLAGS_ALL);
xferchan->_softhangup = 0; xferchan->_softhangup = 0;
if ((f = ast_read(xferchan))) { if ((f = ast_read(xferchan)))
ast_frfree(f); ast_frfree(f);
f = NULL;
}
} else {
ast_hangup(newchan);
return -1;
}
newchan->_state = AST_STATE_UP; newchan->_state = AST_STATE_UP;
ast_clear_flag(newchan, AST_FLAGS_ALL); ast_clear_flag(newchan, AST_FLAGS_ALL);
newchan->_softhangup = 0; newchan->_softhangup = 0;
if ((tobj = ast_calloc(1, sizeof(*tobj)))) { tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj));
if (!tobj) {
ast_hangup(xferchan);
ast_hangup(newchan);
return -1;
}
tobj->chan = xferchan; tobj->chan = xferchan;
tobj->peer = newchan; tobj->peer = newchan;
tobj->bconfig = *config; tobj->bconfig = *config;
@ -773,18 +779,7 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st
if (stream_and_wait(newchan, xfersound, newchan->language, "")) if (stream_and_wait(newchan, xfersound, newchan->language, ""))
ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
ast_bridge_call_thread_launch(tobj); ast_bridge_call_thread_launch(tobj);
} else { return -1; /* XXX meaning the channel is bridged ? */
ast_hangup(xferchan);
ast_hangup(newchan);
}
return -1;
}
}
}
finishup(transferee);
return FEATURE_RETURN_SUCCESS;
} }

Loading…
Cancel
Save