diff --git a/daemon/src/dht/dhtaccount.cpp b/daemon/src/dht/dhtaccount.cpp index f5274a806f6c4c96fd87d17859c3914b0ac62158..a702885044c221fab1aadf46f874ee35f8145984 100644 --- a/daemon/src/dht/dhtaccount.cpp +++ b/daemon/src/dht/dhtaccount.cpp @@ -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 diff --git a/daemon/src/dht/dhtaccount.h b/daemon/src/dht/dhtaccount.h index ad83598e3e1d2f18af726057cf71e96da8fc3da8..18c95f5440d7e735b8809adfc4062613ae1f3537 100644 --- a/daemon/src/dht/dhtaccount.h +++ b/daemon/src/dht/dhtaccount.h @@ -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.