[Asterisk-code-review] res pjsip: Add CLI "pjsip dump endpt [details]" (asterisk[master])

Mark Michelson asteriskteam at digium.com
Thu Jan 21 15:21:59 CST 2016


Mark Michelson has submitted this change and it was merged.

Change subject: res_pjsip: Add CLI "pjsip dump endpt [details]"
......................................................................


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
---
M include/asterisk/res_pjproject.h
M res/res_pjproject.c
M res/res_pjsip.c
3 files changed, 137 insertions(+), 3 deletions(-)

Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  Mark Michelson: Looks good to me, approved
  Anonymous Coward #1000019: Verified



diff --git a/include/asterisk/res_pjproject.h b/include/asterisk/res_pjproject.h
index 2095cae..8828b34 100644
--- a/include/asterisk/res_pjproject.h
+++ b/include/asterisk/res_pjproject.h
@@ -19,6 +19,14 @@
 #ifndef _RES_PJPROJECT_H
 #define _RES_PJPROJECT_H
 
+/*! \brief Determines whether the res_pjproject module is loaded */
+#define CHECK_PJPROJECT_MODULE_LOADED()                 \
+	do {                                                \
+		if (!ast_module_check("res_pjproject.so")) {    \
+			return AST_MODULE_LOAD_DECLINE;             \
+		}                                               \
+	} while(0)
+
 /*!
  * \brief Retrieve a pjproject build option
  *
@@ -43,7 +51,33 @@
  *   \endcode
  *
  */
-int ast_pjproject_get_buildopt(char *option, char *format_string, ...) __attribute__((format(scanf, 2,3)));
+int ast_pjproject_get_buildopt(char *option, char *format_string, ...) __attribute__((format(scanf, 2, 3)));
+
+/*!
+ * \brief Begin PJPROJECT log interception for CLI output.
+ * \since 13.8.0
+ *
+ * \param fd CLI file descriptior to send intercepted output.
+ *
+ * \note ast_pjproject_log_intercept_begin() and
+ * ast_pjproject_log_intercept_end() must always be called
+ * in pairs.
+ *
+ * \return Nothing
+ */
+void ast_pjproject_log_intercept_begin(int fd);
+
+/*!
+ * \brief End PJPROJECT log interception for CLI output.
+ * \since 13.8.0
+ *
+ * \note ast_pjproject_log_intercept_begin() and
+ * ast_pjproject_log_intercept_end() must always be called
+ * in pairs.
+ *
+ * \return Nothing
+ */
+void ast_pjproject_log_intercept_end(void);
 
 /*!
  * \brief Increment the res_pjproject reference count.
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index de1cecb..e9f0d15 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -57,6 +57,19 @@
 
 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;
@@ -65,6 +78,16 @@
 	int log_line = 0;
 	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) {
@@ -124,6 +147,23 @@
 	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 b3c6773..2b7625a 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 @@
 	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 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 @@
 	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 @@
 	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 @@
 	ast_threadpool_shutdown(sip_threadpool);
 
 	ast_sip_destroy_cli();
+	ast_pjproject_unref();
+
 	return 0;
 }
 

-- 
To view, visit https://gerrit.asterisk.org/2023
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: If2d98a3641c9873364d1daaad971376311aef3cb
Gerrit-PatchSet: 3
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Owner: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Anonymous Coward #1000019
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Mark Michelson <mmichelson at digium.com>



More information about the asterisk-code-review mailing list