mirror of https://github.com/kiwix/libkiwix.git
Merge pull request #1074 from aryanA101a/main
Add IPv6 support to HTTP daemon
This commit is contained in:
commit
a1ce3d10b1
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
namespace kiwix {
|
namespace kiwix {
|
||||||
|
|
||||||
|
enum class IpMode { ipv4, ipv6, all };
|
||||||
typedef zim::size_type size_type;
|
typedef zim::size_type size_type;
|
||||||
typedef zim::offset_type offset_type;
|
typedef zim::offset_type offset_type;
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
namespace kiwix
|
namespace kiwix
|
||||||
{
|
{
|
||||||
|
@ -62,8 +63,10 @@ namespace kiwix
|
||||||
{ m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; }
|
{ m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; }
|
||||||
void setBlockExternalLinks(bool blockExternalLinks)
|
void setBlockExternalLinks(bool blockExternalLinks)
|
||||||
{ m_blockExternalLinks = blockExternalLinks; }
|
{ m_blockExternalLinks = blockExternalLinks; }
|
||||||
|
void setIpMode(IpMode mode) { m_ipMode = mode; }
|
||||||
int getPort();
|
int getPort();
|
||||||
std::string getAddress();
|
std::string getAddress();
|
||||||
|
IpMode getIpMode() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::shared_ptr<Library> mp_library;
|
std::shared_ptr<Library> mp_library;
|
||||||
|
@ -78,6 +81,7 @@ namespace kiwix
|
||||||
bool m_withTaskbar = true;
|
bool m_withTaskbar = true;
|
||||||
bool m_withLibraryButton = true;
|
bool m_withLibraryButton = true;
|
||||||
bool m_blockExternalLinks = false;
|
bool m_blockExternalLinks = false;
|
||||||
|
IpMode m_ipMode = IpMode::ipv4;
|
||||||
int m_ipConnectionLimit = 0;
|
int m_ipConnectionLimit = 0;
|
||||||
std::unique_ptr<InternalServer> mp_server;
|
std::unique_ptr<InternalServer> mp_server;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,11 @@
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace kiwix {
|
namespace kiwix {
|
||||||
|
struct IpAddress{
|
||||||
|
std::string addr;
|
||||||
|
std::string addr6;
|
||||||
|
};
|
||||||
|
|
||||||
typedef std::pair<std::string, std::string> LangNameCodePair;
|
typedef std::pair<std::string, std::string> LangNameCodePair;
|
||||||
typedef std::vector<LangNameCodePair> FeedLanguages;
|
typedef std::vector<LangNameCodePair> FeedLanguages;
|
||||||
typedef std::vector<std::string> FeedCategories;
|
typedef std::vector<std::string> FeedCategories;
|
||||||
|
@ -217,14 +222,14 @@ std::string getMimeTypeForFile(const std::string& filename);
|
||||||
|
|
||||||
/** Provides all available network interfaces
|
/** Provides all available network interfaces
|
||||||
*
|
*
|
||||||
* This function provides the available IPv4 network interfaces
|
* This function provides the available IPv4 and IPv6 network interfaces
|
||||||
*/
|
*/
|
||||||
std::map<std::string, std::string> getNetworkInterfaces();
|
std::map<std::string,IpAddress> getNetworkInterfaces();
|
||||||
|
|
||||||
/** Provides the best IP address
|
/** 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 getNetworkInterfaces
|
||||||
*/
|
*/
|
||||||
std::string getBestPublicIp();
|
std::string getBestPublicIp(bool ipv6);
|
||||||
|
|
||||||
/** Converts file size to human readable format.
|
/** Converts file size to human readable format.
|
||||||
*
|
*
|
||||||
|
|
11
meson.build
11
meson.build
|
@ -48,7 +48,10 @@ if host_machine.system() == 'windows' and static_deps
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if host_machine.system() == 'windows'
|
if host_machine.system() == 'windows'
|
||||||
add_project_arguments('-DNOMINMAX', language: 'cpp')
|
add_project_arguments('-DNOMINMAX', language: 'cpp')
|
||||||
|
extra_libs += ['-liphlpapi']
|
||||||
|
else
|
||||||
|
extra_link_args = []
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all_deps = [thread_dep, libicu_dep, libzim_dep, pugixml_dep, libcurl_dep, microhttpd_dep, zlib_dep, xapian_dep]
|
all_deps = [thread_dep, libicu_dep, libzim_dep, pugixml_dep, libcurl_dep, microhttpd_dep, zlib_dep, xapian_dep]
|
||||||
|
@ -58,12 +61,6 @@ inc = include_directories('include', extra_include)
|
||||||
conf = configuration_data()
|
conf = configuration_data()
|
||||||
conf.set('LIBKIWIX_VERSION', '"@0@"'.format(meson.project_version()))
|
conf.set('LIBKIWIX_VERSION', '"@0@"'.format(meson.project_version()))
|
||||||
|
|
||||||
if build_machine.system() == 'windows'
|
|
||||||
extra_link_args = ['-lshlwapi', '-lwinmm']
|
|
||||||
else
|
|
||||||
extra_link_args = []
|
|
||||||
endif
|
|
||||||
|
|
||||||
subdir('include')
|
subdir('include')
|
||||||
subdir('scripts')
|
subdir('scripts')
|
||||||
subdir('static')
|
subdir('static')
|
||||||
|
|
|
@ -51,6 +51,7 @@ bool Server::start() {
|
||||||
m_withTaskbar,
|
m_withTaskbar,
|
||||||
m_withLibraryButton,
|
m_withLibraryButton,
|
||||||
m_blockExternalLinks,
|
m_blockExternalLinks,
|
||||||
|
m_ipMode,
|
||||||
m_indexTemplateString,
|
m_indexTemplateString,
|
||||||
m_ipConnectionLimit));
|
m_ipConnectionLimit));
|
||||||
return mp_server->start();
|
return mp_server->start();
|
||||||
|
@ -84,4 +85,9 @@ std::string Server::getAddress()
|
||||||
return mp_server->getAddress();
|
return mp_server->getAddress();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IpMode Server::getIpMode() const
|
||||||
|
{
|
||||||
|
return mp_server->getIpMode();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -416,6 +416,7 @@ InternalServer::InternalServer(LibraryPtr library,
|
||||||
bool withTaskbar,
|
bool withTaskbar,
|
||||||
bool withLibraryButton,
|
bool withLibraryButton,
|
||||||
bool blockExternalLinks,
|
bool blockExternalLinks,
|
||||||
|
IpMode ipMode,
|
||||||
std::string indexTemplateString,
|
std::string indexTemplateString,
|
||||||
int ipConnectionLimit) :
|
int ipConnectionLimit) :
|
||||||
m_addr(addr),
|
m_addr(addr),
|
||||||
|
@ -428,6 +429,7 @@ InternalServer::InternalServer(LibraryPtr library,
|
||||||
m_withTaskbar(withTaskbar),
|
m_withTaskbar(withTaskbar),
|
||||||
m_withLibraryButton(withLibraryButton),
|
m_withLibraryButton(withLibraryButton),
|
||||||
m_blockExternalLinks(blockExternalLinks),
|
m_blockExternalLinks(blockExternalLinks),
|
||||||
|
m_ipMode(ipMode),
|
||||||
m_indexTemplateString(indexTemplateString.empty() ? RESOURCE::templates::index_html : indexTemplateString),
|
m_indexTemplateString(indexTemplateString.empty() ? RESOURCE::templates::index_html : indexTemplateString),
|
||||||
m_ipConnectionLimit(ipConnectionLimit),
|
m_ipConnectionLimit(ipConnectionLimit),
|
||||||
mp_daemon(nullptr),
|
mp_daemon(nullptr),
|
||||||
|
@ -451,28 +453,48 @@ bool InternalServer::start() {
|
||||||
if (m_verbose.load())
|
if (m_verbose.load())
|
||||||
flags |= MHD_USE_DEBUG;
|
flags |= MHD_USE_DEBUG;
|
||||||
|
|
||||||
struct sockaddr_in sockAddr;
|
|
||||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
struct sockaddr_in sockAddr4={0};
|
||||||
sockAddr.sin_family = AF_INET;
|
sockAddr4.sin_family = AF_INET;
|
||||||
sockAddr.sin_port = htons(m_port);
|
sockAddr4.sin_port = htons(m_port);
|
||||||
|
struct sockaddr_in6 sockAddr6={0};
|
||||||
|
sockAddr6.sin6_family = AF_INET6;
|
||||||
|
sockAddr6.sin6_port = htons(m_port);
|
||||||
|
|
||||||
if (m_addr.empty()) {
|
if (m_addr.empty()) {
|
||||||
if (0 != INADDR_ANY) {
|
if (0 != INADDR_ANY) {
|
||||||
sockAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
sockAddr6.sin6_addr = in6addr_any;
|
||||||
|
sockAddr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
}
|
}
|
||||||
m_addr = kiwix::getBestPublicIp();
|
m_addr = kiwix::getBestPublicIp(m_ipMode == IpMode::ipv6 || m_ipMode == IpMode::all);
|
||||||
} else {
|
} else {
|
||||||
if (inet_pton(AF_INET, m_addr.c_str(), &(sockAddr.sin_addr.s_addr)) == 0) {
|
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;
|
||||||
|
if (ipv6){
|
||||||
|
m_ipMode = IpMode::all;
|
||||||
|
} else if (!ipv4) {
|
||||||
std::cerr << "Ip address " << m_addr << " is not a valid ip address" << std::endl;
|
std::cerr << "Ip address " << m_addr << " is not a valid ip address" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_ipMode == IpMode::all) {
|
||||||
|
flags|=MHD_USE_DUAL_STACK;
|
||||||
|
} else if (m_ipMode == IpMode::ipv6) {
|
||||||
|
flags|=MHD_USE_IPv6;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr* sockaddr = (m_ipMode==IpMode::all || m_ipMode==IpMode::ipv6)
|
||||||
|
? (struct sockaddr*)&sockAddr6
|
||||||
|
: (struct sockaddr*)&sockAddr4;
|
||||||
|
|
||||||
mp_daemon = MHD_start_daemon(flags,
|
mp_daemon = MHD_start_daemon(flags,
|
||||||
m_port,
|
m_port,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
&staticHandlerCallback,
|
&staticHandlerCallback,
|
||||||
this,
|
this,
|
||||||
MHD_OPTION_SOCK_ADDR, &sockAddr,
|
MHD_OPTION_SOCK_ADDR, sockaddr,
|
||||||
MHD_OPTION_THREAD_POOL_SIZE, m_nbThreads,
|
MHD_OPTION_THREAD_POOL_SIZE, m_nbThreads,
|
||||||
MHD_OPTION_PER_IP_CONNECTION_LIMIT, m_ipConnectionLimit,
|
MHD_OPTION_PER_IP_CONNECTION_LIMIT, m_ipConnectionLimit,
|
||||||
MHD_OPTION_END);
|
MHD_OPTION_END);
|
||||||
|
|
|
@ -103,6 +103,7 @@ class InternalServer {
|
||||||
bool withTaskbar,
|
bool withTaskbar,
|
||||||
bool withLibraryButton,
|
bool withLibraryButton,
|
||||||
bool blockExternalLinks,
|
bool blockExternalLinks,
|
||||||
|
IpMode ipMode,
|
||||||
std::string indexTemplateString,
|
std::string indexTemplateString,
|
||||||
int ipConnectionLimit);
|
int ipConnectionLimit);
|
||||||
virtual ~InternalServer();
|
virtual ~InternalServer();
|
||||||
|
@ -118,6 +119,7 @@ class InternalServer {
|
||||||
void stop();
|
void stop();
|
||||||
std::string getAddress() { return m_addr; }
|
std::string getAddress() { return m_addr; }
|
||||||
int getPort() { return m_port; }
|
int getPort() { return m_port; }
|
||||||
|
IpMode getIpMode() const { return m_ipMode; }
|
||||||
|
|
||||||
private: // functions
|
private: // functions
|
||||||
std::unique_ptr<Response> handle_request(const RequestContext& request);
|
std::unique_ptr<Response> handle_request(const RequestContext& request);
|
||||||
|
@ -174,6 +176,7 @@ class InternalServer {
|
||||||
bool m_withTaskbar;
|
bool m_withTaskbar;
|
||||||
bool m_withLibraryButton;
|
bool m_withLibraryButton;
|
||||||
bool m_blockExternalLinks;
|
bool m_blockExternalLinks;
|
||||||
|
IpMode m_ipMode;
|
||||||
std::string m_indexTemplateString;
|
std::string m_indexTemplateString;
|
||||||
int m_ipConnectionLimit;
|
int m_ipConnectionLimit;
|
||||||
struct MHD_Daemon* mp_daemon;
|
struct MHD_Daemon* mp_daemon;
|
||||||
|
|
|
@ -32,12 +32,14 @@
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include <iphlpapi.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ioctl.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
@ -75,90 +77,126 @@ std::string kiwix::download(const std::string& url) {
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, std::string> kiwix::getNetworkInterfaces() {
|
|
||||||
std::map<std::string, std::string> interfaces;
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
SOCKET sd = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
|
|
||||||
if (sd == INVALID_SOCKET) {
|
|
||||||
std::cerr << "Failed to get a socket. Error " << WSAGetLastError() << std::endl;
|
|
||||||
return interfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERFACE_INFO InterfaceList[20];
|
std::map<std::string,kiwix::IpAddress> getNetworkInterfacesWin() {
|
||||||
unsigned long nBytesReturned;
|
std::map<std::string,kiwix::IpAddress> interfaces;
|
||||||
if (WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &InterfaceList,
|
|
||||||
sizeof(InterfaceList), &nBytesReturned, 0, 0) == SOCKET_ERROR) {
|
|
||||||
std::cerr << "Failed calling WSAIoctl: error " << WSAGetLastError() << std::endl;
|
|
||||||
return interfaces;
|
|
||||||
}
|
|
||||||
|
|
||||||
int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
|
const int working_buffer_size = 15000;
|
||||||
for (int i = 0; i < nNumInterfaces; ++i) {
|
const int max_tries = 3;
|
||||||
sockaddr_in *pAddress;
|
|
||||||
pAddress = (sockaddr_in *) & (InterfaceList[i].iiAddress.AddressIn);
|
|
||||||
if(pAddress->sin_family == AF_INET) {
|
|
||||||
/* Add to the map */
|
|
||||||
std::string interfaceName = std::string(inet_ntoa(pAddress->sin_addr));
|
|
||||||
interfaces[interfaceName] = interfaceName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* Get Network interfaces information */
|
|
||||||
char buf[16384];
|
|
||||||
struct ifconf ifconf;
|
|
||||||
int fd = socket(PF_INET, SOCK_DGRAM, 0); /* Only IPV4 */
|
|
||||||
ifconf.ifc_len = sizeof(buf);
|
|
||||||
ifconf.ifc_buf=buf;
|
|
||||||
if(ioctl(fd, SIOCGIFCONF, &ifconf)!=0) {
|
|
||||||
perror("ioctl(SIOCGIFCONF)");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Go through each interface */
|
ULONG flags = GAA_FLAG_INCLUDE_PREFIX;
|
||||||
struct ifreq *ifreq;
|
|
||||||
ifreq = ifconf.ifc_req;
|
// default to unspecified address family (both)
|
||||||
for (int i = 0; i < ifconf.ifc_len; ) {
|
ULONG family = AF_UNSPEC;
|
||||||
if (ifreq->ifr_addr.sa_family == AF_INET) {
|
|
||||||
/* Get the network interface ip */
|
ULONG outBufLen = working_buffer_size;
|
||||||
char host[128] = { 0 };
|
ULONG Iterations = 0;
|
||||||
const int error = getnameinfo(&(ifreq->ifr_addr), sizeof(ifreq->ifr_addr),
|
DWORD dwRetVal = 0;
|
||||||
host, sizeof(host),
|
PIP_ADAPTER_ADDRESSES interfacesHead = NULL;
|
||||||
0, 0, NI_NUMERICHOST);
|
|
||||||
if (!error) {
|
// Successively allocate the required memory until GetAdaptersAddresses does not
|
||||||
std::string interfaceName = std::string(ifreq->ifr_name);
|
// results in ERROR_BUFFER_OVERFLOW for a maximum of max_tries
|
||||||
std::string interfaceIp = std::string(host);
|
do{
|
||||||
/* Add to the map */
|
interfacesHead = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
|
||||||
interfaces[interfaceName] = interfaceIp;
|
if (interfacesHead == NULL) {
|
||||||
} else {
|
std::cerr << "Memory allocation failed for IP_ADAPTER_ADDRESSES struct" << std::endl;
|
||||||
perror("getnameinfo()");
|
return interfaces;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* some systems have ifr_addr.sa_len and adjust the length that
|
dwRetVal = GetAdaptersAddresses(family, flags, NULL, interfacesHead, &outBufLen);
|
||||||
* way, but not mine. weird */
|
} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < max_tries));
|
||||||
size_t len;
|
|
||||||
#ifndef __linux__
|
if (dwRetVal == NO_ERROR) {
|
||||||
len = IFNAMSIZ + ifreq->ifr_addr.sa_len;
|
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;
|
||||||
#else
|
unsigned int i = 0;
|
||||||
len = sizeof(*ifreq);
|
for (PIP_ADAPTER_ADDRESSES temp = interfacesHead; temp != NULL;
|
||||||
#endif
|
temp = temp->Next) {
|
||||||
ifreq = (struct ifreq*)((char*)ifreq+len);
|
pUnicast = temp->FirstUnicastAddress;
|
||||||
i += len;
|
if (pUnicast != NULL) {
|
||||||
|
for (i = 0; pUnicast != NULL; i++){
|
||||||
|
if (pUnicast->Address.lpSockaddr->sa_family == AF_INET)
|
||||||
|
{
|
||||||
|
sockaddr_in *si = (sockaddr_in *)(pUnicast->Address.lpSockaddr);
|
||||||
|
char host[INET_ADDRSTRLEN]={0};
|
||||||
|
inet_ntop(AF_INET, &(si->sin_addr), host, sizeof(host));
|
||||||
|
interfaces[temp->AdapterName].addr=host;
|
||||||
|
}
|
||||||
|
else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6)
|
||||||
|
{
|
||||||
|
sockaddr_in6 *si = (sockaddr_in6 *)(pUnicast->Address.lpSockaddr);
|
||||||
|
char host[INET6_ADDRSTRLEN]={0};
|
||||||
|
inet_ntop(AF_INET6, &(si->sin6_addr), host, sizeof(host));
|
||||||
|
if (!IN6_IS_ADDR_LINKLOCAL(&(si->sin6_addr)))
|
||||||
|
interfaces[temp->AdapterName].addr6=host;
|
||||||
|
}
|
||||||
|
pUnicast = pUnicast->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cerr << "Call to GetAdaptersAddresses failed with error: "<< dwRetVal << std::endl;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
if (interfacesHead) free(interfacesHead);
|
||||||
|
|
||||||
return interfaces;
|
return interfaces;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string kiwix::getBestPublicIp() {
|
#else
|
||||||
auto interfaces = getNetworkInterfaces();
|
|
||||||
|
std::map<std::string,kiwix::IpAddress> getNetworkInterfacesPosix() {
|
||||||
|
std::map<std::string,kiwix::IpAddress> interfaces;
|
||||||
|
|
||||||
|
struct ifaddrs *interfacesHead;
|
||||||
|
if (getifaddrs(&interfacesHead) == -1) {
|
||||||
|
perror("getifaddrs");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ifaddrs *temp = interfacesHead; temp != NULL; temp = temp->ifa_next) {
|
||||||
|
if (temp->ifa_addr == NULL) continue;
|
||||||
|
|
||||||
|
if (temp->ifa_addr->sa_family == AF_INET) {
|
||||||
|
sockaddr_in *si = (sockaddr_in *)(temp->ifa_addr);
|
||||||
|
char host[INET_ADDRSTRLEN] = {0};
|
||||||
|
inet_ntop(AF_INET, &(si->sin_addr), host, sizeof(host));
|
||||||
|
interfaces[temp->ifa_name].addr=host;
|
||||||
|
} else if (temp->ifa_addr->sa_family == AF_INET6) {
|
||||||
|
sockaddr_in6 *si = (sockaddr_in6 *)(temp->ifa_addr);
|
||||||
|
char host[INET6_ADDRSTRLEN] = {0};
|
||||||
|
inet_ntop(AF_INET6, &(si->sin6_addr), host, sizeof(host));
|
||||||
|
if (!IN6_IS_ADDR_LINKLOCAL(&(si->sin6_addr)))
|
||||||
|
interfaces[temp->ifa_name].addr6=host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
freeifaddrs(interfacesHead);
|
||||||
|
|
||||||
|
return interfaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::map<std::string,kiwix::IpAddress> kiwix::getNetworkInterfaces() {
|
||||||
|
#ifdef _WIN32
|
||||||
|
return getNetworkInterfacesWin();
|
||||||
|
#else
|
||||||
|
return getNetworkInterfacesPosix();
|
||||||
|
#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();
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
const char* const prioritizedNames[] =
|
const char* const prioritizedNames[] =
|
||||||
{ "eth0", "eth1", "wlan0", "wlan1", "en0", "en1" };
|
{ "eth0", "eth1", "wlan0", "wlan1", "en0", "en1" };
|
||||||
for(auto name: prioritizedNames) {
|
for(auto name: prioritizedNames) {
|
||||||
auto it = interfaces.find(name);
|
auto it=interfaces.find(name);
|
||||||
if(it != interfaces.end()) {
|
if(it != interfaces.end() && !(ipv6 && (*it).second.addr6.empty())) {
|
||||||
return it->second;
|
bestPublicIp = (*it).second;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -166,12 +204,12 @@ std::string kiwix::getBestPublicIp() {
|
||||||
const char* const prefixes[] = { "192.168", "172.16.", "10.0" };
|
const char* const prefixes[] = { "192.168", "172.16.", "10.0" };
|
||||||
for(auto prefix : prefixes){
|
for(auto prefix : prefixes){
|
||||||
for(auto& itr : interfaces) {
|
for(auto& itr : interfaces) {
|
||||||
auto interfaceIp = itr.second;
|
std::string interfaceIp(itr.second.addr);
|
||||||
if (interfaceIp.find(prefix) == 0) {
|
if (interfaceIp.find(prefix) == 0 && !(ipv6 && itr.second.addr6.empty())) {
|
||||||
return interfaceIp;
|
bestPublicIp = itr.second;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return ipv6 ? bestPublicIp.addr6 : bestPublicIp.addr;
|
||||||
return "127.0.0.1";
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue