<p>George Joseph has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15806">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip_messaging: Refactor outgoing URI processing<br><br> * Implemented the new "to" parameter of the MessageSend()<br>   dialplan application.  This allows a user to specify<br>   a complete SIP "To" header separate from the Request URI.<br><br> * Completely refactored the get_outbound_endpoint() function<br>   to actually handle all the destination combinations that<br>   we advertized as supporting.<br><br> * Added lots of debugging.<br><br>ASTERISK-29404<br>Reported by Brian J. Murrell<br><br>Change-Id: I67a485196d9199916468f7f98bfb9a0b993a4cce<br>---<br>M res/res_pjsip_messaging.c<br>1 file changed, 444 insertions(+), 103 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/06/15806/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c</span><br><span>index 9287324..8a01e9c 100644</span><br><span>--- a/res/res_pjsip_messaging.c</span><br><span>+++ b/res/res_pjsip_messaging.c</span><br><span>@@ -25,15 +25,83 @@</span><br><span> </span><br><span> /*** DOCUMENTATION</span><br><span>      <info name="MessageDestinationInfo" language="en_US" tech="PJSIP"></span><br><span style="color: hsl(0, 100%, 40%);">-          <para>Specifying a prefix of <literal>pjsip:</literal> will send the</span><br><span style="color: hsl(0, 100%, 40%);">-          message as a SIP MESSAGE request.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                <para>The <literal>destination</literal> parameter is used to construct</span><br><span style="color: hsl(120, 100%, 40%);">+             the Request URI for an outgoing message.  It can be in one of the following</span><br><span style="color: hsl(120, 100%, 40%);">+           formats, all prefixed with the <literal>pjsip:</literal> message tech.</para></span><br><span style="color: hsl(120, 100%, 40%);">+               <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="endpoint"></span><br><span style="color: hsl(120, 100%, 40%);">+                                <para>Request URI comes from the endpoint's default aor and contact.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                   </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                 <enum name="endpoint/aor"></span><br><span style="color: hsl(120, 100%, 40%);">+                            <para>Request URI comes from the specific aor/contact.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                     </enum></span><br><span style="color: hsl(120, 100%, 40%);">+                 <enum name="endpoint@domain"></span><br><span style="color: hsl(120, 100%, 40%);">+                         <para>Request URI from the endpoint's default aor and contact.  The domain is discarded.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                       </enum></span><br><span style="color: hsl(120, 100%, 40%);">+         </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+             <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <para>These all use the endpoint to send the message with the specified URI:</para></span><br><span style="color: hsl(120, 100%, 40%);">+               <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="endpoint/&lt;sip[s]:host&gt;>"/></span><br><span style="color: hsl(120, 100%, 40%);">+                       <enum name="endpoint/&lt;sip[s]:user@host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="endpoint/&quot;display name&quot; &lt;sip[s]:host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                  <enum name="endpoint/&quot;display name&quot; &lt;sip[s]:user@host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                     <enum name="endpoint/sip[s]:host"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <enum name="endpoint/sip[s]:user@host"/></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="endpoint/host"/></span><br><span style="color: hsl(120, 100%, 40%);">+                  <enum name="endpoint/user@host"/></span><br><span style="color: hsl(120, 100%, 40%);">+             </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+             <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+         <para>These all use the default endpoint to send the message with the specified URI:</para></span><br><span style="color: hsl(120, 100%, 40%);">+               <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="&lt;sip[s]:host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                    <enum name="&lt;sip[s]:user@host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                       <enum name="&quot;display name&quot; &lt;sip[s]:host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <enum name="&quot;display name&quot; &lt;sip[s]:user@host&gt;"/></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="sip[s]:host"/></span><br><span style="color: hsl(120, 100%, 40%);">+                    <enum name="sip[s]:user@host"/></span><br><span style="color: hsl(120, 100%, 40%);">+               </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+             <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <para>These use the default endpoint to send the message with the specified host:</para></span><br><span style="color: hsl(120, 100%, 40%);">+          <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+                      <enum name="host"/></span><br><span style="color: hsl(120, 100%, 40%);">+                   <enum name="user@host"/></span><br><span style="color: hsl(120, 100%, 40%);">+              </enumlist></span><br><span style="color: hsl(120, 100%, 40%);">+             <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <para>In all cases URIs not already prefixed with <literal>sip:</literal> or</span><br><span style="color: hsl(120, 100%, 40%);">+                        <literal>sips:</literal> will automatically be prefixed with <literal>sip:</literal>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+            <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span>        </info></span><br><span>        <info name="MessageFromInfo" language="en_US" tech="PJSIP"></span><br><span style="color: hsl(0, 100%, 40%);">-         <para>The <literal>from</literal> parameter can be a configured endpoint</span><br><span style="color: hsl(0, 100%, 40%);">-              or in the form of "display-name" &lt;URI&gt;.</para></span><br><span style="color: hsl(120, 100%, 40%);">+          <para>The <literal>from</literal> parameter is used to specity the <literal>From:</literal></span><br><span style="color: hsl(120, 100%, 40%);">+             header in the outgoing SIP MESSAGE.  It will override the value specified in</span><br><span style="color: hsl(120, 100%, 40%);">+          MESSAGE(from) which itself will override any <literal>from</literal> value from</span><br><span style="color: hsl(120, 100%, 40%);">+           an incoming SIP MESSAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+              </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span>        </info></span><br><span>        <info name="MessageToInfo" language="en_US" tech="PJSIP"></span><br><span style="color: hsl(0, 100%, 40%);">-           <para>Ignored</para></span><br><span style="color: hsl(120, 100%, 40%);">+              <para>The <literal>to</literal> parameter is used to specity the <literal>To:</literal></span><br><span style="color: hsl(120, 100%, 40%);">+         header in the outgoing SIP MESSAGE.  It will override the value specified in</span><br><span style="color: hsl(120, 100%, 40%);">+          MESSAGE(to) which itself will override any <literal>to</literal> value from</span><br><span style="color: hsl(120, 100%, 40%);">+               an incoming SIP MESSAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+              </para></span><br><span style="color: hsl(120, 100%, 40%);">+                 <para></span><br><span style="color: hsl(120, 100%, 40%);">+          </para></span><br><span>        </info></span><br><span>  ***/</span><br><span> #include "asterisk.h"</span><br><span>@@ -47,6 +115,7 @@</span><br><span> #include "asterisk/res_pjsip.h"</span><br><span> #include "asterisk/res_pjsip_session.h"</span><br><span> #include "asterisk/taskprocessor.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/uri.h"</span><br><span> </span><br><span> const pjsip_method pjsip_message_method = {PJSIP_OTHER_METHOD, {"MESSAGE", 7} };</span><br><span> </span><br><span>@@ -114,133 +183,347 @@</span><br><span> </span><br><span> /*!</span><br><span>  * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Puts pointer past 'sip[s]:' string that should be at the</span><br><span style="color: hsl(0, 100%, 40%);">- * front of the given 'fromto' parameter</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieves an endpoint and URI from the "to" string.</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param fromto 'From' or 'To' field containing 'sip:'</span><br><span style="color: hsl(0, 100%, 40%);">- */</span><br><span style="color: hsl(0, 100%, 40%);">-static const char *skip_sip(const char *fromto)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-    const char *p;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  /* need to be one past 'sip:' or 'sips:' */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!(p = strstr(fromto, "sip"))) {</span><br><span style="color: hsl(0, 100%, 40%);">-           return fromto;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       p += 3;</span><br><span style="color: hsl(0, 100%, 40%);">- if (*p == 's') {</span><br><span style="color: hsl(0, 100%, 40%);">-                ++p;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       return ++p;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Retrieves an endpoint if specified in the given 'to'</span><br><span style="color: hsl(120, 100%, 40%);">+ * This URI is used as the Request URI.</span><br><span>  *</span><br><span>  * Expects the given 'to' to be in one of the following formats:</span><br><span style="color: hsl(0, 100%, 40%);">- *      sip[s]:endpoint[/aor]</span><br><span style="color: hsl(0, 100%, 40%);">- *      sip[s]:endpoint[/uri] - Where uri is: sip[s]:user@domain</span><br><span style="color: hsl(0, 100%, 40%);">- *      sip[s]:endpoint[@domain]</span><br><span style="color: hsl(0, 100%, 40%);">- *      sip[s]:unknown_user@domain <-- will use default outbound endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ * Why we allow so many is a mystery.</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * If an optional aor is given it will try to find an associated uri</span><br><span style="color: hsl(0, 100%, 40%);">- * to return.  If an optional uri is given then that will be returned,</span><br><span style="color: hsl(0, 100%, 40%);">- * otherwise uri will be NULL.</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint             - We'll get URI from the default aor/contact</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/aor         - We'll get the URI from the specific aor/contact</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint@domain      - We toss the domain part and just use the endpoint</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * \param to 'From' or 'To' field with possible endpoint</span><br><span style="color: hsl(0, 100%, 40%);">- * \param uri Optional uri to return</span><br><span style="color: hsl(120, 100%, 40%);">+ *      These all use the endpoint and specified URI</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/<sip[s]:host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/<sip[s]:user@host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/"Bob" <sip[s]:host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/"Bob" <sip[s]:user@host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/sip[s]:host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/sip[s]:user@host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/user@host</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *      These all use the default endpoint and specified URI</span><br><span style="color: hsl(120, 100%, 40%);">+ *      <sip[s]:host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      <sip[s]:user@host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      "Bob" <sip[s]:host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      "Bob" <sip[s]:user@host></span><br><span style="color: hsl(120, 100%, 40%);">+ *      sip[s]:host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      sip[s]:user@host</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *      These use the default endpoint and specified host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      host</span><br><span style="color: hsl(120, 100%, 40%);">+ *      user@host</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The ones that have the sip[s] scheme are the easiest to parse.</span><br><span style="color: hsl(120, 100%, 40%);">+ * The rest all have some issue.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint vs host              : We have to test for endpoint first</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint/aor vs endpoint/host : We have to test for aor first</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                      What if there's an aor with the same</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                      name as the host?</span><br><span style="color: hsl(120, 100%, 40%);">+ *      endpoint@domain vs user@host  : We have to test for endpoint first.</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                      What if there's an endpoint with the</span><br><span style="color: hsl(120, 100%, 40%);">+ *                                      same name as the user?</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param to 'To' field with possible endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri Pointer to a char* which will be set to the URI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *            Must be ast_free'd by the caller.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note  The logic below could probably be condensed but then it wouldn't be</span><br><span style="color: hsl(120, 100%, 40%);">+ * as clear.</span><br><span>  */</span><br><span> static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- char *name;</span><br><span style="color: hsl(0, 100%, 40%);">-     char *aor_uri;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_sip_endpoint *endpoint;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *destination;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *endpoint_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *slash = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *atsign = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  char *scheme = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_sip_endpoint *endpoint = NULL;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   name = ast_strdupa(skip_sip(to));</span><br><span style="color: hsl(120, 100%, 40%);">+     destination = ast_strdupa(to);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      /* attempt to extract the endpoint name */</span><br><span style="color: hsl(0, 100%, 40%);">-      if ((aor_uri = strchr(name, '/'))) {</span><br><span style="color: hsl(0, 100%, 40%);">-            /* format was 'endpoint/(aor_name | uri)' */</span><br><span style="color: hsl(0, 100%, 40%);">-            *aor_uri++ = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">-      } else if ((aor_uri = strchr(name, '@'))) {</span><br><span style="color: hsl(0, 100%, 40%);">-             /* format was 'endpoint@domain' - discard the domain */</span><br><span style="color: hsl(0, 100%, 40%);">-         *aor_uri = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+      slash = strchr(destination, '/');</span><br><span style="color: hsl(120, 100%, 40%);">+     atsign = strchr(destination, '@');</span><br><span style="color: hsl(120, 100%, 40%);">+    scheme = S_OR(strstr(destination, "sip:"), strstr(destination, "sips:"));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* If it's just one word, it could be an endpoint name or just a hostname */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!slash && !atsign && !scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+           endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", destination);</span><br><span style="color: hsl(120, 100%, 40%);">+              if (endpoint) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       /* It's an endpoint */</span><br><span style="color: hsl(120, 100%, 40%);">+                    struct ast_sip_contact *contact = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     endpoint_name = destination;</span><br><span style="color: hsl(120, 100%, 40%);">+                  contact = ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if (!contact) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               /*</span><br><span style="color: hsl(120, 100%, 40%);">+                             * We're getting the contact using the same method as</span><br><span style="color: hsl(120, 100%, 40%);">+                              * ast_sip_create_request() so if there's no contact</span><br><span style="color: hsl(120, 100%, 40%);">+                               * we can never send this message.</span><br><span style="color: hsl(120, 100%, 40%);">+                             */</span><br><span style="color: hsl(120, 100%, 40%);">+                           ao2_cleanup(endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+                                endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_debug(3, "Dest: FAIL: '%s' Found endpoint '%s' but didn't find an aor/contact for it\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    to, endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              ao2_cleanup(contact);</span><br><span style="color: hsl(120, 100%, 40%);">+                         *uri = ast_strdup(contact->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                    to, endpoint_name, *uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                     }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * It's a hostname that we need to add a scheme to</span><br><span style="color: hsl(120, 100%, 40%);">+                         */</span><br><span style="color: hsl(120, 100%, 40%);">+                   char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                    sprintf(temp_uri, "sip:%s", destination);</span><br><span style="color: hsl(120, 100%, 40%);">+                   *uri = temp_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+                      endpoint = ast_sip_default_outbound_endpoint();</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_debug(3, "Dest: '%s' Didn't find endpoint so adding scheme and using URI '%s' with default endpoint\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             to, *uri);</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             /* There's nothing left to parse so... */</span><br><span style="color: hsl(120, 100%, 40%);">+         return endpoint;</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 there's a '/', it MUST be following an endpoint name */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (slash) {</span><br><span style="color: hsl(120, 100%, 40%);">+          char *afterslash = slash + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+         *slash = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                endpoint_name = destination;</span><br><span style="color: hsl(120, 100%, 40%);">+          endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+            /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there's a slash but there's isn't a valid endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+              * before it, there's nothing else we can do.</span><br><span style="color: hsl(120, 100%, 40%);">+              */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!endpoint) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_debug(3, "Dest: '%s' FAIL: Didn't find endpoint with name '%s' before the slash\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         to, endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                 return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span> </span><br><span>                /*</span><br><span style="color: hsl(0, 100%, 40%);">-               * We may want to match without any user options getting</span><br><span style="color: hsl(0, 100%, 40%);">-                 * in the way.</span><br><span style="color: hsl(120, 100%, 40%);">+                 * If we found a scheme, then everything after the slash MUST be a URI.</span><br><span style="color: hsl(120, 100%, 40%);">+                * We don't need to do any further modification.</span><br><span>                  */</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(name);</span><br><span style="color: hsl(120, 100%, 40%);">+            if (scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 *uri = ast_strdup(afterslash);</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_debug(3, "Dest: '%s' Found endpoint '%s' and found URI '%s' after slash\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                             to, endpoint_name, *uri);</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /* It now may be an aor or a URI without a scheme */</span><br><span style="color: hsl(120, 100%, 40%);">+                  struct ast_sip_aor *aor;</span><br><span style="color: hsl(120, 100%, 40%);">+                      struct ast_sip_contact *contact = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     aor = ast_sip_location_retrieve_aor(afterslash);</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (aor) {</span><br><span style="color: hsl(120, 100%, 40%);">+                            ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after slash\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     to, endpoint_name, ast_sorcery_object_get_id(aor));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                         contact = ast_sip_location_retrieve_first_aor_contact(aor);</span><br><span style="color: hsl(120, 100%, 40%);">+                           if (contact) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                        *uri = ast_strdup(contact->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                                   ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' for aor '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                               to, endpoint_name, *uri, ast_sorcery_object_get_id(aor));</span><br><span style="color: hsl(120, 100%, 40%);">+                             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                                      /*</span><br><span style="color: hsl(120, 100%, 40%);">+                                     * An aor without a contact is useless and since</span><br><span style="color: hsl(120, 100%, 40%);">+                                       * ast_sip_create_message() won't be able to find one</span><br><span style="color: hsl(120, 100%, 40%);">+                                      * either, we just need to bail.</span><br><span style="color: hsl(120, 100%, 40%);">+                                       */</span><br><span style="color: hsl(120, 100%, 40%);">+                                   ao2_cleanup(endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+                                        endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                                      *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                                  ast_debug(3, "Dest: '%s' FAIL: Found endpoint '%s' but didn't find contact for aor '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                             to, endpoint_name, ast_sorcery_object_get_id(aor));</span><br><span style="color: hsl(120, 100%, 40%);">+                           }</span><br><span style="color: hsl(120, 100%, 40%);">+                             ao2_cleanup(contact);</span><br><span style="color: hsl(120, 100%, 40%);">+                         ao2_cleanup(aor);</span><br><span style="color: hsl(120, 100%, 40%);">+                     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              /*</span><br><span style="color: hsl(120, 100%, 40%);">+                             * It's probably a uri without a scheme but we don't have a way to tell.</span><br><span style="color: hsl(120, 100%, 40%);">+                               * We're going to assume it is and prepend it with a scheme.</span><br><span style="color: hsl(120, 100%, 40%);">+                               */</span><br><span style="color: hsl(120, 100%, 40%);">+                           *uri = ast_malloc(strlen(afterslash) + strlen("sip:") + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                         sprintf(*uri, "sip:%s", afterslash);</span><br><span style="color: hsl(120, 100%, 40%);">+                                ast_debug(3, "Dest: '%s' Found endpoint '%s' but didn't find aor after slash so using URI '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                      to, endpoint_name, *uri);</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           return endpoint;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* at this point, if name is not empty then it</span><br><span style="color: hsl(0, 100%, 40%);">-     might be an endpoint, so try to retrieve it */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_strlen_zero(name)</span><br><span style="color: hsl(0, 100%, 40%);">-               || !(endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint",</span><br><span style="color: hsl(0, 100%, 40%);">-                 name))) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* an endpoint was not found, so assume sending directly</span><br><span style="color: hsl(0, 100%, 40%);">-                   to a uri and use the default outbound endpoint */</span><br><span style="color: hsl(0, 100%, 40%);">-            *uri = ast_strdup(to);</span><br><span style="color: hsl(0, 100%, 40%);">-          return ast_sip_default_outbound_endpoint();</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * If there's an '@' but no scheme then it's either following an endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+         * and being followed by a domain name (which we discard).</span><br><span style="color: hsl(120, 100%, 40%);">+     * OR is's a user@host uri without a scheme.  It's probably the latter but because</span><br><span style="color: hsl(120, 100%, 40%);">+     * endpoint@domain looks just line user@host, we'll test for endpoint first.</span><br><span style="color: hsl(120, 100%, 40%);">+       */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!endpoint && atsign && !scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+         char *afterat = atsign + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           *atsign = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+               endpoint_name = destination;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Apprently there may be ';<user_options>' after the endpoint name ??? */</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_SIP_USER_OPTIONS_TRUNCATE_CHECK(endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+           endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+            /* If it's an endpoint, just return it because we discard the domain. */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (endpoint) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       struct ast_sip_contact *contact =</span><br><span style="color: hsl(120, 100%, 40%);">+                             ast_sip_location_retrieve_contact_from_aor_list(endpoint->aors);</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (!contact) {</span><br><span style="color: hsl(120, 100%, 40%);">+                               /*</span><br><span style="color: hsl(120, 100%, 40%);">+                             * We're getting the contact using the same method as</span><br><span style="color: hsl(120, 100%, 40%);">+                              * ast_sip_create_request() so if there's no contact</span><br><span style="color: hsl(120, 100%, 40%);">+                               * we can never send this message.</span><br><span style="color: hsl(120, 100%, 40%);">+                             */</span><br><span style="color: hsl(120, 100%, 40%);">+                           ao2_cleanup(endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+                                endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                              *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_debug(3, "Dest: '%s' FAIL: Found endpoint '%s' but didn't find contact\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                  to, endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                              *uri = ast_strdup(contact->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+                           ao2_cleanup(contact);</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_debug(3, "Dest: '%s' Found endpoint '%s' and found contact with URI '%s' (discarding domain %s)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                     to, endpoint_name, *uri, afterat);</span><br><span style="color: hsl(120, 100%, 40%);">+                    }</span><br><span style="color: hsl(120, 100%, 40%);">+             } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * It's probably a uri with a user but without a scheme but we don't have a way to tell.</span><br><span style="color: hsl(120, 100%, 40%);">+                       * We're going to assume it is and prepend it with a scheme.</span><br><span style="color: hsl(120, 100%, 40%);">+                       */</span><br><span style="color: hsl(120, 100%, 40%);">+                   *uri = ast_malloc(strlen(to) + strlen("sip:") + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                 sprintf(*uri, "sip:%s", to);</span><br><span style="color: hsl(120, 100%, 40%);">+                        endpoint = ast_sip_default_outbound_endpoint();</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_debug(3, "Dest: '%s' Didn't find endpoint before the '@' so using URI '%s' with default endpoint\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                                to, *uri);</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%);">+           return endpoint;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (ast_strlen_zero(aor_uri)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * If all else fails, we assume it's a URI or just a hostname.</span><br><span style="color: hsl(120, 100%, 40%);">+     */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+         *uri = ast_strdup(destination);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_debug(3, "Dest: '%s' Didn't find an endpoint but did find a scheme so using URI '%s' with default endpoint\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                      to, *uri);</span><br><span>   } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                struct ast_sip_aor *aor;</span><br><span style="color: hsl(0, 100%, 40%);">-                struct ast_sip_contact *contact = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-         char *end;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-              /* Trim off any stray angle bracket that shouldn't be here */</span><br><span style="color: hsl(0, 100%, 40%);">-               end = strchr(aor_uri, '>');</span><br><span style="color: hsl(0, 100%, 40%);">-          if (end) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      *end = '\0';</span><br><span style="color: hsl(0, 100%, 40%);">-            }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /*</span><br><span style="color: hsl(0, 100%, 40%);">-               * if what's in 'uri' is a retrievable aor use the uri on it</span><br><span style="color: hsl(0, 100%, 40%);">-                 * instead, otherwise assume what's there is already a uri</span><br><span style="color: hsl(0, 100%, 40%);">-           */</span><br><span style="color: hsl(0, 100%, 40%);">-             aor = ast_sip_location_retrieve_aor(aor_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-           if (aor && (contact = ast_sip_location_retrieve_first_aor_contact(aor))) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      aor_uri = (char *) contact->uri;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-               /* need to copy because underlying uri goes away */</span><br><span style="color: hsl(0, 100%, 40%);">-             *uri = ast_strdup(aor_uri);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-             ao2_cleanup(contact);</span><br><span style="color: hsl(0, 100%, 40%);">-           ao2_cleanup(aor);</span><br><span style="color: hsl(120, 100%, 40%);">+             *uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);</span><br><span style="color: hsl(120, 100%, 40%);">+                sprintf(*uri, "sip:%s", destination);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_debug(3, "Dest: '%s' Didn't find an endpoint and didn't find scheme so adding scheme and using URI '%s' with default endpoint\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       to, *uri);</span><br><span>   }</span><br><span style="color: hsl(120, 100%, 40%);">+     endpoint = ast_sip_default_outbound_endpoint();</span><br><span> </span><br><span>  return endpoint;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>  * \internal</span><br><span style="color: hsl(0, 100%, 40%);">- * \brief Overwrite fields in the outbound 'To' header</span><br><span style="color: hsl(0, 100%, 40%);">- *</span><br><span style="color: hsl(0, 100%, 40%);">- * Updates display name in an outgoing To header.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Replace the To URI in the tdata with the supplied one</span><br><span>  *</span><br><span>  * \param tdata the outbound message data structure</span><br><span style="color: hsl(0, 100%, 40%);">- * \param to info to copy into the header</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param to URI to replace the To URI with</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0: success, -1: failure</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static void update_to(pjsip_tx_data *tdata, char *to)</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_to_uri(pjsip_tx_data *tdata, char *to)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        pjsip_name_addr *parsed_name_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+    pjsip_sip_uri *sip_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+       pjsip_name_addr *tdata_name_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+     pjsip_sip_uri *tdata_sip_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *buf = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEBUG_BUF_SIZE 256</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),</span><br><span style="color: hsl(120, 100%, 40%);">+                PJSIP_PARSE_URI_AS_NAMEADDR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!parsed_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)</span><br><span style="color: hsl(120, 100%, 40%);">+                  && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri))) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "To address '%s' is not a valid SIP/SIPS URI\n", to);</span><br><span style="color: hsl(120, 100%, 40%);">+          return -1;</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%);">+   sip_uri = pjsip_uri_get_uri(parsed_name_addr->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (DEBUG_ATLEAST(3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               buf = ast_alloca(DEBUG_BUF_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+             pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, sip_uri, buf, DEBUG_BUF_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_debug(3, "Parsed To: %.*s  %s\n", (int)parsed_name_addr->display.slen,</span><br><span style="color: hsl(120, 100%, 40%);">+                       parsed_name_addr->display.ptr, buf);</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%);">+   tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!tdata_name_addr || (!PJSIP_URI_SCHEME_IS_SIP(tdata_name_addr->uri)</span><br><span style="color: hsl(120, 100%, 40%);">+                    && !PJSIP_URI_SCHEME_IS_SIPS(tdata_name_addr->uri))) {</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Highly unlikely but we have to check */</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "tdata To address '%s' is not a valid SIP/SIPS URI\n", to);</span><br><span style="color: hsl(120, 100%, 40%);">+            return -1;</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%);">+   tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (DEBUG_ATLEAST(3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               buf[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, DEBUG_BUF_SIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_debug(3, "Original tdata To: %.*s  %s\n", (int)tdata_name_addr->display.slen,</span><br><span style="color: hsl(120, 100%, 40%);">+                        tdata_name_addr->display.ptr, buf);</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%);">+   /* Replace the uri */</span><br><span style="color: hsl(120, 100%, 40%);">+ pjsip_sip_uri_assign(tdata->pool, tdata_sip_uri, sip_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* The display name isn't part of the URI so we need to replace it separately */</span><br><span style="color: hsl(120, 100%, 40%);">+  pj_strdup(tdata->pool, &tdata_name_addr->display, &parsed_name_addr->display);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     if (DEBUG_ATLEAST(3)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               buf[0] = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+                pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, buf, 256);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_debug(3, "New tdata To: %.*s  %s\n", (int)tdata_name_addr->display.slen,</span><br><span style="color: hsl(120, 100%, 40%);">+                     tdata_name_addr->display.ptr, buf);</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%);">+   return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+#undef DEBUG_BUF_SIZE</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%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Update the display name in the To uri in the tdata with the one from the supplied uri</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param tdata the outbound message data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param to uri containing the display name to replace in the the To uri</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0: success, -1: failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_to_display_name(pjsip_tx_data *tdata, char *to)</span><br><span> {</span><br><span>   pjsip_name_addr *parsed_name_addr;</span><br><span> </span><br><span>       parsed_name_addr = (pjsip_name_addr *) pjsip_parse_uri(tdata->pool, to, strlen(to),</span><br><span>               PJSIP_PARSE_URI_AS_NAMEADDR);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      if (parsed_name_addr) {</span><br><span>              if (pj_strlen(&parsed_name_addr->display)) {</span><br><span>                  pjsip_name_addr *name_addr =</span><br><span>                                 (pjsip_name_addr *) PJSIP_MSG_TO_HDR(tdata->msg)->uri;</span><br><span> </span><br><span>                     pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>          }</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return -1;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -254,15 +537,17 @@</span><br><span>  *</span><br><span>  * \param tdata the outbound message data structure</span><br><span>  * \param from info to copy into the header</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0: success, -1: failure</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static void update_from(pjsip_tx_data *tdata, char *from)</span><br><span style="color: hsl(120, 100%, 40%);">+static int update_from(pjsip_tx_data *tdata, char *from)</span><br><span> {</span><br><span>        pjsip_name_addr *name_addr;</span><br><span>  pjsip_sip_uri *uri;</span><br><span>  pjsip_name_addr *parsed_name_addr;</span><br><span> </span><br><span>       if (ast_strlen_zero(from)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            return;</span><br><span style="color: hsl(120, 100%, 40%);">+               return 0;</span><br><span>    }</span><br><span> </span><br><span>        name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;</span><br><span>@@ -276,7 +561,7 @@</span><br><span>             if (!PJSIP_URI_SCHEME_IS_SIP(parsed_name_addr->uri)</span><br><span>                               && !PJSIP_URI_SCHEME_IS_SIPS(parsed_name_addr->uri)) {</span><br><span>                    ast_log(LOG_WARNING, "From address '%s' is not a valid SIP/SIPS URI\n", from);</span><br><span style="color: hsl(0, 100%, 40%);">-                        return;</span><br><span style="color: hsl(120, 100%, 40%);">+                       return -1;</span><br><span>           }</span><br><span> </span><br><span>                parsed_uri = pjsip_uri_get_uri(parsed_name_addr->uri);</span><br><span>@@ -285,9 +570,12 @@</span><br><span>                     pj_strdup(tdata->pool, &name_addr->display, &parsed_name_addr->display);</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+         /* Unlike the To header, we only want to replace the user, host and port */</span><br><span>          pj_strdup(tdata->pool, &uri->user, &parsed_uri->user);</span><br><span>              pj_strdup(tdata->pool, &uri->host, &parsed_uri->host);</span><br><span>              uri->port = parsed_uri->port;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         return 0;</span><br><span>    } else {</span><br><span>             /* assume it is 'user[@domain]' format */</span><br><span>            char *domain = strchr(from, '@');</span><br><span>@@ -302,7 +590,11 @@</span><br><span>             } else {</span><br><span>                     pj_strdup2(tdata->pool, &uri->user, from);</span><br><span>                 }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           return 0;</span><br><span>    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return -1;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -618,13 +910,8 @@</span><br><span>    }</span><br><span>    ++to;/* Now skip the ':' */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* Make sure we start with sip: */</span><br><span style="color: hsl(0, 100%, 40%);">-      mdata->to = ast_begins_with(to, "sip:") ? ast_strdup(to) : ast_strdup(to - 4);</span><br><span style="color: hsl(120, 100%, 40%);">+   mdata->to = ast_strdup(to);</span><br><span>       mdata->from = ast_strdup(from);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!mdata->to || !mdata->from) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ao2_ref(mdata, -1);</span><br><span style="color: hsl(0, 100%, 40%);">-             return NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span> </span><br><span>        /*</span><br><span>    * Sometimes from URI can contain URI parameters, so remove them.</span><br><span>@@ -667,6 +954,25 @@</span><br><span>     }</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 Send a MESSAGE</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param mdata The outbound message data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return 0: success, -1: failure</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * mdata contains the To and From specified in the call to the MessageSend</span><br><span style="color: hsl(120, 100%, 40%);">+ * dialplan app.  It also contains the ast_msg object that contains the</span><br><span style="color: hsl(120, 100%, 40%);">+ * message body and may contain the To and From from the channel datastore,</span><br><span style="color: hsl(120, 100%, 40%);">+ * usually set with the MESSAGE or MESSAGE_DATA dialplan functions but</span><br><span style="color: hsl(120, 100%, 40%);">+ * could also come from an incoming sip MESSAGE.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * The mdata->to is always used as the basis for the Request URI</span><br><span style="color: hsl(120, 100%, 40%);">+ * while the mdata->msg->to is used for the To header.  If</span><br><span style="color: hsl(120, 100%, 40%);">+ * mdata->msg->to isn't available, mdata->to is used for the To header.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> static int msg_send(void *data)</span><br><span> {</span><br><span>   struct msg_data *mdata = data; /* The caller holds a reference */</span><br><span>@@ -681,6 +987,9 @@</span><br><span>      RAII_VAR(char *, uri, NULL, ast_free);</span><br><span>       RAII_VAR(struct ast_sip_endpoint *, endpoint, NULL, ao2_cleanup);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "mdata From: %s msg From: %s mdata Destination: %s msg To: %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              mdata->from, ast_msg_get_from(mdata->msg), mdata->to, ast_msg_get_to(mdata->msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     endpoint = get_outbound_endpoint(mdata->to, &uri);</span><br><span>    if (!endpoint) {</span><br><span>             ast_log(LOG_ERROR,</span><br><span>@@ -689,13 +998,41 @@</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ ast_debug(3, "Request URI: %s\n", uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (ast_sip_create_request("MESSAGE", NULL, endpoint, uri, NULL, &tdata)) {</span><br><span>            ast_log(LOG_WARNING, "PJSIP MESSAGE - Could not create request\n");</span><br><span>                return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   update_to(tdata, mdata->to);</span><br><span style="color: hsl(0, 100%, 40%);">- update_from(tdata, mdata->from);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* If there was a To in the actual message, */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ast_strlen_zero(ast_msg_get_to(mdata->msg))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                char *msg_to = ast_strdupa(ast_msg_get_to(mdata->msg));</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%);">+             * It's possible that the message To was copied from</span><br><span style="color: hsl(120, 100%, 40%);">+               * an incoming MESSAGE in which case it'll have the</span><br><span style="color: hsl(120, 100%, 40%);">+                * pjsip: tech prepended to it.  We need to remove it.</span><br><span style="color: hsl(120, 100%, 40%);">+                 */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (ast_begins_with(msg_to, "pjsip:")) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    msg_to += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+             update_to_uri(tdata, msg_to);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there was no To in the message, it's still possible</span><br><span style="color: hsl(120, 100%, 40%);">+          * that there is a display name in the mdata To.  If so,</span><br><span style="color: hsl(120, 100%, 40%);">+               * we'll copy the URI display name to the tdata To.</span><br><span style="color: hsl(120, 100%, 40%);">+                */</span><br><span style="color: hsl(120, 100%, 40%);">+           update_to_display_name(tdata, uri);</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 (!ast_strlen_zero(mdata->from)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               update_from(tdata, mdata->from);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (!ast_strlen_zero(ast_msg_get_from(mdata->msg))) {</span><br><span style="color: hsl(120, 100%, 40%);">+               update_from(tdata, (char *)ast_msg_get_from(mdata->msg));</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  update_content_type(tdata, mdata->msg, &body);</span><br><span> </span><br><span>    if (ast_sip_add_body(tdata, &body)) {</span><br><span>@@ -704,10 +1041,14 @@</span><br><span>           return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * This copies any headers set with MESSAGE_DATA() to the</span><br><span style="color: hsl(120, 100%, 40%);">+      * tdata.</span><br><span style="color: hsl(120, 100%, 40%);">+      */</span><br><span>  vars_to_headers(mdata->msg, tdata);</span><br><span> </span><br><span>   ast_debug(1, "Sending message to '%s' (via endpoint %s) from '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">-         mdata->to, ast_sorcery_object_get_id(endpoint), mdata->from);</span><br><span style="color: hsl(120, 100%, 40%);">+           uri, ast_sorcery_object_get_id(endpoint), mdata->from);</span><br><span> </span><br><span>       if (ast_sip_send_request(tdata, NULL, endpoint, NULL, NULL)) {</span><br><span>               ast_log(LOG_ERROR, "PJSIP MESSAGE - Could not send request\n");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15806">change 15806</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/+/15806"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I67a485196d9199916468f7f98bfb9a0b993a4cce </div>
<div style="display:none"> Gerrit-Change-Number: 15806 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>