summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjim <jim@13f79535-47bb-0310-9956-ffa450edef68>2014-04-28 18:12:01 +0000
committerjim <jim@13f79535-47bb-0310-9956-ffa450edef68>2014-04-28 18:12:01 +0000
commit3b3ed9d579991987b7945a79f4af9724340db3d4 (patch)
tree26b6c47cb17fa119ef7b6bf11c05f59cf531fcfd
parenta4b960aa84162b8593d82967c074b2cab0c4f9ff (diff)
downloadlibapr-3b3ed9d579991987b7945a79f4af9724340db3d4.tar.gz
Merge r1587045, r1587543 from trunk:
Add apr_sockaddr_info_copy(), for making a deep copy of an apr_sockaddr_t into a specified pool. Submitted by: Yann Ylavic <ylavic.dev gmail.com> Reviewed by: trawick Add testcase for apr_sockaddr_info_copy() Submitted by: Yann Ylavic <ylavic.dev gmail.com> Reviewed by: trawick Submitted by: trawick Reviewed/backported by: jim git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.6.x@1590729 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES4
-rw-r--r--include/apr_network_io.h10
-rw-r--r--network_io/unix/sockaddr.c36
-rw-r--r--test/testsock.c51
4 files changed, 101 insertions, 0 deletions
diff --git a/CHANGES b/CHANGES
index 3cbed173d..6c22eda1e 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,10 @@
-*- coding: utf-8 -*-
Changes for APR 1.6.0
+ *) Add apr_sockaddr_info_copy(), for making a deep copy of an
+ apr_sockaddr_t into a specified pool. [Yann Ylavic
+ <ylavic.dev gmail.com>]
+
*) Added Unix domain socket support.
[Mladen Turk]
diff --git a/include/apr_network_io.h b/include/apr_network_io.h
index 180bb8f58..5d07ef201 100644
--- a/include/apr_network_io.h
+++ b/include/apr_network_io.h
@@ -429,6 +429,16 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
apr_pool_t *p);
/**
+ * Copy apr_sockaddr_t src to dst on pool p.
+ * @param dst The destination apr_sockaddr_t.
+ * @param src The source apr_sockaddr_t.
+ * @param p The pool for the apr_sockaddr_t and associated storage.
+ */
+APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst,
+ const apr_sockaddr_t *src,
+ apr_pool_t *p);
+
+/**
* Look up the host name from an apr_sockaddr_t.
* @param hostname The hostname.
* @param sa The apr_sockaddr_t.
diff --git a/network_io/unix/sockaddr.c b/network_io/unix/sockaddr.c
index 03ac1fddf..5b7859729 100644
--- a/network_io/unix/sockaddr.c
+++ b/network_io/unix/sockaddr.c
@@ -661,6 +661,42 @@ APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
return find_addresses(sa, hostname, family, port, flags, p);
}
+APR_DECLARE(apr_status_t) apr_sockaddr_info_copy(apr_sockaddr_t **dst,
+ const apr_sockaddr_t *src,
+ apr_pool_t *p)
+{
+ apr_sockaddr_t *d;
+ const apr_sockaddr_t *s;
+
+ for (*dst = d = NULL, s = src; s; s = s->next) {
+ if (!d) {
+ *dst = d = apr_pmemdup(p, s, sizeof *s);
+ }
+ else {
+ d = d->next = apr_pmemdup(p, s, sizeof *s);
+ }
+ if (s->hostname) {
+ if (s == src || s->hostname != src->hostname) {
+ d->hostname = apr_pstrdup(p, s->hostname);
+ }
+ else {
+ d->hostname = (*dst)->hostname;
+ }
+ }
+ if (s->servname) {
+ if (s == src || s->servname != src->servname) {
+ d->servname = apr_pstrdup(p, s->servname);
+ }
+ else {
+ d->servname = (*dst)->servname;
+ }
+ }
+ d->pool = p;
+ apr_sockaddr_vars_set(d, s->family, s->port);
+ }
+ return APR_SUCCESS;
+}
+
APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname,
apr_sockaddr_t *sockaddr,
apr_int32_t flags)
diff --git a/test/testsock.c b/test/testsock.c
index e80d25c3f..909f8c392 100644
--- a/test/testsock.c
+++ b/test/testsock.c
@@ -97,6 +97,56 @@ static void test_addr_info(abts_case *tc, void *data)
ABTS_INT_EQUAL(tc, 0, ntohs(sa->sa.sin.sin_port));
}
+static void test_addr_copy(abts_case *tc, void *data)
+{
+ apr_status_t rv;
+ apr_sockaddr_t *sa1, *sa2;
+ int rc;
+ const char *hosts[] = {
+ "127.0.0.1",
+#if APR_HAVE_IPV6
+ "::1",
+#endif
+ NULL
+ }, **host = hosts;
+
+ /* Loop up to and including NULL */
+ do {
+ rv = apr_sockaddr_info_get(&sa1, *host, APR_UNSPEC, 80, 0, p);
+ APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv);
+
+ rv = apr_sockaddr_info_copy(&sa2, sa1, p);
+ APR_ASSERT_SUCCESS(tc, "Problem copying sockaddr", rv);
+
+ ABTS_PTR_NOTNULL(tc, sa1);
+ do {
+ ABTS_PTR_NOTNULL(tc, sa2);
+
+ rc = apr_sockaddr_equal(sa2, sa1);
+ ABTS_INT_NEQUAL(tc, 0, rc);
+ ABTS_INT_EQUAL(tc, 80, sa1->port);
+ ABTS_INT_EQUAL(tc, sa2->port, sa1->port);
+ ABTS_INT_EQUAL(tc, 80, ntohs(sa1->sa.sin.sin_port));
+ ABTS_INT_EQUAL(tc, ntohs(sa2->sa.sin.sin_port), ntohs(sa1->sa.sin.sin_port));
+
+ if (*host) {
+ ABTS_PTR_NOTNULL(tc, sa1->hostname);
+ ABTS_PTR_NOTNULL(tc, sa2->hostname);
+ ABTS_STR_EQUAL(tc, *host, sa1->hostname);
+ ABTS_STR_EQUAL(tc, sa1->hostname, sa2->hostname);
+ ABTS_TRUE(tc, sa1->hostname != sa2->hostname);
+ }
+ else {
+ ABTS_PTR_EQUAL(tc, NULL, sa1->hostname);
+ ABTS_PTR_EQUAL(tc, NULL, sa2->hostname);
+ }
+
+ } while ((sa2 = sa2->next, sa1 = sa1->next));
+ ABTS_PTR_EQUAL(tc, NULL, sa2);
+
+ } while (*host++);
+}
+
static void test_serv_by_name(abts_case *tc, void *data)
{
apr_status_t rv;
@@ -499,6 +549,7 @@ abts_suite *testsock(abts_suite *suite)
suite = ADD_SUITE(suite)
socket_name = IPV4_SOCKET_NAME;
abts_run_test(suite, test_addr_info, NULL);
+ abts_run_test(suite, test_addr_copy, NULL);
abts_run_test(suite, test_serv_by_name, NULL);
abts_run_test(suite, test_create_bind_listen, NULL);
abts_run_test(suite, test_send, NULL);