Commit e87e7462 authored by Adrien Béraud's avatar Adrien Béraud

dht: save values to the disk

Refs #56312

Change-Id: Ic07fc68b3130be181405c8971b4f66bb496abbc7
parent f39901da
......@@ -65,6 +65,7 @@
#include <unistd.h>
#include <pwd.h>
#include <dirent.h>
#include <algorithm>
#include <array>
......@@ -89,18 +90,19 @@ DHTAccount::DHTAccount(const std::string& accountID, bool /* presenceEnabled */)
fileutils::check_dir(fileutils::get_cache_dir().c_str());
nodePath_ = fileutils::get_cache_dir()+DIR_SEPARATOR_STR+getAccountID();
fileutils::check_dir(nodePath_.c_str());
WARN("node cache path: %s", nodePath_.c_str());
if (privkeyPath_.empty()) {
fileutils::check_dir(fileutils::get_data_dir().c_str());
const auto idPath = fileutils::get_data_dir()+DIR_SEPARATOR_STR+getAccountID();
fileutils::check_dir(idPath.c_str());
privkeyPath_ = idPath+DIR_SEPARATOR_STR+"id_rsa";
WARN("privkeyPath : %s", privkeyPath_.c_str());
}
if (certPath_.empty()) {
certPath_ = privkeyPath_+".pub";
WARN("certPath : %s", certPath_.c_str());
}
/* ~/.local/{appname} */
fileutils::check_dir(fileutils::get_data_dir().c_str());
/* ~/.local/{appname}/{accountID} */
const auto idPath = fileutils::get_data_dir()+DIR_SEPARATOR_STR+getAccountID();
fileutils::check_dir(idPath.c_str());
privkeyPath_ = idPath + DIR_SEPARATOR_STR "id_rsa";
certPath_ = privkeyPath_ + ".pub";
dataPath_ = idPath + DIR_SEPARATOR_STR "values";
fileutils::check_dir(dataPath_.c_str());
int rc = gnutls_global_init();
if (rc != GNUTLS_E_SUCCESS) {
ERROR("Error initializing GnuTLS : %s", gnutls_strerror(rc));
......@@ -469,10 +471,10 @@ void DHTAccount::doRegister()
return;
}
DEBUG("doRegister");
try {
if (dht_.isRunning()) {
ERROR("DHT already running");
ERROR("DHT already running (stopping it first).");
dht_.join();
}
dht_.run(dhtPort_, loadIdentity(), [=](dht::Dht::Status s4, dht::Dht::Status s6) {
WARN("Dht status : %d %d", (int)s4, (int)s6);
......@@ -500,6 +502,9 @@ void DHTAccount::doRegister()
break;
}
});
dht_.importValues(loadValues());
dht_.put(dht_.getId(), dht::Value{dht::ServiceAnnouncement::TYPE.id, dht::ServiceAnnouncement(getTlsListenerPort())}, [](bool ok) {
DEBUG("Peer announce callback ! %d", ok);
});
......@@ -534,6 +539,7 @@ void DHTAccount::doUnregister(std::function<void(bool)> released_cb)
{
Manager::instance().unregisterEventHandler((uintptr_t)this);
saveNodes(dht_.exportNodes());
saveValues(dht_.exportValues());
dht_.join();
tlsListener_.reset();
setRegistrationState(RegistrationState::UNREGISTERED);
......@@ -557,6 +563,15 @@ void DHTAccount::saveNodes(const std::vector<dht::Dht::NodeExport>& nodes) const
}
}
void DHTAccount::saveValues(const std::vector<dht::Dht::ValuesExport>& values) const
{
for (const auto& v : values) {
const std::string fname = dataPath_ + DIR_SEPARATOR_STR + v.first.toString();
std::ofstream file(fname, std::ios::trunc | std::ios::out | std::ios::binary);
file.write((const char*)v.second.data(), v.second.size());
}
}
std::vector<dht::Dht::NodeExport>
DHTAccount::loadNodes() const
{
......@@ -581,6 +596,35 @@ DHTAccount::loadNodes() const
}
}
std::vector<dht::Dht::ValuesExport>
DHTAccount::loadValues() const
{
struct dirent *entry;
DIR *dp = opendir(dataPath_.c_str());
if (!dp) {
ERROR("Could not load values from %s", dataPath_.c_str());
return {};
}
std::vector<dht::Dht::ValuesExport> values;
while ((entry = readdir(dp))) {
try {
const std::string fname {entry->d_name};
if (fname == "." || fname == "..")
continue;
std::ifstream ifs(dataPath_+DIR_SEPARATOR_STR+fname, std::ifstream::in | std::ifstream::binary);
std::istreambuf_iterator<char> begin(ifs), end;
values.push_back({{fname}, std::vector<uint8_t>{begin, end}});
} catch (const std::exception& e) {
ERROR("Error reading value: %s", e.what());
continue;
}
}
closedir(dp);
return values;
}
void DHTAccount::initTlsConfiguration()
{
// TLS listener is unique and should be only modified through IP2IP_PROFILE
......
......@@ -54,6 +54,7 @@ namespace Conf {
const char *const DHT_PORT_KEY = "dhtPort";
const char *const DHT_PRIVKEY_PATH_KEY = "dhtPrivkeyPath";
const char *const DHT_CERT_PATH_KEY = "dhtCertificatePath";
const char *const DHT_VALUES_PATH_KEY = "dhtValuesPath";
}
namespace YAML {
......@@ -280,9 +281,10 @@ class DHTAccount : public SIPAccountBase {
dht::DhtRunner dht_ {};
std::string nodePath_ {};
std::string privkeyPath_ {};
std::string certPath_ {};
std::string nodePath_ {};
std::string dataPath_ {};
/**
* If identityPath_ is a valid private key file (PEM or DER),
......@@ -290,10 +292,13 @@ class DHTAccount : public SIPAccountBase {
* Check if the given path contains a valid private key.
* @return the key if a valid private key exists there, nullptr otherwise.
*/
dht::crypto::Identity loadIdentity() const;
void saveIdentity(const dht::crypto::Identity id) const;
void saveNodes(const std::vector<dht::Dht::NodeExport>& nodes) const;
void saveNodes(const std::vector<dht::Dht::NodeExport>&) const;
void saveValues(const std::vector<dht::Dht::ValuesExport>&) const;
dht::crypto::Identity loadIdentity() const;
std::vector<dht::Dht::NodeExport> loadNodes() const;
std::vector<dht::Dht::ValuesExport> loadValues() const;
/**
* Initializes tls settings from configuration file.
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment