diff --git a/src/SyncClient.cpp b/src/SyncClient.cpp index 953106a..679be12 100644 --- a/src/SyncClient.cpp +++ b/src/SyncClient.cpp @@ -8,6 +8,7 @@ #include #endif +#include #include #include #include @@ -101,6 +102,7 @@ static std::string string_join(std::vector const& srcs, static bool dns_resolve(std::string const& target, std::vector& endpoints, bool ipv4 = true) { std::vector target_parts; + bool ipv6_url{false}; { size_t rindex = target.rfind(':'); if (rindex == target.npos) { @@ -110,7 +112,17 @@ static bool dns_resolve(std::string const& target, #endif return false; } - target_parts.push_back(target.substr(0, rindex)); + + std::string host(target.substr(0, rindex)); + + // host format is [ipv6] + if (!ipv4 && !host.empty() && host[0] == '[' && + host[host.size() - 1] == ']') { + host = target.substr(1, rindex - 2); + ipv6_url = true; + } + + target_parts.push_back(host); target_parts.push_back(target.substr(rindex + 1)); } @@ -132,6 +144,16 @@ static bool dns_resolve(std::string const& target, } #endif + if (ipv6_url) { + // check valid ipv6 + struct sockaddr_in6 sa6; + if (inet_pton(AF_INET6, target_parts[0].c_str(), &(sa6.sin6_addr)) == 1) { + endpoints.emplace_back(target); + return true; + } + return false; + } + struct addrinfo hints = {}, *addrs; hints.ai_family = ipv4 ? AF_INET : AF_INET6; hints.ai_socktype = SOCK_STREAM; diff --git a/tst/EtcdResolverTest.cpp b/tst/EtcdResolverTest.cpp index 2d00bf6..14f7ad1 100644 --- a/tst/EtcdResolverTest.cpp +++ b/tst/EtcdResolverTest.cpp @@ -9,6 +9,9 @@ static const std::string etcd_v4_url = etcdv3::detail::resolve_etcd_endpoints("http://127.0.0.1:2379"); static const std::string etcd_v6_url = etcdv3::detail::resolve_etcd_endpoints("http://::1:2379"); +// http://[ipv6]:port url +static const std::string etcd_ipv6_url = + etcdv3::detail::resolve_etcd_endpoints("http://[::1]:2379"); TEST_CASE("test ipv4 connection") { std::cout << "ipv4 endpoints: " << etcd_v4_url << std::endl; @@ -20,4 +23,8 @@ TEST_CASE("test ipv6 connection") { std::cout << "ipv6 endpoints: " << etcd_v6_url << std::endl; etcd::Client etcd(etcd_v6_url); REQUIRE(etcd.head().get().is_ok()); + + std::cout << "ipv6 endpoints: " << etcd_ipv6_url << std::endl; + etcd::Client etcd1(etcd_ipv6_url); + REQUIRE(etcd1.head().get().is_ok()); }