[Asterisk-code-review] res pjproject: Add utility functions to convert between sock... (asterisk[master])
Joshua Colp
asteriskteam at digium.com
Fri Sep 7 04:47:41 CDT 2018
Joshua Colp has submitted this change and it was merged. ( https://gerrit.asterisk.org/10046 )
Change subject: res_pjproject: Add utility functions to convert between socket structures
......................................................................
res_pjproject: Add utility functions to convert between socket structures
Currently, to convert from a pj_sockaddr to an ast_sockaddr, the address
needs to be rendered to a string and then parsed into the correct
structure. This also involves a call to getaddrinfo(3). The same is true
for the inverse operation.
Instead, because we know the internal structure of both ast_sockaddr and
pj_sockaddr, we can translate directly between the two without the
need for an intermediate string.
Change-Id: If0fc4bba9643f755604c6ffbb0d7cc46020bc761
---
M include/asterisk/res_pjproject.h
M res/res_pjproject.c
M res/res_pjproject.exports.in
3 files changed, 205 insertions(+), 1 deletion(-)
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
diff --git a/include/asterisk/res_pjproject.h b/include/asterisk/res_pjproject.h
index 17ebdd2..d195c0f 100644
--- a/include/asterisk/res_pjproject.h
+++ b/include/asterisk/res_pjproject.h
@@ -22,6 +22,8 @@
#include <pj/types.h>
#include <pj/pool.h>
+struct ast_sockaddr;
+
/*!
* \brief Retrieve a pjproject build option
*
@@ -97,4 +99,28 @@
*/
void ast_pjproject_caching_pool_destroy(pj_caching_pool *cp);
+/*!
+ * \brief Fill a pj_sockaddr from an ast_sockaddr
+ * \since 13.24.0
+ *
+ * \param addr The source address to copy
+ * \param pjaddr The target address to receive the copied address
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pjaddr);
+
+/*!
+ * \brief Fill an ast_sockaddr from a pj_sockaddr
+ * \since 13.24.0
+ *
+ * \param addr The target address to receive the copied address
+ * \param pjaddr The source address to copy
+ *
+ * \retval 0 Success
+ * \retval -1 Failure
+ */
+int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr);
+
#endif /* _RES_PJPROJECT_H */
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index ebd71b9..5b133ec 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -110,6 +110,8 @@
#include "asterisk/res_pjproject.h"
#include "asterisk/vector.h"
#include "asterisk/sorcery.h"
+#include "asterisk/test.h"
+#include "asterisk/netsock2.h"
static struct ast_sorcery *pjproject_sorcery;
static pj_log_func *log_cb_orig;
@@ -471,6 +473,176 @@
pj_caching_pool_destroy(cp);
}
+int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pjaddr)
+{
+ if (addr->ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
+ pjaddr->ipv4.sin_family = pj_AF_INET();
+ pjaddr->ipv4.sin_addr = sin->sin_addr;
+ pjaddr->ipv4.sin_port = sin->sin_port;
+ } else if (addr->ss.ss_family == AF_INET6) {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;
+ pjaddr->ipv6.sin6_family = pj_AF_INET6();
+ pjaddr->ipv6.sin6_port = sin->sin6_port;
+ pjaddr->ipv6.sin6_flowinfo = sin->sin6_flowinfo;
+ pjaddr->ipv6.sin6_scope_id = sin->sin6_scope_id;
+ memcpy(&pjaddr->ipv6.sin6_addr, &sin->sin6_addr, sizeof(pjaddr->ipv6.sin6_addr));
+ } else {
+ memset(pjaddr, 0, sizeof(*pjaddr));
+ return -1;
+ }
+ return 0;
+}
+
+int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *pjaddr)
+{
+ if (pjaddr->addr.sa_family == pj_AF_INET()) {
+ struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
+ sin->sin_family = AF_INET;
+ sin->sin_addr = pjaddr->ipv4.sin_addr;
+ sin->sin_port = pjaddr->ipv4.sin_port;
+ addr->len = sizeof(struct sockaddr_in);
+ } else if (pjaddr->addr.sa_family == pj_AF_INET6()) {
+ struct sockaddr_in6 *sin = (struct sockaddr_in6 *) &addr->ss;
+ sin->sin6_family = AF_INET6;
+ sin->sin6_port = pjaddr->ipv6.sin6_port;
+ sin->sin6_flowinfo = pjaddr->ipv6.sin6_flowinfo;
+ sin->sin6_scope_id = pjaddr->ipv6.sin6_scope_id;
+ memcpy(&sin->sin6_addr, &pjaddr->ipv6.sin6_addr, sizeof(sin->sin6_addr));
+ addr->len = sizeof(struct sockaddr_in6);
+ } else {
+ memset(addr, 0, sizeof(*addr));
+ return -1;
+ }
+ return 0;
+}
+
+#ifdef TEST_FRAMEWORK
+static void fill_with_garbage(void *x, ssize_t len)
+{
+ unsigned char *w = x;
+ while (len > 0) {
+ int r = ast_random();
+ memcpy(w, &r, len > sizeof(r) ? sizeof(r) : len);
+ w += sizeof(r);
+ len -= sizeof(r);
+ }
+}
+
+AST_TEST_DEFINE(ast_sockaddr_to_pj_sockaddr_test)
+{
+ char *candidates[] = {
+ "127.0.0.1:5555",
+ "[::]:4444",
+ "192.168.0.100:0",
+ "[fec0::1:80]:0",
+ "[fec0::1]:80",
+ NULL,
+ }, **candidate = candidates;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "ast_sockaddr_to_pj_sockaddr_test";
+ info->category = "/res/res_pjproject/";
+ info->summary = "Validate conversions from an ast_sockaddr to a pj_sockaddr";
+ info->description = "This test converts an ast_sockaddr to a pj_sockaddr and validates\n"
+ "that the two evaluate to the same string when formatted.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ while (*candidate) {
+ struct ast_sockaddr addr = {{0,}};
+ pj_sockaddr pjaddr;
+ char buffer[512];
+
+ fill_with_garbage(&pjaddr, sizeof(pj_sockaddr));
+
+ if (!ast_sockaddr_parse(&addr, *candidate, 0)) {
+ ast_test_status_update(test, "Failed to parse candidate IP: %s\n", *candidate);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_sockaddr_to_pj_sockaddr(&addr, &pjaddr)) {
+ ast_test_status_update(test, "Failed to convert ast_sockaddr to pj_sockaddr: %s\n", *candidate);
+ return AST_TEST_FAIL;
+ }
+
+ pj_sockaddr_print(&pjaddr, buffer, sizeof(buffer), 1 | 2);
+
+ if (strcmp(*candidate, buffer)) {
+ ast_test_status_update(test, "Converted sockaddrs do not match: \"%s\" and \"%s\"\n",
+ *candidate,
+ buffer);
+ return AST_TEST_FAIL;
+ }
+
+ candidate++;
+ }
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(ast_sockaddr_from_pj_sockaddr_test)
+{
+ char *candidates[] = {
+ "127.0.0.1:5555",
+ "[::]:4444",
+ "192.168.0.100:0",
+ "[fec0::1:80]:0",
+ "[fec0::1]:80",
+ NULL,
+ }, **candidate = candidates;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "ast_sockaddr_from_pj_sockaddr_test";
+ info->category = "/res/res_pjproject/";
+ info->summary = "Validate conversions from a pj_sockaddr to an ast_sockaddr";
+ info->description = "This test converts a pj_sockaddr to an ast_sockaddr and validates\n"
+ "that the two evaluate to the same string when formatted.";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ while (*candidate) {
+ struct ast_sockaddr addr = {{0,}};
+ pj_sockaddr pjaddr;
+ pj_str_t t;
+ char buffer[512];
+
+ fill_with_garbage(&addr, sizeof(addr));
+
+ pj_strset(&t, *candidate, strlen(*candidate));
+
+ if (pj_sockaddr_parse(pj_AF_UNSPEC(), 0, &t, &pjaddr) != PJ_SUCCESS) {
+ ast_test_status_update(test, "Failed to parse candidate IP: %s\n", *candidate);
+ return AST_TEST_FAIL;
+ }
+
+ if (ast_sockaddr_from_pj_sockaddr(&addr, &pjaddr)) {
+ ast_test_status_update(test, "Failed to convert pj_sockaddr to ast_sockaddr: %s\n", *candidate);
+ return AST_TEST_FAIL;
+ }
+
+ snprintf(buffer, sizeof(buffer), "%s", ast_sockaddr_stringify(&addr));
+
+ if (strcmp(*candidate, buffer)) {
+ ast_test_status_update(test, "Converted sockaddrs do not match: \"%s\" and \"%s\"\n",
+ *candidate,
+ buffer);
+ return AST_TEST_FAIL;
+ }
+
+ candidate++;
+ }
+
+ return AST_TEST_PASS;
+}
+#endif
+
static int load_module(void)
{
ast_debug(3, "Starting PJPROJECT logging to Asterisk logger\n");
@@ -540,6 +712,9 @@
ast_cli_register_multiple(pjproject_cli, ARRAY_LEN(pjproject_cli));
+ AST_TEST_REGISTER(ast_sockaddr_to_pj_sockaddr_test);
+ AST_TEST_REGISTER(ast_sockaddr_from_pj_sockaddr_test);
+
return AST_MODULE_LOAD_SUCCESS;
}
@@ -563,6 +738,9 @@
ast_sorcery_unref(pjproject_sorcery);
+ AST_TEST_UNREGISTER(ast_sockaddr_to_pj_sockaddr_test);
+ AST_TEST_UNREGISTER(ast_sockaddr_from_pj_sockaddr_test);
+
return 0;
}
diff --git a/res/res_pjproject.exports.in b/res/res_pjproject.exports.in
index f1821a6..c823197 100644
--- a/res/res_pjproject.exports.in
+++ b/res/res_pjproject.exports.in
@@ -1,6 +1,6 @@
{
global:
- LINKER_SYMBOL_PREFIXast_pjproject_*;
+ LINKER_SYMBOL_PREFIXast_*;
local:
*;
};
--
To view, visit https://gerrit.asterisk.org/10046
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings
Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: If0fc4bba9643f755604c6ffbb0d7cc46020bc761
Gerrit-Change-Number: 10046
Gerrit-PatchSet: 3
Gerrit-Owner: Sean Bright <sean.bright at gmail.com>
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Jenkins2
Gerrit-Reviewer: Joshua Colp <jcolp at digium.com>
Gerrit-Reviewer: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Michael L. Young <elgueromexicano at gmail.com>
Gerrit-Reviewer: Richard Mudgett <rmudgett at digium.com>
Gerrit-Reviewer: Sean Bright <sean.bright at gmail.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20180907/2c335c2c/attachment-0001.html>
More information about the asterisk-code-review
mailing list