From 3ff60b75b144d70034a768fc7d7da4537bf7cd7a Mon Sep 17 00:00:00 2001 From: George Joseph Date: Sat, 8 Mar 2014 16:50:36 +0000 Subject: pjsip_cli: Create pjsip show channel and contact, and general cli code cleanup. Created the 'pjsip show channel' and 'pjsip show contact' commands. Refactored out the hated ast_hashtab. Replaced with ao2_container. Cleaned up function naming. Internal only, no public name changes. Cleaned up whitespace and brace formatting in cli code. Changed some NULL checking from "if"s to ast_asserts. Fixed some register/unregister ordering to reduce deadlock potential. Fixed ast_sip_location_add_contact where the 'name' buffer was too short. Fixed some self-assignment issues in res_pjsip_outbound_registration. (closes issue ASTERISK-23276) Review: http://reviewboard.asterisk.org/r/3283/ ........ Merged revisions 410287 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410288 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- res/res_pjsip/config_auth.c | 62 ++++--- res/res_pjsip/config_transport.c | 53 +++--- res/res_pjsip/location.c | 310 ++++++++++++++++++++----------- res/res_pjsip/pjsip_cli.c | 136 +++++++++----- res/res_pjsip/pjsip_configuration.c | 323 +++++++++++++++++++++------------ res/res_pjsip_endpoint_identifier_ip.c | 68 ++++--- res/res_pjsip_outbound_registration.c | 57 +++--- 7 files changed, 645 insertions(+), 364 deletions(-) (limited to 'res') diff --git a/res/res_pjsip/config_auth.c b/res/res_pjsip/config_auth.c index bfba26253..05ec4c9ae 100644 --- a/res/res_pjsip/config_auth.c +++ b/res/res_pjsip/config_auth.c @@ -199,10 +199,10 @@ static struct ast_sip_endpoint_formatter endpoint_auth_formatter = { .format_ami = format_ami_endpoint_auth }; -static struct ao2_container *cli_get_auth_container(void) +static struct ao2_container *cli_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(ast_sip_get_sorcery(), "auth", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); @@ -211,34 +211,36 @@ static struct ao2_container *cli_get_auth_container(void) } s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, 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 cli_iterator(const void *container, ao2_callback_fn callback, void *args) +static int cli_iterator(void *container, ao2_callback_fn callback, void *args) { - const struct ast_sip_auth_vector *vector = container; + return ast_sip_for_each_auth(container, callback, args); +} - return ast_sip_for_each_auth(vector, callback, args); +static void *cli_retrieve_by_id(const char *id) +{ + return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), SIP_SORCERY_AUTH_TYPE, id); } -static int cli_print_auth_header(void *obj, void *arg, int flags) +static int cli_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_MAX_WIDTH - indent - 20; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); ast_str_append(&context->output_buffer, 0, "%*s: \n", indent, "I/OAuth", filler, filler, @@ -247,17 +249,13 @@ static int cli_print_auth_header(void *obj, void *arg, int flags) return 0; } -static int cli_print_auth_body(void *obj, void *arg, int flags) +static int cli_print_body(void *obj, void *arg, int flags) { struct ast_sip_auth *auth = obj; struct ast_sip_cli_context *context = arg; char title[32]; - context->current_auth = auth; - - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); snprintf(title, sizeof(title), "%sAuth", context->auth_direction ? context->auth_direction : ""); @@ -275,15 +273,6 @@ static int cli_print_auth_body(void *obj, void *arg, int flags) return 0; } -static struct ast_sip_cli_formatter_entry cli_auth_formatter = { - .name = SIP_SORCERY_AUTH_TYPE, - .print_header = cli_print_auth_header, - .print_body = cli_print_auth_body, - .get_container = cli_get_auth_container, - .iterator = cli_iterator, - .comparator = ast_sorcery_object_id_compare, -}; - static struct ast_cli_entry cli_commands[] = { AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Auths", .command = "pjsip list auths", @@ -299,6 +288,8 @@ static struct ast_cli_entry cli_commands[] = { " Show the configured PJSIP Auth\n"), }; +static struct ast_sip_cli_formatter_entry *cli_formatter; + /*! \brief Initialize sorcery with auth support */ int ast_sip_initialize_sorcery_auth(void) { @@ -326,7 +317,21 @@ int ast_sip_initialize_sorcery_auth(void) "userpass", auth_type_handler, auth_type_to_str, NULL, 0, 0); ast_sip_register_endpoint_formatter(&endpoint_auth_formatter); - ast_sip_register_cli_formatter(&cli_auth_formatter); + + cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!cli_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n"); + return -1; + } + cli_formatter->name = SIP_SORCERY_AUTH_TYPE; + cli_formatter->print_header = cli_print_header; + cli_formatter->print_body = cli_print_body; + cli_formatter->get_container = cli_get_container; + cli_formatter->iterate = cli_iterator; + cli_formatter->get_id = ast_sorcery_object_get_id; + cli_formatter->retrieve_by_id = cli_retrieve_by_id; + + ast_sip_register_cli_formatter(cli_formatter); ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); return 0; @@ -335,6 +340,7 @@ int ast_sip_initialize_sorcery_auth(void) int ast_sip_destroy_sorcery_auth(void) { ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands)); - ast_sip_unregister_cli_formatter(&cli_auth_formatter); + ast_sip_unregister_cli_formatter(cli_formatter); + return 0; } diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c index 797427b4a..1559ab77c 100644 --- a/res/res_pjsip/config_transport.c +++ b/res/res_pjsip/config_transport.c @@ -509,7 +509,7 @@ static int tos_to_str(const void *obj, const intptr_t *args, char **buf) static struct ao2_container *cli_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(ast_sip_get_sorcery(), "transport", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); @@ -518,19 +518,20 @@ static struct ao2_container *cli_get_container(void) } s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, 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 cli_iterator(const void *container, ao2_callback_fn callback, void *args) +static int cli_iterate(void *container, ao2_callback_fn callback, void *args) { const struct ast_sip_endpoint *endpoint = container; struct ast_sip_transport *transport = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), @@ -539,18 +540,22 @@ static int cli_iterator(const void *container, ao2_callback_fn callback, void *a if (!transport) { return -1; } + return callback(transport, args, 0); } +static void *cli_retrieve_by_id(const char *id) +{ + return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "transport", id); +} + static int cli_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_MAX_WIDTH - indent - 61; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); ast_str_append(&context->output_buffer, 0, "%*s: \n", @@ -565,9 +570,7 @@ static int cli_print_body(void *obj, void *arg, int flags) struct ast_sip_cli_context *context = arg; char hoststr[PJ_INET6_ADDRSTRLEN]; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); pj_sockaddr_print(&transport->host, hoststr, sizeof(hoststr), 3); @@ -586,15 +589,6 @@ static int cli_print_body(void *obj, void *arg, int flags) return 0; } -static struct ast_sip_cli_formatter_entry cli_formatter = { - .name = "transport", - .print_header = cli_print_header, - .print_body = cli_print_body, - .get_container = cli_get_container, - .iterator = cli_iterator, - .comparator = ast_sorcery_object_id_compare, -}; - static struct ast_cli_entry cli_commands[] = { AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Transports", .command = "pjsip list transports", @@ -610,6 +604,8 @@ static struct ast_cli_entry cli_commands[] = { " Show the configured PJSIP Transport\n"), }; +static struct ast_sip_cli_formatter_entry *cli_formatter; + /*! \brief Initialize sorcery with transport support */ int ast_sip_initialize_sorcery_transport(void) { @@ -643,7 +639,21 @@ int ast_sip_initialize_sorcery_transport(void) ast_sorcery_object_field_register(sorcery, "transport", "cos", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_transport, cos)); ast_sip_register_endpoint_formatter(&endpoint_transport_formatter); - ast_sip_register_cli_formatter(&cli_formatter); + + cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!cli_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n"); + return -1; + } + cli_formatter->name = "transport"; + cli_formatter->print_header = cli_print_header; + cli_formatter->print_body = cli_print_body; + cli_formatter->get_container = cli_get_container; + cli_formatter->iterate = cli_iterate; + cli_formatter->get_id = ast_sorcery_object_get_id; + cli_formatter->retrieve_by_id = cli_retrieve_by_id; + + ast_sip_register_cli_formatter(cli_formatter); ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); return 0; @@ -652,6 +662,7 @@ int ast_sip_initialize_sorcery_transport(void) int ast_sip_destroy_sorcery_transport(void) { ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands)); - ast_sip_unregister_cli_formatter(&cli_formatter); + ast_sip_unregister_cli_formatter(cli_formatter); + return 0; } diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index eb12d8e74..e526c4665 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -181,7 +181,7 @@ struct ast_sip_contact *ast_sip_location_retrieve_contact(const char *contact_na int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent) { - char name[AST_UUID_STR_LEN]; + char name[MAX_OBJECT_FIELD * 2 + 3]; RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup); snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), uri); @@ -279,21 +279,21 @@ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variab return 0; } -static int contact_to_vl(void *object, void *arg, int flags) +static int contact_to_var_list(void *object, void *arg, int flags) { - struct ast_sip_contact *contact = object; + struct ast_sip_contact_wrapper *wrapper = object; struct ast_variable **var = arg; - ast_variable_list_append(&*var, ast_variable_new("contact", contact->uri, "")); + ast_variable_list_append(&*var, ast_variable_new("contact", wrapper->contact->uri, "")); return 0; } -static int contacts_to_vl(const void *obj, struct ast_variable **fields) +static int contacts_to_var_list(const void *obj, struct ast_variable **fields) { const struct ast_sip_aor *aor = obj; - ast_sip_for_each_contact(aor, contact_to_vl, fields); + ast_sip_for_each_contact(aor, contact_to_var_list, fields); return 0; } @@ -323,12 +323,21 @@ int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg) return 0; } +static void contact_wrapper_destroy(void *obj) +{ + struct ast_sip_contact_wrapper *wrapper = obj; + ast_free(wrapper->aor_id); + ast_free(wrapper->contact_id); + ao2_ref(wrapper->contact, -1); +} + int ast_sip_for_each_contact(const struct ast_sip_aor *aor, ao2_callback_fn on_contact, void *arg) { RAII_VAR(struct ao2_container *, contacts, NULL, ao2_cleanup); - struct ast_sip_contact *contact; struct ao2_iterator i; + int res = 0; + void *object = NULL; if (!on_contact || !(contacts = ast_sip_location_retrieve_aor_contacts(aor))) { @@ -336,26 +345,44 @@ int ast_sip_for_each_contact(const struct ast_sip_aor *aor, } i = ao2_iterator_init(contacts, 0); - while ((contact = ao2_iterator_next(&i))) { - int res; + while ((object = ao2_iterator_next(&i))) { + RAII_VAR(struct ast_sip_contact *, contact, object, ao2_cleanup); + RAII_VAR(struct ast_sip_contact_wrapper *, wrapper, NULL, ao2_cleanup); + const char *aor_id = ast_sorcery_object_get_id(aor); + + wrapper = ao2_alloc(sizeof(struct ast_sip_contact_wrapper), contact_wrapper_destroy); + if (!wrapper) { + res = -1; + break; + } + wrapper->contact_id = ast_malloc(strlen(aor_id) + strlen(contact->uri) + 2); + if (!wrapper->contact_id) { + res = -1; + break; + } + sprintf(wrapper->contact_id, "%s/%s", aor_id, contact->uri); + wrapper->aor_id = ast_strdup(aor_id); + if (!wrapper->aor_id) { + res = -1; + break; + } + wrapper->contact = contact; + ao2_bump(wrapper->contact); - ast_sorcery_object_set_extended(contact, "@aor_id", ast_sorcery_object_get_id(aor)); - if ((res = on_contact(contact, arg, 0))) { - ao2_iterator_destroy(&i); - return -1; + if ((res = on_contact(wrapper, arg, 0))) { + break; } } ao2_iterator_destroy(&i); - return 0; + return res; } int ast_sip_contact_to_str(void *object, void *arg, int flags) { - struct ast_sip_contact *contact = object; + struct ast_sip_contact_wrapper *wrapper = object; struct ast_str **buf = arg; - ast_str_append(buf, 0, "%s/%s,", - ast_sorcery_object_get_extended(contact, "aor_id"), contact->uri); + ast_str_append(buf, 0, "%s,", wrapper->contact_id); return 0; } @@ -448,10 +475,10 @@ struct ast_sip_endpoint_formatter endpoint_aor_formatter = { .format_ami = format_ami_endpoint_aor }; -static struct ao2_container *cli_get_aor_container(void) +static struct ao2_container *cli_aor_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(ast_sip_get_sorcery(), "aor", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); @@ -460,90 +487,144 @@ static struct ao2_container *cli_get_aor_container(void) } s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, 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_contact_container(void *obj, void *arg, int flags) +static int cli_contact_populate_container(void *obj, void *arg, int flags) { - struct ast_sip_contact *contact = obj; - struct ao2_container *container = arg; + ao2_link(arg, obj); - ao2_link(container, contact); return 0; } -static int gather_aor_contacts(void *obj, void *arg, int flags) +static int cli_aor_gather_contacts(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; - struct ao2_container *container = arg; - ast_sip_for_each_contact(aor, populate_contact_container, container); - return 0; + + return ast_sip_for_each_contact(aor, cli_contact_populate_container, arg); } -static int cli_contact_compare(const void *left, const void *right, int flags) +static const char *cli_contact_get_id(const void *obj) { - const struct ast_sip_contact *left_contact = left; - const struct ast_sip_contact *right_contact = right; - int rc; + const struct ast_sip_contact_wrapper *wrapper = obj; + return wrapper->contact_id; +} - if (!left_contact || !right_contact) { - return 0; +static int cli_contact_sort(const void *obj, const void *arg, int flags) +{ + const struct ast_sip_contact_wrapper *left_wrapper = obj; + const struct ast_sip_contact_wrapper *right_wrapper = arg; + const char *right_key = arg; + int cmp = 0; + + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_OBJECT: + right_key = right_wrapper->contact_id; + /* Fall through */ + case OBJ_SEARCH_KEY: + cmp = strcmp(left_wrapper->contact_id, right_key); + break; + case OBJ_SEARCH_PARTIAL_KEY: + cmp = strncmp(left_wrapper->contact_id, right_key, strlen(right_key)); + break; + default: + cmp = 0; + break; } - rc = strcmp(ast_sorcery_object_get_extended(left_contact, "aor_id"), - ast_sorcery_object_get_extended(right_contact, "aor_id")); - if (rc) { - return rc; + + return cmp; +} + +static int cli_contact_compare(void *obj, void *arg, int flags) +{ + const struct ast_sip_contact_wrapper *left_wrapper = obj; + const struct ast_sip_contact_wrapper *right_wrapper = arg; + const char *right_key = arg; + int cmp = 0; + + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_OBJECT: + right_key = right_wrapper->contact_id; + /* Fall through */ + case OBJ_SEARCH_KEY: + if (strcmp(left_wrapper->contact_id, right_key) == 0) {; + cmp = CMP_MATCH | CMP_STOP; + } + break; + case OBJ_SEARCH_PARTIAL_KEY: + if (strncmp(left_wrapper->contact_id, right_key, strlen(right_key)) == 0) { + cmp = CMP_MATCH; + } + break; + default: + cmp = 0; + break; + } + + return cmp; +} + +static int cli_contact_hash(const void *obj, int flags) +{ + const struct ast_sip_contact_wrapper *wrapper = obj; + if (flags & OBJ_SEARCH_OBJECT) { + return ast_str_hash(wrapper->contact_id); + } else if (flags & OBJ_SEARCH_KEY) { + return ast_str_hash(obj); } - return strcmp(left_contact->uri, right_contact->uri); + + return -1; +} + +static int cli_contact_iterate(void *container, ao2_callback_fn callback, void *args) +{ + return ast_sip_for_each_contact(container, callback, args); } -static struct ao2_container *cli_get_contact_container(void) +static struct ao2_container *cli_contact_get_container(void) { RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup); struct ao2_container *child_container; - parent_container = cli_get_aor_container(); + parent_container = cli_aor_get_container(); if (!parent_container) { return NULL; } - child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - cli_contact_compare, NULL); + child_container = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 17, + cli_contact_hash, cli_contact_sort, cli_contact_compare); if (!child_container) { return NULL; } - ao2_ref(child_container, +1); - ao2_callback(parent_container, OBJ_NODATA, gather_aor_contacts, child_container); + ao2_callback(parent_container, OBJ_NODATA, cli_aor_gather_contacts, child_container); return child_container; } -static int cli_contact_iterator(const void *container, ao2_callback_fn callback, void *args) +static void *cli_contact_retrieve_by_id(const char *id) { - const struct ast_sip_aor *array = container; - - return ast_sip_for_each_contact(array, callback, args); + return ao2_find(cli_contact_get_container(), id, OBJ_KEY | OBJ_NOLOCK); } -static int cli_print_contact_header(void *obj, void *arg, int flags) +static int cli_contact_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 - 18; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); + ast_str_append(&context->output_buffer, 0, "%*s: \n", indent, "Contact", filler, filler, CLI_HEADER_FILLER); @@ -551,27 +632,20 @@ static int cli_print_contact_header(void *obj, void *arg, int flags) return 0; } -static int cli_print_contact_body(void *obj, void *arg, int flags) +static int cli_contact_print_body(void *obj, void *arg, int flags) { - struct ast_sip_contact *contact = obj; + struct ast_sip_contact_wrapper *wrapper = obj; + struct ast_sip_contact *contact = wrapper->contact; struct ast_sip_cli_context *context = arg; - char *print_name = NULL; - int print_name_len; int indent; int flexwidth; - const char *aor_id = ast_sorcery_object_get_extended(contact, "aor_id"); RAII_VAR(struct ast_sip_contact_status *, status, ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(contact)), ao2_cleanup); - if (!context->output_buffer) { - return -1; - } - - print_name_len = strlen(aor_id) + strlen(contact->uri) + 2; - print_name = ast_alloca(print_name_len); - snprintf(print_name, print_name_len, "%s/%s", aor_id, contact->uri); + ast_assert(contact->uri != NULL); + ast_assert(context->output_buffer != NULL); indent = CLI_INDENT_TO_SPACES(context->indent_level); flexwidth = CLI_LAST_TABSTOP - indent - 2; @@ -580,31 +654,40 @@ static int cli_print_contact_body(void *obj, void *arg, int flags) indent, "Contact", flexwidth, flexwidth, - print_name, + wrapper->contact_id, (status ? (status->status == AVAILABLE ? "Avail" : "Unavail") : "Unknown"), (status ? ((long long) status->rtt) / 1000.0 : NAN)); return 0; } -static int cli_aor_iterator(const void *container, ao2_callback_fn callback, void *args) +static int cli_aor_iterate(void *container, ao2_callback_fn callback, void *args) { const char *aor_list = container; return ast_sip_for_each_aor(aor_list, callback, args); } -static int cli_print_aor_header(void *obj, void *arg, int flags) +static void *cli_aor_retrieve_by_id(const char *id) +{ + return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "aor", id); +} + +static const char *cli_aor_get_id(const void *obj) +{ + return ast_sorcery_object_get_id(obj); +} + +static int cli_aor_print_header(void *obj, void *arg, int flags) { struct ast_sip_cli_context *context = arg; - struct ast_sip_cli_formatter_entry *formatter_entry; + RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup); int indent = CLI_INDENT_TO_SPACES(context->indent_level); int filler = CLI_LAST_TABSTOP - indent - 7; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); + ast_str_append(&context->output_buffer, 0, "%*s: \n", indent, "Aor", filler, filler, CLI_HEADER_FILLER); @@ -612,27 +695,26 @@ static int cli_print_aor_header(void *obj, void *arg, int flags) if (context->recurse) { context->indent_level++; formatter_entry = ast_sip_lookup_cli_formatter("contact"); - if (formatter_entry && formatter_entry->print_header) { + if (formatter_entry) { formatter_entry->print_header(NULL, context, 0); } context->indent_level--; } + return 0; } -static int cli_print_aor_body(void *obj, void *arg, int flags) +static int cli_aor_print_body(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; struct ast_sip_cli_context *context = arg; - struct ast_sip_cli_formatter_entry *formatter_entry; + RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup); int indent; int flexwidth; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); - context->current_aor = aor; +// context->current_aor = aor; indent = CLI_INDENT_TO_SPACES(context->indent_level); flexwidth = CLI_LAST_TABSTOP - indent - 12; @@ -647,8 +729,8 @@ static int cli_print_aor_body(void *obj, void *arg, int flags) context->indent_level++; formatter_entry = ast_sip_lookup_cli_formatter("contact"); - if (formatter_entry && formatter_entry->print_body && formatter_entry->iterator) { - formatter_entry->iterator(aor, formatter_entry->print_body, context); + if (formatter_entry) { + formatter_entry->iterate(aor, formatter_entry->print_body, context); } context->indent_level--; @@ -666,24 +748,6 @@ static int cli_print_aor_body(void *obj, void *arg, int flags) return 0; } -static struct ast_sip_cli_formatter_entry cli_contact_formatter = { - .name = "contact", - .print_header = cli_print_contact_header, - .print_body = cli_print_contact_body, - .get_container = cli_get_contact_container, - .iterator = cli_contact_iterator, - .comparator = cli_contact_compare, -}; - -static struct ast_sip_cli_formatter_entry cli_aor_formatter = { - .name = "aor", - .print_header = cli_print_aor_header, - .print_body = cli_print_aor_body, - .get_container = cli_get_aor_container, - .iterator = cli_aor_iterator, - .comparator = ast_sorcery_object_id_compare, -}; - static struct ast_cli_entry cli_commands[] = { AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Aors", .command = "pjsip list aors", @@ -706,8 +770,15 @@ static struct ast_cli_entry cli_commands[] = { .command = "pjsip show contacts", .usage = "Usage: pjsip show contacts\n" " Show the configured PJSIP contacts\n"), + AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "Show PJSIP Contact", + .command = "pjsip show contact", + .usage = "Usage: pjsip show contact\n" + " Show the configured PJSIP contact\n"), }; +struct ast_sip_cli_formatter_entry *contact_formatter; +struct ast_sip_cli_formatter_entry *aor_formatter; + /*! \brief Initialize sorcery with location support */ int ast_sip_initialize_sorcery_location(void) { @@ -737,23 +808,52 @@ int ast_sip_initialize_sorcery_location(void) ast_sorcery_object_field_register(sorcery, "aor", "authenticate_qualify", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, authenticate_qualify)); ast_sorcery_object_field_register(sorcery, "aor", "max_contacts", "0", OPT_UINT_T, 0, FLDSET(struct ast_sip_aor, max_contacts)); ast_sorcery_object_field_register(sorcery, "aor", "remove_existing", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, remove_existing)); - ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_vl, 0, 0); + ast_sorcery_object_field_register_custom(sorcery, "aor", "contact", "", permanent_uri_handler, contacts_to_str, contacts_to_var_list, 0, 0); ast_sorcery_object_field_register(sorcery, "aor", "mailboxes", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, mailboxes)); ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy)); ast_sorcery_object_field_register(sorcery, "aor", "support_path", "no", OPT_BOOL_T, 1, FLDSET(struct ast_sip_aor, support_path)); ast_sip_register_endpoint_formatter(&endpoint_aor_formatter); - ast_sip_register_cli_formatter(&cli_contact_formatter); - ast_sip_register_cli_formatter(&cli_aor_formatter); + + contact_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!contact_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for contact_formatter\n"); + return -1; + } + contact_formatter->name = "contact"; + contact_formatter->print_header = cli_contact_print_header; + contact_formatter->print_body = cli_contact_print_body; + contact_formatter->get_container = cli_contact_get_container; + contact_formatter->iterate = cli_contact_iterate; + contact_formatter->get_id = cli_contact_get_id; + contact_formatter->retrieve_by_id = cli_contact_retrieve_by_id; + + aor_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!aor_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for aor_formatter\n"); + return -1; + } + aor_formatter->name = "aor"; + aor_formatter->print_header = cli_aor_print_header; + aor_formatter->print_body = cli_aor_print_body; + aor_formatter->get_container = cli_aor_get_container; + aor_formatter->iterate = cli_aor_iterate; + aor_formatter->get_id = cli_aor_get_id; + aor_formatter->retrieve_by_id = cli_aor_retrieve_by_id; + + ast_sip_register_cli_formatter(contact_formatter); + ast_sip_register_cli_formatter(aor_formatter); ast_cli_register_multiple(cli_commands, ARRAY_LEN(cli_commands)); + return 0; } int ast_sip_destroy_sorcery_location(void) { ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands)); - ast_sip_unregister_cli_formatter(&cli_contact_formatter); - ast_sip_unregister_cli_formatter(&cli_aor_formatter); + ast_sip_unregister_cli_formatter(contact_formatter); + ast_sip_unregister_cli_formatter(aor_formatter); + return 0; } diff --git a/res/res_pjsip/pjsip_cli.c b/res/res_pjsip/pjsip_cli.c index 6ad820a0c..17876024d 100644 --- a/res/res_pjsip/pjsip_cli.c +++ b/res/res_pjsip/pjsip_cli.c @@ -31,15 +31,7 @@ #include "asterisk/utils.h" #include "asterisk/sorcery.h" -static struct ast_hashtab *formatter_registry; - -struct ast_sip_cli_formatter_entry *ast_sip_lookup_cli_formatter(const char *name) -{ - struct ast_sip_cli_formatter_entry fake_entry = { - .name = name, - }; - return ast_hashtab_lookup(formatter_registry, &fake_entry); -} +static struct ao2_container *formatter_registry; int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags) { @@ -91,6 +83,7 @@ int ast_sip_cli_print_sorcery_objectset(void *obj, void *arg, int flags) } static char *complete_show_sorcery_object(struct ao2_container *container, + struct ast_sip_cli_formatter_entry *formatter_entry, const char *word, int state) { char *result = NULL; @@ -101,9 +94,10 @@ static char *complete_show_sorcery_object(struct ao2_container *container, void *object; while ((object = ao2_t_iterator_next(&i, "iterate thru endpoints table"))) { - if (!strncasecmp(word, ast_sorcery_object_get_id(object), wordlen) + const char *id = formatter_entry->get_id(object); + if (!strncasecmp(word, id, wordlen) && ++which > state) { - result = ast_strdup(ast_sorcery_object_get_id(object)); + result = ast_strdup(id); } ao2_t_ref(object, -1, "toss iterator endpoint ptr before break"); if (result) { @@ -111,6 +105,7 @@ static char *complete_show_sorcery_object(struct ao2_container *container, } } ao2_iterator_destroy(&i); + return result; } @@ -123,20 +118,15 @@ static void dump_str_and_free(int fd, struct ast_str *buf) char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { RAII_VAR(struct ao2_container *, container, NULL, ao2_cleanup); + RAII_VAR(struct ast_sip_cli_formatter_entry *, formatter_entry, NULL, ao2_cleanup); RAII_VAR(void *, object, NULL, ao2_cleanup); int is_container = 0; const char *cmd1; const char *cmd2; const char *object_id; char formatter_type[64]; - struct ast_sip_cli_formatter_entry *formatter_entry; struct ast_sip_cli_context context = { - .peers_mon_online = 0, - .peers_mon_offline = 0, - .peers_unmon_online = 0, - .peers_unmon_offline = 0, - .a = a, .indent_level = 0, .show_details = 0, .show_details_only_level_0 = 0, @@ -203,7 +193,7 @@ char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_ if (cmd == CLI_GENERATE) { ast_free(context.output_buffer); - return complete_show_sorcery_object(container, a->word, a->n); + return complete_show_sorcery_object(container, formatter_entry, a->word, a->n); } if (is_container) { @@ -219,8 +209,8 @@ char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_ ast_cli(a->fd, "No object specified.\n"); return CLI_FAILURE; } - object = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), formatter_type, - object_id); + + object = formatter_entry->retrieve_by_id(object_id); if (!object) { dump_str_and_free(a->fd, context.output_buffer); ast_cli(a->fd, "Unable to find object %s.\n\n", object_id); @@ -234,44 +224,110 @@ char *ast_sip_cli_traverse_objects(struct ast_cli_entry *e, int cmd, struct ast_ return CLI_SUCCESS; } -static int compare_formatters(const void *a, const void *b) +static int formatter_sort(const void *obj, const void *arg, int flags) { - const struct ast_sip_cli_formatter_entry *afe = a; - const struct ast_sip_cli_formatter_entry *bfe = b; - if (!afe || !bfe) { - ast_log(LOG_ERROR, "One of the arguments to compare_formatters was NULL\n"); - return -1; + const struct ast_sip_cli_formatter_entry *left_obj = obj; + const struct ast_sip_cli_formatter_entry *right_obj = arg; + const char *right_key = arg; + int cmp = 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 strcmp(afe->name, bfe->name); + + return cmp; } -static unsigned int hash_formatters(const void *a) +static int formatter_compare(void *obj, void *arg, int flags) { - const struct ast_sip_cli_formatter_entry *afe = a; - return ast_hashtab_hash_string(afe->name); + const struct ast_sip_cli_formatter_entry *left_obj = obj; + const struct ast_sip_cli_formatter_entry *right_obj = arg; + const char *right_key = arg; + int cmp = 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 cmp; +} + +static int formatter_hash(const void *obj, int flags) +{ + const struct ast_sip_cli_formatter_entry *left_obj = obj; + if (flags & OBJ_SEARCH_OBJECT) { + return ast_str_hash(left_obj->name); + } else if (flags & OBJ_SEARCH_KEY) { + return ast_str_hash(obj); + } + + return -1; +} + +struct ast_sip_cli_formatter_entry *ast_sip_lookup_cli_formatter(const char *name) +{ + return ao2_find(formatter_registry, name, OBJ_SEARCH_KEY | OBJ_NOLOCK); } int ast_sip_register_cli_formatter(struct ast_sip_cli_formatter_entry *formatter) { - ast_hashtab_insert_safe(formatter_registry, formatter); + ast_assert(formatter != NULL); + ast_assert(formatter->name != NULL); + ast_assert(formatter->print_body != NULL); + ast_assert(formatter->print_header != NULL); + ast_assert(formatter->get_container != NULL); + ast_assert(formatter->iterate != NULL); + ast_assert(formatter->get_id != NULL); + ast_assert(formatter->retrieve_by_id != NULL); + + ao2_link(formatter_registry, formatter); + return 0; } int ast_sip_unregister_cli_formatter(struct ast_sip_cli_formatter_entry *formatter) { - struct ast_sip_cli_formatter_entry *entry = ast_hashtab_lookup(formatter_registry, formatter); - - if (!entry) { - return -1; + if (formatter) { + ao2_wrlock(formatter_registry); + if (ao2_ref(formatter, -1) == 2) { + ao2_unlink_flags(formatter_registry, formatter, OBJ_NOLOCK); + } + ao2_unlock(formatter_registry); } - ast_hashtab_remove_this_object(formatter_registry, entry); return 0; } int ast_sip_initialize_cli(void) { - formatter_registry = ast_hashtab_create(17, compare_formatters, - ast_hashtab_resize_java, ast_hashtab_newsize_java, hash_formatters, 0); + formatter_registry = ao2_container_alloc_hash(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 17, + formatter_hash, formatter_sort, formatter_compare); + if (!formatter_registry) { ast_log(LOG_ERROR, "Unable to create formatter_registry.\n"); return -1; @@ -282,7 +338,5 @@ int ast_sip_initialize_cli(void) void ast_sip_destroy_cli(void) { - if (formatter_registry) { - ast_hashtab_destroy(formatter_registry, ast_free_ptr); - } + ao2_ref(formatter_registry, -1); } 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: \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: Exten: CLCID: \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: Exten: CLCID: \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(¤t_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: \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); } diff --git a/res/res_pjsip_endpoint_identifier_ip.c b/res/res_pjsip_endpoint_identifier_ip.c index 414f430a2..cc9bc3534 100644 --- a/res/res_pjsip_endpoint_identifier_ip.c +++ b/res/res_pjsip_endpoint_identifier_ip.c @@ -270,16 +270,14 @@ struct ast_sip_endpoint_formatter endpoint_identify_formatter = { .format_ami = format_ami_endpoint_identify }; -static int populate_identify_container(void *obj, void *arg, int flags) +static int cli_populate_container(void *obj, void *arg, int flags) { - struct ast_sip_ip_identify_match *ident = obj; - struct ao2_container *container = arg; + ao2_link(arg, obj); - ao2_link(container, ident); return 0; } -static int cli_iterator(const void *container, ao2_callback_fn callback, void *args) +static int cli_iterator(void *container, ao2_callback_fn callback, void *args) { const struct ast_sip_endpoint *endpoint = container; struct ao2_container *identifies; @@ -301,16 +299,17 @@ static int cli_iterator(const void *container, ao2_callback_fn callback, void *a return 0; } -static int gather_endpoint_identifies(void *obj, void *arg, int flags) +static int cli_endpoint_gather_identifies(void *obj, void *arg, int flags) { struct ast_sip_endpoint *endpoint = obj; struct ao2_container *container = arg; - cli_iterator(endpoint, populate_identify_container, container); + cli_iterator(endpoint, cli_populate_container, container); + return 0; } -static struct ao2_container *cli_get_identify_container(void) +static struct ao2_container *cli_get_container(void) { RAII_VAR(struct ao2_container *, parent_container, NULL, ao2_cleanup); RAII_VAR(struct ao2_container *, s_parent_container, NULL, ao2_cleanup); @@ -323,7 +322,7 @@ static struct ao2_container *cli_get_identify_container(void) } s_parent_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, ast_sorcery_object_id_compare); if (!s_parent_container) { return NULL; } @@ -333,26 +332,28 @@ static struct ao2_container *cli_get_identify_container(void) } child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, ast_sorcery_object_id_compare); if (!child_container) { return NULL; } - ao2_callback(s_parent_container, OBJ_NODATA, gather_endpoint_identifies, child_container); - ao2_ref(child_container, +1); + ao2_callback(s_parent_container, OBJ_NODATA, cli_endpoint_gather_identifies, child_container); + return child_container; } +static void *cli_retrieve_by_id(const char *id) +{ + return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "identify", id); +} -static int cli_print_identify_header(void *obj, void *arg, int flags) +static int cli_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_MAX_WIDTH - indent - 14; - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); ast_str_append(&context->output_buffer, 0, "%*s: \n", @@ -361,15 +362,13 @@ static int cli_print_identify_header(void *obj, void *arg, int flags) return 0; } -static int cli_print_identify_body(void *obj, void *arg, int flags) +static int cli_print_body(void *obj, void *arg, int flags) { RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free); struct ip_identify_match *ident = obj; struct ast_sip_cli_context *context = arg; - if (!context->output_buffer || !str) { - return -1; - } + ast_assert(context->output_buffer != NULL); ast_str_append(&context->output_buffer, 0, "%*s: ", CLI_INDENT_TO_SPACES(context->indent_level), "Identify"); @@ -379,14 +378,7 @@ static int cli_print_identify_body(void *obj, void *arg, int flags) return 0; } -static struct ast_sip_cli_formatter_entry cli_identify_formatter = { - .name = "identify", - .print_header = cli_print_identify_header, - .print_body = cli_print_identify_body, - .get_container = cli_get_identify_container, - .comparator = ast_sorcery_object_id_compare, - .iterator = cli_iterator, -}; +static struct ast_sip_cli_formatter_entry *cli_formatter; static int load_module(void) { @@ -403,7 +395,21 @@ static int load_module(void) ast_sip_register_endpoint_identifier(&ip_identifier); ast_sip_register_endpoint_formatter(&endpoint_identify_formatter); - ast_sip_register_cli_formatter(&cli_identify_formatter); + + cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!cli_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n"); + return -1; + } + cli_formatter->name = "identify"; + cli_formatter->print_header = cli_print_header; + cli_formatter->print_body = cli_print_body; + cli_formatter->get_container = cli_get_container; + cli_formatter->iterate = cli_iterator; + cli_formatter->get_id = ast_sorcery_object_get_id; + cli_formatter->retrieve_by_id = cli_retrieve_by_id; + + ast_sip_register_cli_formatter(cli_formatter); return AST_MODULE_LOAD_SUCCESS; } @@ -411,14 +417,16 @@ static int load_module(void) static int reload_module(void) { ast_sorcery_reload_object(ast_sip_get_sorcery(), "identify"); + return 0; } static int unload_module(void) { - ast_sip_unregister_cli_formatter(&cli_identify_formatter); + ast_sip_unregister_cli_formatter(cli_formatter); ast_sip_unregister_endpoint_formatter(&endpoint_identify_formatter); ast_sip_unregister_endpoint_identifier(&ip_identifier); + return 0; } diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index 019ac51cd..b35e27eb8 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -1132,7 +1132,7 @@ static int ami_show_outbound_registrations(struct mansession *s, static struct ao2_container *cli_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(ast_sip_get_sorcery(), "registration", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); @@ -1141,33 +1141,36 @@ static struct ao2_container *cli_get_container(void) } s_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, - ast_sorcery_object_id_compare, NULL); + ast_sorcery_object_id_sort, 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 cli_iterator(const void *container, ao2_callback_fn callback, void *args) +static int cli_iterator(void *container, ao2_callback_fn callback, void *args) { - struct ao2_container *ao2container = (struct ao2_container *) container; + ao2_callback(container, OBJ_NODATA, callback, args); - ao2_callback(ao2container, OBJ_NODATA, callback, args); return 0; } +static void *cli_retrieve_by_id(const char *id) +{ + return ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "registration", id); +} + static int cli_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, " \n"); @@ -1182,9 +1185,7 @@ static int cli_print_body(void *obj, void *arg, int flags) const char *id = ast_sorcery_object_get_id(registration); #define REGISTRATION_URI_FIELD_LEN 53 - if (!context->output_buffer) { - return -1; - } + ast_assert(context->output_buffer != NULL); ast_str_append(&context->output_buffer, 0, " %-s/%-*.*s %-16s %-16s\n", id, @@ -1205,15 +1206,6 @@ static int cli_print_body(void *obj, void *arg, int flags) return 0; } -static struct ast_sip_cli_formatter_entry cli_formatter = { - .name = "registration", - .print_header = cli_print_header, - .print_body = cli_print_body, - .get_container = cli_get_container, - .iterator = cli_iterator, - .comparator = ast_sorcery_object_id_compare, -}; - /* * A function pointer to callback needs to be within the * module in order to avoid problems with an undefined @@ -1240,6 +1232,8 @@ static struct ast_cli_entry cli_outbound_registration[] = { " Show the configured PJSIP Registration\n"), }; +static struct ast_sip_cli_formatter_entry *cli_formatter; + static int load_module(void) { ast_sorcery_apply_default(ast_sip_get_sorcery(), "registration", "config", "pjsip.conf,criteria=type=registration"); @@ -1264,10 +1258,24 @@ static int load_module(void) ast_sorcery_reload_object(ast_sip_get_sorcery(), "registration"); sip_outbound_registration_perform_all(); - ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration)); ast_manager_register_xml("PJSIPUnregister", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_unregister); ast_manager_register_xml("PJSIPShowRegistrationsOutbound", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING,ami_show_outbound_registrations); - ast_sip_register_cli_formatter(&cli_formatter); + + cli_formatter = ao2_alloc(sizeof(struct ast_sip_cli_formatter_entry), NULL); + if (!cli_formatter) { + ast_log(LOG_ERROR, "Unable to allocate memory for cli formatter\n"); + return -1; + } + cli_formatter->name = "registration"; + cli_formatter->print_header = cli_print_header; + cli_formatter->print_body = cli_print_body; + cli_formatter->get_container = cli_get_container; + cli_formatter->iterate = cli_iterator; + cli_formatter->get_id = ast_sorcery_object_get_id; + cli_formatter->retrieve_by_id = cli_retrieve_by_id; + + ast_sip_register_cli_formatter(cli_formatter); + ast_cli_register_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration)); return AST_MODULE_LOAD_SUCCESS; } @@ -1281,10 +1289,11 @@ static int reload_module(void) static int unload_module(void) { - ast_sip_unregister_cli_formatter(&cli_formatter); ast_cli_unregister_multiple(cli_outbound_registration, ARRAY_LEN(cli_outbound_registration)); + ast_sip_unregister_cli_formatter(cli_formatter); ast_manager_unregister("PJSIPShowRegistrationsOutbound"); ast_manager_unregister("PJSIPUnregister"); + return 0; } -- cgit v1.2.3