<p>sungtae kim has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/7960">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: Add AMI action 'PJSIPShowContacts'<br><br>Add an AMI action which provides information on all<br>configured Contacts.<br><br>ASTERISK-27581<br><br>Change-Id: I2eed42c74bbc725fad26b8b33b1a5b3161950c73<br>---<br>M res/res_pjsip.c<br>M res/res_pjsip/pjsip_options.c<br>2 files changed, 188 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/60/7960/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">diff --git a/res/res_pjsip.c b/res/res_pjsip.c<br>index 0311dfd..aad47af 100644<br>--- a/res/res_pjsip.c<br>+++ b/res/res_pjsip.c<br>@@ -2362,6 +2362,79 @@<br> </syntax><br> </managerEventInstance><br> </managerEvent><br>+ <managerEvent language="en_US" name="ContactList"><br>+ <managerEventInstance class="EVENT_FLAG_COMMAND"><br>+ <synopsis>Provide details about a contact section.</synopsis><br>+ <syntax><br>+ <parameter name="ObjectType"><br>+ <para>The object's type. This will always be 'contact'.</para><br>+ </parameter><br>+ <parameter name="ObjectName"><br>+ <para>The name of this object.</para><br>+ </parameter><br>+ <parameter name="ViaAddr"><br>+ <para>IP address of the last Via header in REGISTER request.<br>+ Will only appear in the event if available.</para><br>+ </parameter><br>+ <parameter name="ViaPort"><br>+ <para>Port number of the last Via header in REGISTER request.<br>+ Will only appear in the event if available.</para><br>+ </parameter><br>+ <parameter name="QualifyTimeout"><br>+ <para>The elapsed time in decimal seconds after which an OPTIONS<br>+ message is sent before the contact is considered unavailable.</para><br>+ </parameter><br>+ <parameter name="CallId"><br>+ <para>Content of the Call-ID header in REGISTER request.<br>+ Will only appear in the event if available.</para><br>+ </parameter><br>+ <parameter name="RegServer"><br>+ <para>Asterisk Server name.</para><br>+ </parameter><br>+ <parameter name="PruneOnBoot"><br>+ <para>If true delete the contact on Asterisk restart/boot.</para><br>+ </parameter><br>+ <parameter name="Path"><br>+ <para>The Path header received on the REGISTER.</para><br>+ </parameter><br>+ <parameter name="Endpoint"><br>+ <para>The name of the endpoint associated with this information.</para><br>+ </parameter><br>+ <parameter name="AuthenticateQualify"><br>+ <para>A boolean indicating whether a qualify should be authenticated.</para><br>+ </parameter><br>+ <parameter name="Uri"><br>+ <para>This contact's URI.</para><br>+ </parameter><br>+ <parameter name="QualifyFrequency"><br>+ <para>The interval in seconds at which the contact will be qualified.</para><br>+ </parameter><br>+ <parameter name="UserAgent"><br>+ <para>Content of the User-Agent header in REGISTER request</para><br>+ </parameter><br>+ <parameter name="ExpirationTime"><br>+ <para>Absolute time that this contact is no longer valid after</para><br>+ </parameter><br>+ <parameter name="OutboundProxy"><br>+ <para>The contact's outbound proxy.</para><br>+ </parameter><br>+ <parameter name="ID"><br>+ <para>The sorcery ID of the contact.</para><br>+ </parameter><br>+ <parameter name="Status"><br>+ <para>This contact's status.</para><br>+ <enumlist><br>+ <enum name="Reachable"/><br>+ <enum name="Unreachable"/><br>+ <enum name="NonQualified"/><br>+ </enumlist><br>+ </parameter><br>+ <parameter name="RoundtripUsec"><br>+ <para>The round trip time in microseconds.</para><br>+ </parameter><br>+ </syntax><br>+ </managerEventInstance><br>+ </managerEvent><br> <managerEvent language="en_US" name="ContactStatusDetail"><br> <managerEventInstance class="EVENT_FLAG_COMMAND"><br> <synopsis>Provide details about a contact's status.</synopsis><br>@@ -2574,6 +2647,33 @@<br> </managerEvent><br> </responses><br> </manager><br>+ <manager name="PJSIPShowContacts" language="en_US"><br>+ <synopsis><br>+ Lists PJSIP Contacts.<br>+ </synopsis><br>+ <syntax /><br>+ <description><br>+ <para>Provides a listing of all Contacts. For each Contact an <literal>ContactList<br>+ </literal> event is raised that contains relevant attributes and status information.<br>+ Once all contacts have been listed an <literal>ContactListComplete</literal> event<br>+ is issued.<br>+ </para><br>+ </description><br>+ <responses><br>+ <list-elements><br>+ <xi:include xpointer="xpointer(/docs/managerEvent[@name='ContactList'])" /><br>+ </list-elements><br>+ <managerEvent language="en_US" name="ContactListComplete"><br>+ <managerEventInstance class="EVENT_FLAG_COMMAND"><br>+ <synopsis>Provide final information about a contact list.</synopsis><br>+ <syntax><br>+ <parameter name="EventList"/><br>+ <parameter name="ListItems"/><br>+ </syntax><br>+ </managerEventInstance><br>+ </managerEvent><br>+ </responses><br>+ </manager><br> <br> ***/<br> <br>diff --git a/res/res_pjsip/pjsip_options.c b/res/res_pjsip/pjsip_options.c<br>index 9d7402b..56a80af 100644<br>--- a/res/res_pjsip/pjsip_options.c<br>+++ b/res/res_pjsip/pjsip_options.c<br>@@ -929,6 +929,90 @@<br> return 0;<br> }<br> <br>+static struct ao2_container *cli_get_contacts(void)<br>+{<br>+ struct ao2_container *contacts;<br>+<br>+ contacts = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "contact",<br>+ AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);<br>+<br>+ return contacts;<br>+}<br>+<br>+static int sip_contact_to_ami(const struct ast_sip_contact *contact,<br>+ struct ast_str **buf)<br>+{<br>+ return ast_sip_sorcery_object_to_ami(contact, buf);<br>+}<br>+<br>+static int format_ami_contactlist_handler(void *obj, void *arg, int flags)<br>+{<br>+ struct ast_sip_contact *contact = obj;<br>+ struct ast_sip_ami *ami = arg;<br>+ struct ast_str *buf;<br>+ struct ast_sip_contact_status *status;<br>+<br>+ buf = ast_sip_create_ami_event("ContactList", ami);<br>+<br>+ if (!buf) {<br>+ return CMP_STOP;<br>+ }<br>+<br>+ if (sip_contact_to_ami(contact, &buf)) {<br>+ return CMP_STOP;<br>+ }<br>+<br>+ /* Add extra info */<br>+ ast_str_append(&buf, 0, "ID: %s\r\n", ast_sorcery_object_get_id(contact));<br>+ status = ast_sorcery_retrieve_by_id(<br>+ ast_sip_get_sorcery(), CONTACT_STATUS,<br>+ ast_sorcery_object_get_id(contact));<br>+ ast_str_append(&buf, 0, "Status: %s\r\n", ast_sip_get_contact_status_label(status ? status->status : UNKNOWN));<br>+ if (!status || status->status == UNKNOWN) {<br>+ ast_str_append(&buf, 0, "RoundtripUsec: N/A\r\n");<br>+ } else {<br>+ ast_str_append(&buf, 0, "RoundtripUsec: %" PRId64 "\r\n", status->rtt);<br>+ }<br>+<br>+ astman_append(ami->s, "%s\r\n", ast_str_buffer(buf));<br>+<br>+ ami->count++;<br>+<br>+ ast_free(buf);<br>+<br>+ return 0;<br>+}<br>+<br>+static int ami_show_contacts(struct mansession *s, const struct message *m)<br>+{<br>+ struct ast_sip_ami ami = { .s = s, .m = m, .action_id = astman_get_header(m, "ActionID"), };<br>+ struct ao2_container *contacts;<br>+<br>+ contacts = cli_get_contacts();<br>+ if (!contacts) {<br>+ astman_send_error(s, m, "Could not get Contacts\n");<br>+ return 0;<br>+ }<br>+<br>+ if (!ao2_container_count(contacts)) {<br>+ astman_send_error(s, m, "No Contacts found\n");<br>+ ao2_ref(contacts, -1);<br>+ return 0;<br>+ }<br>+<br>+ astman_send_listack(s, m, "A listing of Contacts follows, presented as ContactList events",<br>+ "start");<br>+<br>+ ao2_callback(contacts, OBJ_NODATA, format_ami_contactlist_handler, &ami);<br>+<br>+ astman_send_list_complete_start(s, m, "ContactListComplete", ami.count);<br>+ astman_send_list_complete_end(s);<br>+<br>+ ao2_ref(contacts, -1);<br>+<br>+ return 0;<br>+}<br>+<br> static int ami_sip_qualify(struct mansession *s, const struct message *m)<br> {<br> const char *endpoint_name = astman_get_header(m, "Endpoint");<br>@@ -1481,6 +1565,10 @@<br> ast_manager_register_xml("PJSIPQualify", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, ami_sip_qualify);<br> ast_cli_register_multiple(cli_options, ARRAY_LEN(cli_options));<br> <br>+ if (ast_manager_register_xml("PJSIPShowContacts", EVENT_FLAG_SYSTEM, ami_show_contacts)) {<br>+ return -1;<br>+ }<br>+<br> update_all_unqualified_endpoints();<br> qualify_and_schedule_all();<br> <br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/7960">change 7960</a>. To unsubscribe, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/7960"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I2eed42c74bbc725fad26b8b33b1a5b3161950c73 </div>
<div style="display:none"> Gerrit-Change-Number: 7960 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: sungtae kim <pchero21@gmail.com> </div>