<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15821">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip_dialog_info_body_generator: Add LOCAL/REMOTE tags in dialog-info+xml<br><br>RFC 4235 Section 4.1.6 describes XML elements that should be<br>sent to subscribed endpoints to identify the local and remote<br>participants in the dialog.<br><br>This patch adds this functionality to PJSIP by iterating through the<br>ringing channels causing the NOTIFY, and inserts the channel info<br>into the dialog so that information is properly passed to the endpoint<br>in dialog-info+xml.<br><br>ASTERISK-24601<br>Patch submitted: Joshua Elson<br>Modified by: Joseph Nadiv and Sean Bright<br>Tested by: Joseph Nadiv<br><br>Change-Id: I20c5cf5b45f34d7179df6573c5abf863eb72964b<br>---<br>A doc/CHANGES-staging/res_pjsip_dialog_info_body_generator.txt<br>M res/res_pjsip_dialog_info_body_generator.c<br>2 files changed, 123 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/res_pjsip_dialog_info_body_generator.txt b/doc/CHANGES-staging/res_pjsip_dialog_info_body_generator.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..0dd0a57</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_pjsip_dialog_info_body_generator.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_pjsip_dialog_info_body_generator</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+PJSIP now supports RFC 4235 Section 4.1.6 dialog-info+xml local and</span><br><span style="color: hsl(120, 100%, 40%);">+remote elements by iterating through ringing channels and inserting</span><br><span style="color: hsl(120, 100%, 40%);">+that info into NOTIFY packet sent to the endpoint.</span><br><span>diff --git a/res/res_pjsip_dialog_info_body_generator.c b/res/res_pjsip_dialog_info_body_generator.c</span><br><span>index 3934a8a..88aa6c2 100644</span><br><span>--- a/res/res_pjsip_dialog_info_body_generator.c</span><br><span>+++ b/res/res_pjsip_dialog_info_body_generator.c</span><br><span>@@ -30,6 +30,7 @@</span><br><span> #include <pjlib.h></span><br><span> </span><br><span> #include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/callerid.h"</span><br><span> #include "asterisk/res_pjsip.h"</span><br><span> #include "asterisk/res_pjsip_pubsub.h"</span><br><span> #include "asterisk/res_pjsip_presence_xml.h"</span><br><span>@@ -60,6 +61,35 @@</span><br><span>         return ast_sip_presence_xml_create_node(state_data->pool, NULL, "dialog-info");</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Find the channel that is causing the RINGING update, ref'd</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel *find_ringing_channel(struct ao2_container *device_state_info)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ao2_iterator citer;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_device_state_info *device_state;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel *c = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct timeval tv = {0,};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* iterate ringing devices and get the oldest of all causing channels */</span><br><span style="color: hsl(120, 100%, 40%);">+      citer = ao2_iterator_init(device_state_info, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      for (; (device_state = ao2_iterator_next(&citer)); ao2_ref(device_state, -1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!device_state->causing_channel || (device_state->device_state != AST_DEVICE_RINGING &&</span><br><span style="color: hsl(120, 100%, 40%);">+                              device_state->device_state != AST_DEVICE_RINGINUSE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     continue;</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_channel_lock(device_state->causing_channel);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ast_tvzero(tv) || ast_tvcmp(ast_channel_creationtime(device_state->causing_channel), tv) < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     c = device_state->causing_channel;</span><br><span style="color: hsl(120, 100%, 40%);">+                 tv = ast_channel_creationtime(c);</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_channel_unlock(device_state->causing_channel);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_iterator_destroy(&citer);</span><br><span style="color: hsl(120, 100%, 40%);">+     return c ? ast_channel_ref(c) : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int dialog_info_generate_body_content(void *body, void *data)</span><br><span> {</span><br><span>      pj_xml_node *dialog_info = body, *dialog, *state;</span><br><span>@@ -67,13 +97,14 @@</span><br><span>      struct dialog_info_xml_state *datastore_state;</span><br><span>       struct ast_sip_exten_state_data *state_data = data;</span><br><span>  char *local = ast_strdupa(state_data->local), *stripped, *statestring = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+      char *remote = ast_strdupa(state_data->remote);</span><br><span>   char *pidfstate = NULL, *pidfnote = NULL;</span><br><span>    enum ast_sip_pidf_state local_state;</span><br><span>         char version_str[32], sanitized[PJSIP_MAX_URL_SIZE];</span><br><span>         struct ast_sip_endpoint *endpoint = NULL;</span><br><span>    unsigned int notify_early_inuse_ringing = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        if (!local || !state_data->datastores) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!local || !remote || !state_data->datastores) {</span><br><span>               return -1;</span><br><span>   }</span><br><span> </span><br><span>@@ -133,7 +164,93 @@</span><br><span>         dialog = ast_sip_presence_xml_create_node(state_data->pool, dialog_info, "dialog");</span><br><span>     ast_sip_presence_xml_create_attr(state_data->pool, dialog, "id", state_data->exten);</span><br><span>         if (!ast_strlen_zero(statestring) && !strcmp(statestring, "early")) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct ast_channel *callee = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+            char local_target[PJSIP_MAX_URL_SIZE + 32] = "";</span><br><span style="color: hsl(120, 100%, 40%);">+            char *local_cid_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          pj_xml_node *local_node, *local_identity_node, *local_target_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>                 ast_sip_presence_xml_create_attr(state_data->pool, dialog, "direction", "recipient");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                if (state_data->device_state_info) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       callee = find_ringing_channel(state_data->device_state_info);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (callee) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 static char *anonymous = "anonymous";</span><br><span style="color: hsl(120, 100%, 40%);">+                       static char *invalid = "anonymous.invalid";</span><br><span style="color: hsl(120, 100%, 40%);">+                 char *remote_cid_name;</span><br><span style="color: hsl(120, 100%, 40%);">+                        char *remote_connected_num;</span><br><span style="color: hsl(120, 100%, 40%);">+                   int remote_connected_num_restricted;</span><br><span style="color: hsl(120, 100%, 40%);">+                  char *local_caller_num;</span><br><span style="color: hsl(120, 100%, 40%);">+                       pjsip_dialog *dlg = ast_sip_subscription_get_dialog(state_data->sub);</span><br><span style="color: hsl(120, 100%, 40%);">+                      pjsip_sip_uri *dlg_remote_fromhdr = pjsip_uri_get_uri(dlg->local.info->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                    char remote_target[PJSIP_MAX_URL_SIZE + 32];</span><br><span style="color: hsl(120, 100%, 40%);">+                  char dlg_remote_uri[PJSIP_MAX_URL_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+                      char *from_domain_stripped;</span><br><span style="color: hsl(120, 100%, 40%);">+                   char from_domain_sanitized[PJSIP_MAX_URL_SIZE];</span><br><span style="color: hsl(120, 100%, 40%);">+                       pj_xml_node *remote_node, *remote_identity_node, *remote_target_node;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* We use the local dialog URI to determine the domain to use in the XML itself */</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_copy_pj_str(dlg_remote_uri, &dlg_remote_fromhdr->host, sizeof(dlg_remote_uri));</span><br><span style="color: hsl(120, 100%, 40%);">+                    from_domain_stripped = ast_strip_quoted(dlg_remote_uri, "<", ">");</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_sip_sanitize_xml(from_domain_stripped, from_domain_sanitized, sizeof(from_domain_sanitized));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_channel_lock(callee);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* The remote node uses the connected line information, so who is calling the</span><br><span style="color: hsl(120, 100%, 40%);">+                  * monitored endpoint.</span><br><span style="color: hsl(120, 100%, 40%);">+                         */</span><br><span style="color: hsl(120, 100%, 40%);">+                   remote_cid_name = S_COR(ast_channel_connected(callee)->id.name.valid,</span><br><span style="color: hsl(120, 100%, 40%);">+                              S_COR((ast_channel_connected(callee)->id.name.presentation &</span><br><span style="color: hsl(120, 100%, 40%);">+                                           AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED, anonymous,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      ast_channel_connected(callee)->id.name.str), "");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                      remote_connected_num_restricted = (ast_channel_connected(callee)->id.number.presentation &</span><br><span style="color: hsl(120, 100%, 40%);">+                             AST_PRES_RESTRICTION) == AST_PRES_RESTRICTED;</span><br><span style="color: hsl(120, 100%, 40%);">+                 remote_connected_num = S_COR(ast_channel_connected(callee)->id.number.valid,</span><br><span style="color: hsl(120, 100%, 40%);">+                               S_COR(remote_connected_num_restricted, anonymous,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     ast_channel_connected(callee)->id.number.str), "invalid");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     snprintf(remote_target, sizeof(remote_target), "sip:%s@%s", remote_connected_num,</span><br><span style="color: hsl(120, 100%, 40%);">+                           remote_connected_num_restricted ? invalid : from_domain_sanitized);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* The local node uses the callerid information, so what the callerid would be</span><br><span style="color: hsl(120, 100%, 40%);">+                         * if the monitored endpoint was calling.</span><br><span style="color: hsl(120, 100%, 40%);">+                      */</span><br><span style="color: hsl(120, 100%, 40%);">+                   local_cid_name = S_COR(ast_channel_caller(callee)->id.name.valid,</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_channel_caller(callee)->id.name.str, "");</span><br><span style="color: hsl(120, 100%, 40%);">+                    local_caller_num = S_COR(ast_channel_caller(callee)->id.number.valid,</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_channel_caller(callee)->id.number.str, "invalid");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 snprintf(local_target, sizeof(local_target), "sip:%s@%s", local_caller_num,</span><br><span style="color: hsl(120, 100%, 40%);">+                         from_domain_sanitized);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_channel_unlock(callee);</span><br><span style="color: hsl(120, 100%, 40%);">+                   callee = ast_channel_unref(callee);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 remote_node = ast_sip_presence_xml_create_node(state_data->pool, dialog, "remote");</span><br><span style="color: hsl(120, 100%, 40%);">+                      remote_identity_node = ast_sip_presence_xml_create_node(state_data->pool, remote_node, "identity");</span><br><span style="color: hsl(120, 100%, 40%);">+                      remote_target_node = ast_sip_presence_xml_create_node(state_data->pool, remote_node, "target");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        pj_strdup2(state_data->pool, &remote_identity_node->content, remote_target);</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (!ast_strlen_zero(remote_cid_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ast_sip_presence_xml_create_attr(state_data->pool, remote_identity_node, "display", remote_cid_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_sip_presence_xml_create_attr(state_data->pool, remote_target_node, "uri", remote_target);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (state_data->device_state_info) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       local_node = ast_sip_presence_xml_create_node(state_data->pool, dialog, "local");</span><br><span style="color: hsl(120, 100%, 40%);">+                        local_identity_node = ast_sip_presence_xml_create_node(state_data->pool, local_node, "identity");</span><br><span style="color: hsl(120, 100%, 40%);">+                        local_target_node = ast_sip_presence_xml_create_node(state_data->pool, local_node, "target");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* If a channel is not available we fall back to the sanitized local URI instead */</span><br><span style="color: hsl(120, 100%, 40%);">+                   pj_strdup2(state_data->pool, &local_identity_node->content, S_OR(local_target, sanitized));</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (!ast_strlen_zero(local_cid_name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               ast_sip_presence_xml_create_attr(state_data->pool, local_identity_node, "display", local_cid_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                      }</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_sip_presence_xml_create_attr(state_data->pool, local_target_node, "uri", S_OR(local_target, sanitized));</span><br><span style="color: hsl(120, 100%, 40%);">+             }</span><br><span>    }</span><br><span> </span><br><span>        state = ast_sip_presence_xml_create_node(state_data->pool, dialog, "state");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15821">change 15821</a>. To unsubscribe, or for help writing mail filters, 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/c/asterisk/+/15821"/><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-Change-Id: I20c5cf5b45f34d7179df6573c5abf863eb72964b </div>
<div style="display:none"> Gerrit-Change-Number: 15821 </div>
<div style="display:none"> Gerrit-PatchSet: 6 </div>
<div style="display:none"> Gerrit-Owner: Joe <ynadiv@corpit.xyz> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>