diff options
author | Matthew Jordan <mjordan@digium.com> | 2013-12-20 21:32:13 +0000 |
---|---|---|
committer | Matthew Jordan <mjordan@digium.com> | 2013-12-20 21:32:13 +0000 |
commit | b172d369c4057cddad18c0d6b1100233c07ebbd7 (patch) | |
tree | 0665c20e48161773916473a951bac27315d26d2b /res/res_pjsip/location.c | |
parent | a0c288bb23164c6ff91019172980c8aff6fd8c8d (diff) |
res_pjsip: Add PJSIP CLI commands
Implements the following cli commands:
pjsip list aors
pjsip list auths
pjsip list channels
pjsip list contacts
pjsip list endpoints
pjsip show aor(s)
pjsip show auth(s)
pjsip show channels
pjsip show endpoint(s)
Also...
Minor modifications made to the AMI command implementations to facilitate
reuse.
New function ast_variable_list_sort added to config.c and config.h to implement
variable list sorting.
(issue ASTERISK-22610)
patches:
pjsip_cli_v2.patch uploaded by george.joseph (License 6322)
........
Merged revisions 404480 from http://svn.asterisk.org/svn/asterisk/branches/12
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@404507 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip/location.c')
-rw-r--r-- | res/res_pjsip/location.c | 245 |
1 files changed, 228 insertions, 17 deletions
diff --git a/res/res_pjsip/location.c b/res/res_pjsip/location.c index 52f69cfd8..3bd4dea10 100644 --- a/res/res_pjsip/location.c +++ b/res/res_pjsip/location.c @@ -25,6 +25,7 @@ #include "asterisk/astobj2.h" #include "asterisk/sorcery.h" #include "include/res_pjsip_private.h" +#include "asterisk/res_pjsip_cli.h" /*! \brief Destructor for AOR */ static void aor_destroy(void *obj) @@ -284,12 +285,37 @@ int ast_sip_for_each_aor(const char *aors, ao2_callback_fn on_aor, void *arg) return 0; } -int ast_sip_for_each_contact(const struct ast_sip_aor *aor, - on_contact_t on_contact, void *arg) +static void destroy_contact_pair(void *obj) +{ + struct ast_sip_aor_contact_pair *pair = obj; + ao2_cleanup(pair->aor); + ao2_cleanup(pair->contact); +} + +static struct ast_sip_aor_contact_pair *create_contact_pair( + struct ast_sip_aor *aor, struct ast_sip_contact *contact) +{ + struct ast_sip_aor_contact_pair *pair = ao2_alloc( + sizeof(*pair), destroy_contact_pair); + + if (!pair) { + return NULL; + } + + pair->aor = aor; + pair->contact = contact; + + ao2_ref(pair->aor, +1); + ao2_ref(pair->contact, +1); + + return pair; +} + +int ast_sip_for_each_contact(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; - int num; struct ao2_iterator i; if (!on_contact || @@ -297,13 +323,13 @@ int ast_sip_for_each_contact(const struct ast_sip_aor *aor, return 0; } - num = ao2_container_count(contacts); i = ao2_iterator_init(contacts, 0); while ((contact = ao2_iterator_next(&i))) { - int res = on_contact(aor, contact, --num == 0, arg); + int res; + RAII_VAR(struct ast_sip_aor_contact_pair *, + acp, create_contact_pair(aor, contact), ao2_cleanup); - ao2_ref(contact, -1); - if (res) { + if (!acp || (res = on_contact(acp, arg, 0))) { ao2_iterator_destroy(&i); return -1; } @@ -312,18 +338,13 @@ int ast_sip_for_each_contact(const struct ast_sip_aor *aor, return 0; } -int ast_sip_contact_to_str(const struct ast_sip_aor *aor, - const struct ast_sip_contact *contact, - int last, void *arg) +int ast_sip_contact_to_str(void *object, void *arg, int flags) { + struct ast_sip_aor_contact_pair *acp = object; struct ast_str **buf = arg; - ast_str_append(buf, 0, "%s/%s", - ast_sorcery_object_get_id(aor), contact->uri); - - if (!last) { - ast_str_append(buf, 0, ","); - } + ast_str_append(buf, 0, "%s/%s,", + ast_sorcery_object_get_id(acp->aor), acp->contact->uri); return 0; } @@ -335,7 +356,7 @@ static int sip_aor_to_ami(const struct ast_sip_aor *aor, struct ast_str **buf) static int format_ami_aor_handler(void *obj, void *arg, int flags) { - const struct ast_sip_aor *aor = obj; + struct ast_sip_aor *aor = obj; struct ast_sip_ami *ami = arg; const struct ast_sip_endpoint *endpoint = ami->arg; RAII_VAR(struct ast_str *, buf, @@ -352,6 +373,7 @@ static int format_ami_aor_handler(void *obj, void *arg, int flags) sip_aor_to_ami(aor, &buf); ast_str_append(&buf, 0, "Contacts: "); ast_sip_for_each_contact(aor, ast_sip_contact_to_str, &buf); + ast_str_truncate(buf, -1); ast_str_append(&buf, 0, "\r\n"); num = ao2_container_count(contacts); @@ -377,6 +399,193 @@ struct ast_sip_endpoint_formatter endpoint_aor_formatter = { .format_ami = format_ami_endpoint_aor }; +static int populate_contact_container(void *obj, void *arg, int flags) +{ + struct ast_sip_aor_contact_pair *acp = obj; + struct ao2_container *container = arg; + ao2_link_flags(container, acp, OBJ_NOLOCK); + return 0; +} + +static int gather_aor_channels(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; +} + +static struct ao2_container *cli_get_contact_container(struct ast_sorcery *sip_sorcery) +{ + 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; + + parent_container = ast_sorcery_retrieve_by_fields(sip_sorcery, "aor", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + if (!parent_container) { + return NULL; + } + + 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; + } + + ao2_container_dup(s_parent_container, parent_container, OBJ_ORDER_ASCENDING); + + child_container = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, 0, NULL, NULL); + if (!child_container) { + return NULL; + } + + ao2_callback(s_parent_container, OBJ_NODATA, gather_aor_channels, child_container); + + return child_container; +} + + +static int cli_print_contact_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_str_append(&context->output_buffer, 0, + "%*s: <Aor/ContactUri%*.*s> <Status....> <RTT(ms)..>\n", + indent, "Contact", filler, filler, CLI_HEADER_FILLER); + + return 0; +} + +static int cli_print_contact_body(void *obj, void *arg, int flags) +{ + struct ast_sip_aor_contact_pair *acp = obj; + struct ast_sip_cli_context *context = arg; + char *print_name = NULL; + int print_name_len; + int indent; + int flexwidth; + + RAII_VAR(struct ast_sip_contact_status *, status, + ast_sorcery_retrieve_by_id( ast_sip_get_sorcery(), CONTACT_STATUS, ast_sorcery_object_get_id(acp->contact)), + ao2_cleanup); + + if (!context->output_buffer) { + return -1; + } + + print_name_len = strlen(ast_sorcery_object_get_id(acp->aor)) + + strlen(acp->contact->uri) + 2; + if (!(print_name = alloca(print_name_len))) { + return -1; + } + snprintf(print_name, print_name_len, "%s/%s", + ast_sorcery_object_get_id(acp->aor), acp->contact->uri); + + 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 %11.3f\n", + indent, + "Contact", + flexwidth, flexwidth, + print_name, + (status ? (status->status == AVAILABLE ? "Avail" : "Unavail") : "Unknown"), + (status ? ((long long) status->rtt) / 1000.0 : NAN)); + + return 0; +} + +static struct ao2_container *cli_get_aor_container(struct ast_sorcery *sip_sorcery) +{ + return ast_sorcery_retrieve_by_fields(sip_sorcery, "aor", + AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); +} + +static int cli_print_aor_header(void *obj, void *arg, int flags) +{ + struct ast_sip_cli_context *context = arg; + struct ast_sip_cli_formatter_entry *formatter_entry; + + int indent = CLI_INDENT_TO_SPACES(context->indent_level); + int filler = CLI_LAST_TABSTOP - indent - 7; + + if (!context->output_buffer) { + return -1; + } + ast_str_append(&context->output_buffer, 0, + "%*s: <Aor%*.*s> <MaxContact>\n", + indent, "Aor", filler, filler, CLI_HEADER_FILLER); + + if (context->recurse) { + context->indent_level++; + formatter_entry = ast_sip_lookup_cli_formatter("contact"); + 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) +{ + struct ast_sip_aor *aor = obj; + struct ast_sip_cli_context *context = arg; + struct ast_sip_cli_formatter_entry *formatter_entry; + int indent; + int flexwidth; + + if (!context->output_buffer) { + return -1; + } + + context->current_aor = aor; + + indent = CLI_INDENT_TO_SPACES(context->indent_level); + flexwidth = CLI_LAST_TABSTOP - indent - 12; + + ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %12d\n", + indent, + "Aor", + flexwidth, flexwidth, + ast_sorcery_object_get_id(aor), aor->max_contacts); + + if (context->recurse) { + context->indent_level++; + formatter_entry = ast_sip_lookup_cli_formatter("contact"); + if (formatter_entry) { + ast_sip_for_each_contact(aor, formatter_entry->print_body, context); + } + context->indent_level--; + } + + if (context->show_details || (context->show_details_only_level_0 && context->indent_level == 0)) { + ast_str_append(&context->output_buffer, 0, "\n"); + ast_sip_cli_print_sorcery_objectset(aor, context, 0); + } + + 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, +}; + +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, +}; + /*! \brief Initialize sorcery with location support */ int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery) { @@ -408,6 +617,8 @@ int ast_sip_initialize_sorcery_location(struct ast_sorcery *sorcery) ast_sorcery_object_field_register(sorcery, "aor", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct ast_sip_aor, outbound_proxy)); ast_sip_register_endpoint_formatter(&endpoint_aor_formatter); + ast_sip_register_cli_formatter(&cli_contact_formatter); + ast_sip_register_cli_formatter(&cli_aor_formatter); return 0; } |