diff options
-rw-r--r-- | apps/app_ices.c | 4 | ||||
-rw-r--r-- | channels/chan_phone.c | 4 | ||||
-rw-r--r-- | channels/chan_sip.c | 9 | ||||
-rw-r--r-- | channels/vgrabbers.c | 8 | ||||
-rw-r--r-- | codecs/codec_dahdi.c | 7 | ||||
-rw-r--r-- | include/asterisk/astdb.h | 10 | ||||
-rw-r--r-- | include/asterisk/utils.h | 40 | ||||
-rw-r--r-- | main/alertpipe.c | 13 | ||||
-rw-r--r-- | main/asterisk.c | 4 | ||||
-rw-r--r-- | main/db.c | 121 | ||||
-rw-r--r-- | main/http.c | 4 | ||||
-rw-r--r-- | main/loader.c | 43 | ||||
-rw-r--r-- | main/manager.c | 4 | ||||
-rw-r--r-- | main/tcptls.c | 13 | ||||
-rw-r--r-- | main/udptl.c | 4 | ||||
-rw-r--r-- | main/utils.c | 34 | ||||
-rw-r--r-- | res/res_agi.c | 16 | ||||
-rw-r--r-- | res/res_http_websocket.c | 24 | ||||
-rw-r--r-- | res/res_musiconhold.c | 7 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_cli.c | 24 | ||||
-rw-r--r-- | res/res_pktccops.c | 5 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 3 | ||||
-rw-r--r-- | res/res_sorcery_astdb.c | 6 | ||||
-rw-r--r-- | res/res_speech.c | 2 | ||||
-rw-r--r-- | res/res_stasis.c | 4 | ||||
-rw-r--r-- | res/res_timing_pthread.c | 4 |
26 files changed, 248 insertions, 169 deletions
diff --git a/apps/app_ices.c b/apps/app_ices.c index d0fdf5cf1..a043d3de4 100644 --- a/apps/app_ices.c +++ b/apps/app_ices.c @@ -115,7 +115,6 @@ static int ices_exec(struct ast_channel *chan, const char *data) int fds[2]; int ms = -1; int pid = -1; - int flags; struct ast_format *oreadformat; struct ast_frame *f; char filename[256]=""; @@ -130,8 +129,7 @@ static int ices_exec(struct ast_channel *chan, const char *data) ast_log(LOG_WARNING, "Unable to create pipe\n"); return -1; } - flags = fcntl(fds[1], F_GETFL); - fcntl(fds[1], F_SETFL, flags | O_NONBLOCK); + ast_fd_set_flags(fds[1], O_NONBLOCK); ast_stopstream(chan); diff --git a/channels/chan_phone.c b/channels/chan_phone.c index b418b282b..67b1e1242 100644 --- a/channels/chan_phone.c +++ b/channels/chan_phone.c @@ -1193,7 +1193,6 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai { /* Make a phone_pvt structure for this interface */ struct phone_pvt *tmp; - int flags; tmp = ast_calloc(1, sizeof(*tmp)); if (tmp) { @@ -1226,8 +1225,7 @@ static struct phone_pvt *mkif(const char *iface, int mode, int txgain, int rxgai ioctl(tmp->fd, PHONE_VAD, tmp->silencesupression); #endif tmp->mode = mode; - flags = fcntl(tmp->fd, F_GETFL); - fcntl(tmp->fd, F_SETFL, flags | O_NONBLOCK); + ast_fd_set_flags(tmp->fd, O_NONBLOCK); tmp->owner = NULL; ao2_cleanup(tmp->lastformat); tmp->lastformat = NULL; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 559e5c05b..b8cc7bf76 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -2948,14 +2948,7 @@ static void *_sip_tcp_helper_thread(struct ast_tcptls_session_instance *tcptls_s goto cleanup; } - if ((flags = fcntl(tcptls_session->fd, F_GETFL)) == -1) { - ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); - goto cleanup; - } - - flags |= O_NONBLOCK; - if (fcntl(tcptls_session->fd, F_SETFL, flags) == -1) { - ast_log(LOG_ERROR, "error setting socket to non blocking mode, fcntl() failed: %s\n", strerror(errno)); + if (ast_fd_set_flags(tcptls_session->fd, O_NONBLOCK)) { goto cleanup; } diff --git a/channels/vgrabbers.c b/channels/vgrabbers.c index 45dced4e1..3deb32fd1 100644 --- a/channels/vgrabbers.c +++ b/channels/vgrabbers.c @@ -227,12 +227,8 @@ static void *grab_v4l1_open(const char *dev, struct fbuf_t *geom, int fps) v->b = *geom; b = &v->b; /* shorthand */ - i = fcntl(fd, F_GETFL); - if (-1 == fcntl(fd, F_SETFL, i | O_NONBLOCK)) { - /* non fatal, just emit a warning */ - ast_log(LOG_WARNING, "error F_SETFL for %s [%s]\n", - dev, strerror(errno)); - } + ast_fd_set_flags(fd, O_NONBLOCK); + /* set format for the camera. * In principle we could retry with a different format if the * one we are asking for is not supported. diff --git a/codecs/codec_dahdi.c b/codecs/codec_dahdi.c index f207b6486..edf5038ca 100644 --- a/codecs/codec_dahdi.c +++ b/codecs/codec_dahdi.c @@ -615,7 +615,6 @@ static int dahdi_translate(struct ast_trans_pvt *pvt, uint32_t dst_dahdi_fmt, ui /* Request translation through zap if possible */ int fd; struct codec_dahdi_pvt *dahdip = pvt->pvt; - int flags; int tried_once = 0; const char *dev_filename = "/dev/dahdi/transcode"; @@ -661,11 +660,7 @@ retry: return -1; } - flags = fcntl(fd, F_GETFL); - if (flags > - 1) { - if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) - ast_log(LOG_WARNING, "Could not set non-block mode!\n"); - } + ast_fd_set_flags(fd, O_NONBLOCK); dahdip->fd = fd; diff --git a/include/asterisk/astdb.h b/include/asterisk/astdb.h index 8a870ae83..383864baf 100644 --- a/include/asterisk/astdb.h +++ b/include/asterisk/astdb.h @@ -83,6 +83,16 @@ int ast_db_deltree(const char *family, const char *keytree); */ struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree); +/*! + * \brief Get a list of values with the given key prefix + * + * \param family The family to search under + * \param key_prefix The key prefix to search under + * + * \retval NULL An error occurred + */ +struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix); + /*! \brief Free structure created by ast_db_gettree() */ void ast_db_freetree(struct ast_db_entry *entry); diff --git a/include/asterisk/utils.h b/include/asterisk/utils.h index 03705b321..876e53c29 100644 --- a/include/asterisk/utils.h +++ b/include/asterisk/utils.h @@ -1142,4 +1142,44 @@ int ast_compare_versions(const char *version1, const char *version2); */ int ast_check_ipv6(void); +enum ast_fd_flag_operation { + AST_FD_FLAG_SET, + AST_FD_FLAG_CLEAR, +}; + +/* + * \brief Set flags on the given file descriptor + * \since 13.19 + * + * If getting or setting flags of the given file descriptor fails, logs an + * error message. + * + * \param fd File descriptor to set flags on + * \param flags The flag(s) to set + * + * \return -1 on error + * \return 0 if successful + */ +#define ast_fd_set_flags(fd, flags) \ + __ast_fd_set_flags((fd), (flags), AST_FD_FLAG_SET, __FILE__, __LINE__, __PRETTY_FUNCTION__) + +/* + * \brief Clear flags on the given file descriptor + * \since 13.19 + * + * If getting or setting flags of the given file descriptor fails, logs an + * error message. + * + * \param fd File descriptor to clear flags on + * \param flags The flag(s) to clear + * + * \return -1 on error + * \return 0 if successful + */ +#define ast_fd_clear_flags(fd, flags) \ + __ast_fd_set_flags((fd), (flags), AST_FD_FLAG_CLEAR, __FILE__, __LINE__, __PRETTY_FUNCTION__) + +int __ast_fd_set_flags(int fd, int flags, enum ast_fd_flag_operation op, + const char *file, int lineno, const char *function); + #endif /* _ASTERISK_UTILS_H */ 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 0026b36d7..7edf66f34 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -1691,7 +1691,6 @@ static void *listener(void *unused) int s; socklen_t len; int x; - int flags; struct pollfd fds[1]; for (;;) { if (ast_socket < 0) @@ -1729,8 +1728,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. */ @@ -129,6 +129,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); @@ -169,6 +183,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); @@ -184,6 +199,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)); } @@ -475,19 +491,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'; @@ -495,41 +556,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/http.c b/main/http.c index d1a443a4f..e8d395b15 100644 --- a/main/http.c +++ b/main/http.c @@ -1955,9 +1955,7 @@ static void *httpd_helper_thread(void *data) } /* make sure socket is non-blocking */ - flags = fcntl(ser->fd, F_GETFL); - flags |= O_NONBLOCK; - fcntl(ser->fd, F_SETFL, flags); + ast_fd_set_flags(ser->fd, O_NONBLOCK); /* Setup HTTP worker private data to keep track of request body reading. */ ao2_cleanup(ser->private_data); diff --git a/main/loader.c b/main/loader.c index 7d792b08e..b1a02d542 100644 --- a/main/loader.c +++ b/main/loader.c @@ -382,35 +382,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) { @@ -947,6 +951,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. */ @@ -1000,8 +1005,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) { @@ -1195,9 +1201,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; @@ -1444,11 +1451,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/manager.c b/main/manager.c index 5bc87d547..81052651e 100644 --- a/main/manager.c +++ b/main/manager.c @@ -6684,9 +6684,7 @@ static void *session_do(void *data) } /* make sure socket is non-blocking */ - flags = fcntl(ser->fd, F_GETFL); - flags |= O_NONBLOCK; - fcntl(ser->fd, F_SETFL, flags); + ast_fd_set_flags(ser->fd, O_NONBLOCK); ao2_lock(session); /* Hook to the tail of the event queue */ diff --git a/main/tcptls.c b/main/tcptls.c index ef22094bf..3c2d6788f 100644 --- a/main/tcptls.c +++ b/main/tcptls.c @@ -805,7 +805,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); @@ -843,8 +843,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->fd = fd; tcptls_session->parent = desc; ast_sockaddr_copy(&tcptls_session->remote_address, &addr); @@ -1061,7 +1060,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; @@ -1075,8 +1073,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; @@ -1164,7 +1161,6 @@ error: void ast_tcptls_server_start(struct ast_tcptls_session_args *desc) { - int flags; int x = 1; int tls_changed = 0; @@ -1267,8 +1263,7 @@ void ast_tcptls_server_start(struct ast_tcptls_session_args *desc) ast_log(LOG_ERROR, "Unable to listen for %s!\n", desc->name); goto error; } - 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 a568cd1ec..44e9eb9bb 100644 --- a/main/udptl.c +++ b/main/udptl.c @@ -1014,7 +1014,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) { @@ -1045,8 +1044,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 034203046..0b8dc7aeb 100644 --- a/main/utils.c +++ b/main/utils.c @@ -2798,3 +2798,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; +} diff --git a/res/res_agi.c b/res/res_agi.c index 4caa13bb1..f19303f4d 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -2048,7 +2048,7 @@ static int handle_connection(const char *agiurl, const struct ast_sockaddr addr, FastAGI defaults to port 4573 */ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds) { - int s = 0, flags; + int s = 0; char *host, *script; int num_addrs = 0, i = 0; struct ast_sockaddr *addrs; @@ -2078,14 +2078,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds) continue; } - if ((flags = fcntl(s, F_GETFL)) < 0) { - ast_log(LOG_WARNING, "fcntl(F_GETFL) failed: %s\n", strerror(errno)); - close(s); - continue; - } - - if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) { - ast_log(LOG_WARNING, "fnctl(F_SETFL) failed: %s\n", strerror(errno)); + if (ast_fd_set_flags(s, O_NONBLOCK)) { close(s); continue; } @@ -2251,9 +2244,8 @@ static enum agi_result launch_script(struct ast_channel *chan, char *script, int close(toast[1]); return AGI_RESULT_FAILURE; } - res = fcntl(audio[1], F_GETFL); - if (res > -1) - res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK); + + res = ast_fd_set_flags(audio[1], O_NONBLOCK); if (res < 0) { ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno)); close(fromast[0]); diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c index 75a6eba64..a65fc8ae2 100644 --- a/res/res_http_websocket.c +++ b/res/res_http_websocket.c @@ -445,19 +445,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_is_secure)(struct ast_websocket *session int AST_OPTIONAL_API_NAME(ast_websocket_set_nonblock)(struct ast_websocket *session) { - int flags; - - if ((flags = fcntl(session->fd, F_GETFL)) == -1) { - return -1; - } - - flags |= O_NONBLOCK; - - if ((flags = fcntl(session->fd, F_SETFL, flags)) == -1) { - return -1; - } - - return 0; + return ast_fd_set_flags(session->fd, O_NONBLOCK); } int AST_OPTIONAL_API_NAME(ast_websocket_set_timeout)(struct ast_websocket *session, int timeout) @@ -944,17 +932,11 @@ static struct ast_http_uri websocketuri = { /*! \brief Simple echo implementation which echoes received text and binary frames */ static void websocket_echo_callback(struct ast_websocket *session, struct ast_variable *parameters, struct ast_variable *headers) { - int flags, res; + int res; ast_debug(1, "Entering WebSocket echo loop\n"); - if ((flags = fcntl(ast_websocket_fd(session), F_GETFL)) == -1) { - goto end; - } - - flags |= O_NONBLOCK; - - if (fcntl(ast_websocket_fd(session), F_SETFL, flags) == -1) { + if (ast_fd_set_flags(ast_websocket_fd(session), O_NONBLOCK)) { goto end; } diff --git a/res/res_musiconhold.c b/res/res_musiconhold.c index d79151676..dee9c2da8 100644 --- a/res/res_musiconhold.c +++ b/res/res_musiconhold.c @@ -924,7 +924,6 @@ static struct mohclass *_get_mohbyname(const char *name, int warn, int flags, co static struct mohdata *mohalloc(struct mohclass *cl) { struct mohdata *moh; - long flags; if (!(moh = ast_calloc(1, sizeof(*moh)))) return NULL; @@ -936,10 +935,8 @@ static struct mohdata *mohalloc(struct mohclass *cl) } /* Make entirely non-blocking */ - flags = fcntl(moh->pipe[0], F_GETFL); - fcntl(moh->pipe[0], F_SETFL, flags | O_NONBLOCK); - flags = fcntl(moh->pipe[1], F_GETFL); - fcntl(moh->pipe[1], F_SETFL, flags | O_NONBLOCK); + ast_fd_set_flags(moh->pipe[0], O_NONBLOCK); + ast_fd_set_flags(moh->pipe[1], O_NONBLOCK); moh->f.frametype = AST_FRAME_VOICE; moh->f.subclass.format = cl->format; diff --git a/res/res_pjsip/pjsip_cli.c b/res/res_pjsip/pjsip_cli.c index 56ec191ed..4544a1717 100644 --- a/res/res_pjsip/pjsip_cli.c +++ b/res/res_pjsip/pjsip_cli.c @@ -82,31 +82,22 @@ int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags) return 0; } -static char *complete_show_sorcery_object(struct ao2_container *container, +static void complete_show_sorcery_object(struct ao2_container *container, struct ast_sip_cli_formatter_entry *formatter_entry, - const char *word, int state) + const char *word) { - char *result = NULL; - int wordlen = strlen(word); - int which = 0; - - struct ao2_iterator i = ao2_iterator_init(container, 0); + size_t wordlen = strlen(word); void *object; + struct ao2_iterator i = ao2_iterator_init(container, 0); while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) { const char *id = formatter_entry->get_id(object); - if (!strncasecmp(word, id, wordlen) - && ++which > state) { - result = ast_strdup(id); + if (!strncasecmp(word, id, wordlen)) { + ast_cli_completion_add(ast_strdup(id)); } ao2_t_ref(object, -1, "toss iterator endpoint ptr before break"); - if (result) { - break; - } } ao2_iterator_destroy(&i); - - return result; } static void dump_str_and_free(int fd, struct ast_str *buf) @@ -211,7 +202,8 @@ char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_ if (cmd == CLI_GENERATE) { ast_free(context.output_buffer); - return complete_show_sorcery_object(container, formatter_entry, a->word, a->n); + complete_show_sorcery_object(container, formatter_entry, a->word); + return NULL; } if (is_container) { diff --git a/res/res_pktccops.c b/res/res_pktccops.c index 037e533d3..8a4c3a5c0 100644 --- a/res/res_pktccops.c +++ b/res/res_pktccops.c @@ -650,7 +650,7 @@ static struct cops_gate *cops_gate_cmd(int cmd, struct cops_cmts *cmts, static int cops_connect(char *host, char *port) { - int s, sfd = -1, flags; + int s, sfd = -1; struct addrinfo hints; struct addrinfo *rp; struct addrinfo *result; @@ -676,8 +676,7 @@ static int cops_connect(char *host, char *port) if (sfd == -1) { ast_log(LOG_WARNING, "Failed socket\n"); } - flags = fcntl(sfd, F_GETFL); - fcntl(sfd, F_SETFL, flags | O_NONBLOCK); + ast_fd_set_flags(sfd, O_NONBLOCK); #ifdef HAVE_SO_NOSIGPIPE setsockopt(sfd, SOL_SOCKET, SO_NOSIGPIPE, &trueval, sizeof(trueval)); #endif diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c index 5271d1bf4..c921f36b3 100644 --- a/res/res_rtp_asterisk.c +++ b/res/res_rtp_asterisk.c @@ -2765,8 +2765,7 @@ static int create_new_socket(const char *type, int af) } ast_log(LOG_WARNING, "Unable to allocate %s socket: %s\n", type, strerror(errno)); } else { - long flags = fcntl(sock, F_GETFL); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + ast_fd_set_flags(sock, O_NONBLOCK); #ifdef SO_NO_CHECK if (nochecksums) { setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, &nochecksums, sizeof(nochecksums)); diff --git a/res/res_sorcery_astdb.c b/res/res_sorcery_astdb.c index fee857525..135709ebd 100644 --- a/res/res_sorcery_astdb.c +++ b/res/res_sorcery_astdb.c @@ -336,14 +336,14 @@ static void sorcery_astdb_retrieve_prefix(const struct ast_sorcery *sorcery, voi const char *family_prefix = data; size_t family_len = strlen(family_prefix) + strlen(type) + 1; /* +1 for slash delimiter */ char family[family_len + 1]; - char tree[prefix_len + sizeof("%")]; + char tree[prefix_len + 1]; RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree); struct ast_db_entry *entry; - snprintf(tree, sizeof(tree), "%.*s%%", (int) prefix_len, prefix); + snprintf(tree, sizeof(tree), "%.*s", (int) prefix_len, prefix); snprintf(family, sizeof(family), "%s/%s", family_prefix, type); - if (!(entries = ast_db_gettree(family, tree))) { + if (!(entries = ast_db_gettree_by_prefix(family, tree))) { return; } diff --git a/res/res_speech.c b/res/res_speech.c index 7d75985ca..f61588f57 100644 --- a/res/res_speech.c +++ b/res/res_speech.c @@ -365,5 +365,5 @@ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, - .load_pri = AST_MODPRI_APP_DEPEND, + .load_pri = AST_MODPRI_APP_DEPEND - 1, ); diff --git a/res/res_stasis.c b/res/res_stasis.c index b1cea3ad5..9a06a5287 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -2124,8 +2124,8 @@ static int load_module(void) return AST_MODULE_LOAD_SUCCESS; } -AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS, "Stasis application support", - .load_pri = AST_MODPRI_APP_DEPEND, +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Stasis application support", + .load_pri = AST_MODPRI_APP_DEPEND - 1, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, diff --git a/res/res_timing_pthread.c b/res/res_timing_pthread.c index 1e76720ec..0654059f9 100644 --- a/res/res_timing_pthread.c +++ b/res/res_timing_pthread.c @@ -132,9 +132,7 @@ static void *pthread_timer_open(void) } for (i = 0; i < ARRAY_LEN(timer->pipe); ++i) { - int flags = fcntl(timer->pipe[i], F_GETFL); - flags |= O_NONBLOCK; - fcntl(timer->pipe[i], F_SETFL, flags); + ast_fd_set_flags(timer->pipe[i], O_NONBLOCK); } ao2_lock(pthread_timers); |