diff options
-rw-r--r-- | include/asterisk/features_config.h | 15 | ||||
-rw-r--r-- | main/astmm.c | 107 | ||||
-rw-r--r-- | main/bridge_basic.c | 80 | ||||
-rw-r--r-- | main/features_config.c | 15 | ||||
-rw-r--r-- | main/taskprocessor.c | 5 |
5 files changed, 182 insertions, 40 deletions
diff --git a/include/asterisk/features_config.h b/include/asterisk/features_config.h index b15759ba6..baaff183b 100644 --- a/include/asterisk/features_config.h +++ b/include/asterisk/features_config.h @@ -102,6 +102,21 @@ struct ast_features_xfer_config { struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan); /*! + * \brief Get the transfer configuration option xferfailsound + * + * \note The channel should be locked before calling this function. + * \note The returned value has to be freed. + * + * If no channel is provided, then option is pulled from the global + * transfer configuration. + * + * \param chan The channel to get configuration options for + * \retval NULL Failed to get configuration + * \retval non-NULL The xferfailsound + */ +char *ast_get_chan_features_xferfailsound(struct ast_channel *chan); + +/*! * \brief Configuration relating to call pickup */ struct ast_features_pickup_config { diff --git a/main/astmm.c b/main/astmm.c index 5812174d5..331778489 100644 --- a/main/astmm.c +++ b/main/astmm.c @@ -672,6 +672,32 @@ int __ast_vasprintf(char **strp, const char *fmt, va_list ap, const char *file, return size; } +/*! + * \internal + * \brief Count the number of bytes in the specified freed region. + * + * \param freed Already freed region blocks storage. + * + * \note reglock must be locked before calling. + * + * \return Number of bytes in freed region. + */ +static size_t freed_regions_size(struct ast_freed_regions *freed) +{ + size_t total_len = 0; + int idx; + struct ast_region *old; + + for (idx = 0; idx < ARRAY_LEN(freed->regions); ++idx) { + old = freed->regions[idx]; + if (old) { + total_len += old->len; + } + } + + return total_len; +} + static char *handle_memory_atexit_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { switch (cmd) { @@ -774,12 +800,54 @@ static char *handle_memory_atexit_summary(struct ast_cli_entry *e, int cmd, stru return CLI_SUCCESS; } +/*! + * \internal + * \brief Common summary output at the end of the memory show commands. + * + * \param fd CLI output file descriptor. + * \param whales_len Accumulated size of free large allocations. + * \param minnows_len Accumulated size of free small allocations. + * \param total_len Accumulated size of all current allocations. + * \param selected_len Accumulated size of the selected allocations. + * \param cache_len Accumulated size of the allocations that are part of a cache. + * \param count Number of selected allocations. + * + * \return Nothing + */ +static void print_memory_show_common_stats(int fd, + unsigned int whales_len, + unsigned int minnows_len, + unsigned int total_len, + unsigned int selected_len, + unsigned int cache_len, + unsigned int count) +{ + if (cache_len) { + ast_cli(fd, "%10u bytes allocated (%u in caches) in %u selected allocations\n\n", + selected_len, cache_len, count); + } else { + ast_cli(fd, "%10u bytes allocated in %u selected allocations\n\n", + selected_len, count); + } + + ast_cli(fd, "%10u bytes in all allocations\n", total_len); + ast_cli(fd, "%10u bytes in deferred free large allocations\n", whales_len); + ast_cli(fd, "%10u bytes in deferred free small allocations\n", minnows_len); + ast_cli(fd, "%10u bytes in deferred free allocations\n", + whales_len + minnows_len); + ast_cli(fd, "%10u bytes in all allocations and deferred free allocations\n", + total_len + whales_len + minnows_len); +} + static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { const char *fn = NULL; struct ast_region *reg; unsigned int idx; - unsigned int len = 0; + unsigned int whales_len; + unsigned int minnows_len; + unsigned int total_len = 0; + unsigned int selected_len = 0; unsigned int cache_len = 0; unsigned int count = 0; @@ -813,6 +881,7 @@ static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, st ast_mutex_lock(®lock); for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) { + total_len += reg->len; if (fn && strcasecmp(fn, reg->file)) { continue; } @@ -823,21 +892,21 @@ static char *handle_memory_show_allocations(struct ast_cli_entry *e, int cmd, st (unsigned int) reg->len, reg->cache ? " (cache)" : "", reg->func, reg->lineno, reg->file); - len += reg->len; + selected_len += reg->len; if (reg->cache) { cache_len += reg->len; } ++count; } } + + whales_len = freed_regions_size(&whales); + minnows_len = freed_regions_size(&minnows); ast_mutex_unlock(®lock); - if (cache_len) { - ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n", - len, cache_len, count); - } else { - ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count); - } + print_memory_show_common_stats(a->fd, + whales_len, minnows_len, total_len, + selected_len, cache_len, count); return CLI_SUCCESS; } @@ -850,7 +919,10 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct int idx; int cmp; struct ast_region *reg; - unsigned int len = 0; + unsigned int whales_len; + unsigned int minnows_len; + unsigned int total_len = 0; + unsigned int selected_len = 0; unsigned int cache_len = 0; unsigned int count = 0; struct file_summary { @@ -868,7 +940,7 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct e->usage = "Usage: memory show summary [<file>]\n" " Summarizes heap memory allocations by file, or optionally\n" - " by line, if a file is specified.\n"; + " by line if a file is specified.\n"; return NULL; case CLI_GENERATE: return NULL; @@ -883,6 +955,7 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct ast_mutex_lock(®lock); for (idx = 0; idx < ARRAY_LEN(regions); ++idx) { for (reg = regions[idx]; reg; reg = AST_LIST_NEXT(reg, node)) { + total_len += reg->len; if (fn) { if (strcasecmp(fn, reg->file)) { continue; @@ -941,11 +1014,14 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct ++cur->count; } } + + whales_len = freed_regions_size(&whales); + minnows_len = freed_regions_size(&minnows); ast_mutex_unlock(®lock); /* Dump the whole list */ for (cur = list; cur; cur = cur->next) { - len += cur->len; + selected_len += cur->len; cache_len += cur->cache_len; count += cur->count; if (cur->cache_len) { @@ -967,12 +1043,9 @@ static char *handle_memory_show_summary(struct ast_cli_entry *e, int cmd, struct } } - if (cache_len) { - ast_cli(a->fd, "%u bytes allocated (%u in caches) in %u allocations\n", - len, cache_len, count); - } else { - ast_cli(a->fd, "%u bytes allocated in %u allocations\n", len, count); - } + print_memory_show_common_stats(a->fd, + whales_len, minnows_len, total_len, + selected_len, cache_len, count); return CLI_SUCCESS; } diff --git a/main/bridge_basic.c b/main/bridge_basic.c index dc5d7f016..c4cf2a074 100644 --- a/main/bridge_basic.c +++ b/main/bridge_basic.c @@ -1296,8 +1296,6 @@ struct attended_transfer_properties { AST_STRING_FIELD(exten); /*! Context of transfer target */ AST_STRING_FIELD(context); - /*! Sound to play on failure */ - AST_STRING_FIELD(failsound); /*! Sound to play when transfer completes */ AST_STRING_FIELD(xfersound); /*! The channel technology of the transferer channel */ @@ -1421,12 +1419,21 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc( struct ast_flags *transferer_features; props = ao2_alloc(sizeof(*props), attended_transfer_properties_destructor); - if (!props || ast_string_field_init(props, 64)) { + if (!props) { + ast_log(LOG_ERROR, "Unable to create props - channel %s, context %s\n", + ast_channel_name(transferer), context); return NULL; } ast_cond_init(&props->cond, NULL); + if (ast_string_field_init(props, 64)) { + ast_log(LOG_ERROR, "Unable to initialize prop fields - channel %s, context %s\n", + ast_channel_name(transferer), context); + ao2_ref(props, -1); + return NULL; + } + props->target_framehook_id = -1; props->transferer = ast_channel_ref(transferer); @@ -1447,7 +1454,6 @@ static struct attended_transfer_properties *attended_transfer_properties_alloc( props->atxfernoanswertimeout = xfer_cfg->atxfernoanswertimeout; props->atxferloopdelay = xfer_cfg->atxferloopdelay; ast_string_field_set(props, context, get_transfer_context(transferer, context)); - ast_string_field_set(props, failsound, xfer_cfg->xferfailsound); ast_string_field_set(props, xfersound, xfer_cfg->xfersound); ao2_ref(xfer_cfg, -1); @@ -1708,6 +1714,44 @@ static void play_sound(struct ast_channel *chan, const char *sound) } /*! + * \brief Helper method to play a fail sound on a channel in a bridge + * + * \param chan The channel to play the fail sound to + */ +static void play_failsound(struct ast_channel *chan) +{ + char *sound; + + ast_channel_lock(chan); + sound = ast_get_chan_features_xferfailsound(chan); + ast_channel_unlock(chan); + + if (sound) { + play_sound(chan, sound); + ast_free(sound); + } +} + +/*! + * \brief Helper method to stream a fail sound on a channel + * + * \param chan The channel to stream the fail sound to + */ +static void stream_failsound(struct ast_channel *chan) +{ + char *sound; + + ast_channel_lock(chan); + sound = ast_get_chan_features_xferfailsound(chan); + ast_channel_unlock(chan); + + if (sound) { + ast_stream_and_wait(chan, sound, AST_DIGIT_NONE); + ast_free(sound); + } +} + +/*! * \brief Helper method to place a channel in a bridge on hold */ static void hold(struct ast_channel *chan) @@ -2049,7 +2093,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer { switch (stimulus) { case STIMULUS_TRANSFEREE_HANGUP: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); publish_transfer_fail(props); return TRANSFER_FAIL; case STIMULUS_DTMF_ATXFER_COMPLETE: @@ -2061,7 +2105,7 @@ static enum attended_transfer_state calling_target_exit(struct attended_transfer case STIMULUS_TRANSFER_TARGET_HANGUP: case STIMULUS_TIMEOUT: case STIMULUS_DTMF_ATXFER_ABORT: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); return TRANSFER_REBRIDGE; case STIMULUS_DTMF_ATXFER_THREEWAY: bridge_unhold(props->transferee_bridge); @@ -2090,7 +2134,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope { switch (stimulus) { case STIMULUS_TRANSFEREE_HANGUP: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); publish_transfer_fail(props); return TRANSFER_FAIL; case STIMULUS_DTMF_ATXFER_COMPLETE: @@ -2101,7 +2145,7 @@ static enum attended_transfer_state hesitant_exit(struct attended_transfer_prope case STIMULUS_TRANSFER_TARGET_HANGUP: case STIMULUS_TIMEOUT: case STIMULUS_DTMF_ATXFER_ABORT: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); return TRANSFER_RESUME; case STIMULUS_DTMF_ATXFER_THREEWAY: return TRANSFER_THREEWAY; @@ -2163,7 +2207,7 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro * a sound to the transferer to indicate the transferee is gone. */ bridge_basic_change_personality(props->target_bridge, BRIDGE_BASIC_PERSONALITY_NORMAL, NULL); - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); ast_bridge_merge_inhibit(props->target_bridge, -1); /* These next two lines are here to ensure that our reference to the target bridge * is cleaned up properly and that the target bridge is not destroyed when the @@ -2180,7 +2224,7 @@ static enum attended_transfer_state consulting_exit(struct attended_transfer_pro case STIMULUS_TRANSFER_TARGET_HANGUP: return TRANSFER_REBRIDGE; case STIMULUS_DTMF_ATXFER_ABORT: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); return TRANSFER_REBRIDGE; case STIMULUS_DTMF_ATXFER_THREEWAY: bridge_unhold(props->transferee_bridge); @@ -2212,7 +2256,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe { switch (stimulus) { case STIMULUS_TRANSFEREE_HANGUP: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); publish_transfer_fail(props); return TRANSFER_FAIL; case STIMULUS_TRANSFERER_HANGUP: @@ -2222,7 +2266,7 @@ static enum attended_transfer_state double_checking_exit(struct attended_transfe return TRANSFER_COMPLETE; case STIMULUS_TRANSFER_TARGET_HANGUP: case STIMULUS_DTMF_ATXFER_ABORT: - play_sound(props->transferer, props->failsound); + play_failsound(props->transferer); return TRANSFER_RESUME; case STIMULUS_DTMF_ATXFER_THREEWAY: bridge_unhold(props->target_bridge); @@ -3298,7 +3342,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, props->transfer_target = dial_transfer(bridge_channel->chan, destination); if (!props->transfer_target) { ast_log(LOG_ERROR, "Unable to request outbound channel for attended transfer target.\n"); - ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); attended_transfer_properties_shutdown(props); return 0; @@ -3309,7 +3353,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, props->target_bridge = ast_bridge_basic_new(); if (!props->target_bridge) { ast_log(LOG_ERROR, "Unable to create bridge for attended transfer target.\n"); - ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); ast_hangup(props->transfer_target); props->transfer_target = NULL; @@ -3320,7 +3364,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, if (attach_framehook(props, props->transfer_target)) { ast_log(LOG_ERROR, "Unable to attach framehook to transfer target.\n"); - ast_stream_and_wait(props->transferer, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); ast_hangup(props->transfer_target); props->transfer_target = NULL; @@ -3335,7 +3379,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, if (ast_call(props->transfer_target, destination, 0)) { ast_log(LOG_ERROR, "Unable to place outbound call to transfer target.\n"); - ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); ast_hangup(props->transfer_target); props->transfer_target = NULL; @@ -3351,7 +3395,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL, AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n"); - ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); ast_hangup(props->transfer_target); props->transfer_target = NULL; @@ -3361,7 +3405,7 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, if (ast_pthread_create_detached(&thread, NULL, attended_transfer_monitor_thread, props)) { ast_log(LOG_ERROR, "Unable to create monitoring thread for attended transfer.\n"); - ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE); + stream_failsound(props->transferer); ast_bridge_channel_write_unhold(bridge_channel); attended_transfer_properties_shutdown(props); return 0; diff --git a/main/features_config.c b/main/features_config.c index 9fed53b32..9126a86c7 100644 --- a/main/features_config.c +++ b/main/features_config.c @@ -1158,6 +1158,21 @@ struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_ch return cfg->global->xfer; } +char *ast_get_chan_features_xferfailsound(struct ast_channel *chan) +{ + char *res; + struct ast_features_xfer_config *cfg = ast_get_chan_features_xfer_config(chan); + + if (!cfg) { + return NULL; + } + + res = ast_strdup(cfg->xferfailsound); + ao2_ref(cfg, -1); + + return res; +} + struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan) { RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup); diff --git a/main/taskprocessor.c b/main/taskprocessor.c index 59e4a2fa1..05d646128 100644 --- a/main/taskprocessor.c +++ b/main/taskprocessor.c @@ -713,12 +713,7 @@ struct ast_taskprocessor *ast_taskprocessor_get(const char *name, enum ast_tps_o } p = __allocate_taskprocessor(name, listener); - if (!p) { - ao2_ref(listener, -1); - return NULL; - } - /* Unref listener here since the taskprocessor has gained a reference to the listener */ ao2_ref(listener, -1); return p; } |