<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/<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/"display name" <sip[s]:host>"/></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name="endpoint/"display name" <sip[s]:user@host>"/></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="<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%);">+ <enum name=""display name" <sip[s]:host>"/></span><br><span style="color: hsl(120, 100%, 40%);">+ <enum name=""display name" <sip[s]:user@host>"/></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" <URI>.</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>