diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/app.c | 2 | ||||
-rw-r--r-- | main/asterisk.c | 7 | ||||
-rw-r--r-- | main/cli.c | 53 | ||||
-rw-r--r-- | main/config_options.c | 2 | ||||
-rw-r--r-- | main/file.c | 5 | ||||
-rw-r--r-- | main/logger.c | 3 | ||||
-rw-r--r-- | main/manager.c | 8 | ||||
-rw-r--r-- | main/media_cache.c | 44 | ||||
-rw-r--r-- | main/utils.c | 1 |
9 files changed, 109 insertions, 16 deletions
diff --git a/main/app.c b/main/app.c index 826e41128..e1d70498c 100644 --- a/main/app.c +++ b/main/app.c @@ -1112,6 +1112,8 @@ static int control_streamfile(struct ast_channel *chan, if (!strcasecmp(end, ":end")) { *end = '\0'; end++; + } else { + end = NULL; } } diff --git a/main/asterisk.c b/main/asterisk.c index da804e196..7636ec7b4 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -2343,6 +2343,7 @@ static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_ar e->usage = "Usage: core stop now\n" " Shuts down a running Asterisk immediately, hanging up all active calls .\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2363,6 +2364,7 @@ static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast "Usage: core stop gracefully\n" " Causes Asterisk to not accept new calls, and exit when all\n" " active calls have terminated normally.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2382,6 +2384,7 @@ static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struc e->usage = "Usage: core stop when convenient\n" " Causes Asterisk to perform a shutdown when all active calls have ended.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2403,6 +2406,7 @@ static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli "Usage: core restart now\n" " Causes Asterisk to hangup all calls and exec() itself performing a cold\n" " restart.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2423,6 +2427,7 @@ static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct "Usage: core restart gracefully\n" " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n" " restart when all active calls have ended.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2442,6 +2447,7 @@ static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, st e->usage = "Usage: core restart when convenient\n" " Causes Asterisk to perform a cold restart when all active calls have ended.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; @@ -2463,6 +2469,7 @@ static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_ "Usage: core abort shutdown\n" " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n" " call operations.\n"; + ast_cli_allow_at_shutdown(e); return NULL; case CLI_GENERATE: return NULL; diff --git a/main/cli.c b/main/cli.c index 0ac5d612a..f2bedc91a 100644 --- a/main/cli.c +++ b/main/cli.c @@ -63,6 +63,7 @@ ASTERISK_REGISTER_FILE() #include "asterisk/bridge.h" #include "asterisk/stasis_channels.h" #include "asterisk/stasis_bridges.h" +#include "asterisk/vector.h" /*! * \brief List of restrictions per user. @@ -109,6 +110,9 @@ static struct module_level_list debug_modules = AST_RWLIST_HEAD_INIT_VALUE; AST_THREADSTORAGE(ast_cli_buf); +AST_RWLOCK_DEFINE_STATIC(shutdown_commands_lock); +static AST_VECTOR(, struct ast_cli_entry *) shutdown_commands; + /*! \brief Initial buffer size for resulting strings in ast_cli() */ #define AST_CLI_INITLEN 256 @@ -2031,6 +2035,7 @@ static void cli_shutdown(void) /*! \brief initialize the _full_cmd string in * each of the builtins. */ void ast_builtins_init(void) { + AST_VECTOR_INIT(&shutdown_commands, 0); ast_cli_register_multiple(cli_cli, ARRAY_LEN(cli_cli)); ast_register_cleanup(cli_shutdown); } @@ -2209,6 +2214,13 @@ static int cli_is_registered(struct ast_cli_entry *e) return 0; } +static void remove_shutdown_command(struct ast_cli_entry *e) +{ + ast_rwlock_wrlock(&shutdown_commands_lock); + AST_VECTOR_REMOVE_ELEM_UNORDERED(&shutdown_commands, e, AST_VECTOR_ELEM_CLEANUP_NOOP); + ast_rwlock_unlock(&shutdown_commands_lock); +} + int ast_cli_unregister(struct ast_cli_entry *e) { if (e->inuse) { @@ -2217,6 +2229,7 @@ int ast_cli_unregister(struct ast_cli_entry *e) AST_RWLIST_WRLOCK(&helpers); AST_RWLIST_REMOVE(&helpers, e, list); AST_RWLIST_UNLOCK(&helpers); + remove_shutdown_command(e); ast_free(e->_full_cmd); e->_full_cmd = NULL; if (e->handler) { @@ -2675,10 +2688,27 @@ char *ast_cli_generator(const char *text, const char *word, int state) return __ast_cli_generator(text, word, state, 1); } +static int allowed_on_shutdown(struct ast_cli_entry *e) +{ + int found = 0; + int i; + + ast_rwlock_rdlock(&shutdown_commands_lock); + for (i = 0; i < AST_VECTOR_SIZE(&shutdown_commands); ++i) { + if (e == AST_VECTOR_GET(&shutdown_commands, i)) { + found = 1; + break; + } + } + ast_rwlock_unlock(&shutdown_commands_lock); + + return found; +} + int ast_cli_command_full(int uid, int gid, int fd, const char *s) { const char *args[AST_MAX_ARGS + 1]; - struct ast_cli_entry *e; + struct ast_cli_entry *e = NULL; int x; char *duplicate = parse_args(s, &x, args + 1, AST_MAX_ARGS, NULL); char tmp[AST_MAX_ARGS + 1]; @@ -2702,6 +2732,11 @@ int ast_cli_command_full(int uid, int gid, int fd, const char *s) goto done; } + if (ast_shutting_down() && !allowed_on_shutdown(e)) { + ast_cli(fd, "Command '%s' cannot be run during shutdown\n", s); + goto done; + } + ast_join(tmp, sizeof(tmp), args + 1); /* Check if the user has rights to run this command. */ if (!cli_has_permissions(uid, gid, tmp)) { @@ -2724,8 +2759,11 @@ int ast_cli_command_full(int uid, int gid, int fd, const char *s) } else if (retval == CLI_FAILURE) { ast_cli(fd, "Command '%s' failed.\n", s); } - ast_atomic_fetchadd_int(&e->inuse, -1); + done: + if (e) { + ast_atomic_fetchadd_int(&e->inuse, -1); + } ast_free(duplicate); return retval == CLI_SUCCESS ? RESULT_SUCCESS : RESULT_FAILURE; } @@ -2751,3 +2789,14 @@ void ast_cli_print_timestr_fromseconds(int fd, int seconds, const char *prefix) { print_uptimestr(fd, ast_tv(seconds, 0), prefix, 0); } + +int ast_cli_allow_at_shutdown(struct ast_cli_entry *e) +{ + int res; + + ast_rwlock_wrlock(&shutdown_commands_lock); + res = AST_VECTOR_APPEND(&shutdown_commands, e); + ast_rwlock_unlock(&shutdown_commands_lock); + + return res; +} diff --git a/main/config_options.c b/main/config_options.c index f8c7b0c67..e59e5cf7a 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -1346,7 +1346,7 @@ static int int_handler_fn(const struct aco_option *opt, struct ast_variable *var */ static int uint_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) { unsigned int *field = (unsigned int *)(obj + opt->args[0]); - unsigned int flags = PARSE_INT32 | opt->flags; + unsigned int flags = PARSE_UINT32 | opt->flags; int res = 0; if (opt->flags & PARSE_IN_RANGE) { res = opt->flags & PARSE_DEFAULT ? diff --git a/main/file.c b/main/file.c index f0f826a4f..654937a58 100644 --- a/main/file.c +++ b/main/file.c @@ -54,6 +54,7 @@ ASTERISK_REGISTER_FILE() #include "asterisk/stasis.h" #include "asterisk/json.h" #include "asterisk/stasis_system.h" +#include "asterisk/media_cache.h" /*! \brief * The following variable controls the layout of localized sound files. @@ -644,6 +645,10 @@ static int fileexists_test(const char *filename, const char *fmt, const char *la return 0; } + if (!ast_media_cache_retrieve(filename, NULL, buf, buflen)) { + return filehelper(buf, result_cap, NULL, ACTION_EXISTS); + } + if (ast_language_is_prefix && !is_absolute_path(filename)) { /* new layout */ if (lang) { snprintf(buf, buflen, "%s/%s", lang, filename); diff --git a/main/logger.c b/main/logger.c index 13f6de890..42a1c7000 100644 --- a/main/logger.c +++ b/main/logger.c @@ -1514,7 +1514,8 @@ static void logger_print_normal(struct logmsg *logmsg) continue; } - syslog_level = LOG_MAKEPRI(chan->facility, syslog_level); + /* Don't use LOG_MAKEPRI because it's broken in glibc<2.17 */ + syslog_level = chan->facility | syslog_level; /* LOG_MAKEPRI(chan->facility, syslog_level); */ if (!chan->formatter.format_log(chan, logmsg, buf, BUFSIZ)) { syslog(syslog_level, "%s", buf); } diff --git a/main/manager.c b/main/manager.c index 2adcb3e5a..e74b253ff 100644 --- a/main/manager.c +++ b/main/manager.c @@ -6138,6 +6138,14 @@ static int process_message(struct mansession *s, const struct message *m) return 0; } + if (ast_shutting_down()) { + ast_log(LOG_ERROR, "Unable to process manager action '%s'. Asterisk is shutting down.\n", action); + mansession_lock(s); + astman_send_error(s, m, "Asterisk is shutting down"); + mansession_unlock(s); + return 0; + } + if (!s->session->authenticated && strcasecmp(action, "Login") && strcasecmp(action, "Logoff") diff --git a/main/media_cache.c b/main/media_cache.c index 1f81e3ae1..958a05bb2 100644 --- a/main/media_cache.c +++ b/main/media_cache.c @@ -189,23 +189,31 @@ static void media_cache_item_del_from_astdb(struct ast_bucket_file *bucket_file) static void bucket_file_update_path(struct ast_bucket_file *bucket_file, const char *preferred_file_name) { - if (ast_strlen_zero(preferred_file_name)) { - return; - } + char *ext; - if (!strcmp(bucket_file->path, preferred_file_name)) { - return; - } + if (!ast_strlen_zero(preferred_file_name) && strcmp(bucket_file->path, preferred_file_name)) { + /* Use the preferred file name if available */ + + rename(bucket_file->path, preferred_file_name); + ast_copy_string(bucket_file->path, preferred_file_name, + sizeof(bucket_file->path)); + } else if (!strchr(bucket_file->path, '.') && (ext = strrchr(ast_sorcery_object_get_id(bucket_file), '.'))) { + /* If we don't have a file extension and were provided one in the URI, use it */ + char new_path[PATH_MAX]; + + ast_bucket_file_metadata_set(bucket_file, "ext", ext); - rename(bucket_file->path, preferred_file_name); - ast_copy_string(bucket_file->path, preferred_file_name, - sizeof(bucket_file->path)); + snprintf(new_path, sizeof(new_path), "%s%s", bucket_file->path, ext); + rename(bucket_file->path, new_path); + ast_copy_string(bucket_file->path, new_path, sizeof(bucket_file->path)); + } } int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name, char *file_path, size_t len) { struct ast_bucket_file *bucket_file; + char *ext; SCOPED_AO2LOCK(media_lock, media_cache); if (ast_strlen_zero(uri)) { @@ -220,11 +228,18 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name, if (bucket_file) { if (!ast_bucket_file_is_stale(bucket_file)) { ast_copy_string(file_path, bucket_file->path, len); + if ((ext = strrchr(file_path, '.'))) { + *ext = '\0'; + } ao2_ref(bucket_file, -1); + + ast_debug(5, "Returning media at local file: %s\n", file_path); return 0; } - /* Stale! Drop the ref, as we're going to retrieve it next. */ + /* Stale! Remove the item completely, as we're going to replace it next */ + ao2_unlink_flags(media_cache, bucket_file, OBJ_NOLOCK); + ast_bucket_file_delete(bucket_file); ao2_ref(bucket_file, -1); } @@ -233,7 +248,7 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name, */ bucket_file = ast_bucket_file_retrieve(uri); if (!bucket_file) { - ast_log(LOG_WARNING, "Failed to obtain media at '%s'\n", uri); + ast_debug(2, "Failed to obtain media at '%s'\n", uri); return -1; } @@ -243,9 +258,14 @@ int ast_media_cache_retrieve(const char *uri, const char *preferred_file_name, bucket_file_update_path(bucket_file, preferred_file_name); media_cache_item_sync_to_astdb(bucket_file); ast_copy_string(file_path, bucket_file->path, len); + if ((ext = strrchr(file_path, '.'))) { + *ext = '\0'; + } ao2_link_flags(media_cache, bucket_file, OBJ_NOLOCK); ao2_ref(bucket_file, -1); + ast_debug(5, "Returning media at local file: %s\n", file_path); + return 0; } @@ -692,7 +712,7 @@ int ast_media_cache_init(void) { ast_register_atexit(media_cache_shutdown); - media_cache = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_RWLOCK, AO2_BUCKETS, + media_cache = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_MUTEX, AO2_BUCKETS, media_cache_hash, media_cache_cmp); if (!media_cache) { return -1; diff --git a/main/utils.c b/main/utils.c index 8a9f91062..6a778b90c 100644 --- a/main/utils.c +++ b/main/utils.c @@ -1153,6 +1153,7 @@ static char *handle_show_locks(struct ast_cli_entry *e, int cmd, struct ast_cli_ "Usage: core show locks\n" " This command is for lock debugging. It prints out which locks\n" "are owned by each active thread.\n"; + ast_cli_allow_on_shutdown(e); return NULL; case CLI_GENERATE: |