Remove dead bridging code from features
authorMatthew Jordan <mjordan@digium.com>
Thu, 25 Jul 2013 14:34:09 +0000 (14:34 +0000)
committerMatthew Jordan <mjordan@digium.com>
Thu, 25 Jul 2013 14:34:09 +0000 (14:34 +0000)
This removes the previously #if 0'd code. The functionality removed has either
been subsumed by the Bridging API or is no longer applicable.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@395400 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/features.c

index 346e4af..49f7718 100644 (file)
@@ -775,109 +775,11 @@ static void set_c_e_p(struct ast_channel *chan, const char *context, const char
        ast_channel_priority_set(chan, pri);
 }
 
-#if 0
-static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
-       const char *caller_name, struct ast_channel *requestor,
-       struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
-       int timeout, int *outstate, const char *language);
-#endif
-
 static const struct ast_datastore_info channel_app_data_datastore = {
        .type = "Channel appdata datastore",
        .destroy = ast_free_ptr,
 };
 
-#if 0
-static int set_chan_app_data(struct ast_channel *chan, const char *src_app_data)
-{
-       struct ast_datastore *datastore;
-       char *dst_app_data;
-
-       datastore = ast_datastore_alloc(&channel_app_data_datastore, NULL);
-       if (!datastore) {
-               return -1;
-       }
-
-       dst_app_data = ast_malloc(strlen(src_app_data) + 1);
-       if (!dst_app_data) {
-               ast_datastore_free(datastore);
-               return -1;
-       }
-
-       ast_channel_data_set(chan, strcpy(dst_app_data, src_app_data));
-       datastore->data = dst_app_data;
-       ast_channel_datastore_add(chan, datastore);
-       return 0;
-}
-#endif
-
-#if 0
-/*!
- * \brief bridge the call
- * \param data thread bridge.
- *
- * Set Last Data for respective channels, reset cdr for channels
- * bridge call, check if we're going back to dialplan
- * if not hangup both legs of the call
- */
-static void *bridge_call_thread(void *data)
-{
-       struct ast_bridge_thread_obj *tobj = data;
-
-       if (tobj->callid) {
-               ast_callid_threadassoc_add(tobj->callid);
-               /* Need to deref and set to null since ast_bridge_thread_obj has no common destructor */
-               tobj->callid = ast_callid_unref(tobj->callid);
-       }
-
-       ast_channel_appl_set(tobj->chan, !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge");
-       if (set_chan_app_data(tobj->chan, ast_channel_name(tobj->peer))) {
-               ast_channel_data_set(tobj->chan, "(Empty)");
-       }
-       ast_channel_appl_set(tobj->peer, !tobj->return_to_pbx ? "Transferred Call" : "ManagerBridge");
-       if (set_chan_app_data(tobj->peer, ast_channel_name(tobj->chan))) {
-               ast_channel_data_set(tobj->peer, "(Empty)");
-       }
-
-       if (tobj->return_to_pbx) {
-               ast_bridge_set_after_goto(tobj->chan, ast_channel_context(tobj->chan),
-                       ast_channel_exten(tobj->chan), ast_channel_priority(tobj->chan));
-               ast_bridge_set_after_goto(tobj->peer, ast_channel_context(tobj->peer),
-                       ast_channel_exten(tobj->peer), ast_channel_priority(tobj->peer));
-       }
-
-       ast_bridge_call(tobj->chan, tobj->peer, &tobj->bconfig);
-
-       ast_bridge_run_after_goto(tobj->chan);
-
-       ast_free(tobj);
-
-       return NULL;
-}
-#endif
-
-#if 0
-/*!
- * \brief create thread for the bridging call
- * \param tobj
- */
-static void bridge_call_thread_launch(struct ast_bridge_thread_obj *tobj)
-{
-       pthread_t thread;
-
-       /* This needs to be unreffed once it has been associated with the new thread. */
-       tobj->callid = ast_read_threadstorage_callid();
-
-       if (ast_pthread_create_detached(&thread, NULL, bridge_call_thread, tobj)) {
-               ast_log(LOG_ERROR, "Failed to create bridge_call_thread.\n");
-               ast_callid_unref(tobj->callid);
-               ast_hangup(tobj->chan);
-               ast_hangup(tobj->peer);
-               ast_free(tobj);
-       }
-}
-#endif
-
 /*!
  * \brief Announce call parking by ADSI
  * \param chan .
@@ -1707,156 +1609,6 @@ int ast_masq_park_call(struct ast_channel *rchan, struct ast_channel *peer, int
        return masq_park_call(rchan, peer, &args);
 }
 
-#if 0
-static int finishup(struct ast_channel *chan)
-{
-       ast_indicate(chan, AST_CONTROL_UNHOLD);
-
-       return ast_autoservice_stop(chan);
-}
-#endif
-
-#if 0
-/*!
- * \internal
- * \brief Builtin transfer park call helper.
- *
- * \param park_me Channel to be parked.
- * \param parker Channel parking the call.
- * \param park_exten Parking lot dialplan access ramp extension.
- *
- * \note Assumes park_me is on hold and in autoservice.
- *
- * \retval -1 on successful park.
- * \retval -1 on park_me hangup.
- * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
- */
-static int xfer_park_call_helper(struct ast_channel *park_me, struct ast_channel *parker, struct ast_exten *park_exten)
-{
-       char *parse;
-       const char *app_data;
-       const char *pl_name;
-       struct ast_park_call_args args = { 0, };
-       struct park_app_args app_args;
-       int res;
-
-       app_data = ast_get_extension_app_data(park_exten);
-       if (!app_data) {
-               app_data = "";
-       }
-       parse = ast_strdupa(app_data);
-       AST_STANDARD_APP_ARGS(app_args, parse);
-
-       /* Find the parking lot */
-       if (!ast_strlen_zero(app_args.pl_name)) {
-               pl_name = app_args.pl_name;
-       } else {
-               pl_name = findparkinglotname(parker);
-       }
-       if (ast_strlen_zero(pl_name)) {
-               /* Parking lot is not specified, so use the default parking lot. */
-               args.parkinglot = parkinglot_addref(default_parkinglot);
-       } else {
-               args.parkinglot = find_parkinglot(pl_name);
-               if (!args.parkinglot && parkeddynamic) {
-                       args.parkinglot = create_dynamic_parkinglot(pl_name, park_me);
-               }
-       }
-
-       if (args.parkinglot) {
-               /* Park the call */
-               res = finishup(park_me);
-               if (res) {
-                       /* park_me hungup on us. */
-                       parkinglot_unref(args.parkinglot);
-                       return -1;
-               }
-               res = masq_park_call(park_me, parker, &args);
-               parkinglot_unref(args.parkinglot);
-       } else {
-               /* Parking failed because parking lot does not exist. */
-               if (!ast_test_flag(&args, AST_PARK_OPT_SILENCE)) {
-                       ast_stream_and_wait(parker, "pbx-parkingfailed", "");
-               }
-               finishup(park_me);
-               res = -1;
-       }
-
-       return res ? AST_FEATURE_RETURN_SUCCESS : -1;
-}
-#endif
-
-#if 0
-/*!
- * \brief set caller and callee according to the direction
- * \param caller, callee, peer, chan, sense
- *
- * Detect who triggered feature and set callee/caller variables accordingly
- */
-static void set_peers(struct ast_channel **caller, struct ast_channel **callee,
-       struct ast_channel *peer, struct ast_channel *chan, int sense)
-{
-       if (sense == FEATURE_SENSE_PEER) {
-               *caller = peer;
-               *callee = chan;
-       } else {
-               *callee = peer;
-               *caller = chan;
-       }
-}
-#endif
-
-#if 0
-/*!
- * \brief support routing for one touch call parking
- * \param chan channel parking call
- * \param peer channel to be parked
- * \param config unsed
- * \param code unused
- * \param sense feature options
- * \param data unused
- *
- * \retval -1 on successful park.
- * \retval -1 on chan hangup.
- * \retval AST_FEATURE_RETURN_SUCCESS on error to keep the bridge connected.
- */
-static int builtin_parkcall(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-       struct ast_channel *parker;
-       struct ast_channel *parkee;
-       struct ast_park_call_args args = { 0, };
-
-       /*
-        * We used to set chan's exten and priority to "s" and 1 here,
-        * but this generates (in some cases) an invalid extension, and
-        * if "s" exists, could errantly cause execution of extensions
-        * you don't expect.  It makes more sense to let nature take its
-        * course when chan finishes, and let the pbx do its thing and
-        * hang up when the park is over.
-        */
-
-       /* Answer if call is not up */
-       if (ast_channel_state(chan) != AST_STATE_UP) {
-               /*
-                * XXX Why are we doing this?  Both of the channels should be up
-                * since you cannot do DTMF features unless you are bridged.
-                */
-               if (ast_answer(chan)) {
-                       return -1;
-               }
-
-               /* Sleep to allow VoIP streams to settle down */
-               if (ast_safe_sleep(chan, 1000)) {
-                       return -1;
-               }
-       }
-
-       /* one direction used to call park_call.... */
-       set_peers(&parker, &parkee, peer, chan, sense);
-       return masq_park_call(parkee, parker, &args) ? AST_FEATURE_RETURN_SUCCESS : -1;
-}
-#endif
-
 /*!
  * \internal
  * \brief Play file to specified channel.
@@ -1888,800 +1640,6 @@ static int play_message_on_chan(struct ast_channel *play_to, struct ast_channel
        return 0;
 }
 
-#if 0
-/*!
- * \internal
- * \brief Play file to specified channels.
- *
- * \param left Channel on left to play file.
- * \param right Channel on right to play file.
- * \param which Play file on indicated channels: which < 0 play left, which == 0 play both, which > 0 play right
- * \param msg Descriptive name of message type being played.
- * \param audiofile Audio file to play to channels.
- *
- * \note Plays file to the indicated channels in turn so please
- * don't use this for very long messages.
- *
- * \retval 0 on success.
- * \retval -1 on error. (Couldn't play file, channel hung up,...)
- */
-static int play_message_to_chans(struct ast_channel *left, struct ast_channel *right, int which, const char *msg, const char *audiofile)
-{
-       /* First play the file to the left channel if requested. */
-       if (which <= 0 && play_message_on_chan(left, right, msg, audiofile)) {
-               return -1;
-       }
-
-       /* Then play the file to the right channel if requested. */
-       if (which >= 0 && play_message_on_chan(right, left, msg, audiofile)) {
-               return -1;
-       }
-
-       return 0;
-}
-#endif
-
-#if 0
-/*!
- * \brief Play message to both caller and callee in bridged call, plays synchronously, autoservicing the
- * other channel during the message, so please don't use this for very long messages
- */
-static int play_message_in_bridged_call(struct ast_channel *caller_chan, struct ast_channel *callee_chan, const char *audiofile)
-{
-       return play_message_to_chans(caller_chan, callee_chan, 0, "automon message",
-               audiofile);
-}
-#endif
-
-#if 0
-/*!
- * \brief Monitor a channel by DTMF
- * \param chan channel requesting monitor
- * \param peer channel to be monitored
- * \param config
- * \param code
- * \param sense feature options
- *
- * \param data
- * Check monitor app enabled, setup channels, both caller/callee chans not null
- * get TOUCH_MONITOR variable for filename if exists, exec monitor app.
- * \retval AST_FEATURE_RETURN_SUCCESS on success.
- * \retval -1 on error.
- */
-static int builtin_automonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-       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, *callee_chan;
-       const char *automon_message_start = NULL;
-       const char *automon_message_stop = NULL;
-       const char *touch_format = NULL;
-       const char *touch_monitor = NULL;
-       const char *touch_monitor_prefix = NULL;
-       struct ast_app *monitor_app;
-
-       monitor_app = pbx_findapp("Monitor");
-       if (!monitor_app) {
-               ast_log(LOG_ERROR,"Cannot record the call. The monitor application is disabled.\n");
-               return -1;
-       }
-
-       set_peers(&caller_chan, &callee_chan, peer, chan, sense);
-
-       /* Find extra messages */
-       automon_message_start = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_START");
-       automon_message_stop = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_MESSAGE_STOP");
-
-       if (!ast_strlen_zero(courtesytone)) {   /* Play courtesy tone if configured */
-               if(play_message_in_bridged_call(caller_chan, callee_chan, courtesytone) == -1) {
-                       return -1;
-               }
-       }
-
-       if (ast_channel_monitor(callee_chan)) {
-               ast_verb(4, "User hit '%s' to stop recording call.\n", code);
-               if (!ast_strlen_zero(automon_message_stop)) {
-                       play_message_in_bridged_call(caller_chan, callee_chan, automon_message_stop);
-               }
-               ast_channel_monitor(callee_chan)->stop(callee_chan, 1);
-               return AST_FEATURE_RETURN_SUCCESS;
-       }
-
-       touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_FORMAT");
-       touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR");
-       touch_monitor_prefix = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MONITOR_PREFIX");
-
-       if (!touch_format)
-               touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_FORMAT");
-
-       if (!touch_monitor)
-               touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR");
-
-       if (!touch_monitor_prefix)
-               touch_monitor_prefix = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MONITOR_PREFIX");
-
-       if (touch_monitor) {
-               len = strlen(touch_monitor) + 50;
-               args = ast_alloca(len);
-               touch_filename = ast_alloca(len);
-               snprintf(touch_filename, len, "%s-%ld-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), touch_monitor);
-               snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
-       } else {
-               caller_chan_id = ast_strdupa(S_COR(ast_channel_caller(caller_chan)->id.number.valid,
-                       ast_channel_caller(caller_chan)->id.number.str, ast_channel_name(caller_chan)));
-               callee_chan_id = ast_strdupa(S_COR(ast_channel_caller(callee_chan)->id.number.valid,
-                       ast_channel_caller(callee_chan)->id.number.str, ast_channel_name(callee_chan)));
-               len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
-               args = ast_alloca(len);
-               touch_filename = ast_alloca(len);
-               snprintf(touch_filename, len, "%s-%ld-%s-%s", S_OR(touch_monitor_prefix, "auto"), (long)time(NULL), caller_chan_id, callee_chan_id);
-               snprintf(args, len, "%s,%s,m", S_OR(touch_format, "wav"), touch_filename);
-       }
-
-       for(x = 0; x < strlen(args); x++) {
-               if (args[x] == '/')
-                       args[x] = '-';
-       }
-
-       ast_verb(4, "User hit '%s' to record call. filename: %s\n", code, args);
-
-       pbx_exec(callee_chan, monitor_app, args);
-       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
-       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MONITOR_OUTPUT", touch_filename);
-
-       if (!ast_strlen_zero(automon_message_start)) {  /* Play start message for both channels */
-               play_message_in_bridged_call(caller_chan, callee_chan, automon_message_start);
-       }
-
-       return AST_FEATURE_RETURN_SUCCESS;
-}
-#endif
-
-#if 0
-static int builtin_automixmonitor(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-       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, *callee_chan;
-       const char *mixmonitor_spy_type = "MixMonitor";
-       const char *touch_format;
-       const char *touch_monitor;
-       struct ast_app *mixmonitor_app;
-       int count = 0;
-
-       mixmonitor_app = pbx_findapp("MixMonitor");
-       if (!mixmonitor_app) {
-               ast_log(LOG_ERROR,"Cannot record the call. The mixmonitor application is disabled.\n");
-               return -1;
-       }
-
-       set_peers(&caller_chan, &callee_chan, peer, chan, sense);
-
-       if (!ast_strlen_zero(courtesytone)) {
-               if (ast_autoservice_start(callee_chan))
-                       return -1;
-               ast_autoservice_ignore(callee_chan, AST_FRAME_DTMF_END);
-               if (ast_stream_and_wait(caller_chan, courtesytone, "")) {
-                       ast_log(LOG_WARNING, "Failed to play courtesy tone!\n");
-                       ast_autoservice_stop(callee_chan);
-                       return -1;
-               }
-               if (ast_autoservice_stop(callee_chan))
-                       return -1;
-       }
-
-       ast_channel_lock(callee_chan);
-       count = ast_channel_audiohook_count_by_source(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
-       ast_channel_unlock(callee_chan);
-
-       /* This means a mixmonitor is attached to the channel, running or not is unknown. */
-       if (count > 0) {
-               ast_verb(3, "User hit '%s' to stop recording call.\n", code);
-
-               /* Make sure they are running */
-               ast_channel_lock(callee_chan);
-               count = ast_channel_audiohook_count_by_source_running(callee_chan, mixmonitor_spy_type, AST_AUDIOHOOK_TYPE_SPY);
-               ast_channel_unlock(callee_chan);
-               if (count > 0) {
-                       struct ast_app *stopmixmonitor_app;
-
-                       stopmixmonitor_app = pbx_findapp("StopMixMonitor");
-                       if (!stopmixmonitor_app) {
-                               ast_log(LOG_ERROR,"Cannot stop recording the call. The stopmixmonitor application is disabled.\n");
-                               return -1;
-                       }
-                       pbx_exec(callee_chan, stopmixmonitor_app, "");
-                       return AST_FEATURE_RETURN_SUCCESS;
-               }
-
-               ast_log(LOG_WARNING,"Stopped MixMonitors are attached to the channel.\n");
-       }
-
-       touch_format = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR_FORMAT");
-       touch_monitor = pbx_builtin_getvar_helper(caller_chan, "TOUCH_MIXMONITOR");
-
-       if (!touch_format)
-               touch_format = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR_FORMAT");
-
-       if (!touch_monitor)
-               touch_monitor = pbx_builtin_getvar_helper(callee_chan, "TOUCH_MIXMONITOR");
-
-       if (touch_monitor) {
-               len = strlen(touch_monitor) + 50;
-               args = ast_alloca(len);
-               touch_filename = ast_alloca(len);
-               snprintf(touch_filename, len, "auto-%ld-%s", (long)time(NULL), touch_monitor);
-               snprintf(args, len, "%s.%s,b", touch_filename, (touch_format) ? touch_format : "wav");
-       } else {
-               caller_chan_id = ast_strdupa(S_COR(ast_channel_caller(caller_chan)->id.number.valid,
-                       ast_channel_caller(caller_chan)->id.number.str, ast_channel_name(caller_chan)));
-               callee_chan_id = ast_strdupa(S_COR(ast_channel_caller(callee_chan)->id.number.valid,
-                       ast_channel_caller(callee_chan)->id.number.str, ast_channel_name(callee_chan)));
-               len = strlen(caller_chan_id) + strlen(callee_chan_id) + 50;
-               args = ast_alloca(len);
-               touch_filename = ast_alloca(len);
-               snprintf(touch_filename, len, "auto-%ld-%s-%s", (long)time(NULL), caller_chan_id, callee_chan_id);
-               snprintf(args, len, "%s.%s,b", touch_filename, S_OR(touch_format, "wav"));
-       }
-
-       for( x = 0; x < strlen(args); x++) {
-               if (args[x] == '/')
-                       args[x] = '-';
-       }
-
-       ast_verb(3, "User hit '%s' to record call. filename: %s\n", code, touch_filename);
-
-       pbx_exec(callee_chan, mixmonitor_app, args);
-       pbx_builtin_setvar_helper(callee_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
-       pbx_builtin_setvar_helper(caller_chan, "TOUCH_MIXMONITOR_OUTPUT", touch_filename);
-       return AST_FEATURE_RETURN_SUCCESS;
-}
-#endif
-
-#if 0
-static int builtin_disconnect(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-       ast_verb(4, "User hit '%s' to disconnect call.\n", code);
-       return AST_FEATURE_RETURN_HANGUP;
-}
-#endif
-
-#if 0
-/*!
- * \brief Find the context for the transfer
- * \param transferer
- * \param transferee
- *
- * Grab the TRANSFER_CONTEXT, if fails try grabbing macrocontext.
- * \return a context string
- */
-static const char *real_ctx(struct ast_channel *transferer, struct ast_channel *transferee)
-{
-       const char *s = pbx_builtin_getvar_helper(transferer, "TRANSFER_CONTEXT");
-       if (ast_strlen_zero(s)) {
-               s = pbx_builtin_getvar_helper(transferee, "TRANSFER_CONTEXT");
-       }
-       if (ast_strlen_zero(s)) { /* Use the non-macro context to transfer the call XXX ? */
-               s = ast_channel_macrocontext(transferer);
-       }
-       if (ast_strlen_zero(s)) {
-               s = ast_channel_context(transferer);
-       }
-       return s;
-}
-#endif
-
-#if 0
-/*!
- * \brief make channels compatible
- * \param c
- * \param newchan
- * \retval 0 on success.
- * \retval -1 on failure.
- */
-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",
-                       ast_channel_name(c), ast_channel_name(newchan));
-               ast_autoservice_chan_hangup_peer(c, newchan);
-               return -1;
-       }
-       return 0;
-}
-#endif
-
-#if 0
-/*!
- * \internal
- * \brief Builtin attended transfer failed cleanup.
- * \since 10.0
- *
- * \param transferee Party A in the transfer.
- * \param transferer Party B in the transfer.
- * \param connected_line Saved connected line info about party A.
- *
- * \note The connected_line data is freed.
- *
- * \return Nothing
- */
-static void atxfer_fail_cleanup(struct ast_channel *transferee, struct ast_channel *transferer, struct ast_party_connected_line *connected_line)
-{
-       finishup(transferee);
-
-       /*
-        * Restore party B connected line info about party A.
-        *
-        * Party B was the caller to party C and is the last known mode
-        * for party B.
-        */
-       if (ast_channel_connected_line_sub(transferee, transferer, connected_line, 0) &&
-               ast_channel_connected_line_macro(transferee, transferer, connected_line, 1, 0)) {
-               ast_channel_update_connected_line(transferer, connected_line, NULL);
-       }
-       ast_party_connected_line_free(connected_line);
-}
-#endif
-
-#if 0
-/*!
- * \brief Attended transfer
- * \param chan transfered user
- * \param peer person transfering call
- * \param config
- * \param code
- * \param sense feature options
- *
- * \param data
- * Get extension to transfer to, if you cannot generate channel (or find extension)
- * return to host channel. After called channel answered wait for hangup of transferer,
- * bridge call between transfer peer (taking them off hold) to attended transfer channel.
- *
- * \return -1 on failure
- */
-static int builtin_atxfer(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, const char *code, int sense, void *data)
-{
-       struct ast_channel *transferer;/* Party B */
-       struct ast_channel *transferee;/* Party A */
-       struct ast_exten *park_exten;
-       const char *chan1_attended_sound;
-       const char *chan2_attended_sound;
-       const char *transferer_real_context;
-       char xferto[256] = "";
-       int res;
-       int outstate=0;
-       struct ast_channel *newchan;
-       struct ast_channel *xferchan;
-       struct ast_bridge_thread_obj *tobj;
-       struct ast_bridge_config bconfig;
-       int l;
-       struct ast_party_connected_line connected_line;
-       struct ast_datastore *features_datastore;
-       struct ast_dial_features *dialfeatures;
-       char *transferer_tech;
-       char *transferer_name;
-       char *transferer_name_orig;
-       char *dash;
-       RAII_VAR(struct ast_features_xfer_config *, xfer_cfg, NULL, ao2_cleanup);
-
-       ast_debug(1, "Executing Attended Transfer %s, %s (sense=%d) \n", ast_channel_name(chan), ast_channel_name(peer), sense);
-       set_peers(&transferer, &transferee, peer, chan, sense);
-       transferer_real_context = real_ctx(transferer, transferee);
-
-       /* Start autoservice on transferee while we talk to the transferer */
-       ast_autoservice_start(transferee);
-       ast_indicate(transferee, AST_CONTROL_HOLD);
-
-       /* Transfer */
-       res = ast_stream_and_wait(transferer, "pbx-transfer", AST_DIGIT_ANY);
-       if (res < 0) {
-               finishup(transferee);
-               return -1;
-       }
-       if (res > 0) { /* If they've typed a digit already, handle it */
-               xferto[0] = (char) res;
-       }
-
-       ast_channel_lock(transferer);
-       xfer_cfg = ast_get_chan_features_xfer_config(transferer);
-       ast_channel_unlock(transferer);
-
-       /* XXX All accesses to the xfer_cfg structure after this point are not thread-safe,
-        * but I don't care because this is dead code.
-        */
-
-       /* this is specific of atxfer */
-       res = ast_app_dtget(transferer, transferer_real_context, xferto, sizeof(xferto), 100, xfer_cfg->transferdigittimeout);
-       if (res < 0) {  /* hangup or error, (would be 0 for invalid and 1 for valid) */
-               finishup(transferee);
-               return -1;
-       }
-       l = strlen(xferto);
-       if (res == 0) {
-               if (l) {
-                       ast_log(LOG_WARNING, "Extension '%s' does not exist in context '%s'\n",
-                               xferto, transferer_real_context);
-               } else {
-                       /* Does anyone care about this case? */
-                       ast_log(LOG_WARNING, "No digits dialed for atxfer.\n");
-               }
-               ast_stream_and_wait(transferer, "pbx-invalid", "");
-               finishup(transferee);
-               return AST_FEATURE_RETURN_SUCCESS;
-       }
-
-       park_exten = get_parking_exten(xferto, transferer, transferer_real_context);
-       if (park_exten) {
-               /* We are transfering the transferee to a parking lot. */
-               return xfer_park_call_helper(transferee, transferer, park_exten);
-       }
-
-       /*
-        * Append context to dialed transfer number.
-        *
-        * NOTE: The local channel needs the /n flag so party C will use
-        * the feature flags set by the dialplan when calling that
-        * party.
-        */
-       snprintf(xferto + l, sizeof(xferto) - l, "@%s/n", transferer_real_context);
-
-       /* If we are performing an attended transfer and we have two channels involved then
-          copy sound file information to play upon attended transfer completion */
-       chan1_attended_sound = pbx_builtin_getvar_helper(transferer, "ATTENDED_TRANSFER_COMPLETE_SOUND");
-       chan2_attended_sound = pbx_builtin_getvar_helper(transferee, "ATTENDED_TRANSFER_COMPLETE_SOUND");
-       if (!ast_strlen_zero(chan1_attended_sound)) {
-               pbx_builtin_setvar_helper(transferer, "BRIDGE_PLAY_SOUND", chan1_attended_sound);
-       }
-       if (!ast_strlen_zero(chan2_attended_sound)) {
-               pbx_builtin_setvar_helper(transferee, "BRIDGE_PLAY_SOUND", chan2_attended_sound);
-       }
-
-       /* Extract redial transferer information from the channel name. */
-       transferer_name_orig = ast_strdupa(ast_channel_name(transferer));
-       transferer_name = ast_strdupa(transferer_name_orig);
-       transferer_tech = strsep(&transferer_name, "/");
-       dash = strrchr(transferer_name, '-');
-       if (dash) {
-               /* Trim off channel name sequence/serial number. */
-               *dash = '\0';
-       }
-
-       /* Stop autoservice so we can monitor all parties involved in the transfer. */
-       if (ast_autoservice_stop(transferee) < 0) {
-               ast_indicate(transferee, AST_CONTROL_UNHOLD);
-               return -1;
-       }
-
-       /* Save connected line info for party B about party A in case transfer fails. */
-       ast_party_connected_line_init(&connected_line);
-       ast_channel_lock(transferer);
-       ast_party_connected_line_copy(&connected_line, ast_channel_connected(transferer));
-       ast_channel_unlock(transferer);
-       connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-
-       /* Dial party C */
-       newchan = feature_request_and_dial(transferer, transferer_name_orig, transferer,
-               transferee, "Local", ast_channel_nativeformats(transferer), xferto,
-               xfer_cfg->atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
-       ast_debug(2, "Dial party C result: newchan:%d, outstate:%d\n", !!newchan, outstate);
-
-       if (!ast_check_hangup(transferer)) {
-               /* Transferer (party B) is up */
-               ast_debug(1, "Actually doing an attended transfer.\n");
-
-               /* Start autoservice on transferee while the transferer deals with party C. */
-               ast_autoservice_start(transferee);
-
-               ast_indicate(transferer, -1);
-               if (!newchan) {
-                       /* any reason besides user requested cancel and busy triggers the failed sound */
-                       switch (outstate) {
-                       case AST_CONTROL_UNHOLD:/* Caller requested cancel or party C answer timeout. */
-                       case AST_CONTROL_BUSY:
-                       case AST_CONTROL_CONGESTION:
-                               if (ast_stream_and_wait(transferer, xfer_cfg->xfersound, "")) {
-                                       ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
-                               }
-                               break;
-                       default:
-                               if (ast_stream_and_wait(transferer, xfer_cfg->xferfailsound, "")) {
-                                       ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
-                               }
-                               break;
-                       }
-                       atxfer_fail_cleanup(transferee, transferer, &connected_line);
-                       return AST_FEATURE_RETURN_SUCCESS;
-               }
-
-               if (check_compat(transferer, newchan)) {
-                       if (ast_stream_and_wait(transferer, xfer_cfg->xferfailsound, "")) {
-                               ast_log(LOG_WARNING, "Failed to play transfer failed sound!\n");
-                       }
-                       atxfer_fail_cleanup(transferee, transferer, &connected_line);
-                       return AST_FEATURE_RETURN_SUCCESS;
-               }
-               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);
-
-               /*
-                * Let party B and C talk as long as they want while party A
-                * languishes in autoservice listening to MOH.
-                */
-               ast_bridge_call(transferer, newchan, &bconfig);
-
-               if (ast_check_hangup(newchan) || !ast_check_hangup(transferer)) {
-                       ast_autoservice_chan_hangup_peer(transferer, newchan);
-                       if (ast_stream_and_wait(transferer, xfer_cfg->xfersound, "")) {
-                               ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
-                       }
-                       atxfer_fail_cleanup(transferee, transferer, &connected_line);
-                       return AST_FEATURE_RETURN_SUCCESS;
-               }
-
-               /* Transferer (party B) is confirmed hung up at this point. */
-               if (check_compat(transferee, newchan)) {
-                       finishup(transferee);
-                       ast_party_connected_line_free(&connected_line);
-                       return -1;
-               }
-
-               ast_indicate(transferee, AST_CONTROL_UNHOLD);
-               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);
-                       ast_party_connected_line_free(&connected_line);
-                       return -1;
-               }
-       } else if (!ast_check_hangup(transferee)) {
-               /* Transferer (party B) has hung up at this point.  Doing blonde transfer. */
-               ast_debug(1, "Actually doing a blonde transfer.\n");
-
-               if (!newchan && !xfer_cfg->atxferdropcall) {
-                       /* Party C is not available, try to call party B back. */
-                       unsigned int tries = 0;
-
-                       if (ast_strlen_zero(transferer_name) || ast_strlen_zero(transferer_tech)) {
-                               ast_log(LOG_WARNING,
-                                       "Transferer channel name: '%s' cannot be used for callback.\n",
-                                       transferer_name_orig);
-                               ast_indicate(transferee, AST_CONTROL_UNHOLD);
-                               ast_party_connected_line_free(&connected_line);
-                               return -1;
-                       }
-
-                       tries = 0;
-                       for (;;) {
-                               /* Try to get party B back. */
-                               ast_debug(1, "We're trying to callback %s/%s\n",
-                                       transferer_tech, transferer_name);
-                               newchan = feature_request_and_dial(transferer, transferer_name_orig,
-                                       transferee, transferee, transferer_tech,
-                                       ast_channel_nativeformats(transferee), transferer_name,
-                                       xfer_cfg->atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
-                               ast_debug(2, "Dial party B result: newchan:%d, outstate:%d\n",
-                                       !!newchan, outstate);
-                               if (newchan) {
-                                       /*
-                                        * We have recalled party B (newchan).  We need to give this
-                                        * call leg the same feature flags as the original party B call
-                                        * leg.
-                                        */
-                                       ast_channel_lock(transferer);
-                                       features_datastore = ast_channel_datastore_find(transferer,
-                                               &dial_features_info, NULL);
-                                       if (features_datastore && (dialfeatures = features_datastore->data)) {
-                                               struct ast_flags my_features = { 0 };
-                                               struct ast_flags peer_features = { 0 };
-
-                                               ast_copy_flags(&my_features, &dialfeatures->my_features,
-                                                       AST_FLAGS_ALL);
-                                               ast_copy_flags(&peer_features, &dialfeatures->peer_features,
-                                                       AST_FLAGS_ALL);
-                                               ast_channel_unlock(transferer);
-                                               add_features_datastore(newchan, &my_features, &peer_features);
-                                       } else {
-                                               ast_channel_unlock(transferer);
-                                       }
-                                       break;
-                               }
-                               if (ast_check_hangup(transferee)) {
-                                       break;
-                               }
-
-                               ++tries;
-                               if (xfer_cfg->atxfercallbackretries <= tries) {
-                                       /* No more callback tries remaining. */
-                                       break;
-                               }
-
-                               if (xfer_cfg->atxferloopdelay) {
-                                       /* Transfer failed, sleeping */
-                                       ast_debug(1, "Sleeping for %d ms before retrying atxfer.\n",
-                                               xfer_cfg->atxferloopdelay);
-                                       ast_safe_sleep(transferee, xfer_cfg->atxferloopdelay);
-                                       if (ast_check_hangup(transferee)) {
-                                               ast_party_connected_line_free(&connected_line);
-                                               return -1;
-                                       }
-                               }
-
-                               /* Retry dialing party C. */
-                               ast_debug(1, "We're retrying to call %s/%s\n", "Local", xferto);
-                               newchan = feature_request_and_dial(transferer, transferer_name_orig,
-                                       transferer, transferee, "Local",
-                                       ast_channel_nativeformats(transferee), xferto,
-                                       xfer_cfg->atxfernoanswertimeout, &outstate, ast_channel_language(transferer));
-                               ast_debug(2, "Redial party C result: newchan:%d, outstate:%d\n",
-                                       !!newchan, outstate);
-                               if (newchan || ast_check_hangup(transferee)) {
-                                       break;
-                               }
-                       }
-               }
-               ast_indicate(transferee, AST_CONTROL_UNHOLD);
-               if (!newchan) {
-                       /* No party C or could not callback party B. */
-                       ast_party_connected_line_free(&connected_line);
-                       return -1;
-               }
-
-               /* newchan is up, we should prepare transferee and bridge them */
-               if (ast_check_hangup(newchan)) {
-                       ast_autoservice_chan_hangup_peer(transferee, newchan);
-                       ast_party_connected_line_free(&connected_line);
-                       return -1;
-               }
-               if (check_compat(transferee, newchan)) {
-                       ast_party_connected_line_free(&connected_line);
-                       return -1;
-               }
-       } else {
-               /*
-                * Both the transferer and transferee have hungup.  If newchan
-                * is up, hang it up as it has no one to talk to.
-                */
-               ast_debug(1, "Everyone is hungup.\n");
-               ast_hangup(newchan);
-               ast_party_connected_line_free(&connected_line);
-               return -1;
-       }
-
-       /* Initiate the channel transfer of party A to party C (or recalled party B). */
-       xferchan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", ast_channel_linkedid(transferee), 0, "Transfered/%s", ast_channel_name(transferee));
-       if (!xferchan) {
-               ast_autoservice_chan_hangup_peer(transferee, newchan);
-               ast_party_connected_line_free(&connected_line);
-               return -1;
-       }
-
-       /* Give party A a momentary ringback tone during transfer. */
-       ast_channel_visible_indication_set(xferchan, AST_CONTROL_RINGING);
-
-       /* Make formats okay */
-       ast_format_copy(ast_channel_readformat(xferchan), ast_channel_readformat(transferee));
-       ast_format_copy(ast_channel_writeformat(xferchan), ast_channel_writeformat(transferee));
-
-       if (ast_channel_masquerade(xferchan, transferee)) {
-               ast_hangup(xferchan);
-               ast_autoservice_chan_hangup_peer(transferee, newchan);
-               ast_party_connected_line_free(&connected_line);
-               return -1;
-       }
-
-       dash = strrchr(xferto, '@');
-       if (dash) {
-               /* Trim off the context. */
-               *dash = '\0';
-       }
-       ast_explicit_goto(xferchan, transferer_real_context, xferto, 1);
-       ast_channel_state_set(xferchan, AST_STATE_UP);
-       ast_clear_flag(ast_channel_flags(xferchan), AST_FLAGS_ALL);
-
-       /* Do the masquerade manually to make sure that is is completed. */
-       ast_do_masquerade(xferchan);
-
-       ast_channel_state_set(newchan, AST_STATE_UP);
-       ast_clear_flag(ast_channel_flags(newchan), AST_FLAGS_ALL);
-       tobj = ast_calloc(1, sizeof(*tobj));
-       if (!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;
-
-       ast_channel_lock(newchan);
-       features_datastore = ast_channel_datastore_find(newchan, &dial_features_info, NULL);
-       if (features_datastore && (dialfeatures = features_datastore->data)) {
-               ast_copy_flags(&tobj->bconfig.features_callee, &dialfeatures->my_features,
-                       AST_FLAGS_ALL);
-       }
-       ast_channel_unlock(newchan);
-
-       ast_channel_lock(xferchan);
-       features_datastore = ast_channel_datastore_find(xferchan, &dial_features_info, NULL);
-       if (features_datastore && (dialfeatures = features_datastore->data)) {
-               ast_copy_flags(&tobj->bconfig.features_caller, &dialfeatures->my_features,
-                       AST_FLAGS_ALL);
-       }
-       ast_channel_unlock(xferchan);
-
-       if (tobj->bconfig.end_bridge_callback_data_fixup) {
-               tobj->bconfig.end_bridge_callback_data_fixup(&tobj->bconfig, tobj->peer, tobj->chan);
-       }
-
-       /*
-        * xferchan is transferee, and newchan is the transfer target
-        * So...in a transfer, who is the caller and who is the callee?
-        *
-        * When the call is originally made, it is clear who is caller and callee.
-        * When a transfer occurs, it is my humble opinion that the transferee becomes
-        * the caller, and the transfer target is the callee.
-        *
-        * The problem is that these macros were set with the intention of the original
-        * caller and callee taking those roles.  A transfer can totally mess things up,
-        * to be technical.  What sucks even more is that you can't effectively change
-        * the macros in the dialplan during the call from the transferer to the transfer
-        * target because the transferee is stuck with whatever role he originally had.
-        *
-        * I think the answer here is just to make sure that it is well documented that
-        * during a transfer, the transferee is the "caller" and the transfer target
-        * is the "callee."
-        *
-        * This means that if party B calls party A, and party B transfers party A to
-        * party C, then A has switched roles for the call.  Now party A will have the
-        * caller macro called on his channel instead of the callee macro.
-        *
-        * Luckily, the method by which the party B to party C bridge is
-        * launched above ensures that the transferee is the "chan" on
-        * the bridge and the transfer target is the "peer," so my idea
-        * for the roles post-transfer does not require extensive code
-        * changes.
-        */
-
-       /* Transfer party C connected line to party A */
-       ast_channel_lock(transferer);
-       /*
-        * Due to a limitation regarding when callerID is set on a Local channel,
-        * we use the transferer's connected line information here.
-        */
-       ast_party_connected_line_copy(&connected_line, ast_channel_connected(transferer));
-       ast_channel_unlock(transferer);
-       connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-       if (ast_channel_connected_line_sub(newchan, xferchan, &connected_line, 0) &&
-               ast_channel_connected_line_macro(newchan, xferchan, &connected_line, 1, 0)) {
-               ast_channel_update_connected_line(xferchan, &connected_line, NULL);
-       }
-
-       /* Transfer party A connected line to party C */
-       ast_channel_lock(xferchan);
-       ast_connected_line_copy_from_caller(&connected_line, ast_channel_caller(xferchan));
-       ast_channel_unlock(xferchan);
-       connected_line.source = AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER;
-       if (ast_channel_connected_line_sub(xferchan, newchan, &connected_line, 0) &&
-               ast_channel_connected_line_macro(xferchan, newchan, &connected_line, 0, 0)) {
-               ast_channel_update_connected_line(newchan, &connected_line, NULL);
-       }
-
-       if (ast_stream_and_wait(newchan, xfer_cfg->xfersound, ""))
-               ast_log(LOG_WARNING, "Failed to play transfer sound!\n");
-       bridge_call_thread_launch(tobj);
-
-       ast_party_connected_line_free(&connected_line);
-       return -1;/* The transferee is masqueraded and the original bridged channels can be hungup. */
-}
-#endif
-
 /*!
  * \internal
  * \brief Get the extension for a given builtin feature
@@ -2729,347 +1687,6 @@ static void set_config_flags(struct ast_channel *chan, struct ast_bridge_config
        }
 }
 
-#if 0
-/*!
- * \internal
- * \brief Get feature and dial.
- *
- * \param caller Channel to represent as the calling channel for the dialed channel.
- * \param caller_name Original caller channel name.
- * \param requestor Channel to say is requesting the dial (usually the caller).
- * \param transferee Channel that the dialed channel will be transferred to.
- * \param type Channel technology type to dial.
- * \param format Codec formats for dialed channel.
- * \param addr destination of the call
- * \param timeout Time limit for dialed channel to answer in ms. Must be greater than zero.
- * \param outstate Status of dialed channel if unsuccessful.
- * \param language Language of the caller.
- *
- * \note
- * outstate can be:
- * 0, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION,
- * AST_CONTROL_ANSWER, or AST_CONTROL_UNHOLD.  If
- * AST_CONTROL_UNHOLD then the caller channel cancelled the
- * transfer or the dialed channel did not answer before the
- * timeout.
- *
- * \details
- * Request channel, set channel variables, initiate call,
- * check if they want to disconnect, go into loop, check if timeout has elapsed,
- * check if person to be transfered hung up, check for answer break loop,
- * set cdr return channel.
- *
- * \retval Channel Connected channel for transfer.
- * \retval NULL on failure to get third party connected.
- *
- * \note This is similar to __ast_request_and_dial() in channel.c
- */
-static struct ast_channel *feature_request_and_dial(struct ast_channel *caller,
-       const char *caller_name, struct ast_channel *requestor,
-       struct ast_channel *transferee, const char *type, struct ast_format_cap *cap, const char *addr,
-       int timeout, int *outstate, const char *language)
-{
-       int state = 0;
-       int cause = 0;
-       int to;
-       int caller_hungup;
-       int transferee_hungup;
-       struct ast_channel *chan;
-       struct ast_channel *monitor_chans[3];
-       struct ast_channel *active_channel;
-       int res;
-       int ready = 0;
-       struct timeval started;
-       int x, len = 0;
-       char disconnect_code[AST_FEATURE_MAX_LEN];
-       char *dialed_code = NULL;
-       struct ast_format_cap *tmp_cap;
-       struct ast_format best_audio_fmt;
-       struct ast_frame *f;
-       int disconnect_res;
-       AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
-
-       tmp_cap = ast_format_cap_alloc_nolock();
-       if (!tmp_cap) {
-               if (outstate) {
-                       *outstate = 0;
-               }
-               return NULL;
-       }
-       ast_best_codec(cap, &best_audio_fmt);
-       ast_format_cap_add(tmp_cap, &best_audio_fmt);
-
-       caller_hungup = ast_check_hangup(caller);
-
-       if (!(chan = ast_request(type, tmp_cap, requestor, addr, &cause))) {
-               ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, addr);
-               switch (cause) {
-               case AST_CAUSE_BUSY:
-                       state = AST_CONTROL_BUSY;
-                       break;
-               case AST_CAUSE_CONGESTION:
-                       state = AST_CONTROL_CONGESTION;
-                       break;
-               default:
-                       state = 0;
-                       break;
-               }
-               goto done;
-       }
-
-       ast_channel_language_set(chan, language);
-       ast_channel_inherit_variables(caller, chan);
-       pbx_builtin_setvar_helper(chan, "TRANSFERERNAME", caller_name);
-
-       ast_channel_lock(chan);
-       ast_connected_line_copy_from_caller(ast_channel_connected(chan), ast_channel_caller(requestor));
-       ast_channel_unlock(chan);
-
-       if (ast_call(chan, addr, timeout)) {
-               ast_log(LOG_NOTICE, "Unable to call channel %s/%s\n", type, addr);
-               switch (ast_channel_hangupcause(chan)) {
-               case AST_CAUSE_BUSY:
-                       state = AST_CONTROL_BUSY;
-                       break;
-               case AST_CAUSE_CONGESTION:
-                       state = AST_CONTROL_CONGESTION;
-                       break;
-               default:
-                       state = 0;
-                       break;
-               }
-               goto done;
-       }
-
-       /* support dialing of the featuremap disconnect code while performing an attended tranfer */
-       ast_channel_lock(chan);
-       disconnect_res = ast_get_builtin_feature(chan, "disconnect",
-                       disconnect_code, sizeof(disconnect_code));
-       ast_channel_unlock(chan);
-
-       if (!disconnect_res) {
-               len = strlen(disconnect_code) + 1;
-               dialed_code = ast_alloca(len);
-               memset(dialed_code, 0, len);
-       }
-
-       x = 0;
-       started = ast_tvnow();
-       to = timeout;
-       AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
-
-       ast_poll_channel_add(caller, chan);
-
-       transferee_hungup = 0;
-       while (!ast_check_hangup(transferee) && (ast_channel_state(chan) != AST_STATE_UP)) {
-               int num_chans = 0;
-
-               monitor_chans[num_chans++] = transferee;
-               monitor_chans[num_chans++] = chan;
-               if (!caller_hungup) {
-                       if (ast_check_hangup(caller)) {
-                               caller_hungup = 1;
-
-#if defined(ATXFER_NULL_TECH)
-                               /* Change caller's name to ensure that it will remain unique. */
-                               set_new_chan_name(caller);
-
-                               /*
-                                * Get rid of caller's physical technology so it is free for
-                                * other calls.
-                                */
-                               set_kill_chan_tech(caller);
-#endif /* defined(ATXFER_NULL_TECH) */
-                       } else {
-                               /* caller is not hungup so monitor it. */
-                               monitor_chans[num_chans++] = caller;
-                       }
-               }
-
-               /* see if the timeout has been violated */
-               if (ast_tvdiff_ms(ast_tvnow(), started) > timeout) {
-                       state = AST_CONTROL_UNHOLD;
-                       ast_log(LOG_NOTICE, "We exceeded our AT-timeout for %s\n", ast_channel_name(chan));
-                       break; /*doh! timeout*/
-               }
-
-               active_channel = ast_waitfor_n(monitor_chans, num_chans, &to);
-               if (!active_channel)
-                       continue;
-
-               f = NULL;
-               if (transferee == active_channel) {
-                       struct ast_frame *dup_f;
-
-                       f = ast_read(transferee);
-                       if (f == NULL) { /*doh! where'd he go?*/
-                               transferee_hungup = 1;
-                               state = 0;
-                               break;
-                       }
-                       if (ast_is_deferrable_frame(f)) {
-                               dup_f = ast_frisolate(f);
-                               if (dup_f) {
-                                       if (dup_f == f) {
-                                               f = NULL;
-                                       }
-                                       AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
-                               }
-                       }
-               } else if (chan == active_channel) {
-                       if (!ast_strlen_zero(ast_channel_call_forward(chan))) {
-                               state = 0;
-                               ast_autoservice_start(transferee);
-                               chan = ast_call_forward(caller, chan, NULL, tmp_cap, NULL, &state);
-                               ast_autoservice_stop(transferee);
-                               if (!chan) {
-                                       break;
-                               }
-                               continue;
-                       }
-                       f = ast_read(chan);
-                       if (f == NULL) { /*doh! where'd he go?*/
-                               switch (ast_channel_hangupcause(chan)) {
-                               case AST_CAUSE_BUSY:
-                                       state = AST_CONTROL_BUSY;
-                                       break;
-                               case AST_CAUSE_CONGESTION:
-                                       state = AST_CONTROL_CONGESTION;
-                                       break;
-                               default:
-                                       state = 0;
-                                       break;
-                               }
-                               break;
-                       }
-
-                       if (f->frametype == AST_FRAME_CONTROL) {
-                               if (f->subclass.integer == AST_CONTROL_RINGING) {
-                                       ast_verb(3, "%s is ringing\n", ast_channel_name(chan));
-                                       ast_indicate(caller, AST_CONTROL_RINGING);
-                               } else if (f->subclass.integer == AST_CONTROL_BUSY) {
-                                       state = f->subclass.integer;
-                                       ast_verb(3, "%s is busy\n", ast_channel_name(chan));
-                                       ast_indicate(caller, AST_CONTROL_BUSY);
-                                       ast_frfree(f);
-                                       break;
-                               } else if (f->subclass.integer == AST_CONTROL_INCOMPLETE) {
-                                       ast_verb(3, "%s dialed incomplete extension %s; ignoring\n", ast_channel_name(chan), ast_channel_exten(chan));
-                               } else if (f->subclass.integer == AST_CONTROL_CONGESTION) {
-                                       state = f->subclass.integer;
-                                       ast_verb(3, "%s is congested\n", ast_channel_name(chan));
-                                       ast_indicate(caller, AST_CONTROL_CONGESTION);
-                                       ast_frfree(f);
-                                       break;
-                               } else if (f->subclass.integer == AST_CONTROL_ANSWER) {
-                                       /* This is what we are hoping for */
-                                       state = f->subclass.integer;
-                                       ast_frfree(f);
-                                       ready=1;
-                                       break;
-                               } else if (f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
-                                       ast_indicate_data(caller, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
-                               } else if (f->subclass.integer == AST_CONTROL_CONNECTED_LINE) {
-                                       if (caller_hungup) {
-                                               struct ast_party_connected_line connected;
-
-                                               /* Just save it for the transfer. */
-                                               ast_party_connected_line_set_init(&connected, ast_channel_connected(caller));
-                                               res = ast_connected_line_parse_data(f->data.ptr, f->datalen,
-                                                       &connected);
-                                               if (!res) {
-                                                       ast_channel_set_connected_line(caller, &connected, NULL);
-                                               }
-                                               ast_party_connected_line_free(&connected);
-                                       } else {
-                                               ast_autoservice_start(transferee);
-                                               if (ast_channel_connected_line_sub(chan, caller, f, 1) &&
-                                                       ast_channel_connected_line_macro(chan, caller, f, 1, 1)) {
-                                                       ast_indicate_data(caller, AST_CONTROL_CONNECTED_LINE,
-                                                               f->data.ptr, f->datalen);
-                                               }
-                                               ast_autoservice_stop(transferee);
-                                       }
-                               } else if (f->subclass.integer == AST_CONTROL_REDIRECTING) {
-                                       if (!caller_hungup) {
-                                               ast_autoservice_start(transferee);
-                                               if (ast_channel_redirecting_sub(chan, caller, f, 1) &&
-                                                       ast_channel_redirecting_macro(chan, caller, f, 1, 1)) {
-                                                       ast_indicate_data(caller, AST_CONTROL_REDIRECTING,
-                                                               f->data.ptr, f->datalen);
-                                               }
-                                               ast_autoservice_stop(transferee);
-                                       }
-                               } else if (f->subclass.integer != -1
-                                       && f->subclass.integer != AST_CONTROL_PROGRESS
-                                       && f->subclass.integer != AST_CONTROL_PROCEEDING) {
-                                       ast_log(LOG_NOTICE, "Don't know what to do about control frame: %d\n", f->subclass.integer);
-                               }
-                               /* else who cares */
-                       } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
-                               ast_write(caller, f);
-                       }
-               } else if (caller == active_channel) {
-                       f = ast_read(caller);
-                       if (f) {
-                               if (f->frametype == AST_FRAME_DTMF && dialed_code) {
-                                       dialed_code[x++] = f->subclass.integer;
-                                       dialed_code[x] = '\0';
-                                       if (strlen(dialed_code) == len) {
-                                               x = 0;
-                                       } else if (x && strncmp(dialed_code, disconnect_code, x)) {
-                                               x = 0;
-                                               dialed_code[x] = '\0';
-                                       }
-                                       if (*dialed_code && !strcmp(dialed_code, disconnect_code)) {
-                                               /* Caller Canceled the call */
-                                               state = AST_CONTROL_UNHOLD;
-                                               ast_frfree(f);
-                                               break;
-                                       }
-                               } else if (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO) {
-                                       ast_write(chan, f);
-                               }
-                       }
-               }
-               if (f)
-                       ast_frfree(f);
-       } /* end while */
-
-       ast_poll_channel_del(caller, chan);
-
-       /*
-        * We need to free all the deferred frames, but we only need to
-        * queue the deferred frames if no hangup was received.
-        */
-       ast_channel_lock(transferee);
-       transferee_hungup = (transferee_hungup || ast_check_hangup(transferee));
-       while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
-               if (!transferee_hungup) {
-                       ast_queue_frame_head(transferee, f);
-               }
-               ast_frfree(f);
-       }
-       ast_channel_unlock(transferee);
-
-done:
-       ast_indicate(caller, -1);
-       if (chan && (ready || ast_channel_state(chan) == AST_STATE_UP)) {
-               state = AST_CONTROL_ANSWER;
-       } else if (chan) {
-               ast_hangup(chan);
-               chan = NULL;
-       }
-
-       tmp_cap = ast_format_cap_destroy(tmp_cap);
-
-       if (outstate)
-               *outstate = state;
-
-       return chan;
-}
-#endif
-
 void ast_channel_log(char *title, struct ast_channel *chan);
 
 void ast_channel_log(char *title, struct ast_channel *chan) /* for debug, this is handy enough to justify keeping it in the source */