diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d033f82..96900b2a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,6 +489,7 @@ if(LIBUV_BUILD_TESTS) test/test-idna.c test/test-ip4-addr.c test/test-ip6-addr.c + test/test-ip-name.c test/test-ipc-heavy-traffic-deadlock-bug.c test/test-ipc-send-recv.c test/test-ipc.c diff --git a/Makefile.am b/Makefile.am index 3a2fba6d..4184a0a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -192,6 +192,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-idna.c \ test/test-ip4-addr.c \ test/test-ip6-addr.c \ + test/test-ip-name.c \ test/test-ipc-heavy-traffic-deadlock-bug.c \ test/test-ipc-send-recv.c \ test/test-ipc.c \ diff --git a/docs/src/misc.rst b/docs/src/misc.rst index 2fe6c1ce..8017e8e1 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -377,6 +377,10 @@ API Convert a binary structure containing an IPv6 address to a string. +.. c:function:: int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) + + Convert a binary structure containing an IPv4 address or an IPv6 address to a string. + .. c:function:: int uv_inet_ntop(int af, const void* src, char* dst, size_t size) .. c:function:: int uv_inet_pton(int af, const char* src, void* dst) diff --git a/include/uv.h b/include/uv.h index 79acd834..606083c8 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1660,6 +1660,7 @@ UV_EXTERN int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr); UV_EXTERN int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size); UV_EXTERN int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size); +UV_EXTERN int uv_ip_name(const struct sockaddr* src, char* dst, size_t size); UV_EXTERN int uv_inet_ntop(int af, const void* src, char* dst, size_t size); UV_EXTERN int uv_inet_pton(int af, const char* src, void* dst); diff --git a/src/uv-common.c b/src/uv-common.c index e81ed79b..b0d5822e 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -274,6 +274,20 @@ int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size) { } +int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) { + switch (src->sa_family) { + case AF_INET: + return uv_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, + dst, size); + case AF_INET6: + return uv_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr, + dst, size); + default: + return UV_EAFNOSUPPORT; + } +} + + int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr, unsigned int flags) { diff --git a/test/test-ip-name.c b/test/test-ip-name.c new file mode 100644 index 00000000..1cb1b605 --- /dev/null +++ b/test/test-ip-name.c @@ -0,0 +1,65 @@ +/* Copyright The libuv project and contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +#include +#include + +union TestAddr { + struct sockaddr addr; + struct sockaddr_in addr4; + struct sockaddr_in6 addr6; +}; + + +TEST_IMPL(ip_name) { + char dst[INET6_ADDRSTRLEN]; + union TestAddr test_addr; + struct sockaddr* addr = &test_addr.addr; + struct sockaddr_in* addr4 = &test_addr.addr4; + struct sockaddr_in6* addr6 = &test_addr.addr6; + + /* test ip4_name */ + ASSERT_EQ(0, uv_ip4_addr("192.168.0.1", TEST_PORT, addr4)); + ASSERT_EQ(0, uv_ip4_name(addr4, dst, INET_ADDRSTRLEN)); + ASSERT_EQ(0, strcmp("192.168.0.1", dst)); + + ASSERT_EQ(0, uv_ip_name(addr, dst, INET_ADDRSTRLEN)); + ASSERT_EQ(0, strcmp("192.168.0.1", dst)); + + /* test ip6_name */ + ASSERT_EQ(0, uv_ip6_addr("fe80::2acf:daff:fedd:342a", TEST_PORT, addr6)); + ASSERT_EQ(0, uv_ip6_name(addr6, dst, INET6_ADDRSTRLEN)); + ASSERT_EQ(0, strcmp("fe80::2acf:daff:fedd:342a", dst)); + + ASSERT_EQ(0, uv_ip_name(addr, dst, INET6_ADDRSTRLEN)); + ASSERT_EQ(0, strcmp("fe80::2acf:daff:fedd:342a", dst)); + + /* test other sa_family */ + addr->sa_family = AF_UNIX; + /* size is not a concern here */ + ASSERT_EQ(UV_EAFNOSUPPORT, uv_ip_name(addr, dst, INET6_ADDRSTRLEN)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/test/test-list.h b/test/test-list.h index 3141a7cb..e0b247f4 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -460,6 +460,7 @@ TEST_DECLARE (poll_multiple_handles) TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) +TEST_DECLARE (ip_name) TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_closesocket) @@ -1106,6 +1107,7 @@ TASK_LIST_START TEST_ENTRY (dlerror) TEST_ENTRY (ip4_addr) TEST_ENTRY (ip6_addr_link_local) + TEST_ENTRY (ip_name) TEST_ENTRY (queue_foreach_delete)