summaryrefslogtreecommitdiff
path: root/res/res_pjsip/pjsip_configuration.c
diff options
context:
space:
mode:
Diffstat (limited to 'res/res_pjsip/pjsip_configuration.c')
-rw-r--r--res/res_pjsip/pjsip_configuration.c323
1 files changed, 208 insertions, 115 deletions
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 0aa63004b..b2a86c3c8 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -1217,10 +1217,10 @@ static int ami_show_endpoints(struct mansession *s, const struct message *m)
return 0;
}
-static struct ao2_container *cli_get_endpoint_container(void)
+static struct ao2_container *cli_endpoint_get_container(void)
{
RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, s_container, NULL, ao2_cleanup);
+ struct ao2_container *s_container;
container = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint",
AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
@@ -1229,100 +1229,175 @@ static struct ao2_container *cli_get_endpoint_container(void)
}
s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- ast_sorcery_object_id_compare, NULL);
+ (void *)ast_sorcery_object_id_sort, (void *)ast_sorcery_object_id_compare);
if (!s_container) {
return NULL;
}
if (ao2_container_dup(s_container, container, 0)) {
+ ao2_ref(s_container, -1);
return NULL;
}
- ao2_ref(s_container, +1);
+
return s_container;
}
-static int populate_channel_container(void *obj, void *arg, int flags)
+static int cli_channel_populate_container(void *obj, void *arg, int flags)
{
struct ast_channel_snapshot *snapshot = obj;
- struct ao2_container *container = arg;
- ao2_link(container, snapshot);
+ ao2_link(arg, snapshot);
+
return 0;
}
-static int cli_channel_iterator(const void *container, ao2_callback_fn callback, void *args)
+static int cli_channel_iterate(void *container, ao2_callback_fn callback, void *args)
{
- const struct ast_sip_endpoint *array = container;
+ const struct ast_sip_endpoint *endpoint = container;
+
+ ast_sip_for_each_channel(endpoint, callback, args);
- return ast_sip_for_each_channel(array, callback, args);
+ return 0;
}
-static int gather_endpoint_channels(void *obj, void *arg, int flags)
+static int cli_channel_sort(const void *obj, const void *arg, int flags)
{
- struct ast_sip_endpoint *endpoint = obj;
- struct ao2_container *channels = arg;
+ const struct ast_channel_snapshot *left_obj = obj;
+ const struct ast_channel_snapshot *right_obj = arg;
+ const char *right_key = arg;
+ int cmp;
- ast_sip_for_each_channel(endpoint, populate_channel_container, channels);
- return 0;
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_obj->name;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ cmp = strcmp(left_obj->name, right_key);
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ cmp = strncmp(left_obj->name, right_key, strlen(right_key));
+ break;
+ default:
+ cmp = 0;
+ break;
+ }
+
+ return cmp;
}
-static int cli_channel_compare(const void *left, const void *right, int flags)
+static int cli_channel_compare(void *obj, void *arg, int flags)
{
- const struct ast_channel_snapshot *left_snap = left;
- const struct ast_channel_snapshot *right_snap = right;
+ const struct ast_channel_snapshot *left_obj = obj;
+ const struct ast_channel_snapshot *right_obj = arg;
+ const char *right_key = arg;
+ int cmp = 0;
- if (!left_snap || !right_snap) {
- return 0;
+ switch (flags & OBJ_SEARCH_MASK) {
+ case OBJ_SEARCH_OBJECT:
+ right_key = right_obj->name;
+ /* Fall through */
+ case OBJ_SEARCH_KEY:
+ if (strcmp(left_obj->name, right_key) == 0) {
+ cmp = CMP_MATCH | CMP_STOP;
+ }
+ break;
+ case OBJ_SEARCH_PARTIAL_KEY:
+ if (strncmp(left_obj->name, right_key, strlen(right_key)) == 0) {
+ cmp = CMP_MATCH;
+ }
+ break;
+ default:
+ cmp = 0;
+ break;
}
- return strcmp(left_snap->name, right_snap->name);
+
+ return cmp;
}
-static struct ao2_container *cli_get_channel_container(void)
+static int cli_channel_hash(const void *obj, int flags)
+{
+ const struct ast_channel_snapshot *snapshot = obj;
+
+ if (flags & OBJ_SEARCH_OBJECT) {
+ return ast_str_hash(snapshot->name);
+ } else if (flags & OBJ_SEARCH_KEY) {
+ return ast_str_hash(obj);
+ }
+
+ return -1;
+}
+
+static int cli_endpoint_gather_channels(void *obj, void *arg, int flags)
+{
+ struct ast_sip_endpoint *endpoint = obj;
+ struct ao2_container *channels = arg;
+
+ ast_sip_for_each_channel(endpoint, cli_channel_populate_container, channels);
+
+ return 0;
+}
+
+static struct ao2_container *cli_channel_get_container(void)
{
RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup);
- RAII_VAR(struct ao2_container *, child_container, NULL, ao2_cleanup);
+ struct ao2_container *child_container;
- parent_container = cli_get_endpoint_container();
+ parent_container = cli_endpoint_get_container();
if (!parent_container) {
return NULL;
}
- child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0,
- cli_channel_compare, NULL);
+ child_container = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 17,
+ cli_channel_hash, cli_channel_sort, cli_channel_compare);
if (!child_container) {
return NULL;
}
- ao2_callback(parent_container, OBJ_NODATA, gather_endpoint_channels, child_container);
- ao2_ref(child_container, +1);
+ ao2_callback(parent_container, OBJ_NODATA, cli_endpoint_gather_channels, child_container);
+
return child_container;
}
-static int cli_print_channel_header(void *obj, void *arg, int flags)
+static const char *cli_channel_get_id(const void *obj)
+{
+ const struct ast_channel_snapshot *snapshot = obj;
+
+ return snapshot->name;
+}
+
+static void *cli_channel_retrieve_by_id(const char *id)
+{
+ RAII_VAR(struct ao2_container *, container, cli_channel_get_container(), ao2_cleanup);
+
+ return ao2_find(container, id, OBJ_KEY | OBJ_NOLOCK);
+}
+
+static int cli_channel_print_header(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
int indent = CLI_INDENT_TO_SPACES(context->indent_level);
int filler = CLI_LAST_TABSTOP - indent - 13;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
+
ast_str_append(&context->output_buffer, 0,
"%*s: <ChannelId%*.*s> <State.....> <Time(sec)>\n",
indent, "Channel", filler, filler, CLI_HEADER_FILLER);
+ if (context->recurse) {
+ context->indent_level++;
+ indent = CLI_INDENT_TO_SPACES(context->indent_level);
+ filler = CLI_LAST_TABSTOP - indent - 38;
+ ast_str_append(&context->output_buffer, 0,
+ "%*s: <Codec> Exten: <DialedExten%*.*s> CLCID: <ConnectedLineCID.......>\n",
+ indent, "Codec", filler, filler, CLI_HEADER_FILLER);
+ context->indent_level--;
+ }
- context->indent_level++;
- indent = CLI_INDENT_TO_SPACES(context->indent_level);
- filler = CLI_LAST_TABSTOP - indent - 38;
- ast_str_append(&context->output_buffer, 0,
- "%*s: <Codec> Exten: <DialedExten%*.*s> CLCID: <ConnectedLineCID.......>\n",
- indent, "Codec", filler, filler, CLI_HEADER_FILLER);
- context->indent_level--;
return 0;
}
-static int cli_print_channel_body(void *obj, void *arg, int flags)
+static int cli_channel_print_body(void *obj, void *arg, int flags)
{
- struct ast_channel_snapshot *snapshot = obj;
+ const struct ast_channel_snapshot *snapshot = obj;
struct ast_sip_cli_context *context = arg;
struct timeval current_time;
char *print_name = NULL;
@@ -1330,9 +1405,7 @@ static int cli_print_channel_body(void *obj, void *arg, int flags)
int indent;
int flexwidth;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
gettimeofday(&current_time, NULL);
@@ -1353,79 +1426,84 @@ static int cli_print_channel_body(void *obj, void *arg, int flags)
ast_state2str(snapshot->state),
current_time.tv_sec - snapshot->creationtime.tv_sec);
- context->indent_level++;
- indent = CLI_INDENT_TO_SPACES(context->indent_level);
- flexwidth = CLI_LAST_TABSTOP - indent - 25;
-
- ast_str_append(&context->output_buffer, 0,
- "%*s: %-7s Exten: %-*.*s CLCID: \"%s\" <%s>\n",
- indent, "Codec",
- snapshot->nativeformats,
- flexwidth, flexwidth,
- snapshot->exten,
- snapshot->connected_name,
- snapshot->connected_number
- );
- context->indent_level--;
- if (context->indent_level == 0) {
- ast_str_append(&context->output_buffer, 0, "\n");
+ if (context->recurse) {
+ context->indent_level++;
+ indent = CLI_INDENT_TO_SPACES(context->indent_level);
+ flexwidth = CLI_LAST_TABSTOP - indent - 25;
+
+ ast_str_append(&context->output_buffer, 0,
+ "%*s: %-7s Exten: %-*.*s CLCID: \"%s\" <%s>\n",
+ indent, "Codec",
+ snapshot->nativeformats,
+ flexwidth, flexwidth,
+ snapshot->exten,
+ snapshot->connected_name,
+ snapshot->connected_number
+ );
+ context->indent_level--;
+ if (context->indent_level == 0) {
+ ast_str_append(&context->output_buffer, 0, "\n");
+ }
}
return 0;
}
-static int cli_endpoint_iterator(const void *container, ao2_callback_fn callback,
- void *args)
+static int cli_endpoint_iterate(void *obj, ao2_callback_fn callback, void *args)
{
- struct ao2_container *ao2container = (struct ao2_container *) container;
+ ao2_callback(obj, OBJ_NODATA, callback, args);
- ao2_callback(ao2container, OBJ_NODATA, callback, args);
return 0;
}
-static void print_child_header(char *type, struct ast_sip_cli_context *context)
+static void *cli_endpoint_retrieve_by_id(const char *id)
{
- struct ast_sip_cli_formatter_entry *formatter_entry;
+ return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id);
+}
+
+static void cli_endpoint_print_child_header(char *type, struct ast_sip_cli_context *context)
+{
+ RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
formatter_entry = ast_sip_lookup_cli_formatter(type);
- if (formatter_entry && formatter_entry->print_header) {
+ if (formatter_entry) {
formatter_entry->print_header(NULL, context, 0);
}
}
-static int cli_print_endpoint_header(void *obj, void *arg, int flags)
+static int cli_endpoint_print_header(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
- if (!context->output_buffer) {
- return -1;
- }
+ ast_assert(context->output_buffer != NULL);
+
ast_str_append(&context->output_buffer, 0,
" Endpoint: <Endpoint/CID.....................................> <State.....> <Channels.>\n");
if (context->recurse) {
context->indent_level++;
- print_child_header("auth", context);
- print_child_header("aor", context);
- print_child_header("transport", context);
- print_child_header("identify", context);
- print_child_header("channel", context);
+ cli_endpoint_print_child_header("auth", context);
+ cli_endpoint_print_child_header("aor", context);
+ cli_endpoint_print_child_header("transport", context);
+ cli_endpoint_print_child_header("identify", context);
+ cli_endpoint_print_child_header("channel", context);
context->indent_level--;
}
+
return 0;
}
-static void print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
+static void cli_endpoint_print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context)
{
- struct ast_sip_cli_formatter_entry *formatter_entry;
+ RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup);
formatter_entry = ast_sip_lookup_cli_formatter(type);
- if (formatter_entry && formatter_entry->print_body && formatter_entry->iterator) {
- formatter_entry->iterator(obj, formatter_entry->print_body, context);
+ if (formatter_entry) {
+ formatter_entry->iterate((void *)obj, formatter_entry->print_body, context);
}
}
-static int cli_print_endpoint_body(void *obj, void *arg, int flags)
+static int cli_endpoint_print_body(void *obj, void *arg, int flags)
{
struct ast_sip_endpoint *endpoint = obj;
RAII_VAR(struct ast_endpoint_snapshot *, endpoint_snapshot, ast_sip_get_endpoint_snapshot(endpoint), ao2_cleanup);
@@ -1438,11 +1516,7 @@ static int cli_print_endpoint_body(void *obj, void *arg, int flags)
int indent;
int flexwidth;
- if (!context->output_buffer) {
- return -1;
- }
-
- context->current_endpoint = endpoint;
+ ast_assert(context->output_buffer != NULL);
if (number) {
print_name_len = strlen(id) + strlen(number) + 2;
@@ -1468,14 +1542,14 @@ static int cli_print_endpoint_body(void *obj, void *arg, int flags)
context->indent_level++;
context->auth_direction = "Out";
- print_child_body("auth", &endpoint->outbound_auths, context);
+ cli_endpoint_print_child_body("auth", &endpoint->outbound_auths, context);
context->auth_direction = "In";
- print_child_body("auth", &endpoint->inbound_auths, context);
+ cli_endpoint_print_child_body("auth", &endpoint->inbound_auths, context);
- print_child_body("aor", endpoint->aors, context);
- print_child_body("transport", endpoint, context);
- print_child_body("identify", endpoint, context);
- print_child_body("channel", endpoint, context);
+ cli_endpoint_print_child_body("aor", endpoint->aors, context);
+ cli_endpoint_print_child_body("transport", endpoint, context);
+ cli_endpoint_print_child_body("identify", endpoint, context);
+ cli_endpoint_print_child_body("channel", endpoint, context);
context->indent_level--;
@@ -1492,24 +1566,6 @@ static int cli_print_endpoint_body(void *obj, void *arg, int flags)
return 0;
}
-static struct ast_sip_cli_formatter_entry cli_channel_formatter = {
- .name = "channel",
- .print_header = cli_print_channel_header,
- .print_body = cli_print_channel_body,
- .get_container = cli_get_channel_container,
- .iterator = cli_channel_iterator,
- .comparator = cli_channel_compare,
-};
-
-static struct ast_sip_cli_formatter_entry cli_endpoint_formatter = {
- .name = "endpoint",
- .print_header = cli_print_endpoint_header,
- .print_body = cli_print_endpoint_body,
- .get_container = cli_get_endpoint_container,
- .iterator = cli_endpoint_iterator,
- .comparator = ast_sorcery_object_id_compare,
-};
-
static struct ast_cli_entry cli_commands[] = {
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Channels",
.command = "pjsip list channels",
@@ -1519,6 +1575,10 @@ static struct ast_cli_entry cli_commands[] = {
.command = "pjsip show channels",
.usage = "Usage: pjsip show channels\n"
" List(detailed) the active PJSIP channels\n"),
+ AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Channel",
+ .command = "pjsip show channel",
+ .usage = "Usage: pjsip show channel\n"
+ " List(detailed) the active PJSIP channel\n"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Endpoints",
.command = "pjsip list endpoints",
@@ -1534,9 +1594,11 @@ static struct ast_cli_entry cli_commands[] = {
" Show the configured PJSIP endpoint\n"),
};
+struct ast_sip_cli_formatter_entry *channel_formatter;
+struct ast_sip_cli_formatter_entry *endpoint_formatter;
+
int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_module_info)
{
-
if (ast_manager_register_xml(AMI_SHOW_ENDPOINTS, EVENT_FLAG_SYSTEM, ami_show_endpoints) ||
ast_manager_register_xml(AMI_SHOW_ENDPOINT, EVENT_FLAG_SYSTEM, ami_show_endpoint)) {
return -1;
@@ -1563,7 +1625,6 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
}
ast_sorcery_apply_default(sip_sorcery, "endpoint", "config", "pjsip.conf,criteria=type=endpoint");
-
ast_sorcery_apply_default(sip_sorcery, "nat_hook", "memory", NULL);
if (ast_sorcery_object_register(sip_sorcery, "endpoint", ast_sip_endpoint_alloc, NULL, sip_endpoint_apply_handler)) {
@@ -1694,8 +1755,38 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
return -1;
}
- ast_sip_register_cli_formatter(&cli_channel_formatter);
- ast_sip_register_cli_formatter(&cli_endpoint_formatter);
+ channel_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!channel_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for channel_formatter\n");
+ ast_sorcery_unref(sip_sorcery);
+ sip_sorcery = NULL;
+ return -1;
+ }
+ channel_formatter->name = "channel";
+ channel_formatter->print_header = cli_channel_print_header;
+ channel_formatter->print_body = cli_channel_print_body;
+ channel_formatter->get_container = cli_channel_get_container;
+ channel_formatter->iterate = cli_channel_iterate;
+ channel_formatter->retrieve_by_id = cli_channel_retrieve_by_id;
+ channel_formatter->get_id = cli_channel_get_id;
+
+ endpoint_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL);
+ if (!endpoint_formatter) {
+ ast_log(LOG_ERROR, "Unable to allocate memory for endpoint_formatter\n");
+ ast_sorcery_unref(sip_sorcery);
+ sip_sorcery = NULL;
+ return -1;
+ }
+ endpoint_formatter->name = "endpoint";
+ endpoint_formatter->print_header = cli_endpoint_print_header;
+ endpoint_formatter->print_body = cli_endpoint_print_body;
+ endpoint_formatter->get_container = cli_endpoint_get_container;
+ endpoint_formatter->iterate = cli_endpoint_iterate;
+ endpoint_formatter->retrieve_by_id = cli_endpoint_retrieve_by_id;
+ endpoint_formatter->get_id = ast_sorcery_object_get_id;
+
+ ast_sip_register_cli_formatter(channel_formatter);
+ ast_sip_register_cli_formatter(endpoint_formatter);
ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sorcery_load(sip_sorcery);
@@ -1705,12 +1796,14 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod
void ast_res_pjsip_destroy_configuration(void)
{
- ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
ast_sip_destroy_sorcery_location();
ast_sip_destroy_sorcery_auth();
ast_sip_destroy_sorcery_transport();
ast_manager_unregister(AMI_SHOW_ENDPOINT);
ast_manager_unregister(AMI_SHOW_ENDPOINTS);
+ ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));
+ ast_sip_unregister_cli_formatter(endpoint_formatter);
+ ast_sip_unregister_cli_formatter(channel_formatter);
ast_sorcery_unref(sip_sorcery);
}