<p>Sean Bright has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/10013">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjsip: Add utility functions to convert between socket structures<br><br>Currently, to convert from a pj_sockaddr to an ast_sockaddr, the address<br>needs to be rendered to a string and then parsed into the correct<br>structure. This also involves a call to getaddrinfo(3). The same is true<br>for the inverse operation.<br><br>Instead, because we know the internal structure of both ast_sockaddr and<br>pj_sockaddr, we can translate directly between the two without the<br>need for an intermediate string.<br><br>Change-Id: If0fc4bba9643f755604c6ffbb0d7cc46020bc761<br>---<br>M include/asterisk/res_pjsip.h<br>M res/res_pjsip.c<br>2 files changed, 181 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/13/10013/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h</span><br><span>index 17282d6..1adbd7f 100644</span><br><span>--- a/include/asterisk/res_pjsip.h</span><br><span>+++ b/include/asterisk/res_pjsip.h</span><br><span>@@ -3211,4 +3211,28 @@</span><br><span>  */</span><br><span> void ast_sip_transport_state_unregister(struct ast_sip_tpmgr_state_callback *element);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Fill a pj_sockaddr from an ast_sockaddr</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.23.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param addr The source address to copy</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param pjaddr The target address to receive the copied address</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pjaddr);</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%);">+ * \brief Fill an ast_sockaddr from a pj_sockaddr</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 13.23.0</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param addr The target address to receive the copied address</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param pjaddr The source address to copy</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval 0 Success</span><br><span style="color: hsl(120, 100%, 40%);">+ * \retval -1 Failure</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #endif /* _RES_PJSIP_H */</span><br><span>diff --git a/res/res_pjsip.c b/res/res_pjsip.c</span><br><span>index ece03d3..50e1e18 100644</span><br><span>--- a/res/res_pjsip.c</span><br><span>+++ b/res/res_pjsip.c</span><br><span>@@ -4759,6 +4759,50 @@</span><br><span>   return ast_threadpool_queue_size(sip_threadpool);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pjaddr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(pjaddr, 0, sizeof(*pjaddr));</span><br><span style="color: hsl(120, 100%, 40%);">+   if (addr->ss.ss_family == AF_INET) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;</span><br><span style="color: hsl(120, 100%, 40%);">+            pjaddr->ipv4.sin_family = pj_AF_INET();</span><br><span style="color: hsl(120, 100%, 40%);">+            pjaddr->ipv4.sin_addr   = sin->sin_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                pjaddr->ipv4.sin_port   = sin->sin_port;</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (addr->ss.ss_family == AF_INET6) {</span><br><span style="color: hsl(120, 100%, 40%);">+               struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;</span><br><span style="color: hsl(120, 100%, 40%);">+          pjaddr->ipv6.sin6_family   = pj_AF_INET6();</span><br><span style="color: hsl(120, 100%, 40%);">+                pjaddr->ipv6.sin6_port     = sin->sin6_port;</span><br><span style="color: hsl(120, 100%, 40%);">+            pjaddr->ipv6.sin6_flowinfo = sin->sin6_flowinfo;</span><br><span style="color: hsl(120, 100%, 40%);">+                pjaddr->ipv6.sin6_scope_id = sin->sin6_scope_id;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(&pjaddr->ipv6.sin6_addr, &sin->sin6_addr, sizeof(pjaddr->ipv6.sin6_addr));</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</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%);">+     return 0;</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%);">+int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(addr, 0, sizeof(*addr));</span><br><span style="color: hsl(120, 100%, 40%);">+       if (pjaddr->addr.sa_family == pj_AF_INET()) {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;</span><br><span style="color: hsl(120, 100%, 40%);">+            sin->sin_family = AF_INET;</span><br><span style="color: hsl(120, 100%, 40%);">+         sin->sin_addr   = pjaddr->ipv4.sin_addr;</span><br><span style="color: hsl(120, 100%, 40%);">+                sin->sin_port   = pjaddr->ipv4.sin_port;</span><br><span style="color: hsl(120, 100%, 40%);">+                addr->len = sizeof(struct sockaddr_in);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else if (pjaddr->addr.sa_family == pj_AF_INET6()) {</span><br><span style="color: hsl(120, 100%, 40%);">+              struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;</span><br><span style="color: hsl(120, 100%, 40%);">+          sin->sin6_family   = AF_INET6;</span><br><span style="color: hsl(120, 100%, 40%);">+             sin->sin6_port     = pjaddr->ipv6.sin6_port;</span><br><span style="color: hsl(120, 100%, 40%);">+            sin->sin6_flowinfo = pjaddr->ipv6.sin6_flowinfo;</span><br><span style="color: hsl(120, 100%, 40%);">+                sin->sin6_scope_id = pjaddr->ipv6.sin6_scope_id;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(&sin->sin6_addr, &pjaddr->ipv6.sin6_addr, sizeof(sin->sin6_addr));</span><br><span style="color: hsl(120, 100%, 40%);">+            addr->len = sizeof(struct sockaddr_in6);</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</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%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef TEST_FRAMEWORK</span><br><span> AST_TEST_DEFINE(xml_sanitization_end_null)</span><br><span> {</span><br><span>@@ -4810,6 +4854,115 @@</span><br><span> </span><br><span>     return AST_TEST_PASS;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(ast_sockaddr_to_pj_sockaddr_test)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *candidates[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                "127.0.0.1:5555",</span><br><span style="color: hsl(120, 100%, 40%);">+           "[::]:4444",</span><br><span style="color: hsl(120, 100%, 40%);">+                "192.168.0.100:0",</span><br><span style="color: hsl(120, 100%, 40%);">+          "[fec0::1:80]:0",</span><br><span style="color: hsl(120, 100%, 40%);">+           "[fec0::1]:80",</span><br><span style="color: hsl(120, 100%, 40%);">+             NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ }, **candidate = candidates;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "ast_sockaddr_to_pj_sockaddr_test";</span><br><span style="color: hsl(120, 100%, 40%);">+         info->category = "/res/res_pjsip/";</span><br><span style="color: hsl(120, 100%, 40%);">+              info->summary = "Validate conversions from an ast_sockaddr to a pj_sockaddr";</span><br><span style="color: hsl(120, 100%, 40%);">+            info->description = "This test converts an ast_sockaddr to a pj_sockaddr and validates\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "that the two evaluate to the same string when formatted.";</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</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%);">+   while (*candidate) {</span><br><span style="color: hsl(120, 100%, 40%);">+          struct ast_sockaddr addr = {{0,}};</span><br><span style="color: hsl(120, 100%, 40%);">+            pj_sockaddr pjaddr;</span><br><span style="color: hsl(120, 100%, 40%);">+           char buffer[512];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!ast_sockaddr_parse(&addr, *candidate, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_test_status_update(test, "Failed to parse candidate IP: %s\n", *candidate);</span><br><span style="color: hsl(120, 100%, 40%);">+                     return AST_TEST_FAIL;</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_sockaddr_to_pj_sockaddr(&addr, &pjaddr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_test_status_update(test, "Failed to convert ast_sockaddr to pj_sockaddr: %s\n", *candidate);</span><br><span style="color: hsl(120, 100%, 40%);">+                    return AST_TEST_FAIL;</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%);">+           pj_sockaddr_print(&pjaddr, buffer, sizeof(buffer), 1 | 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              if (strcmp(*candidate, buffer)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_test_status_update(test, "Converted sockaddrs do not match: \"%s\" and \"%s\"\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           *candidate,</span><br><span style="color: hsl(120, 100%, 40%);">+                           buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return AST_TEST_FAIL;</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%);">+           candidate++;</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 AST_TEST_PASS;</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%);">+AST_TEST_DEFINE(ast_sockaddr_from_pj_sockaddr_test)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    char *candidates[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                "127.0.0.1:5555",</span><br><span style="color: hsl(120, 100%, 40%);">+           "[::]:4444",</span><br><span style="color: hsl(120, 100%, 40%);">+                "192.168.0.100:0",</span><br><span style="color: hsl(120, 100%, 40%);">+          "[fec0::1:80]:0",</span><br><span style="color: hsl(120, 100%, 40%);">+           "[fec0::1]:80",</span><br><span style="color: hsl(120, 100%, 40%);">+             NULL,</span><br><span style="color: hsl(120, 100%, 40%);">+ }, **candidate = candidates;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+               info->name = "ast_sockaddr_from_pj_sockaddr_test";</span><br><span style="color: hsl(120, 100%, 40%);">+               info->category = "/res/res_pjsip/";</span><br><span style="color: hsl(120, 100%, 40%);">+              info->summary = "Validate conversions from a pj_sockaddr to an ast_sockaddr";</span><br><span style="color: hsl(120, 100%, 40%);">+            info->description = "This test converts a pj_sockaddr to an ast_sockaddr and validates\n"</span><br><span style="color: hsl(120, 100%, 40%);">+                        "that the two evaluate to the same string when formatted.";</span><br><span style="color: hsl(120, 100%, 40%);">+         return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+      case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+            break;</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%);">+   while (*candidate) {</span><br><span style="color: hsl(120, 100%, 40%);">+          struct ast_sockaddr addr = {{0,}};</span><br><span style="color: hsl(120, 100%, 40%);">+            pj_sockaddr pjaddr;</span><br><span style="color: hsl(120, 100%, 40%);">+           pj_str_t t;</span><br><span style="color: hsl(120, 100%, 40%);">+           char buffer[512];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+           pj_strset(&t, *candidate, strlen(*candidate));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if (pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &t, &pjaddr) != PJ_SUCCESS) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        ast_test_status_update(test, "Failed to parse candidate IP: %s\n", *candidate);</span><br><span style="color: hsl(120, 100%, 40%);">+                     return AST_TEST_FAIL;</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_sockaddr_from_pj_sockaddr(&addr, &pjaddr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  ast_test_status_update(test, "Failed to convert pj_sockaddr to ast_sockaddr: %s\n", *candidate);</span><br><span style="color: hsl(120, 100%, 40%);">+                    return AST_TEST_FAIL;</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%);">+           snprintf(buffer, sizeof(buffer), "%s", ast_sockaddr_stringify(&addr));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                if (strcmp(*candidate, buffer)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_test_status_update(test, "Converted sockaddrs do not match: \"%s\" and \"%s\"\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                           *candidate,</span><br><span style="color: hsl(120, 100%, 40%);">+                           buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+                      return AST_TEST_FAIL;</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%);">+           candidate++;</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 AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> #endif</span><br><span> </span><br><span> /*!</span><br><span>@@ -5046,6 +5199,8 @@</span><br><span> </span><br><span>    AST_TEST_REGISTER(xml_sanitization_end_null);</span><br><span>        AST_TEST_REGISTER(xml_sanitization_exceeds_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+   AST_TEST_REGISTER(ast_sockaddr_to_pj_sockaddr_test);</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_TEST_REGISTER(ast_sockaddr_from_pj_sockaddr_test);</span><br><span> </span><br><span>   ast_pjproject_ref();</span><br><span> </span><br><span>@@ -5080,6 +5235,8 @@</span><br><span> {</span><br><span>        AST_TEST_UNREGISTER(xml_sanitization_end_null);</span><br><span>      AST_TEST_UNREGISTER(xml_sanitization_exceeds_buffer);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(ast_sockaddr_to_pj_sockaddr_test);</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_TEST_UNREGISTER(ast_sockaddr_from_pj_sockaddr_test);</span><br><span>     ast_cli_unregister_multiple(cli_commands, ARRAY_LEN(cli_commands));</span><br><span> </span><br><span>      /* The thread this is called from cannot call PJSIP/PJLIB functions,</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10013">change 10013</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/10013"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: If0fc4bba9643f755604c6ffbb0d7cc46020bc761 </div>
<div style="display:none"> Gerrit-Change-Number: 10013 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>