summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/app.c2
-rw-r--r--main/asterisk.c7
-rw-r--r--main/cli.c53
-rw-r--r--main/config_options.c2
-rw-r--r--main/file.c5
-rw-r--r--main/logger.c3
-rw-r--r--main/manager.c8
-rw-r--r--main/media_cache.c44
-rw-r--r--main/utils.c1
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: