You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@kvrocks.apache.org by tw...@apache.org on 2023/04/20 09:22:09 UTC
[incubator-kvrocks] branch unstable updated: Convert 0.0.0.0 to local ip addresses when matching the cluster node (#1392)
This is an automated email from the ASF dual-hosted git repository.
twice pushed a commit to branch unstable
in repository https://gitbox.apache.org/repos/asf/incubator-kvrocks.git
The following commit(s) were added to refs/heads/unstable by this push:
new 13b82875 Convert 0.0.0.0 to local ip addresses when matching the cluster node (#1392)
13b82875 is described below
commit 13b828756d90288bc0fa6e7476392da27d2c7f0b
Author: Zevin <ze...@gmail.com>
AuthorDate: Thu Apr 20 17:22:02 2023 +0800
Convert 0.0.0.0 to local ip addresses when matching the cluster node (#1392)
Signed-off-by: Zewen Xu <ze...@gmail.com>
Co-authored-by: Twice <tw...@gmail.com>
Co-authored-by: git-hulk <hu...@gmail.com>
---
src/cluster/cluster.cc | 6 +++---
src/cluster/cluster.h | 1 +
src/common/io_util.cc | 48 +++++++++++++++++++++++++++++++++++++++++++
src/common/io_util.h | 4 +++-
tests/cppunit/io_util_test.cc | 28 +++++++++++++++++++++++++
5 files changed, 83 insertions(+), 4 deletions(-)
diff --git a/src/cluster/cluster.cc b/src/cluster/cluster.cc
index b98a6ca6..e7d76efc 100644
--- a/src/cluster/cluster.cc
+++ b/src/cluster/cluster.cc
@@ -22,12 +22,12 @@
#include <config/config_util.h>
-#include <algorithm>
#include <cstring>
#include <fstream>
#include <memory>
#include "commands/commander.h"
+#include "common/io_util.h"
#include "fmt/format.h"
#include "parse_util.h"
#include "replication.h"
@@ -200,15 +200,15 @@ Status Cluster::SetClusterNodes(const std::string &nodes_str, int64_t version, b
}
}
- // Find myself
if (myid_.empty() || force) {
for (auto &n : nodes_) {
- if (n.second->port == port_ && std::find(binds_.begin(), binds_.end(), n.second->host) != binds_.end()) {
+ if (n.second->port == port_ && util::MatchListeningIP(binds_, n.second->host)) {
myid_ = n.first;
break;
}
}
}
+
myself_ = nullptr;
if (!myid_.empty() && nodes_.find(myid_) != nodes_.end()) {
myself_ = nodes_[myid_];
diff --git a/src/cluster/cluster.h b/src/cluster/cluster.h
index 4ddafc6b..f6d04435 100644
--- a/src/cluster/cluster.h
+++ b/src/cluster/cluster.h
@@ -30,6 +30,7 @@
#include <vector>
#include "commands/commander.h"
+#include "common/io_util.h"
#include "redis_slot.h"
#include "server/redis_connection.h"
#include "status.h"
diff --git a/src/common/io_util.cc b/src/common/io_util.cc
index 22c1cee3..8492d296 100644
--- a/src/common/io_util.cc
+++ b/src/common/io_util.cc
@@ -23,9 +23,11 @@
#include <arpa/inet.h>
#include <fcntl.h>
#include <fmt/format.h>
+#include <ifaddrs.h>
#include <netdb.h>
#include <netinet/tcp.h>
#include <sys/poll.h>
+#include <sys/types.h>
#ifdef __linux__
#include <sys/sendfile.h>
@@ -312,6 +314,52 @@ int AeWait(int fd, int mask, int timeout) {
}
}
+bool MatchListeningIP(std::vector<std::string> &binds, const std::string &ip) {
+ if (std::find(binds.begin(), binds.end(), ip) != binds.end()) {
+ return true;
+ }
+
+ // If binds contains 0.0.0.0, we should resolve ip addresses and check it
+ if (std::find(binds.begin(), binds.end(), "0.0.0.0") != binds.end() ||
+ std::find(binds.begin(), binds.end(), "::") != binds.end()) {
+ auto local_ip_addresses = GetLocalIPAddresses();
+ return std::find(local_ip_addresses.begin(), local_ip_addresses.end(), ip) != local_ip_addresses.end();
+ }
+ return false;
+}
+
+std::vector<std::string> GetLocalIPAddresses() {
+ std::vector<std::string> ip_addresses;
+ ifaddrs *if_addr_struct = nullptr;
+ std::unique_ptr<ifaddrs, decltype(&freeifaddrs)> ifaddrs_ptr(nullptr, &freeifaddrs);
+ if (getifaddrs(&if_addr_struct) == -1) {
+ return ip_addresses;
+ }
+ ifaddrs_ptr.reset(if_addr_struct);
+
+ for (ifaddrs *ifa = if_addr_struct; ifa; ifa = ifa->ifa_next) {
+ if (!ifa->ifa_addr) {
+ continue;
+ }
+ void *tmp_addr_ptr = nullptr;
+ if (ifa->ifa_addr->sa_family == AF_INET) {
+ // check it is IPv4
+ tmp_addr_ptr = &((sockaddr_in *)ifa->ifa_addr)->sin_addr;
+ char address_buffer[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, tmp_addr_ptr, address_buffer, INET_ADDRSTRLEN);
+ ip_addresses.emplace_back(address_buffer);
+ } else if (ifa->ifa_addr->sa_family == AF_INET6) {
+ // check it is IPv6
+ tmp_addr_ptr = &((sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+ char address_buffer[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, tmp_addr_ptr, address_buffer, INET6_ADDRSTRLEN);
+ ip_addresses.emplace_back(address_buffer);
+ }
+ }
+
+ return ip_addresses;
+}
+
template <auto syscall, typename... Args>
Status WriteImpl(int fd, std::string_view data, Args &&...args) {
ssize_t n = 0;
diff --git a/src/common/io_util.h b/src/common/io_util.h
index 7b47fa09..e0d4ade1 100644
--- a/src/common/io_util.h
+++ b/src/common/io_util.h
@@ -38,8 +38,10 @@ int GetPeerAddr(int fd, std::string *addr, uint32_t *port);
int GetLocalPort(int fd);
bool IsPortInUse(uint32_t port);
-int AeWait(int fd, int mask, int milliseconds);
+bool MatchListeningIP(std::vector<std::string> &binds, const std::string &ip);
+std::vector<std::string> GetLocalIPAddresses();
+int AeWait(int fd, int mask, int milliseconds);
Status Write(int fd, const std::string &data);
Status Pwrite(int fd, const std::string &data, off_t offset);
diff --git a/tests/cppunit/io_util_test.cc b/tests/cppunit/io_util_test.cc
new file mode 100644
index 00000000..a7459576
--- /dev/null
+++ b/tests/cppunit/io_util_test.cc
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+#include "common/io_util.h"
+
+#include <gtest/gtest.h>
+
+TEST(IOUtil, MatchListeningIP) {
+ // bind 0.0.0.0 should at least match 127.0.0.1
+ std::vector<std::string> binds{"0.0.0.0"};
+ ASSERT_TRUE(util::MatchListeningIP(binds, "127.0.0.1"));
+}