Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add IPv6 support to HTTP daemon #1074

Merged
merged 2 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

namespace kiwix {

enum class IpMode { ipv4, ipv6, all };
typedef zim::size_type size_type;
typedef zim::offset_type offset_type;

Expand Down
4 changes: 4 additions & 0 deletions include/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <string>
#include <memory>
#include "common.h"

namespace kiwix
{
Expand Down Expand Up @@ -62,8 +63,10 @@ namespace kiwix
{ m_withTaskbar = withTaskbar; m_withLibraryButton = withLibraryButton; }
void setBlockExternalLinks(bool blockExternalLinks)
{ m_blockExternalLinks = blockExternalLinks; }
void setIpMode(IpMode mode) { m_ipMode = mode; }
int getPort();
std::string getAddress();
IpMode getIpMode() const;

protected:
std::shared_ptr<Library> mp_library;
Expand All @@ -78,6 +81,7 @@ namespace kiwix
bool m_withTaskbar = true;
bool m_withLibraryButton = true;
bool m_blockExternalLinks = false;
IpMode m_ipMode = IpMode::ipv4;
int m_ipConnectionLimit = 0;
std::unique_ptr<InternalServer> mp_server;
};
Expand Down
11 changes: 8 additions & 3 deletions include/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
#include <cstdint>

namespace kiwix {
struct IpAddress{
std::string addr;
std::string addr6;
};

typedef std::pair<std::string, std::string> LangNameCodePair;
typedef std::vector<LangNameCodePair> FeedLanguages;
typedef std::vector<std::string> FeedCategories;
Expand Down Expand Up @@ -217,14 +222,14 @@ std::string getMimeTypeForFile(const std::string& filename);

/** 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
* 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.
*
Expand Down
11 changes: 4 additions & 7 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ if host_machine.system() == 'windows' and static_deps
endif

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

all_deps = [thread_dep, libicu_dep, libzim_dep, pugixml_dep, libcurl_dep, microhttpd_dep, zlib_dep, xapian_dep]
Expand All @@ -58,12 +61,6 @@ inc = include_directories('include', extra_include)
conf = configuration_data()
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('scripts')
subdir('static')
Expand Down
6 changes: 6 additions & 0 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ bool Server::start() {
m_withTaskbar,
m_withLibraryButton,
m_blockExternalLinks,
m_ipMode,
m_indexTemplateString,
m_ipConnectionLimit));
return mp_server->start();
Expand Down Expand Up @@ -84,4 +85,9 @@ std::string Server::getAddress()
return mp_server->getAddress();
}

IpMode Server::getIpMode() const
{
return mp_server->getIpMode();
}

}
38 changes: 30 additions & 8 deletions src/server/internalServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ InternalServer::InternalServer(LibraryPtr library,
bool withTaskbar,
bool withLibraryButton,
bool blockExternalLinks,
IpMode ipMode,
std::string indexTemplateString,
int ipConnectionLimit) :
m_addr(addr),
Expand All @@ -428,6 +429,7 @@ InternalServer::InternalServer(LibraryPtr library,
m_withTaskbar(withTaskbar),
m_withLibraryButton(withLibraryButton),
m_blockExternalLinks(blockExternalLinks),
m_ipMode(ipMode),
m_indexTemplateString(indexTemplateString.empty() ? RESOURCE::templates::index_html : indexTemplateString),
m_ipConnectionLimit(ipConnectionLimit),
mp_daemon(nullptr),
Expand All @@ -451,28 +453,48 @@ bool InternalServer::start() {
if (m_verbose.load())
flags |= MHD_USE_DEBUG;

struct sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.sin_family = AF_INET;
sockAddr.sin_port = htons(m_port);

struct sockaddr_in sockAddr4={0};
sockAddr4.sin_family = AF_INET;
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 (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 {
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;
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,
m_port,
NULL,
NULL,
&staticHandlerCallback,
this,
MHD_OPTION_SOCK_ADDR, &sockAddr,
MHD_OPTION_SOCK_ADDR, sockaddr,
MHD_OPTION_THREAD_POOL_SIZE, m_nbThreads,
MHD_OPTION_PER_IP_CONNECTION_LIMIT, m_ipConnectionLimit,
MHD_OPTION_END);
Expand Down
3 changes: 3 additions & 0 deletions src/server/internalServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class InternalServer {
bool withTaskbar,
bool withLibraryButton,
bool blockExternalLinks,
IpMode ipMode,
std::string indexTemplateString,
int ipConnectionLimit);
virtual ~InternalServer();
Expand All @@ -118,6 +119,7 @@ class InternalServer {
void stop();
std::string getAddress() { return m_addr; }
int getPort() { return m_port; }
IpMode getIpMode() const { return m_ipMode; }

private: // functions
std::unique_ptr<Response> handle_request(const RequestContext& request);
Expand Down Expand Up @@ -174,6 +176,7 @@ class InternalServer {
bool m_withTaskbar;
bool m_withLibraryButton;
bool m_blockExternalLinks;
IpMode m_ipMode;
std::string m_indexTemplateString;
int m_ipConnectionLimit;
struct MHD_Daemon* mp_daemon;
Expand Down
Loading
Loading