summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
Diffstat (limited to 'res')
-rw-r--r--res/res_config_sqlite3.c16
-rw-r--r--res/res_pjproject.c224
-rw-r--r--res/res_pjsip_config_wizard.c111
-rw-r--r--res/res_sorcery_memory_cache.c6
4 files changed, 337 insertions, 20 deletions
diff --git a/res/res_config_sqlite3.c b/res/res_config_sqlite3.c
index 04b8e374c..4c4b82051 100644
--- a/res/res_config_sqlite3.c
+++ b/res/res_config_sqlite3.c
@@ -127,8 +127,14 @@ static inline const char *sqlite3_escape_string_helper(struct ast_threadstorage
* add two quotes, and convert NULL pointers to the word "NULL", but we
* don't allow those anyway. Just going to use %q for now. */
struct ast_str *buf = ast_str_thread_get(ts, maxlen);
- char *tmp = ast_str_buffer(buf);
char q = ts == &escape_value_buf ? '\'' : '"';
+ char *tmp;
+
+ if (ast_str_size(buf) < maxlen) {
+ /* realloc if buf is too small */
+ ast_str_make_space(&buf, maxlen);
+ }
+ tmp = ast_str_buffer(buf);
ast_str_reset(buf);
*tmp++ = q; /* Initial quote */
@@ -160,9 +166,15 @@ static const char *sqlite3_escape_column_op(const char *param)
{
size_t maxlen = strlen(param) * 2 + sizeof("\"\" =");
struct ast_str *buf = ast_str_thread_get(&escape_column_buf, maxlen);
- char *tmp = ast_str_buffer(buf);
+ char *tmp;
int space = 0;
+ if (ast_str_size(buf) < maxlen) {
+ /* realloc if buf is too small */
+ ast_str_make_space(&buf, maxlen);
+ }
+ tmp = ast_str_buffer(buf);
+
ast_str_reset(buf);
*tmp++ = '"';
while ((*tmp++ = *param++)) {
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index 7bf9003f9..f54c3713e 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -37,6 +37,44 @@
<support_level>core</support_level>
***/
+/*** DOCUMENTATION
+ <configInfo name="res_pjproject" language="en_US">
+ <synopsis>pjproject common configuration</synopsis>
+ <configFile name="pjproject.conf">
+ <configObject name="log_mappings">
+ <synopsis>PJPROJECT to Asterisk Log Level Mapping</synopsis>
+ <description><para>Warnings and errors in the pjproject libraries are generally handled
+ by Asterisk. In many cases, Asterisk wouldn't even consider them to
+ be warnings or errors so the messages emitted by pjproject directly
+ are either superfluous or misleading. The 'log_mappings'
+ object allows mapping the pjproject levels to Asterisk levels, or nothing.
+ </para>
+ <note><para>The id of this object, as well as its type, must be
+ 'log_mappings' or it won't be found.</para></note>
+ </description>
+ <configOption name="type">
+ <synopsis>Must be of type 'log_mappings'.</synopsis>
+ </configOption>
+ <configOption name="asterisk_error" default="0,1">
+ <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_ERROR.</synopsis>
+ </configOption>
+ <configOption name="asterisk_warning" default="2">
+ <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_WARNING.</synopsis>
+ </configOption>
+ <configOption name="asterisk_notice" default="">
+ <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_NOTICE.</synopsis>
+ </configOption>
+ <configOption name="asterisk_debug" default="3,4,5">
+ <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_DEBUG.</synopsis>
+ </configOption>
+ <configOption name="asterisk_verbose" default="">
+ <synopsis>A comma separated list of pjproject log levels to map to Asterisk LOG_VERBOSE.</synopsis>
+ </configOption>
+ </configObject>
+ </configFile>
+ </configInfo>
+ ***/
+
#include "asterisk.h"
ASTERISK_REGISTER_FILE()
@@ -51,7 +89,9 @@ ASTERISK_REGISTER_FILE()
#include "asterisk/cli.h"
#include "asterisk/res_pjproject.h"
#include "asterisk/vector.h"
+#include "asterisk/sorcery.h"
+static struct ast_sorcery *pjproject_sorcery;
static pj_log_func *log_cb_orig;
static unsigned decor_orig;
@@ -70,6 +110,66 @@ static struct pjproject_log_intercept_data pjproject_log_intercept = {
.fd = -1,
};
+struct log_mappings {
+ /*! Sorcery object details */
+ SORCERY_OBJECT(details);
+ /*! These are all comma-separated lists of pjproject log levels */
+ AST_DECLARE_STRING_FIELDS(
+ /*! pjproject log levels mapped to Asterisk ERROR */
+ AST_STRING_FIELD(asterisk_error);
+ /*! pjproject log levels mapped to Asterisk WARNING */
+ AST_STRING_FIELD(asterisk_warning);
+ /*! pjproject log levels mapped to Asterisk NOTICE */
+ AST_STRING_FIELD(asterisk_notice);
+ /*! pjproject log levels mapped to Asterisk VERBOSE */
+ AST_STRING_FIELD(asterisk_verbose);
+ /*! pjproject log levels mapped to Asterisk DEBUG */
+ AST_STRING_FIELD(asterisk_debug);
+ );
+};
+
+static struct log_mappings *default_log_mappings;
+
+static struct log_mappings *get_log_mappings(void)
+{
+ struct log_mappings *mappings;
+
+ mappings = ast_sorcery_retrieve_by_id(pjproject_sorcery, "log_mappings", "log_mappings");
+ if (!mappings) {
+ return ao2_bump(default_log_mappings);
+ }
+
+ return mappings;
+}
+
+#define __LOG_SUPPRESS -1
+
+static int get_log_level(int pj_level)
+{
+ RAII_VAR(struct log_mappings *, mappings, get_log_mappings(), ao2_cleanup);
+ unsigned char l;
+
+ if (!mappings) {
+ return __LOG_ERROR;
+ }
+
+ l = '0' + fmin(pj_level, 9);
+
+ if (strchr(mappings->asterisk_error, l)) {
+ return __LOG_ERROR;
+ } else if (strchr(mappings->asterisk_warning, l)) {
+ return __LOG_WARNING;
+ } else if (strchr(mappings->asterisk_notice, l)) {
+ return __LOG_NOTICE;
+ } else if (strchr(mappings->asterisk_verbose, l)) {
+ return __LOG_VERBOSE;
+ } else if (strchr(mappings->asterisk_debug, l)) {
+ return __LOG_DEBUG;
+ }
+
+ return __LOG_SUPPRESS;
+}
+
static void log_forwarder(int level, const char *data, int len)
{
int ast_level;
@@ -89,25 +189,19 @@ static void log_forwarder(int level, const char *data, int len)
return;
}
- /* Lower number indicates higher importance */
- switch (level) {
- case 0: /* level zero indicates fatal error, according to docs */
- case 1: /* 1 seems to be used for errors */
- ast_level = __LOG_ERROR;
- break;
- case 2: /* 2 seems to be used for warnings and errors */
- ast_level = __LOG_WARNING;
- break;
- default:
- ast_level = __LOG_DEBUG;
+ ast_level = get_log_level(level);
+
+ if (ast_level == __LOG_SUPPRESS) {
+ return;
+ }
+ if (ast_level == __LOG_DEBUG) {
/* For levels 3 and up, obey the debug level for res_pjproject */
mod_level = ast_opt_dbg_module ?
ast_debug_get_by_module("res_pjproject") : 0;
if (option_debug < level && mod_level < level) {
return;
}
- break;
}
/* PJPROJECT uses indention to indicate function call depth. We'll prepend
@@ -201,14 +295,105 @@ static char *handle_pjproject_show_buildopts(struct ast_cli_entry *e, int cmd, s
return CLI_SUCCESS;
}
+static void mapping_destroy(void *object)
+{
+ struct log_mappings *mappings = object;
+
+ ast_string_field_free_memory(mappings);
+}
+
+static void *mapping_alloc(const char *name)
+{
+ struct log_mappings *mappings = ast_sorcery_generic_alloc(sizeof(*mappings), mapping_destroy);
+ if (!mappings) {
+ return NULL;
+ }
+ ast_string_field_init(mappings, 128);
+
+ return mappings;
+}
+
+static char *handle_pjproject_show_log_mappings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct ast_variable *objset;
+ struct ast_variable *i;
+ struct log_mappings *mappings;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "pjproject show log mappings";
+ e->usage =
+ "Usage: pjproject show log mappings\n"
+ " Show pjproject to Asterisk log mappings\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ ast_cli(a->fd, "PJPROJECT to Asterisk log mappings:\n");
+ ast_cli(a->fd, "Asterisk Level : PJPROJECT log levels\n");
+
+ mappings = get_log_mappings();
+ if (!mappings) {
+ ast_log(LOG_ERROR, "Unable to retrieve pjproject log_mappings\n");
+ return CLI_SUCCESS;
+ }
+
+ objset = ast_sorcery_objectset_create(pjproject_sorcery, mappings);
+ if (!objset) {
+ ao2_ref(mappings, -1);
+ return CLI_SUCCESS;
+ }
+
+ for (i = objset; i; i = i->next) {
+ ast_cli(a->fd, "%-16s : %s\n", i->name, i->value);
+ }
+ ast_variables_destroy(objset);
+
+ ao2_ref(mappings, -1);
+ return CLI_SUCCESS;
+}
+
static struct ast_cli_entry pjproject_cli[] = {
AST_CLI_DEFINE(handle_pjproject_show_buildopts, "Show the compiled config of the pjproject in use"),
+ AST_CLI_DEFINE(handle_pjproject_show_log_mappings, "Show pjproject to Asterisk log mappings"),
};
static int load_module(void)
{
ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");
+ if (!(pjproject_sorcery = ast_sorcery_open())) {
+ ast_log(LOG_ERROR, "Failed to open SIP sorcery failed to open\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ ast_sorcery_apply_default(pjproject_sorcery, "log_mappings", "config", "pjproject.conf,criteria=type=log_mappings");
+ if (ast_sorcery_object_register(pjproject_sorcery, "log_mappings", mapping_alloc, NULL, NULL)) {
+ ast_log(LOG_WARNING, "Failed to register pjproject log_mappings object with sorcery\n");
+ ast_sorcery_unref(pjproject_sorcery);
+ pjproject_sorcery = NULL;
+ return AST_MODULE_LOAD_DECLINE;
+ }
+
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "type", "", OPT_NOOP_T, 0, 0);
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_debug", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_debug));
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_error", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_error));
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_warning", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_warning));
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_notice", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_notice));
+ ast_sorcery_object_field_register(pjproject_sorcery, "log_mappings", "asterisk_verbose", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct log_mappings, asterisk_verbose));
+
+ default_log_mappings = ast_sorcery_alloc(pjproject_sorcery, "log_mappings", "log_mappings");
+ if (!default_log_mappings) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for pjproject log_mappings\n");
+ return AST_MODULE_LOAD_DECLINE;
+ }
+ ast_string_field_set(default_log_mappings, asterisk_error, "0,1");
+ ast_string_field_set(default_log_mappings, asterisk_warning, "2");
+ ast_string_field_set(default_log_mappings, asterisk_debug, "3,4,5");
+
+ ast_sorcery_load(pjproject_sorcery);
+
pj_init();
decor_orig = pj_log_get_decor();
@@ -247,12 +432,27 @@ static int unload_module(void)
pj_shutdown();
+ ao2_cleanup(default_log_mappings);
+ default_log_mappings = NULL;
+
+ ast_sorcery_unref(pjproject_sorcery);
+
return 0;
}
+static int reload_module(void)
+{
+ if (pjproject_sorcery) {
+ ast_sorcery_reload(pjproject_sorcery);
+ }
+
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "PJPROJECT Log and Utility Support",
.support_level = AST_MODULE_SUPPORT_CORE,
.load = load_module,
.unload = unload_module,
+ .reload = reload_module,
.load_pri = AST_MODPRI_CHANNEL_DEPEND - 6,
);
diff --git a/res/res_pjsip_config_wizard.c b/res/res_pjsip_config_wizard.c
index 39d3c3f64..e263437d7 100644
--- a/res/res_pjsip_config_wizard.c
+++ b/res/res_pjsip_config_wizard.c
@@ -45,6 +45,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <pjsip.h>
#include "asterisk/astobj2.h"
+#include "asterisk/cli.h"
#include "asterisk/res_pjsip.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
@@ -276,7 +277,7 @@ struct object_type_wizard {
struct ast_config *last_config;
char object_type[];
};
-static AST_VECTOR(object_type_wizards, struct object_type_wizard *) object_type_wizards;
+static AST_VECTOR_RW(object_type_wizards, struct object_type_wizard *) object_type_wizards;
/*! \brief Callbacks for vector deletes */
#define NOT_EQUALS(a, b) (a != b)
@@ -304,12 +305,15 @@ static struct object_type_wizard *find_wizard(const char *object_type)
{
int idx;
+ AST_VECTOR_RW_RDLOCK(&object_type_wizards);
for(idx = 0; idx < AST_VECTOR_SIZE(&object_type_wizards); idx++) {
struct object_type_wizard *otw = AST_VECTOR_GET(&object_type_wizards, idx);
if (!strcmp(otw->object_type, object_type)) {
+ AST_VECTOR_RW_UNLOCK(&object_type_wizards);
return otw;
}
}
+ AST_VECTOR_RW_UNLOCK(&object_type_wizards);
return NULL;
}
@@ -1137,7 +1141,9 @@ static void wizard_mapped_observer(const char *name, struct ast_sorcery *sorcery
otw->wizard_data = wizard_data;
otw->last_config = NULL;
strcpy(otw->object_type, object_type); /* Safe */
+ AST_VECTOR_RW_WRLOCK(&object_type_wizards);
AST_VECTOR_APPEND(&object_type_wizards, otw);
+ AST_VECTOR_RW_UNLOCK(&object_type_wizards);
ast_debug(1, "Wizard mapped for object_type '%s'\n", object_type);
}
}
@@ -1177,19 +1183,118 @@ static void instance_destroying_observer(const char *name, struct ast_sorcery *s
ast_module_unref(ast_module_info->self);
}
+static char *handle_export_primitives(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ struct ast_sorcery *sorcery;
+ int idx;
+ FILE *f = NULL;
+ const char *fn = NULL;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "pjsip export config_wizard primitives [to]";
+ e->usage =
+ "Usage: pjsip export config_wizard primitives [ to <filename ]\n"
+ " Export the config_wizard objects as pjsip primitives to\n"
+ " the console or to <filename>\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (a->argc > 5) {
+ char date[256]="";
+ time_t t;
+ fn = a->argv[5];
+
+ time(&t);
+ ast_copy_string(date, ctime(&t), sizeof(date));
+ f = fopen(fn, "w");
+ if (!f) {
+ ast_log(LOG_ERROR, "Unable to write %s (%s)\n", fn, strerror(errno));
+ return CLI_FAILURE;
+ }
+
+ fprintf(f, ";!\n");
+ fprintf(f, ";! Automatically generated configuration file\n");
+ fprintf(f, ";! Filename: %s\n", fn);
+ fprintf(f, ";! Generator: %s\n", "'pjsip export config_wizard primitives'");
+ fprintf(f, ";! Creation Date: %s", date);
+ fprintf(f, ";!\n");
+ }
+
+ sorcery = ast_sip_get_sorcery();
+
+ AST_VECTOR_RW_RDLOCK(&object_type_wizards);
+ for(idx = 0; idx < AST_VECTOR_SIZE(&object_type_wizards); idx++) {
+ struct object_type_wizard *otw = AST_VECTOR_GET(&object_type_wizards, idx);
+ struct ao2_container *container;
+ struct ao2_iterator i;
+ void *o;
+
+ container = ast_sorcery_retrieve_by_fields(sorcery, otw->object_type, AST_RETRIEVE_FLAG_MULTIPLE, NULL);
+ if (!container) {
+ continue;
+ }
+
+ i = ao2_iterator_init(container, 0);
+ while ((o = ao2_iterator_next(&i))) {
+ struct ast_variable *vars;
+ struct ast_variable *v;
+
+ vars = ast_sorcery_objectset_create(sorcery, o);
+ if (vars && ast_variable_find_in_list(vars, "@pjsip_wizard")) {
+ if (f) {
+ fprintf(f, "\n[%s]\ntype = %s\n", ast_sorcery_object_get_id(o), otw->object_type);
+ } else {
+ ast_cli(a->fd, "\n[%s]\ntype = %s\n", ast_sorcery_object_get_id(o), otw->object_type);
+ }
+ for (v = vars; v; v = v->next) {
+ if (!ast_strlen_zero(v->value)) {
+ if (f) {
+ fprintf(f, "%s = %s\n", v->name, v->value);
+ } else {
+ ast_cli(a->fd, "%s = %s\n", v->name, v->value);
+ }
+ }
+ }
+ }
+ ast_variables_destroy(vars);
+ ao2_ref(o, -1);
+ }
+ ao2_iterator_destroy(&i);
+ ao2_cleanup(container);
+ }
+ AST_VECTOR_RW_UNLOCK(&object_type_wizards);
+
+ if (f) {
+ fclose(f);
+ ast_cli(a->fd, "Wrote configuration to %s\n", fn);
+ }
+
+
+ return CLI_SUCCESS;
+}
+
+static struct ast_cli_entry config_wizard_cli[] = {
+ AST_CLI_DEFINE(handle_export_primitives, "Export config wizard primitives"),
+};
+
static int load_module(void)
{
- AST_VECTOR_INIT(&object_type_wizards, 12);
+ AST_VECTOR_RW_INIT(&object_type_wizards, 12);
ast_sorcery_global_observer_add(&global_observer);
+ ast_cli_register_multiple(config_wizard_cli, ARRAY_LEN(config_wizard_cli));
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
+ ast_cli_unregister_multiple(config_wizard_cli, ARRAY_LEN(config_wizard_cli));
ast_sorcery_global_observer_remove(&global_observer);
AST_VECTOR_REMOVE_CMP_UNORDERED(&object_type_wizards, NULL, NOT_EQUALS, OTW_DELETE_CB);
- AST_VECTOR_FREE(&object_type_wizards);
+ AST_VECTOR_RW_FREE(&object_type_wizards);
return 0;
}
diff --git a/res/res_sorcery_memory_cache.c b/res/res_sorcery_memory_cache.c
index 99db0ce9c..f2ed5d5c8 100644
--- a/res/res_sorcery_memory_cache.c
+++ b/res/res_sorcery_memory_cache.c
@@ -1830,7 +1830,7 @@ static char *sorcery_memory_cache_expire(struct ast_cli_entry *e, int cmd, struc
}
}
- if (a->argc > 6) {
+ if (a->argc < 5 || a->argc > 6) {
return CLI_SHOWUSAGE;
}
@@ -1884,7 +1884,7 @@ static char *sorcery_memory_cache_stale(struct ast_cli_entry *e, int cmd, struct
}
}
- if (a->argc > 6) {
+ if (a->argc < 5 || a->argc > 6) {
return CLI_SHOWUSAGE;
}
@@ -1943,7 +1943,7 @@ static char *sorcery_memory_cache_populate(struct ast_cli_entry *e, int cmd, str
}
}
- if (a->argc > 5) {
+ if (a->argc != 5) {
return CLI_SHOWUSAGE;
}