diff --git a/res/res_features.c b/res/res_features.c index 82e7d7f3f5f576df3cac319fb2b42976580967fc..a9a0a98c4c1b5db9e0ab320a4e696106a3e9982b 100644 --- a/res/res_features.c +++ b/res/res_features.c @@ -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; int x = 0; size_t len; - struct ast_channel *caller_chan = NULL, *callee_chan = NULL; + struct ast_channel *caller_chan, *callee_chan; if (!monitor_ok) { 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) { finishup(transferee); 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); 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; } +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) { struct ast_channel *transferer; struct ast_channel *transferee; - struct ast_channel *newchan, *xferchan=NULL; - int outstate=0; - struct ast_bridge_config bconfig; const char *transferer_real_context; - char xferto[256],dialstr[265]; + char xferto[256]; 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_config bconfig; + struct ast_frame *f; + int l; if (option_debug) 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) { finishup(transferee); 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; /* this is specific of atxfer */ @@ -677,114 +691,95 @@ static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, st return -1; return FEATURE_RETURN_SUCCESS; } + /* valid extension, res == 1 */ - { - 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); - finishup(transferee); - if (stream_and_wait(transferer, "beeperr", transferer->language, "")) - return -1; - } else { - 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); - ast_indicate(transferer, -1); - if (!newchan) { - finishup(transferee); - /* any reason besides user requested cancel and busy triggers the failed sound */ - if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && - stream_and_wait(transferer, xferfailsound, transferer->language, "")) - return -1; - return FEATURE_RETURN_SUCCESS; - } - { - res = ast_channel_make_compatible(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; - } - 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); - res = ast_bridge_call(transferer,newchan,&bconfig); - if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) { - ast_hangup(newchan); - if (f) { - ast_frfree(f); - f = NULL; - } - if (stream_and_wait(transferer, xfersound, transferer->language, "")) - ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); - finishup(transferee); - transferer->_softhangup = 0; - return FEATURE_RETURN_SUCCESS; - } - - res = ast_channel_make_compatible(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; - } - - - ast_moh_stop(transferee); - - if ((ast_autoservice_stop(transferee) < 0) - || (ast_waitfordigit(transferee, 100) < 0) - || (ast_waitfordigit(newchan, 100) < 0) - || ast_check_hangup(transferee) - || ast_check_hangup(newchan)) { - ast_hangup(newchan); - res = -1; - return -1; - } + 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); + finishup(transferee); + if (stream_and_wait(transferer, "beeperr", transferer->language, "")) + return -1; + return FEATURE_RETURN_SUCCESS; + } - if ((xferchan = ast_channel_alloc(0))) { - ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name); - /* Make formats okay */ - 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); - f = NULL; - } - - } else { - ast_hangup(newchan); - return -1; - } + 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); + if (!newchan) { + finishup(transferee); + /* any reason besides user requested cancel and busy triggers the failed sound */ + if (outstate != AST_CONTROL_UNHOLD && outstate != AST_CONTROL_BUSY && + stream_and_wait(transferer, xferfailsound, transferer->language, "")) + return -1; + return FEATURE_RETURN_SUCCESS; + } - newchan->_state = AST_STATE_UP; - ast_clear_flag(newchan, AST_FLAGS_ALL); - newchan->_softhangup = 0; - - if ((tobj = ast_calloc(1, sizeof(*tobj)))) { - tobj->chan = xferchan; - tobj->peer = newchan; - tobj->bconfig = *config; + if (check_compat(transferer, newchan)) + return -1; + 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); + res = ast_bridge_call(transferer, newchan, &bconfig); + if (newchan->_softhangup || newchan->_state != AST_STATE_UP || !transferer->_softhangup) { + ast_hangup(newchan); + if (stream_and_wait(transferer, xfersound, transferer->language, "")) + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); + finishup(transferee); + transferer->_softhangup = 0; + return FEATURE_RETURN_SUCCESS; + } - if (stream_and_wait(newchan, xfersound, newchan->language, "")) - ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); - ast_bridge_call_thread_launch(tobj); - } else { - ast_hangup(xferchan); - ast_hangup(newchan); - } - return -1; - - } - } + if (check_compat(transferee, newchan)) + return -1; + + ast_moh_stop(transferee); + + if ((ast_autoservice_stop(transferee) < 0) + || (ast_waitfordigit(transferee, 100) < 0) + || (ast_waitfordigit(newchan, 100) < 0) + || ast_check_hangup(transferee) + || ast_check_hangup(newchan)) { + ast_hangup(newchan); + return -1; } - finishup(transferee); - return FEATURE_RETURN_SUCCESS; + xferchan = ast_channel_alloc(0); + if (!xferchan) { + ast_hangup(newchan); + return -1; + } + ast_string_field_build(xferchan, name, "Transfered/%s", transferee->name); + /* Make formats okay */ + 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; + + tobj = ast_calloc(1, sizeof(struct ast_bridge_thread_obj)); + if (!tobj) { + ast_hangup(xferchan); + ast_hangup(newchan); + return -1; + } + tobj->chan = xferchan; + tobj->peer = newchan; + tobj->bconfig = *config; + + if (stream_and_wait(newchan, xfersound, newchan->language, "")) + ast_log(LOG_WARNING, "Failed to play courtesy tone!\n"); + ast_bridge_call_thread_launch(tobj); + return -1; /* XXX meaning the channel is bridged ? */ }