X-Git-Url: http://git.asterisk.org/gitweb/?p=asterisk%2Fasterisk.git;a=blobdiff_plain;f=res%2Fres_pjsip%2Fpjsip_configuration.c;h=deb374e6e3f2c371c36498255caba55804b5e904;hp=c21582e1b9ecbae0cfc486d55674f1dff39b0e9a;hb=b5ca213e34055724a5cd669938e356569847edcb;hpb=8ff02ac951c979b1e5e340b3b1cc05736780be20 diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index c21582e..deb374e 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1168,48 +1168,83 @@ static int ami_show_endpoints(struct mansession *s, const struct message *m) return 0; } -static int populate_channel_container(void *obj, void *arg, int flags) { +static struct ao2_container *cli_get_endpoint_container(void) +{ + RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup); + RAII_VAR(struct ao2_container *, s_container, NULL, ao2_cleanup); + + container = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + if (!container) { + return NULL; + } + + s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, + ast_sorcery_object_id_compare, NULL); + if (!s_container) { + return NULL; + } + + if (ao2_container_dup(s_container, container, 0)) { + return NULL; + } + ao2_ref(s_container, +1); + return s_container; +} + +static int populate_channel_container(void *obj, void *arg, int flags) +{ struct ast_channel_snapshot *snapshot = obj; struct ao2_container *container = arg; - ao2_link_flags(container, snapshot, OBJ_NOLOCK); + + ao2_link(container, snapshot); return 0; } -static int gather_endpoint_channels(void *obj, void *arg, int flags) { +static int cli_channel_iterator(const void *container, ao2_callback_fn callback, void *args) +{ + const struct ast_sip_endpoint *array = container; + + return ast_sip_for_each_channel(array, callback, args); +} + +static int gather_endpoint_channels(void *obj, void *arg, int flags) +{ struct ast_sip_endpoint *endpoint = obj; struct ao2_container *channels = arg; + ast_sip_for_each_channel(endpoint, populate_channel_container, channels); return 0; } -static struct ao2_container *cli_get_channel_container(struct ast_sorcery *sip_sorcery) +static int cli_channel_compare(const void *left, const void *right, int flags) { - RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup); - RAII_VAR(struct ao2_container *, s_parent_container, NULL, ao2_cleanup); - struct ao2_container *child_container; + const struct ast_channel_snapshot *left_snap = left; + const struct ast_channel_snapshot *right_snap = right; - parent_container = ast_sorcery_retrieve_by_fields(sip_sorcery, "endpoint", - AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); - if (!parent_container) { - return NULL; + if (!left_snap || !right_snap) { + return 0; } + return strcmp(left_snap->name, right_snap->name); +} - s_parent_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, &ast_sorcery_object_id_compare, NULL); - if (!s_parent_container) { - return NULL; - } +static struct ao2_container *cli_get_channel_container(void) +{ + RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup); + RAII_VAR(struct ao2_container *, child_container, NULL, ao2_cleanup); - if (ao2_container_dup(s_parent_container, parent_container, OBJ_ORDER_ASCENDING)) { + parent_container = cli_get_endpoint_container(); + if (!parent_container) { return NULL; } - - child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL); + child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, + cli_channel_compare, NULL); if (!child_container) { return NULL; } - ao2_callback(s_parent_container, OBJ_NODATA, gather_endpoint_channels, child_container); - + ao2_callback(parent_container, OBJ_NODATA, gather_endpoint_channels, child_container); + ao2_ref(child_container, +1); return child_container; } @@ -1236,7 +1271,8 @@ static int cli_print_channel_header(void *obj, void *arg, int flags) return 0; } -static int cli_print_channel_body(void *obj, void *arg, int flags) { +static int cli_print_channel_body(void *obj, void *arg, int flags) +{ struct ast_channel_snapshot *snapshot = obj; struct ast_sip_cli_context *context = arg; struct timeval current_time; @@ -1272,7 +1308,8 @@ static int cli_print_channel_body(void *obj, void *arg, int flags) { 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", + ast_str_append(&context->output_buffer, 0, + "%*s: %-7s Exten: %-*.*s CLCID: \"%s\" <%s>\n", indent, "Codec", snapshot->nativeformats, flexwidth, flexwidth, @@ -1281,58 +1318,76 @@ static int cli_print_channel_body(void *obj, void *arg, int flags) { snapshot->connected_number ); context->indent_level--; + if (context->indent_level == 0) { + ast_str_append(&context->output_buffer, 0, "\n"); + } + return 0; } -static struct ao2_container *cli_get_endpoint_container(struct ast_sorcery *sip_sorcery) +static int cli_endpoint_iterator(const void *container, ao2_callback_fn callback, + void *args) { - return ast_sip_get_endpoints(); + struct ao2_container *ao2container = (struct ao2_container *) container; + + ao2_callback(ao2container, OBJ_NODATA, callback, args); + return 0; +} + +static void print_child_header(char *type, struct ast_sip_cli_context *context) +{ + struct ast_sip_cli_formatter_entry *formatter_entry; + + formatter_entry = ast_sip_lookup_cli_formatter(type); + if (formatter_entry && formatter_entry->print_header) { + formatter_entry->print_header(NULL, context, 0); + } } static int cli_print_endpoint_header(void *obj, void *arg, int flags) { struct ast_sip_cli_context *context = arg; - struct ast_sip_cli_formatter_entry *formatter_entry; if (!context->output_buffer) { return -1; } ast_str_append(&context->output_buffer, 0, - " \n"); + " Endpoint: \n"); if (context->recurse) { context->indent_level++; - formatter_entry = ast_sip_lookup_cli_formatter("auth"); - if (formatter_entry) { - formatter_entry->print_header(NULL, context, 0); - } - formatter_entry = ast_sip_lookup_cli_formatter("aor"); - if (formatter_entry) { - formatter_entry->print_header(NULL, context, 0); - } - formatter_entry = ast_sip_lookup_cli_formatter("identify"); - if (formatter_entry) { - formatter_entry->print_header(NULL, context, 0); - } - formatter_entry = ast_sip_lookup_cli_formatter("channel"); - if (formatter_entry) { - formatter_entry->print_header(NULL, context, 0); - } + 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); context->indent_level--; } return 0; } -static int cli_print_endpoint_body(void *obj, void *arg, int flags) { +static void print_child_body(char *type, const void *obj, struct ast_sip_cli_context *context) +{ + struct ast_sip_cli_formatter_entry *formatter_entry; + + 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); + } +} + +static int cli_print_endpoint_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); struct ast_sip_cli_context *context = arg; const char *id = ast_sorcery_object_get_id(endpoint); - struct ast_sip_cli_formatter_entry *formatter_entry; char *print_name = NULL; int print_name_len; char *number = S_COR(endpoint->id.self.number.valid, endpoint->id.self.number.str, NULL); + int indent; + int flexwidth; if (!context->output_buffer) { return -1; @@ -1348,8 +1403,12 @@ static int cli_print_endpoint_body(void *obj, void *arg, int flags) { snprintf(print_name, print_name_len, "%s/%s", id, number); } - ast_str_append(&context->output_buffer, 0, " %-62s %-12.12s %d of %.0f\n", - print_name ? print_name : id, + indent = CLI_INDENT_TO_SPACES(context->indent_level); + flexwidth = CLI_LAST_TABSTOP - indent - 2; + + ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s %d of %.0f\n", + indent, "Endpoint", + flexwidth, flexwidth, print_name ? print_name : id, ast_sip_get_device_state(endpoint), endpoint_snapshot->num_channels, (double) endpoint->devicestate_busy_at ? endpoint->devicestate_busy_at : @@ -1359,23 +1418,21 @@ static int cli_print_endpoint_body(void *obj, void *arg, int flags) { if (context->recurse) { context->indent_level++; - formatter_entry = ast_sip_lookup_cli_formatter("auth"); - if (formatter_entry) { - context->auth_direction = "Out"; - ast_sip_for_each_auth(&endpoint->outbound_auths, formatter_entry->print_body, context); - context->auth_direction = "In"; - ast_sip_for_each_auth(&endpoint->inbound_auths, formatter_entry->print_body, context); - } - formatter_entry = ast_sip_lookup_cli_formatter("aor"); - if (formatter_entry) { - ast_sip_for_each_aor(endpoint->aors, formatter_entry->print_body, context); - } - formatter_entry = ast_sip_lookup_cli_formatter("channel"); - if (formatter_entry) { - ast_sip_for_each_channel(endpoint, formatter_entry->print_body, context); - } + context->auth_direction = "Out"; + print_child_body("auth", &endpoint->outbound_auths, context); + context->auth_direction = "In"; + 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); context->indent_level--; + + if (context->indent_level == 0) { + ast_str_append(&context->output_buffer, 0, "\n"); + } } if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) { @@ -1391,6 +1448,8 @@ static struct ast_sip_cli_formatter_entry cli_channel_formatter = { .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 = { @@ -1398,8 +1457,33 @@ static struct ast_sip_cli_formatter_entry cli_endpoint_formatter = { .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", + .usage = "Usage: pjsip list channels\n" + " List the active PJSIP channels\n"), + AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Channels", + .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, "List PJSIP Endpoints", + .command = "pjsip list endpoints", + .usage = "Usage: pjsip list endpoints\n" + " List the configured PJSIP endpoints\n"), + AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoints", + .command = "pjsip show endpoints", + .usage = "Usage: pjsip show endpoints\n" + " List(detailed) the configured PJSIP endpoints\n"), + AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Endpoint", + .command = "pjsip show endpoint", + .usage = "Usage: pjsip show endpoint \n" + " Show the configured PJSIP endpoint\n"), +}; int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_module_info) { @@ -1420,12 +1504,9 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod ast_sorcery_apply_config(sip_sorcery, "res_pjsip"); - ast_sip_initialize_cli(sip_sorcery); - ast_sip_register_cli_formatter(&cli_channel_formatter); - ast_sip_register_cli_formatter(&cli_endpoint_formatter); + ast_sip_initialize_cli(); - - if (ast_sip_initialize_sorcery_auth(sip_sorcery)) { + if (ast_sip_initialize_sorcery_auth()) { ast_log(LOG_ERROR, "Failed to register SIP authentication support\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; @@ -1527,21 +1608,21 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "redirect_method", "user", redirect_handler, NULL, 0, 0); ast_sorcery_object_field_register_custom(sip_sorcery, "endpoint", "set_var", "", set_var_handler, set_var_to_str, 0, 0); - if (ast_sip_initialize_sorcery_transport(sip_sorcery)) { + if (ast_sip_initialize_sorcery_transport()) { ast_log(LOG_ERROR, "Failed to register SIP transport support with sorcery\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; return -1; } - if (ast_sip_initialize_sorcery_location(sip_sorcery)) { + if (ast_sip_initialize_sorcery_location()) { ast_log(LOG_ERROR, "Failed to register SIP location support with sorcery\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; return -1; } - if (ast_sip_initialize_sorcery_qualify(sip_sorcery)) { + if (ast_sip_initialize_sorcery_qualify()) { ast_log(LOG_ERROR, "Failed to register SIP qualify support with sorcery\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; @@ -1550,20 +1631,24 @@ int ast_res_pjsip_initialize_configuration(const struct ast_module_info *ast_mod ast_sorcery_observer_add(sip_sorcery, "contact", &state_contact_observer); - if (ast_sip_initialize_sorcery_domain_alias(sip_sorcery)) { + if (ast_sip_initialize_sorcery_domain_alias()) { ast_log(LOG_ERROR, "Failed to register SIP domain aliases support with sorcery\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; return -1; } - if (ast_sip_initialize_sorcery_global(sip_sorcery)) { + if (ast_sip_initialize_sorcery_global()) { ast_log(LOG_ERROR, "Failed to register SIP Global support\n"); ast_sorcery_unref(sip_sorcery); sip_sorcery = NULL; return -1; } + ast_sip_register_cli_formatter(&cli_channel_formatter); + ast_sip_register_cli_formatter(&cli_endpoint_formatter); + ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); + ast_sorcery_load(sip_sorcery); return 0; @@ -1571,6 +1656,10 @@ 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_sorcery_unref(sip_sorcery);