diff options
author | jim <jim@13f79535-47bb-0310-9956-ffa450edef68> | 2014-04-28 18:12:01 +0000 |
---|---|---|
committer | jim <jim@13f79535-47bb-0310-9956-ffa450edef68> | 2014-04-28 18:12:01 +0000 |
commit | 3b3ed9d579991987b7945a79f4af9724340db3d4 (patch) | |
tree | 26b6c47cb17fa119ef7b6bf11c05f59cf531fcfd | |
parent | a4b960aa84162b8593d82967c074b2cab0c4f9ff (diff) | |
download | libapr-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-- | CHANGES | 4 | ||||
-rw-r--r-- | include/apr_network_io.h | 10 | ||||
-rw-r--r-- | network_io/unix/sockaddr.c | 36 | ||||
-rw-r--r-- | test/testsock.c | 51 |
4 files changed, 101 insertions, 0 deletions
@@ -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); |