From ebc67d305398caf8738dcc4b7c88b9e40fa3d58e Mon Sep 17 00:00:00 2001 From: George Joseph Date: Tue, 6 Dec 2016 13:54:25 -0700 Subject: [PATCH] res_pjsip_registrar: AMI Add RegistrationInboundContactStatuses command The PJSIPShowRegistrationsInbound AMI command was just dumping out all AORs which was pretty useless and resource heavy since it had to get all endpoints, then all aors for each endpoint, then all contacts for each aor. PJSIPShowRegistrationInboundContactStatuses sends ContactStatusDetail events which meets the intended purpose of the other command and has significantly less overhead. Also, some additional fields that were added to Contact since the original creation of the ContactStatusDetail event have been added to the end of the event. For compatibility purposes, PJSIPShowRegistrationsInbound is left intact. ASTERISK-26644 #close Change-Id: I326f12c9ecb52bf37ba03f0748749de4da01490a --- CHANGES | 13 +++++++ include/asterisk/res_pjsip.h | 10 +++++ res/res_pjsip.c | 25 ++++++++++++- res/res_pjsip/pjsip_options.c | 14 +++++-- res/res_pjsip_registrar.c | 70 ++++++++++++++++++++++++++++++++--- 5 files changed, 122 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index 63f079c692..f54dccd989 100644 --- a/CHANGES +++ b/CHANGES @@ -31,6 +31,19 @@ res_pjsip_outbound_registration for internal state transitions that don't change the reported public status state. +res_pjsip_registrar +------------------ + * The PJSIPShowRegistrationInboundContactStatuses AMI command has been added + to return ContactStatusDetail events as opposed to + PJSIPShowRegistrationsInbound which just a dumps every defined AOR. + +res_pjsip +------------------ + * Six existing contact fields have been added to the end of the + ContactStatusDetail AMI event: + ID, AuthenticateQualify, OutboundProxy, Path, QualifyFrequency and + QualifyTimeout. Existing fields have not been disturbed. + ------------------------------------------------------------------------------ --- Functionality changes from Asterisk 13.12.0 to Asterisk 13.13.0 ---------- ------------------------------------------------------------------------------ diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h index 4ad6607274..c97e4b5343 100644 --- a/include/asterisk/res_pjsip.h +++ b/include/asterisk/res_pjsip.h @@ -2320,6 +2320,16 @@ int ast_sip_sorcery_object_to_ami(const void *obj, struct ast_str **buf); int ast_sip_format_endpoint_ami(struct ast_sip_endpoint *endpoint, struct ast_sip_ami *ami, int *count); +/*! + * \brief Formats the contact and sends over AMI. + * + * \param obj a pointer an ast_sip_contact_wrapper structure + * \param arg a pointer to an ast_sip_ami structure + * \param flags ignored + * \retval 0 Success, otherwise non-zero on error + */ +int ast_sip_format_contact_ami(void *obj, void *arg, int flags); + /*! * \brief Format auth details for AMI. * diff --git a/res/res_pjsip.c b/res/res_pjsip.c index d83bd06a55..227a903cdc 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2090,10 +2090,31 @@ Absolute time that this contact is no longer valid after - IP address:port of the last Via header in REGISTER request + IP address:port of the last Via header in REGISTER request. + Will only appear in the event if available. - Content of the Call-ID header in REGISTER request + Content of the Call-ID header in REGISTER request. + Will only appear in the event if available. + + + The sorcery ID of the contact. + + + A boolean indicating whether a qualify should be authenticated. + + + The contact's outbound proxy. + + + The Path header received on the REGISTER. + + + The interval in seconds at which the contact will be qualified. + + + The elapsed time in decimal seconds after which an OPTIONS + message is sent before the contact is considered unavailable. diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c index 8c8836fd90..698203fac3 100644 --- a/res/res_pjsip/pjsip_options.c +++ b/res/res_pjsip/pjsip_options.c @@ -1227,7 +1227,7 @@ static void qualify_and_schedule_all(void) } -static int format_contact_status(void *obj, void *arg, int flags) +int ast_sip_format_contact_ami(void *obj, void *arg, int flags) { struct ast_sip_contact_wrapper *wrapper = obj; struct ast_sip_contact *contact = wrapper->contact; @@ -1266,7 +1266,15 @@ static int format_contact_status(void *obj, void *arg, int flags) ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt); } ast_str_append(&buf, 0, "EndpointName: %s\r\n", - ast_sorcery_object_get_id(endpoint)); + endpoint ? ast_sorcery_object_get_id(endpoint) : S_OR(contact->endpoint_name, "")); + + ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact)); + ast_str_append(&buf, 0, "AuthenticateQualify: %d\r\n", contact->authenticate_qualify); + ast_str_append(&buf, 0, "OutboundProxy: %s\r\n", contact->outbound_proxy); + ast_str_append(&buf, 0, "Path: %s\r\n", contact->path); + ast_str_append(&buf, 0, "QualifyFrequency: %u\r\n", contact->qualify_frequency); + ast_str_append(&buf, 0, "QualifyTimeout: %.3f\r\n", contact->qualify_timeout); + astman_append(ami->s, "%s\r\n", ast_str_buffer(buf)); ami->count++; @@ -1279,7 +1287,7 @@ static int format_contact_status_for_aor(void *obj, void *arg, int flags) { struct ast_sip_aor *aor = obj; - return ast_sip_for_each_contact(aor, format_contact_status, arg); + return ast_sip_for_each_contact(aor, ast_sip_format_contact_ami, arg); } static int format_ami_contact_status(const struct ast_sip_endpoint *endpoint, diff --git a/res/res_pjsip_registrar.c b/res/res_pjsip_registrar.c index a13f8f86b6..d54bffa0c7 100644 --- a/res/res_pjsip_registrar.c +++ b/res/res_pjsip_registrar.c @@ -46,11 +46,32 @@ - In response InboundRegistrationDetail events showing configuration and status - information are raised for each inbound registration object. As well as AuthDetail - events for each associated auth object. Once all events are completed an - InboundRegistrationDetailComplete is issued. - + In response, InboundRegistrationDetail events showing configuration + and status information are raised for all contacts, static or dynamic. Once all events + are completed an InboundRegistrationDetailComplete is issued. + + + This command just dumps all coonfigured AORs with contacts, even if the contact + is a permanent one. To really get just inbound registrations, use + PJSIPShowRegistrationInboundContactStatuses. + + + + + PJSIPShowRegistrationInboundContactStatuses + + + + + Lists ContactStatuses for PJSIP inbound registrations. + + + + + In response, ContactStatusDetail events showing status information + are raised for each inbound registration (dynamic contact) object. Once all events + are completed a ContactStatusDetailComplete event is issued. + ***/ @@ -793,6 +814,42 @@ static int ami_show_registrations(struct mansession *s, const struct message *m) return 0; } +static int ami_show_registration_contact_statuses(struct mansession *s, const struct message *m) +{ + int count = 0; + struct ast_sip_ami ami = { .s = s, .m = m, .arg = NULL, .action_id = astman_get_header(m, "ActionID"), }; + struct ao2_container *contacts = ast_sorcery_retrieve_by_fields( + ast_sip_get_sorcery(), "contact", AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL); + struct ao2_iterator i; + struct ast_sip_contact *contact; + + astman_send_listack(s, m, "Following are ContactStatusEvents for each Inbound " + "registration", "start"); + + if (contacts) { + i = ao2_iterator_init(contacts, 0); + while ((contact = ao2_iterator_next(&i))) { + struct ast_sip_contact_wrapper wrapper; + + wrapper.aor_id = (char *)contact->aor; + wrapper.contact = contact; + wrapper.contact_id = (char *)ast_sorcery_object_get_id(contact); + + ast_sip_format_contact_ami(&wrapper, &ami, 0); + count++; + + ao2_ref(contact, -1); + } + ao2_iterator_destroy(&i); + ao2_ref(contacts, -1); + } + + astman_send_list_complete_start(s, m, "ContactStatusDetailComplete", count); + astman_send_list_complete_end(s); + return 0; +} + +#define AMI_SHOW_REGISTRATION_CONTACT_STATUSES "PJSIPShowRegistrationInboundContactStatuses" #define AMI_SHOW_REGISTRATIONS "PJSIPShowRegistrationsInbound" static pjsip_module registrar_module = { @@ -825,6 +882,8 @@ static int load_module(void) ast_manager_register_xml(AMI_SHOW_REGISTRATIONS, EVENT_FLAG_SYSTEM, ami_show_registrations); + ast_manager_register_xml(AMI_SHOW_REGISTRATION_CONTACT_STATUSES, EVENT_FLAG_SYSTEM, + ami_show_registration_contact_statuses); return AST_MODULE_LOAD_SUCCESS; } @@ -832,6 +891,7 @@ static int load_module(void) static int unload_module(void) { ast_manager_unregister(AMI_SHOW_REGISTRATIONS); + ast_manager_unregister(AMI_SHOW_REGISTRATION_CONTACT_STATUSES); ast_sip_unregister_service(®istrar_module); return 0; }