Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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();
}

10 changes: 6 additions & 4 deletions src/daemons/MetaDaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ using nebula::Status;
DEFINE_int32(port, 45500, "Meta daemon listening port");
DEFINE_bool(reuse_port, true, "Whether to turn on the SO_REUSEPORT option");
DEFINE_string(data_path, "", "Root data path");
DEFINE_string(meta_server_addrs, "", "It is a list of IPs split by comma, used in cluster deployment"
"the ips number is equal to the replica number."
"If empty, it means it's a single node");
DEFINE_string(meta_server_addrs,
"",
"It is a list of IPs split by comma, used in cluster deployment"
"the ips number is equal to the replica number."
"If empty, it means it's a single node");
DEFINE_string(local_ip, "", "Local ip specified for NetworkUtils::getLocalIP");
DEFINE_int32(num_io_threads, 16, "Number of IO threads");
DEFINE_int32(meta_http_thread_num, 3, "Number of meta daemon's http thread");
Expand Down Expand Up @@ -212,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