mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00
account: add import/export API
- do not read dhtPort when deserializing a Ring account, use a new one at runtime - cache directory is created when generating dhParams - use key stretching for archive encryption - bump OpenDHT to add key stretching support This commit comes with a necessary bump of OpenDHT Tuleap: #335 Change-Id: Iee67569d378baaa33e9acd7cd9557422ab8e0471
This commit is contained in:

committed by
Adrien Béraud

parent
25cdcd8b44
commit
ae5d1adad7
@ -193,6 +193,54 @@
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="importAccounts" tp:name-for-bindings="importAccounts">
|
||||
<tp:docstring>
|
||||
Import previously exported accounts
|
||||
</tp:docstring>
|
||||
<arg type="s" name="path" direction="in">
|
||||
<tp:docstring>
|
||||
Path of the file to import
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="s" name="password" direction="in">
|
||||
<tp:docstring>
|
||||
Decryption password
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="i" direction="out">
|
||||
<tp:docstring>
|
||||
<p>Return code, 0 for success.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="exportAccounts" tp:name-for-bindings="exportAccounts">
|
||||
<tp:docstring>
|
||||
Export account configuration to an encrypted file.
|
||||
</tp:docstring>
|
||||
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="VectorString"/>
|
||||
<arg type="as" name="accountIDs" direction="in">
|
||||
<tp:docstring>
|
||||
A list of account IDs
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="s" name="filepath" direction="in">
|
||||
<tp:docstring>
|
||||
Where to export the account
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="s" name="password" direction="in">
|
||||
<tp:docstring>
|
||||
File encryption password
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
<arg type="i" direction="out">
|
||||
<tp:docstring>
|
||||
<p>Return code, 0 for success.</p>
|
||||
</tp:docstring>
|
||||
</arg>
|
||||
</method>
|
||||
|
||||
<method name="registerAllAccounts" tp:name-for-bindings="registerAllAccounts">
|
||||
<tp:docstring>
|
||||
Send account registration (REGISTER) for all accounts, even if they are not enabled.
|
||||
|
@ -527,3 +527,15 @@ DBusConfigurationManager::getVolume(const std::string& device) -> decltype(DRing
|
||||
{
|
||||
return DRing::getVolume(device);
|
||||
}
|
||||
|
||||
auto
|
||||
DBusConfigurationManager::exportAccounts(const std::vector<std::string>& accountIDs, const std::string& filepath, const std::string& password) -> decltype(DRing::exportAccounts(accountIDs, filepath, password))
|
||||
{
|
||||
return DRing::exportAccounts(accountIDs, filepath, password);
|
||||
}
|
||||
|
||||
auto
|
||||
DBusConfigurationManager::importAccounts(const std::string& archivePath, const std::string& password) -> decltype(DRing::importAccounts(archivePath, password))
|
||||
{
|
||||
return DRing::importAccounts(archivePath, password);
|
||||
}
|
||||
|
@ -137,6 +137,8 @@ class DBusConfigurationManager :
|
||||
bool acceptTrustRequest(const std::string& accountId, const std::string& from);
|
||||
bool discardTrustRequest(const std::string& accountId, const std::string& from);
|
||||
void sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload);
|
||||
int exportAccounts(const std::vector<std::string>& accountIDs, const std::string& filepath, const std::string& password);
|
||||
int importAccounts(const std::string& archivePath, const std::string& password);
|
||||
};
|
||||
|
||||
#endif // __RING_DBUSCONFIGURATIONMANAGER_H__
|
||||
|
@ -157,6 +157,7 @@ AC_TYPE_SIZE_T
|
||||
AC_HEADER_TIME
|
||||
AC_C_VOLATILE
|
||||
AC_CHECK_TYPES([ptrdiff_t])
|
||||
AC_CHECK_LIB(zlib, zlib)
|
||||
|
||||
PKG_PROG_PKG_CONFIG()
|
||||
|
||||
@ -236,7 +237,7 @@ AS_IF([test -n "${CONTRIB_DIR}"], [
|
||||
export PKG_CONFIG_PATH_CUSTOM
|
||||
])
|
||||
export PKG_CONFIG_PATH="${CONTRIB_DIR}/lib/pkgconfig:${CONTRIB_DIR}/lib64/pkgconfig:$PKG_CONFIG_PATH"
|
||||
LDFLAGS="${LDFLAGS} -L${CONTRIB_DIR}/lib"
|
||||
LDFLAGS="${LDFLAGS} -L${CONTRIB_DIR}/lib -lz"
|
||||
|
||||
AS_IF([test "${SYS}" = "darwin"], [
|
||||
export LD_LIBRARY_PATH="${CONTRIB_DIR}/lib:$LD_LIBRARY_PATH"
|
||||
|
@ -1,5 +1,5 @@
|
||||
# OPENDHT
|
||||
OPENDHT_VERSION := 281b62dfd529a226e94d0da19e01acf07871a797
|
||||
OPENDHT_VERSION := 8ae95f1284f3c00c41832ef4d76196481543f59e
|
||||
OPENDHT_URL := https://github.com/savoirfairelinux/opendht/archive/$(OPENDHT_VERSION).tar.gz
|
||||
|
||||
PKGS += opendht
|
||||
|
@ -116,6 +116,7 @@ libring_la_SOURCES = \
|
||||
account.cpp \
|
||||
logger.cpp \
|
||||
fileutils.cpp \
|
||||
archiver.cpp \
|
||||
threadloop.cpp \
|
||||
ip_utils.h \
|
||||
ip_utils.cpp \
|
||||
@ -137,6 +138,7 @@ libring_la_SOURCES = \
|
||||
call.h \
|
||||
logger.h \
|
||||
fileutils.h \
|
||||
archiver.h \
|
||||
noncopyable.h \
|
||||
utf8_utils.h \
|
||||
ring_types.h \
|
||||
|
280
src/archiver.cpp
Normal file
280
src/archiver.cpp
Normal file
@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "archiver.h"
|
||||
|
||||
#include <json/json.h>
|
||||
|
||||
#include "client/ring_signal.h"
|
||||
#include "account_const.h"
|
||||
#include "configurationmanager_interface.h"
|
||||
|
||||
#include "manager.h"
|
||||
#include "fileutils.h"
|
||||
#include "logger.h"
|
||||
|
||||
#include <opendht/crypto.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
namespace ring {
|
||||
|
||||
Archiver&
|
||||
Archiver::instance()
|
||||
{
|
||||
// Meyers singleton
|
||||
static Archiver instance_;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
Archiver::Archiver()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
Archiver::exportAccounts(std::vector<std::string> accountIDs,
|
||||
std::string filepath,
|
||||
std::string password)
|
||||
{
|
||||
if (filepath.empty() || !accountIDs.size()) {
|
||||
RING_ERR("Missing arguments");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
std::size_t found = filepath.find_last_of(DIR_SEPARATOR_STR);
|
||||
auto toDir = filepath.substr(0,found);
|
||||
auto filename = filepath.substr(found+1);
|
||||
|
||||
if (!fileutils::isDirectory(toDir)) {
|
||||
RING_ERR("%s is not a directory", toDir.c_str());
|
||||
return ENOTDIR;
|
||||
}
|
||||
|
||||
// Add
|
||||
Json::Value root;
|
||||
Json::Value array;
|
||||
|
||||
for (size_t i = 0; i < accountIDs.size(); ++i) {
|
||||
auto detailsMap = Manager::instance().getAccountDetails(accountIDs[i]);
|
||||
if (detailsMap.empty()) {
|
||||
RING_WARN("Can't export account %s", accountIDs[i].c_str());
|
||||
continue;
|
||||
}
|
||||
|
||||
auto jsonAccount = accountToJsonValue(detailsMap);
|
||||
array.append(jsonAccount);
|
||||
}
|
||||
root["accounts"] = array;
|
||||
Json::FastWriter fastWriter;
|
||||
std::string output = fastWriter.write(root);
|
||||
|
||||
// Compress
|
||||
std::vector<uint8_t> compressed;
|
||||
try {
|
||||
compressed = compress(output);
|
||||
} catch (const std::runtime_error& ex) {
|
||||
RING_ERR("Export failed: %s", ex.what());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Encrypt using provided password
|
||||
auto encrypted = dht::crypto::aesEncrypt(compressed, password);
|
||||
|
||||
// Write
|
||||
try {
|
||||
fileutils::saveFile(toDir + DIR_SEPARATOR_STR + filename, encrypted);
|
||||
} catch (const std::runtime_error& ex) {
|
||||
RING_ERR("Export failed: %s", ex.what());
|
||||
return EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
Archiver::accountToJsonValue(std::map<std::string, std::string> details) {
|
||||
Json::Value root;
|
||||
std::map<std::string, std::string>::iterator iter;
|
||||
for (iter = details.begin(); iter != details.end(); ++iter) {
|
||||
|
||||
if (iter->first.compare(DRing::Account::ConfProperties::Ringtone::PATH) == 0) {
|
||||
// Ringtone path is not exportable
|
||||
} else if (iter->first.compare(DRing::Account::ConfProperties::TLS::CA_LIST_FILE) == 0 ||
|
||||
iter->first.compare(DRing::Account::ConfProperties::TLS::CERTIFICATE_FILE) == 0 ||
|
||||
iter->first.compare(DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE) == 0) {
|
||||
// replace paths by the files content
|
||||
std::ifstream ifs(iter->second);
|
||||
std::string fileContent((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
root[iter->first] = fileContent;
|
||||
|
||||
} else
|
||||
root[iter->first] = iter->second;
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
int
|
||||
Archiver::importAccounts(std::string archivePath, std::string password)
|
||||
{
|
||||
if (archivePath.empty()) {
|
||||
RING_ERR("Missing arguments");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
// Read file
|
||||
std::vector<uint8_t> file;
|
||||
try {
|
||||
file = fileutils::loadFile(archivePath);
|
||||
} catch (const std::exception& ex) {
|
||||
RING_ERR("Read failed: %s", ex.what());
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
// Decrypt
|
||||
try {
|
||||
file = dht::crypto::aesDecrypt(file, password);
|
||||
} catch (const std::exception& ex) {
|
||||
RING_ERR("Decryption failed: %s", ex.what());
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
// Decompress
|
||||
try {
|
||||
file = decompress(file);
|
||||
} catch (const std::exception& ex) {
|
||||
RING_ERR("Decompression failed: %s", ex.what());
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
try {
|
||||
// Decode string
|
||||
std::string decoded {file.begin(), file.end()};
|
||||
|
||||
// Add
|
||||
Json::Value root;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(decoded.c_str(),root)) {
|
||||
RING_ERR("Failed to parse %s", reader.getFormattedErrorMessages().c_str());
|
||||
return ERANGE;
|
||||
}
|
||||
|
||||
auto& accounts = root["accounts"];
|
||||
for (int i = 0, n = accounts.size(); i < n; ++i) {
|
||||
// Generate a new account id
|
||||
auto accountId = ring::Manager::instance().getNewAccountId();
|
||||
auto details = jsonValueToAccount(accounts[i], accountId);
|
||||
ring::Manager::instance().addAccount(details, accountId);
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
RING_ERR("Import failed: %s", ex.what());
|
||||
return ERANGE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::map<std::string, std::string>
|
||||
Archiver::jsonValueToAccount(Json::Value& value, const std::string& accountId) {
|
||||
auto idPath_ = fileutils::get_data_dir() + DIR_SEPARATOR_STR + accountId;
|
||||
fileutils::check_dir(idPath_.c_str(), 0700);
|
||||
auto detailsMap = DRing::getAccountTemplate(value[DRing::Account::ConfProperties::TYPE].asString());
|
||||
|
||||
for( Json::ValueIterator itr = value.begin() ; itr != value.end() ; itr++ ) {
|
||||
if (itr->asString().empty())
|
||||
continue;
|
||||
if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::CA_LIST_FILE) == 0) {
|
||||
std::string fileContent(itr->asString());
|
||||
fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "ca.key", {fileContent.begin(), fileContent.end()}, 0600);
|
||||
|
||||
} else if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::PRIVATE_KEY_FILE) == 0) {
|
||||
std::string fileContent(itr->asString());
|
||||
fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "dht.key", {fileContent.begin(), fileContent.end()}, 0600);
|
||||
|
||||
} else if (itr.key().asString().compare(DRing::Account::ConfProperties::TLS::CERTIFICATE_FILE) == 0) {
|
||||
std::string fileContent(itr->asString());
|
||||
fileutils::saveFile(idPath_ + DIR_SEPARATOR_STR "dht.crt", {fileContent.begin(), fileContent.end()}, 0600);
|
||||
} else
|
||||
detailsMap[itr.key().asString()] = itr->asString();
|
||||
}
|
||||
|
||||
return detailsMap;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
Archiver::compress(const std::string& str, int compressionlevel)
|
||||
{
|
||||
auto destSize = compressBound(str.size());
|
||||
std::vector<uint8_t> outbuffer(destSize);
|
||||
int ret = ::compress(reinterpret_cast<Bytef*>(outbuffer.data()), &destSize, (Bytef*)str.data(), str.size());
|
||||
|
||||
if (ret != Z_OK) {
|
||||
std::ostringstream oss;
|
||||
oss << "Exception during zlib compression: (" << ret << ") ";
|
||||
throw(std::runtime_error(oss.str()));
|
||||
}
|
||||
|
||||
return outbuffer;
|
||||
}
|
||||
|
||||
std::vector<uint8_t>
|
||||
Archiver::decompress(const std::vector<uint8_t>& str)
|
||||
{
|
||||
z_stream zs; // z_stream is zlib's control structure
|
||||
memset(&zs, 0, sizeof(zs));
|
||||
|
||||
if (inflateInit(&zs) != Z_OK)
|
||||
throw(std::runtime_error("inflateInit failed while decompressing."));
|
||||
|
||||
zs.next_in = (Bytef*)str.data();
|
||||
zs.avail_in = str.size();
|
||||
|
||||
int ret;
|
||||
std::vector<uint8_t> out;
|
||||
|
||||
// get the decompressed bytes blockwise using repeated calls to inflate
|
||||
do {
|
||||
std::array<uint8_t, 32768> outbuffer;
|
||||
zs.next_out = reinterpret_cast<Bytef*>(outbuffer.data());
|
||||
zs.avail_out = outbuffer.size();
|
||||
|
||||
ret = inflate(&zs, 0);
|
||||
if (ret == Z_DATA_ERROR || ret == Z_MEM_ERROR)
|
||||
break;
|
||||
|
||||
if (out.size() < zs.total_out) {
|
||||
// append the block to the output string
|
||||
out.insert(out.end(), outbuffer.begin(), outbuffer.begin() + zs.total_out - out.size());
|
||||
}
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zs);
|
||||
|
||||
// an error occurred that was not EOF
|
||||
if (ret != Z_STREAM_END) {
|
||||
std::ostringstream oss;
|
||||
oss << "Exception during zlib decompression: (" << ret << ") " << zs.msg;
|
||||
throw(std::runtime_error(oss.str()));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ring
|
83
src/archiver.h
Normal file
83
src/archiver.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Savoir-faire Linux Inc.
|
||||
*
|
||||
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "noncopyable.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <zlib.h>
|
||||
|
||||
namespace Json {
|
||||
class Value;
|
||||
};
|
||||
|
||||
namespace ring {
|
||||
|
||||
/**
|
||||
* Archiver is used to generate/read encrypted archives
|
||||
*/
|
||||
class Archiver {
|
||||
public:
|
||||
static Archiver& instance();
|
||||
|
||||
Archiver();
|
||||
|
||||
/**
|
||||
* Create a protected archive containing a list of accounts
|
||||
* @param accountIDs The accounts to exports
|
||||
* @param filepath The filepath where to put the resulting archive
|
||||
* @param password The mandatory password to set on the archive
|
||||
* @returns 0 for OK, error code otherwise
|
||||
*/
|
||||
int exportAccounts(std::vector<std::string> accountIDs,
|
||||
std::string filepath,
|
||||
std::string password);
|
||||
|
||||
/**
|
||||
* Read a protected archive and add accounts found in it
|
||||
* Warning: this function must be called from a registered pjsip thread
|
||||
* @param archivePath The path to the archive file
|
||||
* @param password The password to read the archive
|
||||
* @returns 0 for OK, error code otherwise
|
||||
*/
|
||||
int importAccounts(std::string archivePath, std::string password);
|
||||
|
||||
/**
|
||||
* Compress a STL string using zlib with given compression level and return
|
||||
* the binary data.
|
||||
*/
|
||||
std::vector<uint8_t> compress(const std::string& str, int compressionlevel = Z_BEST_COMPRESSION);
|
||||
|
||||
/**
|
||||
* Decompress an STL string using zlib and return the original data.
|
||||
*/
|
||||
std::vector<uint8_t> decompress(const std::vector<uint8_t>& dat);
|
||||
|
||||
private:
|
||||
NON_COPYABLE(Archiver);
|
||||
|
||||
static Json::Value accountToJsonValue(std::map<std::string, std::string> details);
|
||||
static std::map<std::string, std::string> jsonValueToAccount(Json::Value& value, const std::string& accountId);
|
||||
};
|
||||
|
||||
} // namespace ring
|
@ -34,6 +34,7 @@
|
||||
#endif
|
||||
#include "logger.h"
|
||||
#include "fileutils.h"
|
||||
#include "archiver.h"
|
||||
#include "ip_utils.h"
|
||||
#include "sip/sipaccount.h"
|
||||
#include "ringdht/ringaccount.h"
|
||||
@ -320,6 +321,21 @@ sendTrustRequest(const std::string& accountId, const std::string& to, const std:
|
||||
acc->sendTrustRequest(to, payload);
|
||||
}
|
||||
|
||||
/*
|
||||
* Import/Export accounts
|
||||
*/
|
||||
int
|
||||
exportAccounts(std::vector<std::string> accountIDs, std::string filepath, std::string password)
|
||||
{
|
||||
return ring::Archiver::instance().exportAccounts(accountIDs, filepath, password);
|
||||
}
|
||||
|
||||
int
|
||||
importAccounts(std::string archivePath, std::string password)
|
||||
{
|
||||
return ring::Archiver::instance().importAccounts(archivePath, password);
|
||||
}
|
||||
|
||||
///This function is used as a base for new accounts for clients that support it
|
||||
std::map<std::string, std::string>
|
||||
getAccountTemplate(const std::string& accountType)
|
||||
|
@ -150,6 +150,12 @@ bool discardTrustRequest(const std::string& accountId, const std::string& from);
|
||||
|
||||
void sendTrustRequest(const std::string& accountId, const std::string& to, const std::vector<uint8_t>& payload = {});
|
||||
|
||||
/*
|
||||
* Import/Export accounts
|
||||
*/
|
||||
int exportAccounts(std::vector<std::string> accountIDs, std::string filepath, std::string password);
|
||||
int importAccounts(std::string archivePath, std::string password);
|
||||
|
||||
struct AudioSignal {
|
||||
struct DeviceEvent {
|
||||
constexpr static const char* name = "audioDeviceEvent";
|
||||
|
@ -2433,9 +2433,8 @@ Manager::setAccountDetails(const std::string& accountID,
|
||||
}
|
||||
|
||||
std::string
|
||||
Manager::addAccount(const std::map<std::string, std::string>& details)
|
||||
Manager::getNewAccountId()
|
||||
{
|
||||
/** @todo Deal with both the accountMap_ and the Configuration */
|
||||
std::string newAccountID;
|
||||
static std::uniform_int_distribution<uint64_t> rand_acc_id;
|
||||
|
||||
@ -2448,8 +2447,16 @@ Manager::addAccount(const std::map<std::string, std::string>& details)
|
||||
} while (std::find(accountList.begin(), accountList.end(), newAccountID)
|
||||
!= accountList.end());
|
||||
|
||||
// Get the type
|
||||
return newAccountID;
|
||||
}
|
||||
|
||||
std::string
|
||||
Manager::addAccount(const std::map<std::string, std::string>& details, const std::string& accountId)
|
||||
{
|
||||
/** @todo Deal with both the accountMap_ and the Configuration */
|
||||
auto newAccountID = accountId.empty() ? getNewAccountId() : accountId;
|
||||
|
||||
// Get the type
|
||||
const char* accountType;
|
||||
if (details.find(Conf::CONFIG_ACCOUNT_TYPE) != details.end())
|
||||
accountType = (*details.find(Conf::CONFIG_ACCOUNT_TYPE)).second.c_str();
|
||||
|
@ -499,12 +499,20 @@ class Manager {
|
||||
|
||||
void setAccountActive(const std::string& accountID, bool active);
|
||||
|
||||
/**
|
||||
* Return a new random accountid that is not present in the list
|
||||
* @return A brand new accountid
|
||||
*/
|
||||
std::string getNewAccountId();
|
||||
|
||||
/**
|
||||
* Add a new account, and give it a new account ID automatically
|
||||
* @param details The new account parameters
|
||||
* @param accountId optionnal predetermined accountid to use
|
||||
* @return The account Id given to the new account
|
||||
*/
|
||||
std::string addAccount(const std::map<std::string, std::string> &details);
|
||||
std::string addAccount(const std::map<std::string, std::string> &details,
|
||||
const std::string& accountId = {});
|
||||
|
||||
/**
|
||||
* Delete an existing account, unregister VoIPLink associated, and
|
||||
|
@ -425,7 +425,7 @@ void RingAccount::unserialize(const YAML::Node &node)
|
||||
using yaml_utils::parseValue;
|
||||
|
||||
SIPAccountBase::unserialize(node);
|
||||
parseValue(node, Conf::DHT_PORT_KEY, dhtPort_);
|
||||
|
||||
parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_HISTORY, allowPeersFromHistory_);
|
||||
parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_CONTACT, allowPeersFromContact_);
|
||||
parseValue(node, Conf::DHT_ALLOW_PEERS_FROM_TRUSTED, allowPeersFromTrusted_);
|
||||
@ -1251,6 +1251,9 @@ RingAccount::loadDhParams(const std::string path)
|
||||
void
|
||||
RingAccount::generateDhParams()
|
||||
{
|
||||
//make sure cachePath_ is writable
|
||||
fileutils::check_dir(cachePath_.c_str(), 0700);
|
||||
|
||||
std::packaged_task<decltype(loadDhParams)> task(loadDhParams);
|
||||
dhParams_ = task.get_future();
|
||||
std::thread task_td(std::move(task), cachePath_ + DIR_SEPARATOR_STR "dhParams");
|
||||
|
Reference in New Issue
Block a user