<p>Joshua Colp <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10044">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Richard Mudgett: Looks good to me, but someone else must approve
  Michael L. Young: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Joshua Colp: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_pjproject: 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_pjproject.h<br>M res/res_pjproject.c<br>M res/res_pjproject.exports.in<br>3 files changed, 205 insertions(+), 1 deletion(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/asterisk/res_pjproject.h b/include/asterisk/res_pjproject.h</span><br><span>index 27a2096..844698a 100644</span><br><span>--- a/include/asterisk/res_pjproject.h</span><br><span>+++ b/include/asterisk/res_pjproject.h</span><br><span>@@ -22,6 +22,8 @@</span><br><span> #include <pj/types.h></span><br><span> #include <pj/pool.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_sockaddr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Determines whether the res_pjproject module is loaded */</span><br><span> #define CHECK_PJPROJECT_MODULE_LOADED()                 \</span><br><span>   do {                                                \</span><br><span>@@ -119,4 +121,28 @@</span><br><span>  */</span><br><span> void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp);</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.24.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.24.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_PJPROJECT_H */</span><br><span>diff --git a/res/res_pjproject.c b/res/res_pjproject.c</span><br><span>index 8f7e823..0da72b4 100644</span><br><span>--- a/res/res_pjproject.c</span><br><span>+++ b/res/res_pjproject.c</span><br><span>@@ -110,6 +110,8 @@</span><br><span> #include "asterisk/res_pjproject.h"</span><br><span> #include "asterisk/vector.h"</span><br><span> #include "asterisk/sorcery.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/netsock2.h"</span><br><span> </span><br><span> static struct ast_sorcery *pjproject_sorcery;</span><br><span> static pj_log_func *log_cb_orig;</span><br><span>@@ -481,6 +483,176 @@</span><br><span>  pj_caching_pool_destroy(cp);</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%);">+       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%);">+              memset(pjaddr, 0, sizeof(*pjaddr));</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%);">+    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%);">+              memset(addr, 0, sizeof(*addr));</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%);">+#ifdef TEST_FRAMEWORK</span><br><span style="color: hsl(120, 100%, 40%);">+static void fill_with_garbage(void *x, ssize_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned char *w = x;</span><br><span style="color: hsl(120, 100%, 40%);">+ while (len > 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int r = ast_random();</span><br><span style="color: hsl(120, 100%, 40%);">+         memcpy(w, &r, len > sizeof(r) ? sizeof(r) : len);</span><br><span style="color: hsl(120, 100%, 40%);">+              w += sizeof(r);</span><br><span style="color: hsl(120, 100%, 40%);">+               len -= sizeof(r);</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%);">+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_pjproject/";</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%);">+           fill_with_garbage(&pjaddr, sizeof(pj_sockaddr));</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_pjproject/";</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%);">+           fill_with_garbage(&addr, sizeof(addr));</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 style="color: hsl(120, 100%, 40%);">+#endif</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int load_module(void)</span><br><span> {</span><br><span>      ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");</span><br><span>@@ -550,6 +722,9 @@</span><br><span> </span><br><span>         ast_cli_register_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli));</span><br><span> </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 style="color: hsl(120, 100%, 40%);">+</span><br><span>     return AST_MODULE_LOAD_SUCCESS;</span><br><span> }</span><br><span> </span><br><span>@@ -573,6 +748,9 @@</span><br><span> </span><br><span>   ast_sorcery_unref(pjproject_sorcery);</span><br><span> </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 style="color: hsl(120, 100%, 40%);">+</span><br><span>   return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/res/res_pjproject.exports.in b/res/res_pjproject.exports.in</span><br><span>index f1821a6..c823197 100644</span><br><span>--- a/res/res_pjproject.exports.in</span><br><span>+++ b/res/res_pjproject.exports.in</span><br><span>@@ -1,6 +1,6 @@</span><br><span> {</span><br><span>       global:</span><br><span style="color: hsl(0, 100%, 40%);">-         LINKER_SYMBOL_PREFIXast_pjproject_*;</span><br><span style="color: hsl(120, 100%, 40%);">+          LINKER_SYMBOL_PREFIXast_*;</span><br><span>   local:</span><br><span>               *;</span><br><span> };</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10044">change 10044</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/10044"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 15 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If0fc4bba9643f755604c6ffbb0d7cc46020bc761 </div>
<div style="display:none"> Gerrit-Change-Number: 10044 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Sean Bright <sean.bright@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Michael L. Young <elgueromexicano@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Richard Mudgett <rmudgett@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Sean Bright <sean.bright@gmail.com> </div>