summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/alertpipe.c13
-rw-r--r--main/asterisk.c42
-rw-r--r--main/db.c121
-rw-r--r--main/iostream.c2
-rw-r--r--main/loader.c43
-rw-r--r--main/stasis_channels.c8
-rw-r--r--main/tcptls.c13
-rw-r--r--main/udptl.c4
-rw-r--r--main/utils.c34
9 files changed, 190 insertions, 90 deletions
diff --git a/main/alertpipe.c b/main/alertpipe.c
index fa6ec7bcc..7932a7346 100644
--- a/main/alertpipe.c
+++ b/main/alertpipe.c
@@ -55,17 +55,8 @@ int ast_alertpipe_init(int alert_pipe[2])
ast_log(LOG_WARNING, "Failed to create alert pipe: %s\n", strerror(errno));
return -1;
} else {
- int flags = fcntl(alert_pipe[0], F_GETFL);
- if (fcntl(alert_pipe[0], F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n",
- strerror(errno));
- ast_alertpipe_close(alert_pipe);
- return -1;
- }
- flags = fcntl(alert_pipe[1], F_GETFL);
- if (fcntl(alert_pipe[1], F_SETFL, flags | O_NONBLOCK) < 0) {
- ast_log(LOG_WARNING, "Failed to set non-blocking mode on alert pipe: %s\n",
- strerror(errno));
+ if (ast_fd_set_flags(alert_pipe[0], O_NONBLOCK)
+ || ast_fd_set_flags(alert_pipe[1], O_NONBLOCK)) {
ast_alertpipe_close(alert_pipe);
return -1;
}
diff --git a/main/asterisk.c b/main/asterisk.c
index faac569c0..006a1b03a 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -733,6 +733,27 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
int totalswap = 0;
#if defined(HAVE_SYSINFO)
struct sysinfo sys_info;
+#elif defined(HAVE_SYSCTL)
+ static int pageshift;
+ struct vmtotal vmtotal;
+ struct timeval boottime;
+ time_t now;
+ int mib[2], pagesize, usedswap = 0;
+ size_t len;
+#endif
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "core show sysinfo";
+ e->usage =
+ "Usage: core show sysinfo\n"
+ " List current system information.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+#if defined(HAVE_SYSINFO)
sysinfo(&sys_info);
uptime = sys_info.uptime / 3600;
physmem = sys_info.totalram * sys_info.mem_unit;
@@ -741,12 +762,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
nprocs = sys_info.procs;
#elif defined(HAVE_SYSCTL)
- static int pageshift;
- struct vmtotal vmtotal;
- struct timeval boottime;
- time_t now;
- int mib[2], pagesize, usedswap = 0;
- size_t len;
/* calculate the uptime by looking at boottime */
time(&now);
mib[0] = CTL_KERN;
@@ -794,17 +809,6 @@ static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cl
#endif
#endif
- switch (cmd) {
- case CLI_INIT:
- e->command = "core show sysinfo";
- e->usage =
- "Usage: core show sysinfo\n"
- " List current system information.\n";
- return NULL;
- case CLI_GENERATE:
- return NULL;
- }
-
ast_cli(a->fd, "\nSystem Statistics\n");
ast_cli(a->fd, "-----------------\n");
ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
@@ -1569,7 +1573,6 @@ static void *listener(void *unused)
int s;
socklen_t len;
int x;
- int flags;
struct pollfd fds[1];
for (;;) {
if (ast_socket < 0)
@@ -1607,8 +1610,7 @@ static void *listener(void *unused)
close(s);
break;
}
- flags = fcntl(consoles[x].p[1], F_GETFL);
- fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(consoles[x].p[1], O_NONBLOCK);
consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
/* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
to know if the user didn't send the credentials. */
diff --git a/main/db.c b/main/db.c
index fa125d749..afaf04341 100644
--- a/main/db.c
+++ b/main/db.c
@@ -127,6 +127,20 @@ DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY ke
DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key VARCHAR(256), value VARCHAR(256), PRIMARY KEY(key))")
+/* This query begs an explanation:
+ *
+ * First, the parameter binding syntax used here is slightly different then the other
+ * queries in that we use a numbered parameter so that we can bind once and get the same
+ * value substituted multiple times within the executed query.
+ *
+ * Second, the key comparison is being used to find all keys that are lexicographically
+ * greater than the provided key, but less than the provided key with a high (but
+ * invalid) Unicode codepoint appended to it. This will give us all keys in the database
+ * that have 'key' as a prefix and performs much better than the equivalent "LIKE key ||
+ * '%'" operation.
+ */
+DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
+
static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
{
ast_mutex_lock(&dblock);
@@ -167,6 +181,7 @@ static void clean_statements(void)
clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
clean_stmt(&gettree_stmt, gettree_stmt_sql);
clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
+ clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
clean_stmt(&showkey_stmt, showkey_stmt_sql);
clean_stmt(&put_stmt, put_stmt_sql);
clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
@@ -182,6 +197,7 @@ static int init_statements(void)
|| init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
|| init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
|| init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
+ || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql))
|| init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
|| init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
}
@@ -473,19 +489,64 @@ int ast_db_deltree(const char *family, const char *keytree)
return res;
}
+static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
+{
+ struct ast_db_entry *head = NULL, *prev = NULL, *cur;
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ const char *key, *value;
+ size_t key_len, value_len;
+
+ key = (const char *) sqlite3_column_text(stmt, 0);
+ value = (const char *) sqlite3_column_text(stmt, 1);
+
+ if (!key || !value) {
+ break;
+ }
+
+ key_len = strlen(key);
+ value_len = strlen(value);
+
+ cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2);
+ if (!cur) {
+ break;
+ }
+
+ cur->next = NULL;
+ cur->key = cur->data + value_len + 1;
+ memcpy(cur->data, value, value_len + 1);
+ memcpy(cur->key, key, key_len + 1);
+
+ if (prev) {
+ prev->next = cur;
+ } else {
+ head = cur;
+ }
+ prev = cur;
+ }
+
+ return head;
+}
+
struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
{
char prefix[MAX_DB_FIELD];
sqlite3_stmt *stmt = gettree_stmt;
- struct ast_db_entry *cur, *last = NULL, *ret = NULL;
+ size_t res = 0;
+ struct ast_db_entry *ret;
if (!ast_strlen_zero(family)) {
if (!ast_strlen_zero(keytree)) {
/* Family and key tree */
- snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
+ res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
} else {
/* Family only */
- snprintf(prefix, sizeof(prefix), "/%s", family);
+ res = snprintf(prefix, sizeof(prefix), "/%s", family);
+ }
+
+ if (res >= sizeof(prefix)) {
+ ast_log(LOG_WARNING, "Requested prefix is too long: %s\n", keytree);
+ return NULL;
}
} else {
prefix[0] = '\0';
@@ -493,41 +554,47 @@ struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
}
ast_mutex_lock(&dblock);
- if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
- ast_log(LOG_WARNING, "Could bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
+ if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
+ ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
return NULL;
}
- while (sqlite3_step(stmt) == SQLITE_ROW) {
- const char *key_s, *value_s;
- if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
- break;
- }
- if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
- break;
- }
- if (!(cur = ast_malloc(sizeof(*cur) + strlen(key_s) + strlen(value_s) + 2))) {
- break;
- }
- cur->next = NULL;
- cur->key = cur->data + strlen(value_s) + 1;
- strcpy(cur->data, value_s);
- strcpy(cur->key, key_s);
- if (last) {
- last->next = cur;
- } else {
- ret = cur;
- }
- last = cur;
- }
+ ret = db_gettree_common(stmt);
sqlite3_reset(stmt);
ast_mutex_unlock(&dblock);
return ret;
}
+struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
+{
+ char prefix[MAX_DB_FIELD];
+ size_t res;
+ struct ast_db_entry *ret;
+
+ res = snprintf(prefix, sizeof(prefix), "/%s/%s", family, key_prefix);
+ if (res >= sizeof(prefix)) {
+ ast_log(LOG_WARNING, "Requested key prefix is too long: %s\n", key_prefix);
+ return NULL;
+ }
+
+ ast_mutex_lock(&dblock);
+ if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
+ ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
+ sqlite3_reset(gettree_prefix_stmt);
+ ast_mutex_unlock(&dblock);
+ return NULL;
+ }
+
+ ret = db_gettree_common(gettree_prefix_stmt);
+ sqlite3_reset(gettree_prefix_stmt);
+ ast_mutex_unlock(&dblock);
+
+ return ret;
+}
+
void ast_db_freetree(struct ast_db_entry *dbe)
{
struct ast_db_entry *last;
diff --git a/main/iostream.c b/main/iostream.c
index d91863319..aaa74fae1 100644
--- a/main/iostream.c
+++ b/main/iostream.c
@@ -77,7 +77,7 @@ int ast_iostream_get_fd(struct ast_iostream *stream)
void ast_iostream_nonblock(struct ast_iostream *stream)
{
- fcntl(stream->fd, F_SETFL, fcntl(stream->fd, F_GETFL) | O_NONBLOCK);
+ ast_fd_set_flags(stream->fd, O_NONBLOCK);
}
SSL *ast_iostream_get_ssl(struct ast_iostream *stream)
diff --git a/main/loader.c b/main/loader.c
index 19e30f835..23a29d994 100644
--- a/main/loader.c
+++ b/main/loader.c
@@ -376,35 +376,39 @@ static int verify_key(const unsigned char *key)
return -1;
}
-static int resource_name_match(const char *name1_in, const char *name2_in)
+static size_t resource_name_baselen(const char *name)
{
- char *name1 = (char *) name1_in;
- char *name2 = (char *) name2_in;
+ size_t len = strlen(name);
- /* trim off any .so extensions */
- if (!strcasecmp(name1 + strlen(name1) - 3, ".so")) {
- name1 = ast_strdupa(name1);
- name1[strlen(name1) - 3] = '\0';
+ if (len > 3 && !strcasecmp(name + len - 3, ".so")) {
+ return len - 3;
}
- if (!strcasecmp(name2 + strlen(name2) - 3, ".so")) {
- name2 = ast_strdupa(name2);
- name2[strlen(name2) - 3] = '\0';
+
+ return len;
+}
+
+static int resource_name_match(const char *name1, size_t baselen1, const char *name2)
+{
+ if (baselen1 != resource_name_baselen(name2)) {
+ return -1;
}
- return strcasecmp(name1, name2);
+ return strncasecmp(name1, name2, baselen1);
}
static struct ast_module *find_resource(const char *resource, int do_lock)
{
struct ast_module *cur;
+ size_t resource_baselen = resource_name_baselen(resource);
if (do_lock) {
AST_DLLIST_LOCK(&module_list);
}
AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
- if (!resource_name_match(resource, cur->resource))
+ if (!resource_name_match(resource, resource_baselen, cur->resource)) {
break;
+ }
}
if (do_lock) {
@@ -939,6 +943,7 @@ enum ast_module_reload_result ast_module_reload(const char *name)
struct ast_module *cur;
enum ast_module_reload_result res = AST_MODULE_RELOAD_NOT_FOUND;
int i;
+ size_t name_baselen = name ? resource_name_baselen(name) : 0;
/* If we aren't fully booted, we just pretend we reloaded but we queue this
up to run once we are booted up. */
@@ -992,8 +997,9 @@ enum ast_module_reload_result ast_module_reload(const char *name)
AST_DLLIST_TRAVERSE(&module_list, cur, entry) {
const struct ast_module_info *info = cur->info;
- if (name && resource_name_match(name, cur->resource))
+ if (name && resource_name_match(name, name_baselen, cur->resource)) {
continue;
+ }
if (!cur->flags.running || cur->flags.declined) {
if (res == AST_MODULE_RELOAD_NOT_FOUND) {
@@ -1187,9 +1193,10 @@ AST_LIST_HEAD_NOLOCK(load_order, load_order_entry);
static struct load_order_entry *add_to_load_order(const char *resource, struct load_order *load_order, int required)
{
struct load_order_entry *order;
+ size_t resource_baselen = resource_name_baselen(resource);
AST_LIST_TRAVERSE(load_order, order, entry) {
- if (!resource_name_match(order->resource, resource)) {
+ if (!resource_name_match(resource, resource_baselen, order->resource)) {
/* Make sure we have the proper setting for the required field
(we might have both load= and required= lines in modules.conf) */
order->required |= required;
@@ -1436,11 +1443,15 @@ int load_modules(unsigned int preload_only)
/* now scan the config for any modules we are prohibited from loading and
remove them from the load order */
for (v = ast_variable_browse(cfg, "modules"); v; v = v->next) {
- if (strcasecmp(v->name, "noload"))
+ size_t baselen;
+
+ if (strcasecmp(v->name, "noload")) {
continue;
+ }
+ baselen = resource_name_baselen(v->value);
AST_LIST_TRAVERSE_SAFE_BEGIN(&load_order, order, entry) {
- if (!resource_name_match(order->resource, v->value)) {
+ if (!resource_name_match(v->value, baselen, order->resource)) {
AST_LIST_REMOVE_CURRENT(entry);
ast_free(order->resource);
ast_free(order);
diff --git a/main/stasis_channels.c b/main/stasis_channels.c
index b81dbe599..293db06d3 100644
--- a/main/stasis_channels.c
+++ b/main/stasis_channels.c
@@ -236,22 +236,24 @@ struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *cha
S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
ast_string_field_set(snapshot, caller_number,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
- ast_string_field_set(snapshot, caller_dnid, S_OR(ast_channel_dialed(chan)->number.str, ""));
ast_string_field_set(snapshot, caller_subaddr,
S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
- ast_string_field_set(snapshot, dialed_subaddr,
- S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
ast_string_field_set(snapshot, caller_ani,
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
+
ast_string_field_set(snapshot, caller_rdnis,
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
+
ast_string_field_set(snapshot, caller_dnid,
S_OR(ast_channel_dialed(chan)->number.str, ""));
+ ast_string_field_set(snapshot, dialed_subaddr,
+ S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
ast_string_field_set(snapshot, connected_name,
S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
ast_string_field_set(snapshot, connected_number,
S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
+
ast_string_field_set(snapshot, language, ast_channel_language(chan));
if ((bridge = ast_channel_get_bridge(chan))) {
diff --git a/main/tcptls.c b/main/tcptls.c
index a6d0538af..02a2af5c6 100644
--- a/main/tcptls.c
+++ b/main/tcptls.c
@@ -223,7 +223,7 @@ void *ast_tcptls_server_root(void *data)
pthread_t launched;
for (;;) {
- int i, flags;
+ int i;
if (desc->periodic_fn) {
desc->periodic_fn(desc);
@@ -261,8 +261,7 @@ void *ast_tcptls_server_root(void *data)
close(fd);
continue;
}
- flags = fcntl(fd, F_GETFL);
- fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
+ ast_fd_clear_flags(fd, O_NONBLOCK);
tcptls_session->stream = ast_iostream_from_fd(&fd);
if (!tcptls_session->stream) {
@@ -514,7 +513,6 @@ void ast_ssl_teardown(struct ast_tls_config *cfg)
struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_session_instance *tcptls_session)
{
struct ast_tcptls_session_args *desc;
- int flags;
if (!(desc = tcptls_session->parent)) {
goto client_start_error;
@@ -528,8 +526,7 @@ struct ast_tcptls_session_instance *ast_tcptls_client_start(struct ast_tcptls_se
goto client_start_error;
}
- flags = fcntl(desc->accept_fd, F_GETFL);
- fcntl(desc->accept_fd, F_SETFL, flags & ~O_NONBLOCK);
+ ast_fd_clear_flags(desc->accept_fd, O_NONBLOCK);
if (desc->tls_cfg) {
desc->tls_cfg->enabled = 1;
@@ -621,7 +618,6 @@ error:
void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
{
- int flags;
int x = 1;
int tls_changed = 0;
int sd_socket;
@@ -740,8 +736,7 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc)
}
systemd_socket_activation:
- flags = fcntl(desc->accept_fd, F_GETFL);
- fcntl(desc->accept_fd, F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(desc->accept_fd, O_NONBLOCK);
if (ast_pthread_create_background(&desc->master, NULL, desc->accept_fn, desc)) {
ast_log(LOG_ERROR, "Unable to launch thread for %s on %s: %s\n",
desc->name,
diff --git a/main/udptl.c b/main/udptl.c
index 853e43c44..d982f6bcb 100644
--- a/main/udptl.c
+++ b/main/udptl.c
@@ -1012,7 +1012,6 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s
int x;
int startplace;
int i;
- long int flags;
RAII_VAR(struct udptl_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
if (!cfg || !cfg->general) {
@@ -1043,8 +1042,7 @@ struct ast_udptl *ast_udptl_new_with_bindaddr(struct ast_sched_context *sched, s
ast_log(LOG_WARNING, "Unable to allocate socket: %s\n", strerror(errno));
return NULL;
}
- flags = fcntl(udptl->fd, F_GETFL);
- fcntl(udptl->fd, F_SETFL, flags | O_NONBLOCK);
+ ast_fd_set_flags(udptl->fd, O_NONBLOCK);
#ifdef SO_NO_CHECK
if (cfg->general->nochecksums)
diff --git a/main/utils.c b/main/utils.c
index dd7176295..a070da49f 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -2758,3 +2758,37 @@ int ast_compare_versions(const char *version1, const char *version2)
}
return extra[0] - extra[1];
}
+
+int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op,
+ const char *file, int lineno, const char *function)
+{
+ int f;
+
+ f = fcntl(fd, F_GETFL);
+ if (f == -1) {
+ ast_log(__LOG_ERROR, file, lineno, function,
+ "Failed to get fcntl() flags for file descriptor: %s\n", strerror(errno));
+ return -1;
+ }
+
+ switch (op) {
+ case AST_FD_FLAG_SET:
+ f |= flags;
+ break;
+ case AST_FD_FLAG_CLEAR:
+ f &= ~flags;
+ break;
+ default:
+ ast_assert(0);
+ break;
+ }
+
+ f = fcntl(fd, F_SETFL, f);
+ if (f == -1) {
+ ast_log(__LOG_ERROR, file, lineno, function,
+ "Failed to set fcntl() flags for file descriptor: %s\n", strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}