<p>George Joseph <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15806">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Kevin Harwell: Looks good to me, but someone else must approve
  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_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> * We now also accept a destination in the same format<br>   as Dial()...  PJSIP/number@endpoint<br><br> * Added lots of debugging.<br><br>ASTERISK-29404<br>Reported by Brian J. Murrell<br><br>Change-Id: I67a485196d9199916468f7f98bfb9a0b993a4cce<br>---<br>A doc/CHANGES-staging/res_pjsip_messaging.txt<br>M res/res_pjsip_messaging.c<br>2 files changed, 740 insertions(+), 101 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/res_pjsip_messaging.txt b/doc/CHANGES-staging/res_pjsip_messaging.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..46874dc</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_pjsip_messaging.txt</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_pjsip_messaging</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Implemented the new "to" parameter of the MessageSend()</span><br><span style="color: hsl(120, 100%, 40%);">+dialplan application.  This allows a user to specify</span><br><span style="color: hsl(120, 100%, 40%);">+a complete SIP "To" header separate from the Request URI.</span><br><span style="color: hsl(120, 100%, 40%);">+We now also accept a destination in the same format</span><br><span style="color: hsl(120, 100%, 40%);">+as Dial()...  PJSIP/number@endpoint</span><br><span>diff --git a/res/res_pjsip_messaging.c b/res/res_pjsip_messaging.c</span><br><span>index 9287324..d895945 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,96 @@</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>This form is similar to a dialstring:</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="PJSIP/user@endpoint"/></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>You still need to prefix the destination with</span><br><span style="color: hsl(120, 100%, 40%);">+             the <literal>pjsip:</literal> message technology prefix.  For example:</span><br><span style="color: hsl(120, 100%, 40%);">+            <literal>pjsip:PJSIP/8005551212@myprovider</literal>.</span><br><span style="color: hsl(120, 100%, 40%);">+             The endpoint contact's URI will have the <literal>user</literal> inserted</span><br><span style="color: hsl(120, 100%, 40%);">+             into it and will become the Request URI.  If the contact URI already has</span><br><span style="color: hsl(120, 100%, 40%);">+              a user specified, an error is returned.</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="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 +128,8 @@</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/test.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>@@ -113,134 +196,579 @@</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(0, 100%, 40%);">- * \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 Find a contact and insert a "user@" into its URI.</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(120, 100%, 40%);">+ * \param to Original destination (for error messages only)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param endpoint_name Endpoint name (for error messages only)</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param aors Command separated list of AORs</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param user The user to insert in the contact URI</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri Pointer to buffer in which to return the URI</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return  0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return -1 Fail</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \note If the contact URI found for the endpoint already has a user in</span><br><span style="color: hsl(120, 100%, 40%);">+ * its URI, replacing it is probably not a good idea so an error is returned.</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static const char *skip_sip(const char *fromto)</span><br><span style="color: hsl(120, 100%, 40%);">+static int insert_user_in_contact_uri(const char *to, const char *endpoint_name, const char *aors,</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *user, char **uri)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      const char *p;</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%);">+  char *contact_uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     char *colon = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   char *host;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sip_contact *contact = NULL;</span><br><span> </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(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      contact = ast_sip_location_retrieve_contact_from_aor_list(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%);">+           ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Couldn't find contact for endpoint '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                     to, endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+           return -1;</span><br><span>   }</span><br><span> </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(120, 100%, 40%);">+  contact_uri = ast_strdupa(contact->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_cleanup(contact);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_debug(3, "Dest: '%s' User: '%s'  Endpoint: '%s'  ContactURI: '%s'\n", to, user, endpoint_name, contact_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  atsign = strchr(contact_uri, '@');</span><br><span style="color: hsl(120, 100%, 40%);">+    if (atsign) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there is already a username in the contact URI</span><br><span style="color: hsl(120, 100%, 40%);">+           * messing with it is probably NOT a good thing.</span><br><span style="color: hsl(120, 100%, 40%);">+               */</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: There's already a username in endpoint %s's contact URI '%s'.\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                   to, endpoint_name, contact_uri);</span><br><span style="color: hsl(120, 100%, 40%);">+              return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return ++p;</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Contact URIs must have a scheme so we must insert the user between it and the host.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   colon = strchr(contact_uri, ':');</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!colon) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /* A contact URI without a scheme?  Something's wrong.  Bail */</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: There was no scheme in the contact URI '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                     to, contact_uri);</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%);">+   host = colon + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     scheme = contact_uri;</span><br><span style="color: hsl(120, 100%, 40%);">+ *uri = ast_malloc(strlen(contact_uri) + strlen(user) + 2 /* One for the @ and one for the NULL */);</span><br><span style="color: hsl(120, 100%, 40%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Need to set the NULL after the malloc or the length of contact_uri will be too short</span><br><span style="color: hsl(120, 100%, 40%);">+        * to hold the final result.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   *colon = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+        sprintf(*uri, "%s:%s@%s", scheme, user, host);</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> </span><br><span> /*!</span><br><span>  * \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%);">+ * \brief Get endpoint and URI when the destination is only a single token</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * 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%);">+ * "to" could be one of the following:</span><br><span style="color: hsl(120, 100%, 40%);">+ *                endpoint_name</span><br><span style="color: hsl(120, 100%, 40%);">+ *               hostname</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(0, 100%, 40%);">- *</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%);">+ * \param to Destination specified in MessageSend</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri Pointer to URI variable.  Must be freed by caller</span><br><span style="color: hsl(120, 100%, 40%);">+ * \return endpoint</span><br><span>  */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri)</span><br><span style="color: hsl(0, 100%, 40%);">-{</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%);">+static struct ast_sip_endpoint *handle_single_token(const char *to, char *destination, char **uri) {</span><br><span style="color: hsl(120, 100%, 40%);">+      char *endpoint_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sip_endpoint *endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_contact *contact = 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%);">+     /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * If "to" is just one token, it could be an endpoint name</span><br><span style="color: hsl(120, 100%, 40%);">+   * or a hostname without a scheme.</span><br><span style="color: hsl(120, 100%, 40%);">+     */</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(0, 100%, 40%);">-</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>             /*</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%);">+                 * We can only assume it's a hostname.</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%);">+            char *temp_uri = ast_malloc(strlen(destination) + strlen("sip:") + 1);</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%);">+            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(0, 100%, 40%);">-     }</span><br><span style="color: hsl(120, 100%, 40%);">+     /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * It's an endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+        */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (ast_strlen_zero(aor_uri)) {</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%);">+           ast_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: 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%);">+           ao2_cleanup(endpoint);</span><br><span>               *uri = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-    } 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(120, 100%, 40%);">+            return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span> </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(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%);">+     ao2_cleanup(contact);</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%);">+</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 Get endpoint and URI when the destination contained a '/'</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * "to" could be one of the following:</span><br><span style="color: hsl(120, 100%, 40%);">+ *               endpoint/aor</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%);">+ * \param to Destination specified in MessageSend</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri Pointer to URI variable.  Must be freed by caller</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%);">+static struct ast_sip_endpoint *handle_slash(const char *to, char *destination, char **uri,</span><br><span style="color: hsl(120, 100%, 40%);">+     char *slash, char *atsign, char *scheme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   char *endpoint_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sip_endpoint *endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_contact *contact = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *user = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+    char *afterslash = slash + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_sip_aor *aor;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ast_begins_with(destination, "PJSIP/")) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_debug(3, "Dest: '%s' Dialplan format'\n", to);</span><br><span style="color: hsl(120, 100%, 40%);">+              /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * This has to be the form PJSIP/user@endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+                 */</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!atsign || strchr(afterslash, '/')) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * If there's no "user@" or there's a slash somewhere after</span><br><span style="color: hsl(120, 100%, 40%);">+                  * "PJSIP/" then we go no further.</span><br><span style="color: hsl(120, 100%, 40%);">+                   */</span><br><span style="color: hsl(120, 100%, 40%);">+                   *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_log(LOG_WARNING,</span><br><span style="color: hsl(120, 100%, 40%);">+                          "Dest: '%s' MSG SEND FAIL: Destinations beginning with 'PJSIP/' must be in the form of 'PJSIP/user@endpoint'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                            to);</span><br><span style="color: hsl(120, 100%, 40%);">+                  return NULL;</span><br><span>                 }</span><br><span style="color: hsl(120, 100%, 40%);">+             *atsign = '\0';</span><br><span style="color: hsl(120, 100%, 40%);">+               user = afterslash;</span><br><span style="color: hsl(120, 100%, 40%);">+            endpoint_name = atsign + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_debug(3, "Dest: '%s' User: '%s'  Endpoint: '%s'\n", to, user, endpoint_name);</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%);">+             * Either...</span><br><span style="color: hsl(120, 100%, 40%);">+           *      endpoint/aor</span><br><span style="color: hsl(120, 100%, 40%);">+           *      endpoint/uri</span><br><span style="color: hsl(120, 100%, 40%);">+           */</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%);">+          ast_debug(3, "Dest: '%s' Endpoint: '%s'\n", to, endpoint_name);</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%);">+   endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", endpoint_name);</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_log(LOG_WARNING, "Dest: '%s' MSG SEND FAIL: Didn't find endpoint with name '%s'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 to, endpoint_name);</span><br><span style="color: hsl(120, 100%, 40%);">+           return NULL;</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 (scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+         /*</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 style="color: hsl(120, 100%, 40%);">+           */</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 '/'\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                       to, endpoint_name, *uri);</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 (user) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * This has to be the form PJSIP/user@endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+                 */</span><br><span style="color: hsl(120, 100%, 40%);">+           int rc;</span><br><span> </span><br><span>          /*</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(120, 100%, 40%);">+                 * Set the return URI to be the endpoint's contact URI with the user</span><br><span style="color: hsl(120, 100%, 40%);">+               * portion set to the user that was specified before the endpoint name.</span><br><span>               */</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(120, 100%, 40%);">+           rc = insert_user_in_contact_uri(to, endpoint_name, endpoint->aors, user, uri);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (rc != 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        /*</span><br><span style="color: hsl(120, 100%, 40%);">+                     * insert_user_in_contact_uri prints the warning 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>                 }</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(120, 100%, 40%);">+           ast_debug(3, "Dest: '%s' User: '%s'  Endpoint: '%s'  URI: '%s'\n", to, user,</span><br><span style="color: hsl(120, 100%, 40%);">+                        endpoint_name, *uri);</span><br><span> </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%);">+             return endpoint;</span><br><span>     }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * We're now left with two possibilities...</span><br><span style="color: hsl(120, 100%, 40%);">+        *      endpoint/aor</span><br><span style="color: hsl(120, 100%, 40%);">+   *      endpoint/uri-without-scheme</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%);">+           /*</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%);">+                * for sure.  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 '/' 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%);">+             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%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * Only one possibility left... There was an aor name after the slash.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_debug(3, "Dest: '%s' Found endpoint '%s' and found aor '%s' after '/'\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%);">+               /*</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%);">+           ast_log(LOG_WARNING, "Dest: '%s' MSG SEND 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%);">+           ao2_cleanup(aor);</span><br><span style="color: hsl(120, 100%, 40%);">+             ao2_cleanup(endpoint);</span><br><span style="color: hsl(120, 100%, 40%);">+                *uri = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          return NULL;</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%);">+   *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%);">+     ao2_cleanup(contact);</span><br><span style="color: hsl(120, 100%, 40%);">+ ao2_cleanup(aor);</span><br><span style="color: hsl(120, 100%, 40%);">+</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(120, 100%, 40%);">+ * \brief Get endpoint and URI when the destination contained a '@' but no '/' or scheme</span><br><span>  *</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%);">+ * "to" could be one of the following:</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]:user@host></span><br><span style="color: hsl(120, 100%, 40%);">+ *            sip[s]:user@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%);">+ * \param to Destination specified in MessageSend</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param uri Pointer to URI variable.  Must be freed by caller</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%);">+static struct ast_sip_endpoint *handle_atsign(const char *to, char *destination, char **uri,</span><br><span style="color: hsl(120, 100%, 40%);">+     char *slash, char *atsign, char *scheme)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   char *endpoint_name = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_sip_endpoint *endpoint = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_sip_contact *contact = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+       char *afterat = atsign + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</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 (!endpoint) {</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%);">+            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%);">+   /*</span><br><span style="color: hsl(120, 100%, 40%);">+     * OK, it's an endpoint and a domain (which we ignore)</span><br><span style="color: hsl(120, 100%, 40%);">+     */</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_log(LOG_WARNING, "Dest: '%s' MSG SEND 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%);">+           return NULL;</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%);">+   *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%);">+  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%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Retrieves an endpoint and URI from the "to" string.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This URI is used as the Request URI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Expects the given 'to' to be in one of the following formats:</span><br><span style="color: hsl(120, 100%, 40%);">+ * Why we allow so many is a mystery.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *   Basic:</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 style="color: hsl(120, 100%, 40%);">+ *</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%);">+ *   This form is similar to a dialstring:</span><br><span style="color: hsl(120, 100%, 40%);">+ *      PJSIP/user@endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+ *   In this case, the user will be added to the endpoint contact's URI.</span><br><span style="color: hsl(120, 100%, 40%);">+ *   If the contact URI already has a user, an error is returned.</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 style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_sip_endpoint *get_outbound_endpoint(const char *to, char **uri)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *destination;</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 style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   destination = ast_strdupa(to);</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 (!slash && !atsign && !scheme) {</span><br><span style="color: hsl(120, 100%, 40%);">+           /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there's only a single token, it can be either...</span><br><span style="color: hsl(120, 100%, 40%);">+             *      endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+               *      host</span><br><span style="color: hsl(120, 100%, 40%);">+           */</span><br><span style="color: hsl(120, 100%, 40%);">+           return handle_single_token(to, destination, 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 (slash) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /*</span><br><span style="color: hsl(120, 100%, 40%);">+             * If there's a '/', then the form must be one of the following...</span><br><span style="color: hsl(120, 100%, 40%);">+                 *      PJSIP/user@endpoint</span><br><span style="color: hsl(120, 100%, 40%);">+            *      endpoint/aor</span><br><span style="color: hsl(120, 100%, 40%);">+           *      endpoint/uri</span><br><span style="color: hsl(120, 100%, 40%);">+           */</span><br><span style="color: hsl(120, 100%, 40%);">+           return handle_slash(to, destination, uri, slash, atsign, scheme);</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 (!endpoint && atsign && !scheme) {</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 like 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%);">+           return handle_atsign(to, destination, uri, slash, atsign, scheme);</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%);">+     * 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 style="color: hsl(120, 100%, 40%);">+    } else {</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 style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+     endpoint = ast_sip_default_outbound_endpoint();</span><br><span style="color: hsl(120, 100%, 40%);">+</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%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \internal</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 +782,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 +806,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 +815,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 +835,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>@@ -585,7 +1122,7 @@</span><br><span> </span><br><span> struct msg_data {</span><br><span>   struct ast_msg *msg;</span><br><span style="color: hsl(0, 100%, 40%);">-        char *to;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *destination;</span><br><span>   char *from;</span><br><span> };</span><br><span> </span><br><span>@@ -594,12 +1131,12 @@</span><br><span>       struct msg_data *mdata = obj;</span><br><span> </span><br><span>    ast_free(mdata->from);</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_free(mdata->to);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_free(mdata->destination);</span><br><span> </span><br><span>         ast_msg_destroy(mdata->msg);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static struct msg_data *msg_data_create(const struct ast_msg *msg, const char *to, const char *from)</span><br><span style="color: hsl(120, 100%, 40%);">+static struct msg_data *msg_data_create(const struct ast_msg *msg, const char *destination, const char *from)</span><br><span> {</span><br><span>     char *uri_params;</span><br><span>    struct msg_data *mdata = ao2_alloc(sizeof(*mdata), msg_data_destroy);</span><br><span>@@ -612,19 +1149,14 @@</span><br><span>       mdata->msg = ast_msg_ref((struct ast_msg *) msg);</span><br><span> </span><br><span>     /* To starts with 'pjsip:' which needs to be removed. */</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!(to = strchr(to, ':'))) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!(destination = strchr(destination, ':'))) {</span><br><span>             ao2_ref(mdata, -1);</span><br><span>          return NULL;</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       ++to;/* Now skip the ':' */</span><br><span style="color: hsl(120, 100%, 40%);">+   ++destination;/* 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->destination = ast_strdup(destination);</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 +1199,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,21 +1232,98 @@</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(0, 100%, 40%);">-   endpoint = get_outbound_endpoint(mdata->to, &uri);</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->destination, ast_msg_get_to(mdata->msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     endpoint = get_outbound_endpoint(mdata->destination, &uri);</span><br><span>   if (!endpoint) {</span><br><span>             ast_log(LOG_ERROR,</span><br><span>                   "PJSIP MESSAGE - Could not find endpoint '%s' and no default outbound endpoint configured\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                 mdata->to);</span><br><span style="color: hsl(120, 100%, 40%);">+                        mdata->destination);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_test_suite_event_notify("MSG_ENDPOINT_URI_FAIL",</span><br><span style="color: hsl(120, 100%, 40%);">+                        "MdataFrom: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                 "MsgFrom: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "MdataDestination: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                  "MsgTo: %s\r\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                    mdata->from,</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_msg_get_from(mdata->msg),</span><br><span style="color: hsl(120, 100%, 40%);">+                      mdata->destination,</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_msg_get_to(mdata->msg));</span><br><span style="color: hsl(120, 100%, 40%);">+</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 style="color: hsl(120, 100%, 40%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+    {</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 touri[128];</span><br><span style="color: hsl(120, 100%, 40%);">+              char fromuri[128];</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%);">+                tdata_sip_uri = pjsip_uri_get_uri(tdata_name_addr->uri);</span><br><span style="color: hsl(120, 100%, 40%);">+           pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, touri, sizeof(touri));</span><br><span style="color: hsl(120, 100%, 40%);">+                tdata_name_addr = (pjsip_name_addr *) PJSIP_MSG_FROM_HDR(tdata->msg)->uri;</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%);">+           pjsip_uri_print(PJSIP_URI_IN_FROMTO_HDR, tdata_sip_uri, fromuri, sizeof(fromuri));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_test_suite_event_notify("MSG_FROMTO_URI",</span><br><span style="color: hsl(120, 100%, 40%);">+                       "MdataFrom: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                 "MsgFrom: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                   "MdataDestination: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                  "MsgTo: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                     "Endpoint: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                  "RequestURI: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "ToURI: %s\r\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                     "FromURI: %s\r\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                  mdata->from,</span><br><span style="color: hsl(120, 100%, 40%);">+                       ast_msg_get_from(mdata->msg),</span><br><span style="color: hsl(120, 100%, 40%);">+                      mdata->destination,</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_msg_get_to(mdata->msg),</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_sorcery_object_get_id(endpoint),</span><br><span style="color: hsl(120, 100%, 40%);">+                  uri,</span><br><span style="color: hsl(120, 100%, 40%);">+                  touri,</span><br><span style="color: hsl(120, 100%, 40%);">+                        fromuri</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%);">+#endif</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 +1332,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>@@ -717,17 +1349,17 @@</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static int sip_msg_send(const struct ast_msg *msg, const char *to, const char *from)</span><br><span style="color: hsl(120, 100%, 40%);">+static int sip_msg_send(const struct ast_msg *msg, const char *destination, const char *from)</span><br><span> {</span><br><span>   struct msg_data *mdata;</span><br><span>      int res;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (ast_strlen_zero(to)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ast_strlen_zero(destination)) {</span><br><span>          ast_log(LOG_ERROR, "SIP MESSAGE - a 'To' URI  must be specified\n");</span><br><span>               return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   mdata = msg_data_create(msg, to, from);</span><br><span style="color: hsl(120, 100%, 40%);">+       mdata = msg_data_create(msg, destination, from);</span><br><span>     if (!mdata) {</span><br><span>                return -1;</span><br><span>   }</span><br><span></span><br></pre><div style="white-space:pre-wrap"></div><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: 6 </div>
<div style="display:none"> Gerrit-Owner: George Joseph <gjoseph@digium.com> </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-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>