git migration: Refactor the ASTERISK_FILE_VERSION macro
[asterisk/asterisk.git] / main / channel.c
index 5681ec1..4e418b6 100644 (file)
@@ -29,7 +29,7 @@
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+ASTERISK_REGISTER_FILE()
 
 #include "asterisk/_private.h"
 
@@ -100,9 +100,6 @@ struct ast_epoll_data {
 #define MONITOR_DELAY  150 * 8         /*!< 150 ms of MONITORING DELAY */
 #endif
 
-/*! \brief Prevent new channel allocation if shutting down. */
-static int shutting_down;
-
 static int chancount;
 
 unsigned long global_fin, global_fout;
@@ -275,7 +272,7 @@ static const char *party_number_plan2str(int plan)
 /*! \brief Show channel types - CLI command */
 static char *handle_cli_core_show_channeltypes(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
-#define FORMAT  "%-15.15s  %-40.40s %-12.12s %-12.12s %-12.12s\n"
+#define FORMAT  "%-15.15s  %-40.40s %-13.13s %-13.13s %-13.13s %-13.13s\n"
        struct chanlist *cl;
        int count_chan = 0;
 
@@ -294,13 +291,14 @@ static char *handle_cli_core_show_channeltypes(struct ast_cli_entry *e, int cmd,
        if (a->argc != 3)
                return CLI_SHOWUSAGE;
 
-       ast_cli(a->fd, FORMAT, "Type", "Description",       "Devicestate", "Indications", "Transfer");
-       ast_cli(a->fd, FORMAT, "-----------", "-----------", "-----------", "-----------", "-----------");
+       ast_cli(a->fd, FORMAT, "Type", "Description", "Devicestate", "Presencestate", "Indications", "Transfer");
+       ast_cli(a->fd, FORMAT, "-------------", "-------------", "-------------", "-------------", "-------------", "-------------");
 
        AST_RWLIST_RDLOCK(&backends);
        AST_RWLIST_TRAVERSE(&backends, cl, list) {
                ast_cli(a->fd, FORMAT, cl->tech->type, cl->tech->description,
                        (cl->tech->devicestate) ? "yes" : "no",
+                       (cl->tech->presencestate) ? "yes" : "no",
                        (cl->tech->indicate) ? "yes" : "no",
                        (cl->tech->transfer) ? "yes" : "no");
                count_chan++;
@@ -342,7 +340,7 @@ static char *complete_channeltypes(struct ast_cli_args *a)
 static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct chanlist *cl = NULL;
-       struct ast_str *codec_buf = ast_str_alloca(64);
+       struct ast_str *codec_buf = ast_str_alloca(256);
 
        switch (cmd) {
        case CLI_INIT:
@@ -375,6 +373,7 @@ static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd,
        ast_cli(a->fd,
                "-- Info about channel driver: %s --\n"
                "  Device State: %s\n"
+               "Presence State: %s\n"
                "    Indication: %s\n"
                "     Transfer : %s\n"
                "  Capabilities: %s\n"
@@ -385,6 +384,7 @@ static char *handle_cli_core_show_channeltype(struct ast_cli_entry *e, int cmd,
                "  Text Support: %s\n",
                cl->tech->type,
                (cl->tech->devicestate) ? "yes" : "no",
+               (cl->tech->presencestate) ? "yes" : "no",
                (cl->tech->indicate) ? "yes" : "no",
                (cl->tech->transfer) ? "yes" : "no",
                ast_format_cap_get_names(cl->tech->capabilities, &codec_buf),
@@ -504,13 +504,9 @@ static int ast_channel_softhangup_cb(void *obj, void *arg, int flags)
        return 0;
 }
 
-void ast_begin_shutdown(int hangup)
+void ast_softhangup_all(void)
 {
-       shutting_down = 1;
-
-       if (hangup) {
-               ao2_callback(channels, OBJ_NODATA | OBJ_MULTIPLE, ast_channel_softhangup_cb, NULL);
-       }
+       ao2_callback(channels, OBJ_NODATA | OBJ_MULTIPLE, ast_channel_softhangup_cb, NULL);
 }
 
 /*! \brief returns number of active/allocated channels */
@@ -524,18 +520,6 @@ int ast_undestroyed_channels(void)
        return ast_atomic_fetchadd_int(&chancount, 0);
 }
 
-/*! \brief Cancel a shutdown in progress */
-void ast_cancel_shutdown(void)
-{
-       shutting_down = 0;
-}
-
-/*! \brief Returns non-zero if Asterisk is being shut down */
-int ast_shutting_down(void)
-{
-       return shutting_down;
-}
-
 /*! \brief Set when to hangup channel */
 void ast_channel_setwhentohangup_tv(struct ast_channel *chan, struct timeval offset)
 {
@@ -1212,8 +1196,8 @@ int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
 
 int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
 {
-       RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
        struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD };
+       struct ast_json *blob = NULL;
        int res;
 
        if (!ast_strlen_zero(musicclass)) {
@@ -1228,6 +1212,8 @@ int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
 
        res = ast_queue_frame(chan, &f);
 
+       ast_json_unref(blob);
+
        return res;
 }
 
@@ -2190,7 +2176,7 @@ static void ast_channel_destructor(void *obj)
        struct varshead *headp;
        struct ast_datastore *datastore;
        char device_name[AST_CHANNEL_NAME];
-       struct ast_callid *callid;
+       ast_callid callid;
 
        /* Stop monitoring */
        if (ast_channel_monitor(chan)) {
@@ -2327,9 +2313,6 @@ static void ast_channel_destructor(void *obj)
        }
 
        ast_channel_nativeformats_set(chan, NULL);
-       if (callid) {
-               ast_callid_unref(callid);
-       }
 
        ast_channel_named_callgroups_set(chan, NULL);
        ast_channel_named_pickupgroups_set(chan, NULL);
@@ -2843,14 +2826,14 @@ int __ast_answer(struct ast_channel *chan, unsigned int delay)
                                }
                        }
 
-                       if (res == 0) {
-                               ast_channel_lock(chan);
-                               while ((cur = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
+                       ast_channel_lock(chan);
+                       while ((cur = AST_LIST_REMOVE_HEAD(&frames, frame_list))) {
+                               if (res == 0) {
                                        ast_queue_frame_head(chan, cur);
-                                       ast_frfree(cur);
                                }
-                               ast_channel_unlock(chan);
+                               ast_frfree(cur);
                        }
+                       ast_channel_unlock(chan);
                } while (0);
                break;
        default:
@@ -4131,78 +4114,133 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio)
                                        ast_frfree(f);
                                        f = &ast_null_frame;
                                }
-                       } else if ((f->frametype == AST_FRAME_VOICE) && ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), f->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) {
-                               /* This frame is not one of the current native formats -- drop it on the floor */
-                               struct ast_str *codec_buf = ast_str_alloca(64);
-                               ast_log(LOG_NOTICE, "Dropping incompatible voice frame on %s of format %s since our native format has changed to %s\n",
-                                       ast_channel_name(chan), ast_format_get_name(f->subclass.format), ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
-                               ast_frfree(f);
-                               f = &ast_null_frame;
-                       } else if ((f->frametype == AST_FRAME_VOICE)) {
-                               /* Send frame to audiohooks if present */
-                               if (ast_channel_audiohooks(chan)) {
-                                       struct ast_frame *old_frame = f;
-                                       f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f);
-                                       if (old_frame != f)
-                                               ast_frfree(old_frame);
+                               break;
+                       }
+                       if (f->frametype != AST_FRAME_VOICE) {
+                               break;
+                       }
+                       if (ast_format_cmp(f->subclass.format, ast_channel_rawreadformat(chan)) != AST_FORMAT_CMP_EQUAL
+                               && ast_format_cmp(f->subclass.format, ast_channel_readformat(chan)) != AST_FORMAT_CMP_EQUAL) {
+                               struct ast_format *core_format;
+
+                               /*
+                                * Note: This frame may not be one of the current native
+                                * formats.  We may have gotten it out of the read queue from
+                                * a previous multi-frame translation, from a framehook
+                                * injected frame, or the device we're talking to isn't
+                                * respecting negotiated formats.  Regardless we will accept
+                                * all frames.
+                                *
+                                * Update the read translation path to handle the new format
+                                * that just came in.  If the core wants slinear we need to
+                                * setup a new translation path because the core is usually
+                                * doing something with the audio itself and may not handle
+                                * any other format.  e.g., Softmix bridge, holding bridge
+                                * announcer channel, recording, AMD...  Otherwise, we'll
+                                * setup to pass the frame as is to the core.  In this case
+                                * the core doesn't care.  The channel is likely in
+                                * autoservice, safesleep, or the channel is in a bridge.
+                                * Let the bridge technology deal with format compatibility
+                                * between the channels in the bridge.
+                                *
+                                * Beware of the transcode_via_slin and genericplc options as
+                                * they force any transcoding to go through slin on a bridge.
+                                * Unfortunately transcode_via_slin is enabled by default and
+                                * genericplc is enabled in the codecs.conf.sample file.
+                                *
+                                * XXX Only updating translation to slinear frames has some
+                                * corner cases if slinear is one of the native formats and
+                                * there are different sample rates involved.  We might wind
+                                * up with conflicting translation paths between channels
+                                * where the read translation path on this channel reduces
+                                * the sample rate followed by a write translation path on
+                                * the peer channel that increases the sample rate.
+                                */
+                               core_format = ast_channel_readformat(chan);
+                               if (!ast_format_cache_is_slinear(core_format)) {
+                                       core_format = f->subclass.format;
+                               }
+                               if (ast_set_read_format_path(chan, f->subclass.format, core_format)) {
+                                       /* Drop frame.  We couldn't make it compatible with the core. */
+                                       ast_frfree(f);
+                                       f = &ast_null_frame;
+                                       break;
+                               }
+                       }
+                       /* Send frame to audiohooks if present */
+                       if (ast_channel_audiohooks(chan)) {
+                               struct ast_frame *old_frame = f;
+
+                               f = ast_audiohook_write_list(chan, ast_channel_audiohooks(chan), AST_AUDIOHOOK_DIRECTION_READ, f);
+                               if (old_frame != f) {
+                                       ast_frfree(old_frame);
                                }
-                               if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->read_stream ) {
-                                       /* XXX what does this do ? */
+                       }
+                       if (ast_channel_monitor(chan) && ast_channel_monitor(chan)->read_stream) {
+                               /* XXX what does this do ? */
 #ifndef MONITOR_CONSTANT_DELAY
-                                       int jump = ast_channel_outsmpl(chan) - ast_channel_insmpl(chan) - 4 * f->samples;
-                                       if (jump >= 0) {
-                                               jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
-                                                                        ast_format_get_sample_rate(f->subclass.format),
-                                                                        ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
-                                               if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump, SEEK_FORCECUR) == -1) {
-                                                       ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
-                                               }
-                                               ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + (ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)) + f->samples);
-                                       } else {
-                                               ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + f->samples);
+                               int jump = ast_channel_outsmpl(chan) - ast_channel_insmpl(chan) - 4 * f->samples;
+                               if (jump >= 0) {
+                                       jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+                                               ast_format_get_sample_rate(f->subclass.format),
+                                               ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+                                       if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump, SEEK_FORCECUR) == -1) {
+                                               ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
                                        }
+                                       ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + (ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)) + f->samples);
+                               } else {
+                                       ast_channel_insmpl_set(chan, ast_channel_insmpl(chan) + f->samples);
+                               }
 #else
-                                       int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
-                                                                    ast_format_get_sample_rate(f->subclass.codec),
-                                                                    ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
-                                       if (jump - MONITOR_DELAY >= 0) {
-                                               if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1)
-                                                       ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
-                                               ast_channel_insmpl(chan) += ast_channel_outsmpl(chan) - ast_channel_insmpl(chan);
-                                       } else
-                                               ast_channel_insmpl(chan) += f->samples;
-#endif
-                                       if (ast_channel_monitor(chan)->state == AST_MONITOR_RUNNING) {
-                                               if (ast_writestream(ast_channel_monitor(chan)->read_stream, f) < 0)
-                                                       ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
+                               int jump = calc_monitor_jump((ast_channel_outsmpl(chan) - ast_channel_insmpl(chan)),
+                                       ast_format_get_sample_rate(f->subclass.codec),
+                                       ast_format_get_sample_rate(ast_channel_monitor(chan)->read_stream->fmt->format));
+                               if (jump - MONITOR_DELAY >= 0) {
+                                       if (ast_seekstream(ast_channel_monitor(chan)->read_stream, jump - f->samples, SEEK_FORCECUR) == -1) {
+                                               ast_log(LOG_WARNING, "Failed to perform seek in monitoring read stream, synchronization between the files may be broken\n");
                                        }
+                                       ast_channel_insmpl(chan) += ast_channel_outsmpl(chan) - ast_channel_insmpl(chan);
+                               } else {
+                                       ast_channel_insmpl(chan) += f->samples;
+                               }
+#endif
+                               if (ast_channel_monitor(chan)->state == AST_MONITOR_RUNNING) {
+                                       if (ast_writestream(ast_channel_monitor(chan)->read_stream, f) < 0)
+                                               ast_log(LOG_WARNING, "Failed to write data to channel monitor read stream\n");
                                }
+                       }
 
-                               if (ast_channel_readtrans(chan) && (f = ast_translate(ast_channel_readtrans(chan), f, 1)) == NULL) {
+                       if (ast_channel_readtrans(chan)
+                               && ast_format_cmp(f->subclass.format, ast_channel_rawreadformat(chan)) == AST_FORMAT_CMP_EQUAL) {
+                               f = ast_translate(ast_channel_readtrans(chan), f, 1);
+                               if (!f) {
                                        f = &ast_null_frame;
                                }
+                       }
 
-                               /* it is possible for the translation process on chan->readtrans to have
-                                  produced multiple frames from the single input frame we passed it; if
-                                  this happens, queue the additional frames *before* the frames we may
-                                  have queued earlier. if the readq was empty, put them at the head of
-                                  the queue, and if it was not, put them just after the frame that was
-                                  at the end of the queue.
-                               */
-                               if (AST_LIST_NEXT(f, frame_list)) {
-                                       if (!readq_tail) {
-                                               ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list));
-                                       } else {
-                                               __ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail);
-                                       }
-                                       ast_frfree(AST_LIST_NEXT(f, frame_list));
-                                       AST_LIST_NEXT(f, frame_list) = NULL;
+                       /*
+                        * It is possible for the translation process on the channel to have
+                        * produced multiple frames from the single input frame we passed it; if
+                        * this happens, queue the additional frames *before* the frames we may
+                        * have queued earlier. if the readq was empty, put them at the head of
+                        * the queue, and if it was not, put them just after the frame that was
+                        * at the end of the queue.
+                        */
+                       if (AST_LIST_NEXT(f, frame_list)) {
+                               if (!readq_tail) {
+                                       ast_queue_frame_head(chan, AST_LIST_NEXT(f, frame_list));
+                               } else {
+                                       __ast_queue_frame(chan, AST_LIST_NEXT(f, frame_list), 0, readq_tail);
                                }
-
-                               /* Run generator sitting on the line if timing device not available
-                               * and synchronous generation of outgoing frames is necessary       */
-                               ast_read_generator_actions(chan, f);
+                               ast_frfree(AST_LIST_NEXT(f, frame_list));
+                               AST_LIST_NEXT(f, frame_list) = NULL;
                        }
+
+                       /*
+                        * Run generator sitting on the line if timing device not available
+                        * and synchronous generation of outgoing frames is necessary
+                        */
+                       ast_read_generator_actions(chan, f);
                        break;
                default:
                        /* Just pass it on! */
@@ -4285,6 +4323,7 @@ static int attribute_const is_visible_indication(enum ast_control_frame_type con
        case AST_CONTROL_MCID:
        case AST_CONTROL_UPDATE_RTP_PEER:
        case AST_CONTROL_PVT_CAUSE_CODE:
+       case AST_CONTROL_MASQUERADE_NOTIFY:
        case AST_CONTROL_STREAM_STOP:
        case AST_CONTROL_STREAM_SUSPEND:
        case AST_CONTROL_STREAM_REVERSE:
@@ -4451,7 +4490,9 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
        ast_channel_lock(chan);
 
        /* Don't bother if the channel is about to go away, anyway. */
-       if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE) || ast_check_hangup(chan)) {
+       if ((ast_test_flag(ast_channel_flags(chan), AST_FLAG_ZOMBIE)
+                       || ast_check_hangup(chan))
+               && condition != AST_CONTROL_MASQUERADE_NOTIFY) {
                res = -1;
                goto indicate_cleanup;
        }
@@ -4599,6 +4640,7 @@ int ast_indicate_data(struct ast_channel *chan, int _condition,
        case AST_CONTROL_AOC:
        case AST_CONTROL_END_OF_Q:
        case AST_CONTROL_MCID:
+       case AST_CONTROL_MASQUERADE_NOTIFY:
        case AST_CONTROL_UPDATE_RTP_PEER:
        case AST_CONTROL_STREAM_STOP:
        case AST_CONTROL_STREAM_SUSPEND:
@@ -5047,29 +5089,35 @@ int ast_write(struct ast_channel *chan, struct ast_frame *fr)
                }
 
                /* If the frame is in the raw write format, then it's easy... just use the frame - otherwise we will have to translate */
-               if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) != AST_FORMAT_CMP_NOT_EQUAL) {
+               if (ast_format_cmp(fr->subclass.format, ast_channel_rawwriteformat(chan)) == AST_FORMAT_CMP_EQUAL) {
                        f = fr;
                } else {
-                       if ((ast_format_cap_iscompatible_format(ast_channel_nativeformats(chan), fr->subclass.format) == AST_FORMAT_CMP_NOT_EQUAL) &&
-                           (ast_format_cmp(ast_channel_writeformat(chan), fr->subclass.format) != AST_FORMAT_CMP_EQUAL)) {
-                               struct ast_str *codec_buf = ast_str_alloca(64);
+                       if (ast_format_cmp(ast_channel_writeformat(chan), fr->subclass.format) != AST_FORMAT_CMP_EQUAL) {
+                               struct ast_str *codec_buf = ast_str_alloca(256);
 
                                /*
-                                * XXX Something is not right.  We are not compatible with this
-                                * frame.  Bad things can happen.  Problems range from no audio,
-                                * one-way audio, to unexplained line hangups.  As a last resort
-                                * try to adjust the format.  Ideally, we do not want to do this
-                                * because it indicates a deeper problem.  For now, we log these
-                                * events to reduce user impact and help identify the problem
-                                * areas.
+                                * We are not setup to write this frame.  Things may have changed
+                                * on the peer side of the world and we try to adjust the format to
+                                * make it compatible again.  However, bad things can happen if we
+                                * cannot setup a new translation path.  Problems range from no
+                                * audio, one-way audio, to garbled audio.  The best we can do is
+                                * request the call to hangup since we could not make it compatible.
+                                *
+                                * Being continuously spammed by this message likely indicates a
+                                * problem with the peer because it cannot make up its mind about
+                                * which format to use.
                                 */
-                               ast_log(LOG_WARNING, "Codec mismatch on channel %s setting write format to %s from %s native formats %s\n",
-                                       ast_channel_name(chan), ast_format_get_name(fr->subclass.format), ast_format_get_name(ast_channel_writeformat(chan)),
+                               ast_debug(1, "Channel %s changing write format from %s to %s, native formats %s\n",
+                                       ast_channel_name(chan),
+                                       ast_format_get_name(ast_channel_writeformat(chan)),
+                                       ast_format_get_name(fr->subclass.format),
                                        ast_format_cap_get_names(ast_channel_nativeformats(chan), &codec_buf));
-                               ast_set_write_format(chan, fr->subclass.format);
+                               if (ast_set_write_format(chan, fr->subclass.format)) {
+                                       /* Could not handle the new write format.  Induce a hangup. */
+                                       break;
+                               }
                        }
-
-                       f = (ast_channel_writetrans(chan)) ? ast_translate(ast_channel_writetrans(chan), fr, 0) : fr;
+                       f = ast_channel_writetrans(chan) ? ast_translate(ast_channel_writetrans(chan), fr, 0) : fr;
                }
 
                if (!f) {
@@ -5229,54 +5277,129 @@ done:
        return res;
 }
 
-struct set_format_trans_access {
-       struct ast_trans_pvt *(*get)(const struct ast_channel *chan);
-       void (*set)(struct ast_channel *chan, struct ast_trans_pvt *value);
+int ast_set_read_format_path(struct ast_channel *chan, struct ast_format *raw_format, struct ast_format *core_format)
+{
+       struct ast_trans_pvt *trans_old;
+       struct ast_trans_pvt *trans_new;
+
+       if (ast_format_cmp(ast_channel_rawreadformat(chan), raw_format) == AST_FORMAT_CMP_EQUAL
+               && ast_format_cmp(ast_channel_readformat(chan), core_format) == AST_FORMAT_CMP_EQUAL) {
+               /* Nothing to setup */
+               return 0;
+       }
+
+       ast_debug(1, "Channel %s setting read format path: %s -> %s\n",
+               ast_channel_name(chan),
+               ast_format_get_name(raw_format),
+               ast_format_get_name(core_format));
+
+       /* Setup new translation path. */
+       if (ast_format_cmp(raw_format, core_format) != AST_FORMAT_CMP_EQUAL) {
+               trans_new = ast_translator_build_path(core_format, raw_format);
+               if (!trans_new) {
+                       return -1;
+               }
+       } else {
+               /* No translation needed. */
+               trans_new = NULL;
+       }
+       trans_old = ast_channel_readtrans(chan);
+       if (trans_old) {
+               ast_translator_free_path(trans_old);
+       }
+       ast_channel_readtrans_set(chan, trans_new);
+       ast_channel_set_rawreadformat(chan, raw_format);
+       ast_channel_set_readformat(chan, core_format);
+       return 0;
+}
+
+struct set_format_access {
+       const char *direction;
+       struct ast_trans_pvt *(*get_trans)(const struct ast_channel *chan);
+       void (*set_trans)(struct ast_channel *chan, struct ast_trans_pvt *value);
+       struct ast_format *(*get_format)(struct ast_channel *chan);
+       void (*set_format)(struct ast_channel *chan, struct ast_format *format);
+       struct ast_format *(*get_rawformat)(struct ast_channel *chan);
+       void (*set_rawformat)(struct ast_channel *chan, struct ast_format *format);
+       int setoption;
 };
 
-static const struct set_format_trans_access set_format_readtrans = {
-       .get = ast_channel_readtrans,
-       .set = ast_channel_readtrans_set,
+static const struct set_format_access set_format_access_read = {
+       .direction = "read",
+       .get_trans = ast_channel_readtrans,
+       .set_trans = ast_channel_readtrans_set,
+       .get_format = ast_channel_readformat,
+       .set_format = ast_channel_set_readformat,
+       .get_rawformat = ast_channel_rawreadformat,
+       .set_rawformat = ast_channel_set_rawreadformat,
+       .setoption = AST_OPTION_FORMAT_READ,
 };
 
-static const struct set_format_trans_access set_format_writetrans = {
-       .get = ast_channel_writetrans,
-       .set = ast_channel_writetrans_set,
+static const struct set_format_access set_format_access_write = {
+       .direction = "write",
+       .get_trans = ast_channel_writetrans,
+       .set_trans = ast_channel_writetrans_set,
+       .get_format = ast_channel_writeformat,
+       .set_format = ast_channel_set_writeformat,
+       .get_rawformat = ast_channel_rawwriteformat,
+       .set_rawformat = ast_channel_set_rawwriteformat,
+       .setoption = AST_OPTION_FORMAT_WRITE,
 };
 
-static int set_format(struct ast_channel *chan,
-       struct ast_format_cap *cap_set,
-       struct ast_format *rawformat,
-       struct ast_format *format,
-       const struct set_format_trans_access *trans,
-       const int direction)
+static int set_format(struct ast_channel *chan, struct ast_format_cap *cap_set, const int direction)
 {
        struct ast_trans_pvt *trans_pvt;
        struct ast_format_cap *cap_native;
-       RAII_VAR(struct ast_format *, best_set_fmt, ast_format_cap_get_format(cap_set, 0), ao2_cleanup);
+       const struct set_format_access *access;
+       struct ast_format *rawformat;
+       struct ast_format *format;
+       RAII_VAR(struct ast_format *, best_set_fmt, NULL, ao2_cleanup);
        RAII_VAR(struct ast_format *, best_native_fmt, NULL, ao2_cleanup);
        int res;
 
-       ast_assert(format != NULL);
-       ast_assert(rawformat != NULL);
+       if (!direction) {
+               /* reading */
+               access = &set_format_access_read;
+       } else {
+               /* writing */
+               access = &set_format_access_write;
+       }
+
+       best_set_fmt = ast_format_cap_get_best_by_type(cap_set, AST_MEDIA_TYPE_AUDIO);
+       if (!best_set_fmt) {
+               /*
+                * Not setting any audio formats?
+                * Assume a call without any sounds (video, text)
+                */
+               return 0;
+       }
 
        /* See if the underlying channel driver is capable of performing transcoding for us */
-       if (!ast_channel_setoption(chan, direction ? AST_OPTION_FORMAT_WRITE : AST_OPTION_FORMAT_READ, &best_set_fmt, sizeof(best_set_fmt), 0)) {
-               ast_debug(1, "Channel driver natively set channel %s to %s format %s\n", ast_channel_name(chan),
-                         direction ? "write" : "read", ast_format_get_name(best_set_fmt));
+       res = ast_channel_setoption(chan, access->setoption,
+               &best_set_fmt, sizeof(best_set_fmt), 0);
+       if (!res) {
+               ast_debug(1, "Channel driver natively set channel %s to %s format %s\n",
+                       ast_channel_name(chan), access->direction, ast_format_get_name(best_set_fmt));
 
                ast_channel_lock(chan);
                cap_native = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
-               ast_format_cap_append(cap_native, best_set_fmt, 0);
+               if (!cap_native
+                       || ast_format_cap_append(cap_native, best_set_fmt, 0)) {
+                       ast_channel_unlock(chan);
+                       ao2_cleanup(cap_native);
+                       return -1;
+               }
                ast_channel_nativeformats_set(chan, cap_native);
                ao2_cleanup(cap_native);
-               ast_channel_unlock(chan);
+               access->set_format(chan, best_set_fmt);
+               access->set_rawformat(chan, best_set_fmt);
 
-               trans_pvt = trans->get(chan);
+               trans_pvt = access->get_trans(chan);
                if (trans_pvt) {
                        ast_translator_free_path(trans_pvt);
-                       trans->set(chan, NULL);
+                       access->set_trans(chan, NULL);
                }
+               ast_channel_unlock(chan);
 
                /* If there is a generator on the channel, it needs to know about this
                 * change if it is the write format. */
@@ -5288,7 +5411,19 @@ static int set_format(struct ast_channel *chan,
        }
 
        ast_channel_lock(chan);
+
+       format = access->get_format(chan);
+       rawformat = access->get_rawformat(chan);
+       ast_assert(format != NULL);
+       ast_assert(rawformat != NULL);
+
        cap_native = ast_channel_nativeformats(chan);
+       if (ast_format_cap_empty(cap_native)) {
+               ast_channel_unlock(chan);
+               ast_log(LOG_ERROR, "Unable to set format because channel %s supports no formats\n",
+                               ast_channel_name(chan));
+               return -1;
+       }
 
        /* Find a translation path from the native format to one of the desired formats */
        if (!direction) {
@@ -5299,32 +5434,33 @@ static int set_format(struct ast_channel *chan,
                res = ast_translator_best_choice(cap_native, cap_set, &best_native_fmt, &best_set_fmt);
        }
        if (res < 0) {
-               struct ast_str *codec_from = ast_str_alloca(64);
-               struct ast_str *codec_to = ast_str_alloca(64);
+               struct ast_str *codec_native = ast_str_alloca(256);
+               struct ast_str *codec_set = ast_str_alloca(256);
 
-               ast_format_cap_get_names(cap_native, &codec_from);
+               ast_format_cap_get_names(cap_native, &codec_native);
                ast_channel_unlock(chan);
-               ast_format_cap_get_names(cap_set, &codec_to);
+               ast_format_cap_get_names(cap_set, &codec_set);
 
-               ast_log(LOG_WARNING, "Unable to find a codec translation path from %s to %s\n",
-                       ast_str_buffer(codec_from), ast_str_buffer(codec_to));
+               ast_log(LOG_WARNING, "Unable to find a codec translation path: %s -> %s\n",
+                       ast_str_buffer(direction ? codec_set : codec_native),
+                       ast_str_buffer(direction ? codec_native : codec_set));
                return -1;
        }
 
        /* Now we have a good choice for both. */
        if ((ast_format_cmp(rawformat, best_native_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
                (ast_format_cmp(format, best_set_fmt) != AST_FORMAT_CMP_NOT_EQUAL) &&
-               ((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || trans->get(chan))) {
+               ((ast_format_cmp(rawformat, format) != AST_FORMAT_CMP_NOT_EQUAL) || access->get_trans(chan))) {
                /* the channel is already in these formats, so nothing to do */
                ast_channel_unlock(chan);
                return 0;
        }
 
        /* Free any translation we have right now */
-       trans_pvt = trans->get(chan);
+       trans_pvt = access->get_trans(chan);
        if (trans_pvt) {
                ast_translator_free_path(trans_pvt);
-               trans->set(chan, NULL);
+               access->set_trans(chan, NULL);
        }
 
        /* Build a translation path from the raw format to the desired format */
@@ -5343,25 +5479,19 @@ static int set_format(struct ast_channel *chan,
                        /* writing */
                        trans_pvt = ast_translator_build_path(best_native_fmt, best_set_fmt);
                }
-               trans->set(chan, trans_pvt);
+               access->set_trans(chan, trans_pvt);
                res = trans_pvt ? 0 : -1;
        }
 
        if (!res) {
-               if (!direction) {
-                       /* reading */
-                       ast_channel_set_readformat(chan, best_set_fmt);
-                       ast_channel_set_rawreadformat(chan, best_native_fmt);
-               } else {
-                       /* writing */
-                       ast_channel_set_writeformat(chan, best_set_fmt);
-                       ast_channel_set_rawwriteformat(chan, best_native_fmt);
-               }
+               access->set_format(chan, best_set_fmt);
+               access->set_rawformat(chan, best_native_fmt);
 
-               ast_debug(1, "Set channel %s to %s format %s\n",
+               ast_debug(1, "Channel %s setting %s format path: %s -> %s\n",
                        ast_channel_name(chan),
-                       direction ? "write" : "read",
-                       ast_format_get_name(best_set_fmt));
+                       access->direction,
+                       ast_format_get_name(direction ? best_set_fmt : best_native_fmt),
+                       ast_format_get_name(direction ? best_native_fmt : best_set_fmt));
        }
 
        ast_channel_unlock(chan);
@@ -5387,12 +5517,7 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
        }
        ast_format_cap_append(cap, format, 0);
 
-       res = set_format(chan,
-               cap,
-               ast_channel_rawreadformat(chan),
-               ast_channel_readformat(chan),
-               &set_format_readtrans,
-               0);
+       res = set_format(chan, cap, 0);
 
        ao2_cleanup(cap);
        return res;
@@ -5400,12 +5525,7 @@ int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
 
 int ast_set_read_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap)
 {
-       return set_format(chan,
-               cap,
-               ast_channel_rawreadformat(chan),
-               ast_channel_readformat(chan),
-               &set_format_readtrans,
-               0);
+       return set_format(chan, cap, 0);
 }
 
 int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
@@ -5420,12 +5540,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
        }
        ast_format_cap_append(cap, format, 0);
 
-       res = set_format(chan,
-               cap,
-               ast_channel_rawwriteformat(chan),
-               ast_channel_writeformat(chan),
-               &set_format_writetrans,
-               1);
+       res = set_format(chan, cap, 1);
 
        ao2_cleanup(cap);
        return res;
@@ -5433,12 +5548,7 @@ int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
 
 int ast_set_write_format_from_cap(struct ast_channel *chan, struct ast_format_cap *cap)
 {
-       return set_format(chan,
-               cap,
-               ast_channel_rawwriteformat(chan),
-               ast_channel_writeformat(chan),
-               &set_format_writetrans,
-               1);
+       return set_format(chan, cap, 1);
 }
 
 const char *ast_channel_reason2str(int reason)
@@ -5881,9 +5991,10 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
                        return NULL;
 
                /* XXX Only the audio format calculated as being the best for translation
-                * purposes is used for the request. This needs to be re-evaluated.  It may be
-                * a better choice to send all the audio formats capable of being translated
-                * during the request and allow the channel drivers to pick the best one. */
+                * purposes is used for the request. This is because we don't have the ability
+                * to signal to the initiator which one of their codecs that was offered is
+                * the one that was selected, particularly in a chain of Local channels.
+                */
                joint_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
                if (!joint_cap) {
                        return NULL;
@@ -5898,7 +6009,7 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
                }
 
                if (requestor) {
-                       struct ast_callid *callid;
+                       ast_callid callid;
 
                        ast_channel_lock_both(c, (struct ast_channel *) requestor);
 
@@ -5906,7 +6017,6 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
                        callid = ast_channel_callid(requestor);
                        if (callid) {
                                ast_channel_callid_set(c, callid);
-                               callid = ast_callid_unref(callid);
                        }
 
                        ast_channel_unlock(c);
@@ -6196,15 +6306,17 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
        RAII_VAR(struct ast_format *, best_dst_fmt, NULL, ao2_cleanup);
        int no_path;
 
-       ast_channel_lock_both(from, to);
+       /*
+        * We cannot short circuit this code because it is possible to ask
+        * to make compatible two channels that are "compatible" because
+        * they already have translation paths setup but together make for
+        * a sub-optimal path.  e.g., The From channel has g722 -> ulaw
+        * and the To channel has ulaw -> g722.  They are "compatible" but
+        * together the translations are unnecessary and the audio loses
+        * fidelity in the process.
+        */
 
-       if ((ast_format_cmp(ast_channel_readformat(from), ast_channel_writeformat(to)) != AST_FORMAT_CMP_NOT_EQUAL) &&
-               (ast_format_cmp(ast_channel_readformat(to), ast_channel_writeformat(from)) != AST_FORMAT_CMP_NOT_EQUAL)) {
-               /* Already compatible!  Moving on ... */
-               ast_channel_unlock(to);
-               ast_channel_unlock(from);
-               return 0;
-       }
+       ast_channel_lock_both(from, to);
 
        src_cap = ast_channel_nativeformats(from); /* shallow copy, do not destroy */
        dst_cap = ast_channel_nativeformats(to);   /* shallow copy, do not destroy */
@@ -6244,8 +6356,7 @@ static int ast_channel_make_compatible_helper(struct ast_channel *from, struct a
                                ast_format_get_sample_rate(best_src_fmt) : ast_format_get_sample_rate(best_dst_fmt);
 
                        /* pick the best signed linear format based upon what preserves the sample rate the best. */
-                       ao2_ref(best_src_fmt, -1);
-                       best_src_fmt = ao2_bump(ast_format_cache_get_slin_by_rate(best_sample_rate));
+                       ao2_replace(best_src_fmt, ast_format_cache_get_slin_by_rate(best_sample_rate));
                }
        }
 
@@ -6313,41 +6424,42 @@ void ast_change_name(struct ast_channel *chan, const char *newname)
 
 void ast_channel_inherit_variables(const struct ast_channel *parent, struct ast_channel *child)
 {
-       struct ast_var_t *current, *newvar;
+       struct ast_var_t *current;
+       struct ast_var_t *newvar;
        const char *varname;
+       int vartype;
 
        AST_LIST_TRAVERSE(ast_channel_varshead((struct ast_channel *) parent), current, entries) {
-               int vartype = 0;
-
                varname = ast_var_full_name(current);
-               if (!varname)
+               if (!varname) {
                        continue;
+               }
 
+               vartype = 0;
                if (varname[0] == '_') {
                        vartype = 1;
-                       if (varname[1] == '_')
+                       if (varname[1] == '_') {
                                vartype = 2;
+                       }
                }
 
                switch (vartype) {
                case 1:
                        newvar = ast_var_assign(&varname[1], ast_var_value(current));
-                       if (newvar) {
-                               AST_LIST_INSERT_TAIL(ast_channel_varshead(child), newvar, entries);
-                               ast_debug(1, "Inheriting variable %s from %s to %s.\n",
-                                       ast_var_name(newvar), ast_channel_name(parent), ast_channel_name(child));
-                       }
                        break;
                case 2:
                        newvar = ast_var_assign(varname, ast_var_value(current));
-                       if (newvar) {
-                               AST_LIST_INSERT_TAIL(ast_channel_varshead(child), newvar, entries);
-                               ast_debug(1, "Inheriting variable %s from %s to %s.\n",
-                                       ast_var_name(newvar), ast_channel_name(parent), ast_channel_name(child));
-                       }
                        break;
                default:
-                       break;
+                       continue;
+               }
+               if (newvar) {
+                       ast_debug(1, "Inheriting variable %s from %s to %s.\n",
+                               ast_var_full_name(newvar), ast_channel_name(parent),
+                               ast_channel_name(child));
+                       AST_LIST_INSERT_TAIL(ast_channel_varshead(child), newvar, entries);
+                       ast_channel_publish_varset(child, ast_var_full_name(newvar),
+                               ast_var_value(newvar));
                }
        }
 }
@@ -6429,6 +6541,11 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
         * original channel's backend.  While the features are nice, which is the
         * reason we're keeping it, it's still awesomely weird. XXX */
 
+       /* Indicate to each channel that a masquerade is about to begin. */
+       x = 1;
+       ast_indicate_data(original, AST_CONTROL_MASQUERADE_NOTIFY, &x, sizeof(x));
+       ast_indicate_data(clonechan, AST_CONTROL_MASQUERADE_NOTIFY, &x, sizeof(x));
+
        /*
         * The container lock is necessary for proper locking order
         * because the channels must be unlinked to change their
@@ -6469,8 +6586,9 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
        /* Start the masquerade channel contents rearangement. */
        ast_channel_lock_both(original, clonechan);
 
-       ast_debug(4, "Actually Masquerading %s(%u) into the structure of %s(%u)\n",
-               ast_channel_name(clonechan), ast_channel_state(clonechan), ast_channel_name(original), ast_channel_state(original));
+       ast_debug(1, "Actually Masquerading %s(%u) into the structure of %s(%u)\n",
+               ast_channel_name(clonechan), ast_channel_state(clonechan),
+               ast_channel_name(original), ast_channel_state(original));
 
        /*
         * Remember the original read/write formats.  We turn off any
@@ -6492,6 +6610,9 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
         */
        ast_channel_internal_swap_uniqueid_and_linkedid(clonechan, original);
 
+       /* Make sure the Stasis topic on the channel is updated appropriately */
+       ast_channel_internal_swap_topics(clonechan, original);
+
        /* Swap channel names. This uses ast_channel_name_set directly, so we
         * don't get any spurious rename events.
         */
@@ -6743,6 +6864,19 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
        ast_channel_unlock(original);
        ast_channel_unlock(clonechan);
 
+       /*
+        * Indicate to each channel that a masquerade is complete.
+        *
+        * We can still do this to clonechan even though it is a
+        * zombie because ast_indicate_data() will explicitly pass
+        * this control and ast_hangup() is held off until the
+        * ast_channel_masq() and ast_channel_masqr() pointers are
+        * cleared.
+        */
+       x = 0;
+       ast_indicate_data(original, AST_CONTROL_MASQUERADE_NOTIFY, &x, sizeof(x));
+       ast_indicate_data(clonechan, AST_CONTROL_MASQUERADE_NOTIFY, &x, sizeof(x));
+
        ast_bridge_notify_masquerade(original);
 
        if (clone_hold_state == AST_CONTROL_HOLD) {
@@ -7372,6 +7506,7 @@ static int data_channeltypes_provider_handler(const struct ast_data_search *sear
                ast_data_add_str(data_type, "name", cl->tech->type);
                ast_data_add_str(data_type, "description", cl->tech->description);
                ast_data_add_bool(data_type, "devicestate", cl->tech->devicestate ? 1 : 0);
+               ast_data_add_bool(data_type, "presencestate", cl->tech->presencestate ? 1 : 0);
                ast_data_add_bool(data_type, "indications", cl->tech->indicate ? 1 : 0);
                ast_data_add_bool(data_type, "transfer", cl->tech->transfer ? 1 : 0);
                ast_data_add_bool(data_type, "send_digit_begin", cl->tech->send_digit_begin ? 1 : 0);
@@ -7620,7 +7755,7 @@ void ast_channels_init(void)
 
        ast_plc_reload();
 
-       ast_register_atexit(channels_shutdown);
+       ast_register_cleanup(channels_shutdown);
 
 }
 
@@ -7917,6 +8052,7 @@ void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_p
 
        ast_channel_lock(chan);
        ast_party_connected_line_set(ast_channel_connected(chan), connected, update);
+       ast_channel_publish_snapshot(chan);
        ast_channel_unlock(chan);
 }
 
@@ -10218,12 +10354,14 @@ int ast_channel_is_leaving_bridge(struct ast_channel *chan)
 {
        int hangup_flags = ast_channel_softhangup_internal_flag(chan);
        int hangup_test = hangup_flags & AST_SOFTHANGUP_ASYNCGOTO;
+       int unbridge = ast_channel_unbridged(chan);
 
-       /* This function should only return true if only the ASYNCGOTO
-        * is set. It should false if any other flag is set or if the
-        * ASYNCGOTO flag is not set.
+       /* This function should only return true if either the unbridged flag or
+        * the ASYNCGOTO soft hangup flag is set and when no other soft hangup
+        * flags are set. Any other soft hangup flags being set should make it
+        * return false.
         */
-       return (hangup_test && (hangup_test == hangup_flags));
+       return ((hangup_test || unbridge) && (hangup_test == hangup_flags));
 }
 
 struct ast_channel *ast_channel_bridge_peer(struct ast_channel *chan)