mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
initial config overriding on runtime
This commit is contained in:
parent
e3bfe76f98
commit
5391e6a66a
10 changed files with 259 additions and 127 deletions
|
@ -66,6 +66,10 @@ namespace llarp
|
||||||
void
|
void
|
||||||
Configure(Config conf);
|
Configure(Config conf);
|
||||||
|
|
||||||
|
/// handle SIGHUP
|
||||||
|
void
|
||||||
|
Reload();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
IsUp() const;
|
IsUp() const;
|
||||||
|
|
||||||
|
@ -92,7 +96,7 @@ namespace llarp
|
||||||
makeRouter(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic);
|
makeRouter(llarp_ev_loop_ptr __netloop, std::shared_ptr<Logic> logic);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::unique_ptr<Config> config = nullptr;
|
std::shared_ptr<Config> config = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void
|
void
|
||||||
|
|
|
@ -547,6 +547,18 @@ namespace llarp
|
||||||
"logging", "file", false, DefaultLogFile, AssignmentAcceptor(m_logFile));
|
"logging", "file", false, DefaultLogFile, AssignmentAcceptor(m_logFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::Save() const
|
||||||
|
{
|
||||||
|
m_Parser.Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Config::Override(std::string section, std::string key, std::string value)
|
||||||
|
{
|
||||||
|
m_Parser.AddOverride(std::move(section), std::move(key), std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Config::Load(const fs::path fname, bool isRelay, fs::path defaultDataDir)
|
Config::Load(const fs::path fname, bool isRelay, fs::path defaultDataDir)
|
||||||
{
|
{
|
||||||
|
@ -559,14 +571,13 @@ namespace llarp
|
||||||
ConfigDefinition conf;
|
ConfigDefinition conf;
|
||||||
initializeConfig(conf, params);
|
initializeConfig(conf, params);
|
||||||
addBackwardsCompatibleConfigOptions(conf);
|
addBackwardsCompatibleConfigOptions(conf);
|
||||||
|
m_Parser.Clear();
|
||||||
ConfigParser parser;
|
if (!m_Parser.LoadFile(fname))
|
||||||
if (!parser.LoadFile(fname))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
parser.IterAll([&](std::string_view section, const SectionValues_t& values) {
|
m_Parser.IterAll([&](std::string_view section, const SectionValues_t& values) {
|
||||||
for (const auto& pair : values)
|
for (const auto& pair : values)
|
||||||
{
|
{
|
||||||
conf.addConfigValue(section, pair.first, pair.second);
|
conf.addConfigValue(section, pair.first, pair.second);
|
||||||
|
|
|
@ -224,6 +224,15 @@ namespace llarp
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
generateBaseRouterConfig(fs::path defaultDataDir);
|
generateBaseRouterConfig(fs::path defaultDataDir);
|
||||||
|
|
||||||
|
void
|
||||||
|
Save() const;
|
||||||
|
|
||||||
|
void
|
||||||
|
Override(std::string section, std::string key, std::string value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ConfigParser m_Parser;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace llarp
|
||||||
void
|
void
|
||||||
ConfigParser::Clear()
|
ConfigParser::Clear()
|
||||||
{
|
{
|
||||||
|
m_Overrides.clear();
|
||||||
m_Config.clear();
|
m_Config.clear();
|
||||||
m_Data.clear();
|
m_Data.clear();
|
||||||
}
|
}
|
||||||
|
@ -162,4 +163,32 @@ namespace llarp
|
||||||
return false;
|
return false;
|
||||||
return visit(itr->second);
|
return visit(itr->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigParser::AddOverride(std::string section, std::string key, std::string value)
|
||||||
|
{
|
||||||
|
m_Overrides[section].emplace(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigParser::Save() const
|
||||||
|
{
|
||||||
|
// if we have no overrides keep the config the same on disk
|
||||||
|
if (m_Overrides.empty())
|
||||||
|
return;
|
||||||
|
std::ofstream ofs(m_FileName);
|
||||||
|
// write existing config data
|
||||||
|
ofs.write(m_Data.data(), m_Data.size());
|
||||||
|
// write overrides
|
||||||
|
ofs << std::endl << std::endl << "# overrides" << std::endl;
|
||||||
|
for (const auto& [section, values] : m_Overrides)
|
||||||
|
{
|
||||||
|
ofs << std::endl << "[" << section << "]" << std::endl;
|
||||||
|
for (const auto& [key, value] : values)
|
||||||
|
{
|
||||||
|
ofs << key << "=" << value << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace llarp
|
} // namespace llarp
|
||||||
|
|
|
@ -40,12 +40,21 @@ namespace llarp
|
||||||
bool
|
bool
|
||||||
VisitSection(const char* name, std::function<bool(const SectionValues_t&)> visit) const;
|
VisitSection(const char* name, std::function<bool(const SectionValues_t&)> visit) const;
|
||||||
|
|
||||||
|
/// add a config option that is appended at the end of the config buffer with no comments
|
||||||
|
void
|
||||||
|
AddOverride(std::string section, std::string key, std::string value);
|
||||||
|
|
||||||
|
/// save config and any overrides to the file it was loaded from
|
||||||
|
void
|
||||||
|
Save() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool
|
bool
|
||||||
Parse();
|
Parse();
|
||||||
|
|
||||||
std::vector<char> m_Data;
|
std::vector<char> m_Data;
|
||||||
Config_impl_t m_Config;
|
Config_impl_t m_Config;
|
||||||
|
Config_impl_t m_Overrides;
|
||||||
fs::path m_FileName;
|
fs::path m_FileName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ namespace llarp
|
||||||
if (nullptr != config.get())
|
if (nullptr != config.get())
|
||||||
throw std::runtime_error("Config already exists");
|
throw std::runtime_error("Config already exists");
|
||||||
|
|
||||||
config = std::make_unique<Config>(std::move(conf));
|
config = std::make_shared<Config>(std::move(conf));
|
||||||
|
|
||||||
logic = std::make_shared<Logic>();
|
logic = std::make_shared<Logic>();
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ namespace llarp
|
||||||
nodedb = std::make_unique<llarp_nodedb>(
|
nodedb = std::make_unique<llarp_nodedb>(
|
||||||
nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); });
|
nodedb_dir, [r = router.get()](auto call) { r->QueueDiskIO(std::move(call)); });
|
||||||
|
|
||||||
if (!router->Configure(*config.get(), opts.isRouter, nodedb.get()))
|
if (!router->Configure(config, opts.isRouter, nodedb.get()))
|
||||||
throw std::runtime_error("Failed to configure router");
|
throw std::runtime_error("Failed to configure router");
|
||||||
|
|
||||||
// must be done after router is made so we can use its disk io worker
|
// must be done after router is made so we can use its disk io worker
|
||||||
|
@ -157,8 +157,17 @@ namespace llarp
|
||||||
{
|
{
|
||||||
SigINT();
|
SigINT();
|
||||||
}
|
}
|
||||||
// TODO: Hot reloading would be kewl
|
#ifndef _WIN32
|
||||||
// (it used to exist here, but wasn't maintained)
|
if (sig == SIGHUP)
|
||||||
|
{
|
||||||
|
Reload();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Context::Reload()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -182,7 +191,7 @@ namespace llarp
|
||||||
Context::Close()
|
Context::Close()
|
||||||
{
|
{
|
||||||
llarp::LogDebug("free config");
|
llarp::LogDebug("free config");
|
||||||
config.release();
|
config.reset();
|
||||||
|
|
||||||
llarp::LogDebug("free nodedb");
|
llarp::LogDebug("free nodedb");
|
||||||
nodedb.release();
|
nodedb.release();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#ifndef LLARP_ABSTRACT_ROUTER_HPP
|
#ifndef LLARP_ABSTRACT_ROUTER_HPP
|
||||||
#define LLARP_ABSTRACT_ROUTER_HPP
|
#define LLARP_ABSTRACT_ROUTER_HPP
|
||||||
|
|
||||||
|
#include <config/config.hpp>
|
||||||
#include <config/key_manager.hpp>
|
#include <config/key_manager.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <util/types.hpp>
|
#include <util/types.hpp>
|
||||||
|
@ -134,6 +135,12 @@ namespace llarp
|
||||||
/// call function in disk io thread
|
/// call function in disk io thread
|
||||||
virtual void QueueDiskIO(std::function<void(void)>) = 0;
|
virtual void QueueDiskIO(std::function<void(void)>) = 0;
|
||||||
|
|
||||||
|
virtual std::shared_ptr<Config>
|
||||||
|
GetConfig() const
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
virtual service::Context&
|
virtual service::Context&
|
||||||
hiddenServiceContext() = 0;
|
hiddenServiceContext() = 0;
|
||||||
|
|
||||||
|
@ -159,7 +166,7 @@ namespace llarp
|
||||||
Sign(Signature& sig, const llarp_buffer_t& buf) const = 0;
|
Sign(Signature& sig, const llarp_buffer_t& buf) const = 0;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb) = 0;
|
Configure(std::shared_ptr<Config> conf, bool isRouter, llarp_nodedb* nodedb) = 0;
|
||||||
|
|
||||||
virtual bool
|
virtual bool
|
||||||
IsServiceNode() const = 0;
|
IsServiceNode() const = 0;
|
||||||
|
|
|
@ -262,8 +262,10 @@ namespace llarp
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Router::Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb)
|
Router::Configure(std::shared_ptr<Config> c, bool isRouter, llarp_nodedb* nodedb)
|
||||||
{
|
{
|
||||||
|
m_Config = c;
|
||||||
|
auto& conf = *m_Config;
|
||||||
whitelistRouters = conf.lokid.whitelistRouters;
|
whitelistRouters = conf.lokid.whitelistRouters;
|
||||||
if (whitelistRouters)
|
if (whitelistRouters)
|
||||||
lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr);
|
lokidRPCAddr = lokimq::address(conf.lokid.lokidRPCAddr);
|
||||||
|
|
|
@ -353,7 +353,7 @@ namespace llarp
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Configure(const Config& conf, bool isRouter, llarp_nodedb* nodedb = nullptr) override;
|
Configure(std::shared_ptr<Config> conf, bool isRouter, llarp_nodedb* nodedb = nullptr) override;
|
||||||
|
|
||||||
bool
|
bool
|
||||||
StartRpcServer() override;
|
StartRpcServer() override;
|
||||||
|
@ -499,6 +499,14 @@ namespace llarp
|
||||||
void
|
void
|
||||||
AfterStopIssued();
|
AfterStopIssued();
|
||||||
|
|
||||||
|
std::shared_ptr<Config> m_Config;
|
||||||
|
|
||||||
|
std::shared_ptr<Config>
|
||||||
|
GetConfig() const override
|
||||||
|
{
|
||||||
|
return m_Config;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::atomic<bool> _stopping;
|
std::atomic<bool> _stopping;
|
||||||
std::atomic<bool> _running;
|
std::atomic<bool> _running;
|
||||||
|
|
|
@ -110,7 +110,9 @@ namespace llarp::rpc
|
||||||
auto ftr = result.get_future();
|
auto ftr = result.get_future();
|
||||||
msg.send_reply(CreateJSONResponse(ftr.get()));
|
msg.send_reply(CreateJSONResponse(ftr.get()));
|
||||||
})
|
})
|
||||||
.add_request_command("exit", [&](lokimq::Message& msg) {
|
.add_request_command(
|
||||||
|
"exit",
|
||||||
|
[&](lokimq::Message& msg) {
|
||||||
HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) {
|
HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) {
|
||||||
if (r->IsServiceNode())
|
if (r->IsServiceNode())
|
||||||
{
|
{
|
||||||
|
@ -236,6 +238,48 @@ namespace llarp::rpc
|
||||||
reply(CreateJSONResponse("OK"));
|
reply(CreateJSONResponse("OK"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.add_request_command("config", [&](lokimq::Message& msg) {
|
||||||
|
HandleJSONRequest(msg, [r = m_Router](nlohmann::json obj, ReplyFunction_t reply) {
|
||||||
|
{
|
||||||
|
const auto itr = obj.find("override");
|
||||||
|
if (itr != obj.end())
|
||||||
|
{
|
||||||
|
if (not itr->is_object())
|
||||||
|
{
|
||||||
|
reply(CreateJSONError(stringify("override is not an object")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& [section, value] : itr->items())
|
||||||
|
{
|
||||||
|
if (not value.is_object())
|
||||||
|
{
|
||||||
|
reply(CreateJSONError(
|
||||||
|
stringify("failed to set [", section, "] section is not an object")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const auto& [key, value] : value.items())
|
||||||
|
{
|
||||||
|
if (not value.is_string())
|
||||||
|
{
|
||||||
|
reply(CreateJSONError(stringify(
|
||||||
|
"failed to set [", section, "]:", key, " value is not a string")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
r->GetConfig()->Override(section, key, value.get<std::string>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto itr = obj.find("reload");
|
||||||
|
if (itr != obj.end() and itr->get<bool>())
|
||||||
|
{
|
||||||
|
r->QueueDiskIO([conf = r->GetConfig()]() { conf->Save(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
reply(CreateJSONResponse("OK"));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} // namespace llarp::rpc
|
} // namespace llarp::rpc
|
||||||
|
|
Loading…
Reference in a new issue