Skip to content

Commit

Permalink
Modify the toHostAddr interface to support host resolved (gethostbyna…
Browse files Browse the repository at this point in the history
…me). (vesoft-inc#935)

* Issue vesoft-inc#931 the "meta_server_addrs" in the configuration support the host name.

Modify the toHostAddr interface to support host resolved (gethostbyname).

* replace the gethostbyname with getaddrinfo.

* Refactoring part of the code.
  • Loading branch information
monadbobo authored and dutor committed Dec 19, 2019
1 parent 5c7e6b9 commit cb83e97
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 41 deletions.
87 changes: 66 additions & 21 deletions src/common/network/NetworkUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,28 +267,51 @@ std::string NetworkUtils::intToIPv4(IPv4 ip) {
return buf;
}

StatusOr<HostAddr> NetworkUtils::toHostAddr(folly::StringPiece ip, int32_t port) {
IPv4 ipV4;
if (!ipv4ToInt(ip.toString(), ipV4)) {
return Status::Error("Bad ip format:%s", ip.start());
StatusOr<std::vector<HostAddr>> NetworkUtils::resolveHost(const std::string& host, int32_t port) {
std::vector<HostAddr> addrs;
struct addrinfo hints, *res, *rp;
::memset(&hints, 0, sizeof(struct addrinfo));

hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_ADDRCONFIG;

if (getaddrinfo(host.c_str(), nullptr, &hints, &res) != 0) {
return Status::Error("host not found:%s", host.c_str());
}
return std::make_pair(ipV4, port);
}

StatusOr<HostAddr> NetworkUtils::toHostAddr(folly::StringPiece ipPort) {
auto pos = ipPort.find(':');
if (pos == folly::StringPiece::npos) {
return Status::Error("Bad peer format: %s", ipPort.start());
for (rp = res; rp != nullptr; rp = rp->ai_next) {
switch (rp->ai_family) {
case AF_INET:
break;
case AF_INET6:
VLOG(1) << "Currently does not support Ipv6 address";
continue;
default:
continue;
}

auto address = ((struct sockaddr_in*)rp->ai_addr)->sin_addr.s_addr;
// We need to match the integer byte order generated by ipv4ToInt, so we need to convert
// here.
addrs.emplace_back(htonl(std::move(address)), port);
}

int32_t port;
try {
port = folly::to<int32_t>(ipPort.subpiece(pos + 1));
} catch (const std::exception& ex) {
return Status::Error("Bad port number, error: %s", ex.what());
freeaddrinfo(res);

if (addrs.empty()) {
return Status::Error("host not found: %s", host.c_str());
}

return toHostAddr(ipPort.subpiece(0, pos), port);
return addrs;
}

StatusOr<HostAddr> NetworkUtils::toHostAddr(const std::string &ip, int32_t port) {
IPv4 ipV4;
if (!ipv4ToInt(ip, ipV4)) {
return Status::Error("Bad ip format:%s", ip.c_str());
}
return std::make_pair(ipV4, port);
}

StatusOr<std::vector<HostAddr>> NetworkUtils::toHosts(const std::string& peersStr) {
Expand All @@ -297,11 +320,34 @@ StatusOr<std::vector<HostAddr>> NetworkUtils::toHosts(const std::string& peersSt
folly::split(",", peersStr, peers, true);
hosts.reserve(peers.size());
for (auto& peerStr : peers) {
auto hostAddr = network::NetworkUtils::toHostAddr(folly::trimWhitespace(peerStr));
if (!hostAddr.ok()) {
return hostAddr.status();
auto ipPort = folly::trimWhitespace(peerStr);
auto pos = ipPort.find(':');
if (pos == folly::StringPiece::npos) {
return Status::Error("Bad peer format: %s", ipPort.start());
}
hosts.emplace_back(hostAddr.value());

int32_t port;
try {
port = folly::to<int32_t>(ipPort.subpiece(pos + 1));
} catch (const std::exception& ex) {
return Status::Error("Bad port number, error: %s", ex.what());
}

auto ipAddr = ipPort.subpiece(0, pos).toString();
auto hostAddr = toHostAddr(ipAddr, port);
if (hostAddr.ok()) {
hosts.emplace_back(hostAddr.value());
continue;
}

auto resolveAddr = resolveHost(ipAddr, port);
if (resolveAddr.ok()) {
hosts.insert(hosts.end(), std::make_move_iterator(resolveAddr.value().begin()),
std::make_move_iterator(resolveAddr.value().end()));
continue;
}

return resolveAddr.status();
}
return hosts;
}
Expand Down Expand Up @@ -346,4 +392,3 @@ StatusOr<std::string> NetworkUtils::getLocalIP(std::string defaultIP) {

} // namespace network
} // namespace nebula

8 changes: 3 additions & 5 deletions src/common/network/NetworkUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,9 @@ class NetworkUtils final {
// So don't use it in production code.
static uint16_t getAvailablePort();

// Convert the given IP (must be in the form of "xx.xx.xx.xx") and Port to a HostAddr
static StatusOr<HostAddr> toHostAddr(folly::StringPiece ip, int32_t port);
// Convert the given IP/Port (must be in the form of "xx.xx.xx.xx:pp") to a HostAddr
static StatusOr<HostAddr> toHostAddr(folly::StringPiece ipPort);
static StatusOr<std::vector<HostAddr>> resolveHost(const std::string &host, int32_t port);
// Convert the given IP/HOST and Port to a HostAddr
static StatusOr<HostAddr> toHostAddr(const std::string &ip, int32_t port);
// Retrieve the string-form IP from the given HostAddr
static std::string ipFromHostAddr(const HostAddr& host);
// Retrieve the port number from the given HostAddr
Expand Down Expand Up @@ -72,4 +71,3 @@ class NetworkUtils final {
} // namespace nebula

#endif // COMMON_NETWORK_NETWORKUTILS_H_

47 changes: 33 additions & 14 deletions src/common/network/test/NetworkUtilsTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,22 +87,42 @@ TEST(NetworkUtils, getAvailablePort) {
ASSERT_GT(port, 0);
}

TEST(NetworkUtils, toHostAddr) {
auto s = NetworkUtils::resolveHost("localhost", 1200);
ASSERT_TRUE(s.ok());
auto addr = s.value();
IPv4 ip;
ASSERT_TRUE(NetworkUtils::ipv4ToInt("127.0.0.1", ip));
ASSERT_EQ(addr[0].first, ip);
ASSERT_EQ(addr[0].second, 1200);

auto s2 = NetworkUtils::toHostAddr("8.8.8.8", 1300);
ASSERT_TRUE(s2.ok());
auto addr2 = s2.value();

ASSERT_TRUE(NetworkUtils::ipv4ToInt("8.8.8.8", ip));
ASSERT_EQ(addr2.first, ip);
ASSERT_EQ(addr2.second, 1300);

s2 = NetworkUtils::toHostAddr("a.b.c.d:a23", 1200);
ASSERT_FALSE(s2.ok());
}

TEST(NetworkUtils, toHosts) {
std::string hostsString = "192.168.1.1:10001, 192.168.1.2:10002, 192.168.1.3:10003";
auto addresRet = NetworkUtils::toHosts(hostsString);
ASSERT_TRUE(addresRet.ok());
std::vector<HostAddr> hosts = std::move(addresRet.value());
EXPECT_EQ(3, hosts.size());
auto s = NetworkUtils::toHosts("localhost:1200, 127.0.0.1:1200");
ASSERT_TRUE(s.ok());
auto addr = s.value();

IPv4 ip;
NetworkUtils::ipv4ToInt("192.168.1.1", ip);
int32_t count = 0;
for (auto& host : hosts) {
EXPECT_EQ(ip + count, host.first);
EXPECT_EQ(10001 + count, host.second);
count++;
}
EXPECT_STREQ(hostsString.c_str(), NetworkUtils::toHosts(hosts).c_str());
ASSERT_TRUE(NetworkUtils::ipv4ToInt("127.0.0.1", ip));
ASSERT_EQ(addr[0].first, ip);
ASSERT_EQ(addr[0].second, 1200);

ASSERT_EQ(addr[1].first, ip);
ASSERT_EQ(addr[1].second, 1200);

s = NetworkUtils::toHosts("1.1.2.3:123, a.b.c.d:a23");
ASSERT_FALSE(s.ok());
}

} // namespace network
Expand All @@ -116,4 +136,3 @@ int main(int argc, char** argv) {

return RUN_ALL_TESTS();
}

2 changes: 1 addition & 1 deletion src/daemons/MetaDaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ int main(int argc, char *argv[]) {
return EXIT_FAILURE;
}

auto kvstore = initKV(peersRet.value(), hostAddrRet.value());
auto kvstore = initKV(peersRet.value(), localhost);
if (kvstore == nullptr) {
LOG(ERROR) << "Init kv failed!";
return EXIT_FAILURE;
Expand Down

0 comments on commit cb83e97

Please sign in to comment.