feature:support ipv6 address (#280)
Problem Summary: Now the etcd client address do not support host format such as http://[ipv6]:port. and [RFC 3986](https://datatracker.ietf.org/doc/html/rfc3986#section-3.2.2) ``` A host identified by an Internet Protocol literal address, version 6 [[RFC3513](https://datatracker.ietf.org/doc/html/rfc3513)] or later, is distinguished by enclosing the IP literal within square brackets ("[" and "]"). This is the only place where square bracket characters are allowed in the URI syntax. In anticipation of future, as-yet-undefined IP literal address formats, an implementation may use an optional version flag to indicate such a format explicitly rather than rely on heuristic determination. IP-literal = "[" ( IPv6address / IPvFuture ) "]" ``` the ipv6 address is distinguished by enclosing the IP literal within square brackets ("[" and "]"). What is changed and how it works: if we find the host part of a URL starts with a "[" and ends with a "]". it will be specifically judged whether it is a valid IPv6 address. If it is a valid address, it can be returned directly without call the `getaddrinfo` interface.
This commit is contained in:
parent
1f6a0726d9
commit
662573b6bf
|
|
@ -8,6 +8,7 @@
|
|||
#include <netinet/in.h>
|
||||
#endif
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
|
|
@ -101,6 +102,7 @@ static std::string string_join(std::vector<std::string> const& srcs,
|
|||
static bool dns_resolve(std::string const& target,
|
||||
std::vector<std::string>& endpoints, bool ipv4 = true) {
|
||||
std::vector<std::string> 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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue