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"));
+}