summaryrefslogtreecommitdiff
path: root/res
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2016-01-13 16:49:22 -0600
committerRichard Mudgett <rmudgett@digium.com>2016-01-21 12:47:12 -0600
commit5615db3714fbc8ca14e9c57921d3f05185f197f0 (patch)
tree4d48cbe9c10b7b140fa6699da45d69c4352b23ca /res
parente66021d2ca5e00c60db682ac9091f44781666455 (diff)
res_pjsip: Add CLI "pjsip dump endpt [details]"
Dump the res_pjsip endpt internals. In non-developer mode we will not document or make easily accessible the "details" option even though it is still available. The user has to know it exists to use it. Presumably they would also be aware of the potential crash warning below. Warning: PJPROJECT documents that the function used by this CLI command may cause a crash when asking for details because it tries to access all active memory pools. Change-Id: If2d98a3641c9873364d1daaad971376311aef3cb
Diffstat (limited to 'res')
-rw-r--r--res/res_pjproject.c40
-rw-r--r--res/res_pjsip.c64
2 files changed, 102 insertions, 2 deletions
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index de1cecbc8..e9f0d15c4 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -57,6 +57,19 @@ static unsigned decor_orig;
static AST_VECTOR(buildopts, char *) buildopts;
+/*! Protection from other log intercept instances. There can be only one at a time. */
+AST_MUTEX_DEFINE_STATIC(pjproject_log_intercept_lock);
+
+struct pjproject_log_intercept_data {
+ pthread_t thread;
+ int fd;
+};
+
+static struct pjproject_log_intercept_data pjproject_log_intercept = {
+ .thread = AST_PTHREADT_NULL,
+ .fd = -1,
+};
+
static void log_forwarder(int level, const char *data, int len)
{
int ast_level;
@@ -66,6 +79,16 @@ static void log_forwarder(int level, const char *data, int len)
const char *log_func = "<?>";
int mod_level;
+ if (pjproject_log_intercept.fd != -1
+ && pjproject_log_intercept.thread == pthread_self()) {
+ /*
+ * We are handling a CLI command intercepting PJPROJECT
+ * log output.
+ */
+ ast_cli(pjproject_log_intercept.fd, "%s\n", data);
+ return;
+ }
+
/* Lower number indicates higher importance */
switch (level) {
case 0: /* level zero indicates fatal error, according to docs */
@@ -124,6 +147,23 @@ int ast_pjproject_get_buildopt(char *option, char *format_string, ...)
return res;
}
+void ast_pjproject_log_intercept_begin(int fd)
+{
+ /* Protect from other CLI instances trying to do this at the same time. */
+ ast_mutex_lock(&pjproject_log_intercept_lock);
+
+ pjproject_log_intercept.thread = pthread_self();
+ pjproject_log_intercept.fd = fd;
+}
+
+void ast_pjproject_log_intercept_end(void)
+{
+ pjproject_log_intercept.fd = -1;
+ pjproject_log_intercept.thread = AST_PTHREADT_NULL;
+
+ ast_mutex_unlock(&pjproject_log_intercept_lock);
+}
+
void ast_pjproject_ref(void)
{
ast_module_ref(ast_module_info->self);
diff --git a/res/res_pjsip.c b/res/res_pjsip.c
index b3c6773b4..2b7625aba 100644
--- a/res/res_pjsip.c
+++ b/res/res_pjsip.c
@@ -42,9 +42,11 @@
#include "asterisk/res_pjsip_cli.h"
#include "asterisk/test.h"
#include "asterisk/res_pjsip_presence_xml.h"
+#include "asterisk/res_pjproject.h"
/*** MODULEINFO
<depend>pjproject</depend>
+ <depend>res_pjproject</depend>
<depend>res_sorcery_config</depend>
<depend>res_sorcery_memory</depend>
<depend>res_sorcery_astdb</depend>
@@ -2216,6 +2218,57 @@ struct ast_sip_endpoint *ast_sip_identify_endpoint(pjsip_rx_data *rdata)
return endpoint;
}
+static int do_cli_dump_endpt(void *v_a)
+{
+ struct ast_cli_args *a = v_a;
+
+ ast_pjproject_log_intercept_begin(a->fd);
+ pjsip_endpt_dump(ast_sip_get_pjsip_endpoint(), a->argc == 4 ? PJ_TRUE : PJ_FALSE);
+ ast_pjproject_log_intercept_end();
+
+ return 0;
+}
+
+static char *cli_dump_endpt(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ switch (cmd) {
+ case CLI_INIT:
+#ifdef AST_DEVMODE
+ e->command = "pjsip dump endpt [details]";
+ e->usage =
+ "Usage: pjsip dump endpt [details]\n"
+ " Dump the res_pjsip endpt internals.\n"
+ "\n"
+ "Warning: PJPROJECT documents that the function used by this\n"
+ "CLI command may cause a crash when asking for details because\n"
+ "it tries to access all active memory pools.\n";
+#else
+ /*
+ * In non-developer mode we will not document or make easily accessible
+ * the details option even though it is still available. The user has
+ * to know it exists to use it. Presumably they would also be aware of
+ * the potential crash warning.
+ */
+ e->command = "pjsip dump endpt";
+ e->usage =
+ "Usage: pjsip dump endpt\n"
+ " Dump the res_pjsip endpt internals.\n";
+#endif /* AST_DEVMODE */
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (4 < a->argc
+ || (a->argc == 4 && strcasecmp(a->argv[3], "details"))) {
+ return CLI_SHOWUSAGE;
+ }
+
+ ast_sip_push_task_synchronous(NULL, do_cli_dump_endpt, a);
+
+ return CLI_SUCCESS;
+}
+
static char *cli_show_endpoint_identifiers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
#define ENDPOINT_IDENTIFIER_FORMAT "%-20.20s\n"
@@ -2279,8 +2332,9 @@ static char *cli_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_
}
static struct ast_cli_entry cli_commands[] = {
- AST_CLI_DEFINE(cli_show_settings, "Show global and system configuration options"),
- AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
+ AST_CLI_DEFINE(cli_dump_endpt, "Dump the res_pjsip endpt internals"),
+ AST_CLI_DEFINE(cli_show_settings, "Show global and system configuration options"),
+ AST_CLI_DEFINE(cli_show_endpoint_identifiers, "List registered endpoint identifiers")
};
AST_RWLIST_HEAD_STATIC(endpoint_formatters, ast_sip_endpoint_formatter);
@@ -3895,6 +3949,8 @@ static int load_module(void)
pj_status_t status;
struct ast_threadpool_options options;
+ CHECK_PJPROJECT_MODULE_LOADED();
+
if (pj_init() != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;
}
@@ -4041,6 +4097,8 @@ static int load_module(void)
AST_TEST_REGISTER(xml_sanitization_end_null);
AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);
+ ast_pjproject_ref();
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -4094,6 +4152,8 @@ static int unload_module(void)
ast_threadpool_shutdown(sip_threadpool);
ast_sip_destroy_cli();
+ ast_pjproject_unref();
+
return 0;
}