From 97ad8232e45b64fed430fb5198b65f417d63a832 Mon Sep 17 00:00:00 2001 From: sgourdas Date: Thu, 19 Sep 2024 11:25:07 +0300 Subject: [PATCH] Refactor getBestPublicIp for both protocols --- include/server.h | 6 +++--- include/tools.h | 9 ++++++++- src/server.cpp | 15 ++++++++++++++- src/server/internalServer.cpp | 23 +++++++++++++---------- src/server/internalServer.h | 5 +++-- src/tools/networkTools.cpp | 29 +++++++++++++---------------- test/otherTools.cpp | 12 ++++++++---- 7 files changed, 62 insertions(+), 37 deletions(-) diff --git a/include/server.h b/include/server.h index 68fc445d..55377ccd 100644 --- a/include/server.h +++ b/include/server.h @@ -22,7 +22,7 @@ #include #include -#include "common.h" +#include "tools.h" namespace kiwix { @@ -52,7 +52,7 @@ namespace kiwix void stop(); void setRoot(const std::string& root); - void setAddress(const std::string& addr) { m_addr = addr; } + void setAddress(const std::string& addr); void setPort(int port) { m_port = port; } void setNbThreads(int threads) { m_nbThreads = threads; } void setMultiZimSearchLimit(unsigned int limit) { m_multizimSearchLimit = limit; } @@ -72,7 +72,7 @@ namespace kiwix std::shared_ptr mp_library; std::shared_ptr mp_nameMapper; std::string m_root = ""; - std::string m_addr = ""; + IpAddress m_addr; std::string m_indexTemplateString = ""; int m_port = 80; int m_nbThreads = 1; diff --git a/include/tools.h b/include/tools.h index 3742f8ae..57e79c34 100644 --- a/include/tools.h +++ b/include/tools.h @@ -24,6 +24,7 @@ #include #include #include +#include "common.h" namespace kiwix { @@ -32,6 +33,12 @@ struct IpAddress { std::string addr; // IPv4 address std::string addr6; // IPv6 address + + bool empty() const { return addr.empty() && addr6.empty(); } + bool empty4() const { return addr.empty(); } + bool empty6() const { return addr6.empty(); } + bool valid4(IpMode mode) const { return (mode == IpMode::ipv4 || mode == IpMode::all) && !this->empty4(); } + bool valid6(IpMode mode) const { return (mode == IpMode::ipv6 || mode == IpMode::all) && !this->empty6(); } }; typedef std::pair LangNameCodePair; @@ -216,7 +223,7 @@ std::map getNetworkInterfaces(); /** Provides the best IP address * This function provides the best IP address from the list given by getNetworkInterfacesIPv4Or6() */ -std::string getBestPublicIp(bool ipv6); +IpAddress getBestPublicIps(IpMode mode); /** Provides the best IPv4 adddress * Equivalent to getBestPublicIp(false). Provided for backward compatibility diff --git a/src/server.cpp b/src/server.cpp index afc73240..29cefd11 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -75,12 +75,25 @@ void Server::setRoot(const std::string& root) } } +void Server::setAddress(const std::string& addr) +{ + if (addr.empty()) + return; + + if (addr.find(':') != std::string::npos) { // IPv6 + for (char ch : addr) if (ch == '[' or ch == ']') ch = '\0'; // Clean possible brackets + m_addr.addr6 = addr; + } else { + m_addr.addr = addr; + } +} + int Server::getPort() const { return mp_server->getPort(); } -std::string Server::getAddress() +IpAddress Server::getAddress() const { return mp_server->getAddress(); } diff --git a/src/server/internalServer.cpp b/src/server/internalServer.cpp index 476e1a18..eed10979 100644 --- a/src/server/internalServer.cpp +++ b/src/server/internalServer.cpp @@ -407,7 +407,7 @@ public: InternalServer::InternalServer(LibraryPtr library, std::shared_ptr nameMapper, - std::string addr, + IpAddress addr, int port, std::string root, int nbThreads, @@ -462,18 +462,21 @@ bool InternalServer::start() { sockAddr6.sin6_port = htons(m_port); if (m_addr.empty()) { - if (0 != INADDR_ANY) { - sockAddr6.sin6_addr = in6addr_any; - sockAddr4.sin_addr.s_addr = htonl(INADDR_ANY); - } - m_addr = kiwix::getBestPublicIp(m_ipMode == IpMode::ipv6 || m_ipMode == IpMode::all); + sockAddr6.sin6_addr = in6addr_any; + sockAddr4.sin_addr.s_addr = htonl(INADDR_ANY); + m_addr = kiwix::getBestPublicIps(m_ipMode); } else { - bool ipv6 = inet_pton(AF_INET6, m_addr.c_str(), &(sockAddr6.sin6_addr.s6_addr)) == 1; - bool ipv4 = inet_pton(AF_INET, m_addr.c_str(), &(sockAddr4.sin_addr.s_addr)) == 1; + bool ipv6 = inet_pton(AF_INET6, m_addr.addr6.c_str(), &(sockAddr6.sin6_addr.s6_addr)) == 1; + bool ipv4 = inet_pton(AF_INET, m_addr.addr.c_str(), &(sockAddr4.sin_addr.s_addr)) == 1; + if (ipv6){ - m_ipMode = IpMode::all; + m_ipMode = IpMode::ipv6; } else if (!ipv4) { - std::cerr << "Ip address " << m_addr << " is not a valid ip address" << std::endl; + if(!m_addr.addr.empty()) + std::cerr << "Ip address " << m_addr.addr << " is not a valid ip address" << std::endl; + else + std::cerr << "Ip address " << m_addr.addr6 << " is not a valid ip address" << std::endl; + return false; } } diff --git a/src/server/internalServer.h b/src/server/internalServer.h index 0ca9344c..b0831fef 100644 --- a/src/server/internalServer.h +++ b/src/server/internalServer.h @@ -27,6 +27,7 @@ extern "C" { #include "library.h" #include "name_mapper.h" +#include "tools.h" #include #include @@ -94,7 +95,7 @@ class InternalServer { public: InternalServer(LibraryPtr library, std::shared_ptr nameMapper, - std::string addr, + IpAddress addr, int port, std::string root, int nbThreads, @@ -166,7 +167,7 @@ class InternalServer { typedef ConcurrentCache> SuggestionSearcherCache; private: // data - std::string m_addr; + IpAddress m_addr; int m_port; std::string m_root; // URI-encoded std::string m_rootPrefixOfDecodedURL; // URI-decoded diff --git a/src/tools/networkTools.cpp b/src/tools/networkTools.cpp index 602194ea..b37488aa 100644 --- a/src/tools/networkTools.cpp +++ b/src/tools/networkTools.cpp @@ -211,39 +211,36 @@ std::map getNetworkInterfaces() { return result; } - -std::string getBestPublicIp(bool ipv6) { - IpAddress bestPublicIp = IpAddress{"127.0.0.1","::1"}; +IpAddress getBestPublicIps(IpMode mode) { + IpAddress bestPublicIps = IpAddress{"127.0.0.1","::1"}; std::map interfaces = getNetworkInterfacesIPv4Or6(); #ifndef _WIN32 const char* const prioritizedNames[] = { "eth0", "eth1", "wlan0", "wlan1", "en0", "en1" }; for(auto name: prioritizedNames) { - auto it=interfaces.find(name); - if(it != interfaces.end() && !(ipv6 && (*it).second.addr6.empty())) { - bestPublicIp = (*it).second; - break; - } + const auto it = interfaces.find(name); + if(it == interfaces.end()) continue; + const IpAddress& interfaceIps = (*it).second; + if(!bestPublicIps.empty4() && interfaceIps.valid4(mode)) bestPublicIps.addr = interfaceIps.addr; + if(!bestPublicIps.empty6() && interfaceIps.valid6(mode)) bestPublicIps.addr6 = interfaceIps.addr6; } #endif const char* const prefixes[] = { "192.168", "172.16.", "10.0" }; for(auto prefix : prefixes){ for(auto& itr : interfaces) { - std::string interfaceIp(itr.second.addr); - if (interfaceIp.find(prefix) == 0 && !(ipv6 && itr.second.addr6.empty())) { - bestPublicIp = itr.second; - break; - } + const IpAddress& interfaceIps = itr.second; + if(!bestPublicIps.empty4() && interfaceIps.valid4(mode) && interfaceIps.addr.find(prefix) == 0) bestPublicIps.addr = interfaceIps.addr; + if(!bestPublicIps.empty6() && interfaceIps.valid6(mode)) bestPublicIps.addr6 = interfaceIps.addr6; } } - return ipv6 ? bestPublicIp.addr6 : bestPublicIp.addr; -} + return bestPublicIps; +} std::string getBestPublicIp() { - return getBestPublicIp(false); + return getBestPublicIps(IpMode::ipv4).addr; } } // namespace kiwix diff --git a/test/otherTools.cpp b/test/otherTools.cpp index 3ffca045..083cbe41 100644 --- a/test/otherTools.cpp +++ b/test/otherTools.cpp @@ -18,6 +18,7 @@ */ #include "gtest/gtest.h" +#include "../include/tools.h" #include "../src/tools/otherTools.h" #include "zim/suggestion_iterator.h" #include "../src/server/i18n_utils.h" @@ -252,11 +253,14 @@ TEST(networkTools, getNetworkInterfaces) } } -TEST(networkTools, getBestPublicIp) +TEST(networkTools, getBestPublicIps) { + using kiwix::getBestPublicIps; using kiwix::getBestPublicIp; + using kiwix::IpMode; - std::cout << "getBestPublicIp(true) " << getBestPublicIp(true) << std::endl; - std::cout << "getBestPublicIp(false) " << getBestPublicIp(false) << std::endl; - std::cout << "getBestPublicIp() " << getBestPublicIp() << std::endl; + std::cout << "getBestPublicIps(true) : [" << getBestPublicIps(IpMode::ipv4).addr << ", " << getBestPublicIps(IpMode::ipv4).addr6 << "]" << std::endl; + std::cout << "getBestPublicIps(false) : [" << getBestPublicIps(IpMode::ipv6).addr << ", " << getBestPublicIps(IpMode::ipv6).addr6 << "]" << std::endl; + std::cout << "getBestPublicIps(false) : [" << getBestPublicIps(IpMode::all).addr << ", " << getBestPublicIps(IpMode::all).addr6 << "]" << std::endl; + std::cout << "getBestPublicIp() : " << getBestPublicIp() << std::endl; }