Merge pull request #1093 from kiwix/network_tools_backward_compatibility

Backward compatible support for IPv6
This commit is contained in:
Kelson 2024-06-11 11:27:05 +02:00 committed by GitHub
commit beab8d7041
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 100 additions and 19 deletions

View File

@ -25,10 +25,13 @@
#include <map>
#include <cstdint>
namespace kiwix {
struct IpAddress{
std::string addr;
std::string addr6;
namespace kiwix
{
struct IpAddress
{
std::string addr; // IPv4 address
std::string addr6; // IPv6 address
};
typedef std::pair<std::string, std::string> LangNameCodePair;
@ -223,14 +226,30 @@ std::string getMimeTypeForFile(const std::string& filename);
/** Provides all available network interfaces
*
* This function provides the available IPv4 and IPv6 network interfaces
* as a map from the interface name to its IPv4 and/or IPv6 address(es).
*/
std::map<std::string,IpAddress> getNetworkInterfaces();
std::map<std::string, IpAddress> getNetworkInterfacesIPv4Or6();
/** Provides all available IPv4 network interfaces
*
* This function provides the available IPv4 network interfaces
* as a map from the interface name to its IPv4 address.
*
* Provided for backward compatibility with libkiwix v13.1.0.
*/
std::map<std::string, std::string> getNetworkInterfaces();
/** Provides the best IP address
* This function provides the best IP address from the list given by getNetworkInterfaces
* This function provides the best IP address from the list given by getNetworkInterfacesIPv4Or6()
*/
std::string getBestPublicIp(bool ipv6);
/** Provides the best IPv4 adddress
* Equivalent to getBestPublicIp(false). Provided for backward compatibility
* with libkiwix v13.1.0.
*/
std::string getBestPublicIp();
/** Converts file size to human readable format.
*
* This function will convert a number to its equivalent size using units.

View File

@ -49,6 +49,12 @@
#include <sys/sockio.h>
#endif
namespace kiwix
{
namespace
{
size_t write_callback_to_iss(char* ptr, size_t size, size_t nmemb, void* userdata)
{
auto str = static_cast<std::stringstream*>(userdata);
@ -56,7 +62,9 @@ size_t write_callback_to_iss(char* ptr, size_t size, size_t nmemb, void* userdat
return nmemb;
}
std::string kiwix::download(const std::string& url) {
} // unnamed namespace
std::string download(const std::string& url) {
auto curl = curl_easy_init();
std::stringstream ss;
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
@ -77,10 +85,14 @@ std::string kiwix::download(const std::string& url) {
return ss.str();
}
namespace
{
#ifdef _WIN32
std::map<std::string,kiwix::IpAddress> getNetworkInterfacesWin() {
std::map<std::string,kiwix::IpAddress> interfaces;
std::map<std::string, IpAddress> getNetworkInterfacesWin() {
std::map<std::string, IpAddress> interfaces;
const int working_buffer_size = 15000;
const int max_tries = 3;
@ -145,8 +157,8 @@ std::map<std::string,kiwix::IpAddress> getNetworkInterfacesWin() {
#else
std::map<std::string,kiwix::IpAddress> getNetworkInterfacesPosix() {
std::map<std::string,kiwix::IpAddress> interfaces;
std::map<std::string, IpAddress> getNetworkInterfacesPosix() {
std::map<std::string, IpAddress> interfaces;
struct ifaddrs *interfacesHead;
if (getifaddrs(&interfacesHead) == -1) {
@ -177,7 +189,9 @@ std::map<std::string,kiwix::IpAddress> getNetworkInterfacesPosix() {
#endif
std::map<std::string,kiwix::IpAddress> kiwix::getNetworkInterfaces() {
} // unnamed namespace
std::map<std::string, IpAddress> getNetworkInterfacesIPv4Or6() {
#ifdef _WIN32
return getNetworkInterfacesWin();
#else
@ -185,9 +199,22 @@ std::map<std::string,kiwix::IpAddress> kiwix::getNetworkInterfaces() {
#endif
}
std::string kiwix::getBestPublicIp(bool ipv6) {
kiwix::IpAddress bestPublicIp = kiwix::IpAddress{"127.0.0.1","::1"};
std::map<std::string,kiwix::IpAddress> interfaces = getNetworkInterfaces();
std::map<std::string, std::string> getNetworkInterfaces() {
std::map<std::string, std::string> result;
for ( const auto& kv : getNetworkInterfacesIPv4Or6() ) {
const std::string& interfaceName = kv.first;
const auto& ipAddresses = kv.second;
if ( !ipAddresses.addr.empty() ) {
result[interfaceName] = ipAddresses.addr;
}
}
return result;
}
std::string getBestPublicIp(bool ipv6) {
IpAddress bestPublicIp = IpAddress{"127.0.0.1","::1"};
std::map<std::string, IpAddress> interfaces = getNetworkInterfacesIPv4Or6();
#ifndef _WIN32
const char* const prioritizedNames[] =
@ -213,3 +240,11 @@ std::string kiwix::getBestPublicIp(bool ipv6) {
}
return ipv6 ? bestPublicIp.addr6 : bestPublicIp.addr;
}
std::string getBestPublicIp()
{
return getBestPublicIp(false);
}
} // namespace kiwix

View File

@ -233,3 +233,30 @@ TEST(I18n, parseUserLanguagePreferences)
"{fr, 1}{en, 0.5}"
);
}
#include "../include/tools.h"
TEST(networkTools, getNetworkInterfacesIPv4Or6)
{
for ( const auto& kv : kiwix::getNetworkInterfacesIPv4Or6() ) {
std::cout << kv.first << " : IPv4 addr = " << kv.second.addr
<< " ; IPv6 addr = " << kv.second.addr6
<< std::endl;
}
}
TEST(networkTools, getNetworkInterfaces)
{
for ( const auto& kv : kiwix::getNetworkInterfaces() ) {
std::cout << kv.first << " : IPv4 addr = " << kv.second << std::endl;
}
}
TEST(networkTools, getBestPublicIp)
{
using kiwix::getBestPublicIp;
std::cout << "getBestPublicIp(true) " << getBestPublicIp(true) << std::endl;
std::cout << "getBestPublicIp(false) " << getBestPublicIp(false) << std::endl;
std::cout << "getBestPublicIp() " << getBestPublicIp() << std::endl;
}