simplify the flow of builtin_atxfer().
authorLuigi Rizzo <rizzo@icir.org>
Tue, 18 Apr 2006 13:05:48 +0000 (13:05 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Tue, 18 Apr 2006 13:05:48 +0000 (13:05 +0000)
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

res/res_features.c

index 82e7d7f..a9a0a98 100644 (file)
@@ -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 ? */
 }