Skip to content

Commit

Permalink
Web server: editing of all settings must be done via the WebServerSet…
Browse files Browse the repository at this point in the history
  • Loading branch information
maksis committed Jul 20, 2021
1 parent e8c563a commit ca5e4c5
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 131 deletions.
13 changes: 8 additions & 5 deletions airdcpp-webapi/api/SettingApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ namespace webserver {

auto hasSet = false;
parseSettingValues(aRequest.getRequestBody(), [&](ApiSettingItem& aItem, const json& aValue) {
aItem.setDefaultValue(aValue);
auto settings = aRequest.getSession()->getServer()->getSettingsManager();
settings.setDefaultValue(aItem, aValue);

hasSet = true;
}, aRequest.getSession()->getServer());

Expand Down Expand Up @@ -128,16 +130,18 @@ namespace webserver {

api_return SettingApi::handleResetValues(ApiRequest& aRequest) {
const auto& requestJson = aRequest.getRequestBody();
auto settings = aRequest.getSession()->getServer()->getSettingsManager();

parseSettingKeys(requestJson, [&](ApiSettingItem& aItem) {
aItem.unset();
settings.unset(aItem);
}, aRequest.getSession()->getServer());

return websocketpp::http::status_code::no_content;
}

api_return SettingApi::handleSetValues(ApiRequest& aRequest) {
auto server = aRequest.getSession()->getServer();
auto settings = aRequest.getSession()->getServer()->getSettingsManager();
auto holder = make_shared<SettingHolder>(
[=](const string& aError) {
server->log(aError, LogMessage::SEV_ERROR);
Expand All @@ -147,14 +151,13 @@ namespace webserver {
bool hasSet = false;

parseSettingValues(aRequest.getRequestBody(), [&](ApiSettingItem& aItem, const json& aValue) {
aItem.setValue(aValue);
server->getSettingsManager().setValue(aItem, aValue);
hasSet = true;
}, aRequest.getSession()->getServer());

dcassert(hasSet);

SettingsManager::getInstance()->save();
server->setDirty();

// This may take a while, don't wait
addAsyncTask([=] {
Expand All @@ -170,6 +173,6 @@ namespace webserver {
return p;
}

return aWsm->getSettings().getSettingItem(aKey);
return aWsm->getSettingsManager().getSettingItem(aKey);
}
}
31 changes: 18 additions & 13 deletions airdcpp-webapi/web-server/ApiSettingItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,6 @@ namespace webserver {
// Returns the value and bool indicating whether it's an auto detected value
virtual string getTitle() const noexcept = 0;

virtual void setValue(const json& aJson) = 0;
virtual void setDefaultValue(const json& aJson) = 0;
virtual void unset() noexcept = 0;
virtual json getValue() const noexcept = 0;
virtual json getDefaultValue() const noexcept = 0;
virtual PtrList getListObjectFields() const noexcept = 0;
Expand Down Expand Up @@ -115,6 +112,13 @@ namespace webserver {

return ret;
}

friend class WebServerSettings;

protected:
virtual void setValue(const json& aJson) = 0;
virtual void setDefaultValue(const json& aJson) = 0;
virtual void unset() noexcept = 0;
};

class CoreSettingItem : public ApiSettingItem {
Expand All @@ -137,11 +141,6 @@ namespace webserver {
ApiSettingItem::PtrList getListObjectFields() const noexcept override;
const string& getHelpStr() const noexcept override;

// Throws on invalid JSON
void setValue(const json& aJson) override;
void setDefaultValue(const json& aJson) override;
void unset() noexcept override;

string getTitle() const noexcept override;

const ResourceManager::Strings unit;
Expand All @@ -154,6 +153,12 @@ namespace webserver {

EnumOption::List getEnumOptions() const noexcept override;
bool usingAutoValue(bool aForce) const noexcept override;
protected:
friend class WebServerSettings;
// Throws on invalid JSON
void setValue(const json& aJson) override;
void setDefaultValue(const json& aJson) override;
void unset() noexcept override;
private:
const SettingItem si;
};
Expand All @@ -170,10 +175,6 @@ namespace webserver {
json getValue() const noexcept override;
const json& getValueRef() const noexcept;

void setValue(const json& aJson) override;

void unset() noexcept override;

int num() const;
uint64_t uint64() const;
string str() const;
Expand All @@ -190,11 +191,15 @@ namespace webserver {

const MinMax& getMinMax() const noexcept override;
json getDefaultValue() const noexcept override;
void setDefaultValue(const json& aValue) override;

EnumOption::List getEnumOptions() const noexcept override;
//ServerSettingItem(ServerSettingItem&& rhs) noexcept = default;
//ServerSettingItem& operator=(ServerSettingItem&& rhs) noexcept = default;

void setValue(const json& aJson) override;
void unset() noexcept override;
void setDefaultValue(const json& aValue) override;

private:
const EnumOption::List enumOptions;
const MinMax minMax;
Expand Down
89 changes: 14 additions & 75 deletions airdcpp-webapi/web-server/WebServerManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,8 @@
#include <airdcpp/SimpleXML.h>
#include <airdcpp/TimerManager.h>

#define CONFIG_NAME_XML "WebServer.xml"
#define CONFIG_NAME_JSON "web-server.json"
#define LEGACY_CONFIG_NAME_XML "WebServer.xml"
#define CONFIG_DIR Util::PATH_USER_CONFIG
#define CONFIG_VERSION 1

#define AUTHENTICATION_TIMEOUT 60 // seconds

Expand All @@ -46,19 +44,21 @@
namespace webserver {
using namespace dcpp;
WebServerManager::WebServerManager() :
ios(settings.getSettingItem(WebServerSettings::SERVER_THREADS).getDefaultValue()),
tasks(settings.getSettingItem(WebServerSettings::SERVER_THREADS).getDefaultValue()),
work(tasks),
plainServerConfig(settings.getSettingItem(WebServerSettings::PLAIN_PORT), settings.getSettingItem(WebServerSettings::PLAIN_BIND)),
tlsServerConfig(settings.getSettingItem(WebServerSettings::TLS_PORT), settings.getSettingItem(WebServerSettings::TLS_BIND))
ios(4),
tasks(4),
work(tasks)
{

fileServer.setResourcePath(Util::getPath(Util::PATH_RESOURCES) + "web-resources" + PATH_SEPARATOR);

settingsManager = make_unique<WebServerSettings>(this);
extManager = make_unique<ExtensionManager>(this);
userManager = make_unique<WebUserManager>(this);
contextMenuManager = make_unique<ContextMenuManager>();

plainServerConfig = make_unique<ServerConfig>(settingsManager->getSettingItem(WebServerSettings::PLAIN_PORT), settingsManager->getSettingItem(WebServerSettings::PLAIN_BIND));
tlsServerConfig = make_unique<ServerConfig>(settingsManager->getSettingItem(WebServerSettings::TLS_PORT), settingsManager->getSettingItem(WebServerSettings::TLS_BIND));

// Prevent io service from running until we load
ios.stop();
tasks.stop();
Expand All @@ -70,10 +70,6 @@ namespace webserver {
userManager.reset();
}

string WebServerManager::getConfigFilePath() const noexcept {
return Util::getPath(CONFIG_DIR) + CONFIG_NAME_JSON;
}

bool WebServerManager::isRunning() const noexcept {
return !ios.stopped() || !tasks.stopped();
}
Expand Down Expand Up @@ -241,11 +237,11 @@ namespace webserver {
bool WebServerManager::listen(const MessageCallback& errorF) {
bool hasServer = false;

if (listenEndpoint(endpoint_plain, plainServerConfig, "HTTP", errorF)) {
if (listenEndpoint(endpoint_plain, *plainServerConfig, "HTTP", errorF)) {
hasServer = true;
}

if (listenEndpoint(endpoint_tls, tlsServerConfig, "HTTPS", errorF)) {
if (listenEndpoint(endpoint_tls, *tlsServerConfig, "HTTPS", errorF)) {
hasServer = true;
}

Expand Down Expand Up @@ -451,10 +447,6 @@ namespace webserver {
tasks.post(aCallback);
}

void WebServerManager::setDirty() noexcept {
isDirty = true;
}

void WebServerManager::addSocket(websocketpp::connection_hdl hdl, const WebSocketPtr& aSocket) noexcept {
{
WLock l(cs);
Expand Down Expand Up @@ -507,7 +499,7 @@ namespace webserver {
string WebServerManager::getLocalServerHttpUrl() noexcept {
bool isPlain = isListeningPlain();
decltype(auto) config = isPlain ? plainServerConfig : tlsServerConfig;
return (isPlain ? "http://" : "https://") + getLocalServerAddress(config);
return (isPlain ? "http://" : "https://") + getLocalServerAddress(*config);
}

bool WebServerManager::isAnyAddress(const string& aAddress) noexcept {
Expand Down Expand Up @@ -569,7 +561,7 @@ namespace webserver {
}

bool WebServerManager::hasValidServerConfig() const noexcept {
return plainServerConfig.hasValidConfig() || tlsServerConfig.hasValidConfig();
return plainServerConfig->hasValidConfig() || tlsServerConfig->hasValidConfig();
}

bool WebServerManager::hasUsers() const noexcept {
Expand All @@ -581,71 +573,24 @@ namespace webserver {
}

bool WebServerManager::load(const MessageCallback& aErrorF) noexcept {
const auto legacyXmlPath = Util::getPath(CONFIG_DIR) + CONFIG_NAME_XML;
const auto legacyXmlPath = Util::getPath(CONFIG_DIR) + LEGACY_CONFIG_NAME_XML;
if (Util::fileExists(legacyXmlPath)) {
SettingsManager::loadSettingFile(CONFIG_DIR, CONFIG_NAME_XML, [this](SimpleXML& xml) {
SettingsManager::loadSettingFile(CONFIG_DIR, LEGACY_CONFIG_NAME_XML, [this](SimpleXML& xml) {
if (xml.findChild("WebServer")) {
xml.stepIn();

if (xml.findChild("Config")) {
xml.stepIn();
loadServer(xml, "Server", plainServerConfig, false);
loadServer(xml, "TLSServer", tlsServerConfig, true);

if (xml.findChild("Threads")) {
xml.stepIn();
WEBCFG(SERVER_THREADS).setValue(max(Util::toInt(xml.getData()), 1));
xml.stepOut();
}
xml.resetCurrentChild();

if (xml.findChild("ExtensionsDebugMode")) {
xml.stepIn();
WEBCFG(EXTENSIONS_DEBUG_MODE).setValue(Util::toInt(xml.getData()) > 0 ? true : false);
xml.stepOut();
}
xml.resetCurrentChild();

xml.stepOut();
}

fire(WebServerManagerListener::LoadLegacySettings(), xml);

xml.stepOut();
}
}, aErrorF);

File::deleteFile(legacyXmlPath);
setDirty();
}

WebServerSettings::loadSettingFile(CONFIG_DIR, CONFIG_NAME_JSON, [this, &aErrorF](const json& aJson, int) {
settings.fromJsonThrow(aJson);
}, aErrorF, CONFIG_VERSION);

fire(WebServerManagerListener::LoadSettings(), aErrorF);
return hasValidServerConfig();
}

void WebServerManager::loadServer(SimpleXML& aXml, const string& aTagName, ServerConfig& config_, bool aTls) noexcept {
if (aXml.findChild(aTagName)) {
// getChildIntAttrib returns 0 also for non-existing attributes, get as string instead...
const auto port = aXml.getChildAttrib("Port");
if (!port.empty()) {
config_.port.setValue(Util::toInt(port));
}

config_.bindAddress.setValue(aXml.getChildAttrib("BindAddress"));

if (aTls) {
WEBCFG(TLS_CERT_PATH).setValue(aXml.getChildAttrib("Certificate"));
WEBCFG(TLS_CERT_KEY_PATH).setValue(aXml.getChildAttrib("CertificateKey"));
}
}

aXml.resetCurrentChild();
}

bool WebServerManager::save(const MessageCallback& aCustomErrorF) noexcept {
auto errorF = aCustomErrorF;
if (!errorF) {
Expand All @@ -654,12 +599,6 @@ namespace webserver {
}

fire(WebServerManagerListener::SaveSettings(), errorF);

if (isDirty) {
isDirty = false;
return WebServerSettings::saveSettingFile(settings.toJson(), CONFIG_DIR, CONFIG_NAME_JSON, errorF, CONFIG_VERSION);
}

return true;
}

Expand Down
21 changes: 9 additions & 12 deletions airdcpp-webapi/web-server/WebServerManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,11 @@ namespace webserver {
// Reset sessions for associated sockets
WebSocketPtr getSocket(LocalSessionId aSessionToken) noexcept;

void setDirty() noexcept;
bool load(const MessageCallback& aErrorF) noexcept;
bool save(const MessageCallback& aErrorF) noexcept;
string getConfigFilePath() const noexcept;
WebServerSettings& getSettings() noexcept {
return settings;
WebServerSettings& getSettingsManager() noexcept {
return *settingsManager.get();
}

WebUserManager& getUserManager() noexcept {
Expand All @@ -119,12 +118,12 @@ namespace webserver {
bool hasUsers() const noexcept;
bool waitExtensionsLoaded() const noexcept;

ServerConfig& getPlainServerConfig() noexcept {
return plainServerConfig;
const ServerConfig& getPlainServerConfig() noexcept {
return *plainServerConfig;
}

ServerConfig& getTlsServerConfig() noexcept {
return tlsServerConfig;
const ServerConfig& getTlsServerConfig() noexcept {
return *tlsServerConfig;
}

// Get location of the file server root directory (Web UI files)
Expand Down Expand Up @@ -331,8 +330,6 @@ namespace webserver {
aEndpoint.set_pong_timeout_handler(std::bind(&WebServerManager::handlePongTimeout, aServer, _1, _2));
}

WebServerSettings settings;

context_ptr handleInitTls(websocketpp::connection_hdl hdl);

void addSocket(websocketpp::connection_hdl hdl, const WebSocketPtr& aSocket) noexcept;
Expand All @@ -341,8 +338,8 @@ namespace webserver {

bool initialize(const MessageCallback& errorF);

ServerConfig plainServerConfig;
ServerConfig tlsServerConfig;
unique_ptr<ServerConfig> plainServerConfig;
unique_ptr<ServerConfig> tlsServerConfig;

void loadServer(SimpleXML& xml_, const string& aTagName, ServerConfig& config_, bool aTls) noexcept;
void pingTimer() noexcept;
Expand All @@ -365,6 +362,7 @@ namespace webserver {
unique_ptr<WebUserManager> userManager;
unique_ptr<ExtensionManager> extManager;
unique_ptr<ContextMenuManager> contextMenuManager;
unique_ptr<WebServerSettings> settingsManager;

TimerPtr minuteTimer;
TimerPtr socketPingTimer;
Expand All @@ -383,7 +381,6 @@ namespace webserver {
unique_ptr<boost::thread_group> task_threads;

Callback shutdownF;
bool isDirty = false;
};
}

Expand Down
2 changes: 2 additions & 0 deletions airdcpp-webapi/web-server/WebServerManagerListener.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

#include "forward.h"

#include <airdcpp/forward.h>

namespace webserver {
enum class TransportType {
TYPE_SOCKET, TYPE_HTTP_API, TYPE_HTTP_FILE
Expand Down
Loading

0 comments on commit ca5e4c5

Please sign in to comment.