Commit f73eedaf authored by Sébastien Blin's avatar Sébastien Blin Committed by Adrien Béraud

proxy: support multi dht proxy

The entry to use a dhtproxy should supports multiple proxy to
balance the load. If multiple proxy are specified, the daemon
will select one proxy and use it.

Change-Id: Ib9cf2692e41a726ce1073537bdbbbf33654e50e7
parent 8ee6d40f
......@@ -77,14 +77,15 @@
#include <algorithm>
#include <array>
#include <memory>
#include <sstream>
#include <cctype>
#include <cinttypes>
#include <cstdarg>
#include <initializer_list>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <system_error>
#include <initializer_list>
namespace ring {
......@@ -215,6 +216,7 @@ static constexpr const char * DEFAULT_TURN_SERVER = "turn.jami.net";
static constexpr const char * DEFAULT_TURN_USERNAME = "ring";
static constexpr const char * DEFAULT_TURN_PWD = "ring";
static constexpr const char * DEFAULT_TURN_REALM = "ring";
static const auto PROXY_REGEX = std::regex("(https?://)?([\\w\\.]+)(:(\\d+)|:\\[(.+)-(.+)\\])?");
constexpr const char* const RingAccount::ACCOUNT_TYPE;
/* constexpr */ const std::pair<uint16_t, uint16_t> RingAccount::DHT_PORT_RANGE {4000, 8888};
......@@ -291,6 +293,10 @@ RingAccount::RingAccount(const std::string& accountID, bool /* presenceEnabled *
turnServerPwd_ = DEFAULT_TURN_PWD;
turnServerRealm_ = DEFAULT_TURN_REALM;
turnEnabled_ = true;
std::ifstream proxyCache(cachePath_ + DIR_SEPARATOR_STR "dhtproxy");
if (proxyCache)
std::getline(proxyCache, proxyServerCached_);
}
RingAccount::~RingAccount()
......@@ -1526,10 +1532,21 @@ RingAccount::setAccountDetails(const std::map<std::string, std::string>& details
parseString(details, DRing::Account::ConfProperties::RING_DEVICE_NAME, ringDeviceName_);
parseBool(details, DRing::Account::ConfProperties::PROXY_ENABLED, proxyEnabled_);
auto oldProxyServer = proxyServer_;
parseString(details, DRing::Account::ConfProperties::PROXY_SERVER, proxyServer_);
parseString(details, DRing::Account::ConfProperties::PROXY_PUSH_TOKEN, deviceKey_);
if (proxyServer_.empty())
// Migrate from old versions
if (proxyServer_.empty()
|| ((proxyServer_ == "dhtproxy.jami.net"
|| proxyServer_ == "dhtproxy.ring.cx")
&& proxyServerCached_.empty()))
proxyServer_ = DHT_DEFAULT_PROXY;
if (proxyServer_ != oldProxyServer) {
RING_DBG("DHT Proxy configuration changed, resetting cache");
proxyServerCached_ = {};
auto proxyCachePath = cachePath_ + DIR_SEPARATOR_STR "dhtproxy";
std::remove(proxyCachePath.c_str());
}
#if HAVE_RINGNS
parseString(details, DRing::Account::ConfProperties::RingNS::URI, nameServer_);
......@@ -2103,7 +2120,7 @@ RingAccount::doRegister_()
config.dht_config.node_config.network = 0;
config.dht_config.node_config.maintain_storage = false;
config.dht_config.id = identity_;
config.proxy_server = proxyEnabled_ ? proxyServer_ : std::string();
config.proxy_server = getDhtProxyServer();
config.push_node_id = getAccountID();
config.threaded = true;
if (not config.proxy_server.empty())
......@@ -2851,6 +2868,50 @@ RingAccount::loadDhParams(const std::string path)
}
}
std::string
RingAccount::getDhtProxyServer()
{
if (!proxyEnabled_) return {};
if (proxyServerCached_.empty()) {
std::vector<std::string> proxys;
// Split the list of servers
std::sregex_iterator begin = {proxyServer_.begin(), proxyServer_.end(), PROXY_REGEX}, end;
for (auto it = begin; it != end; ++it) {
auto &match = *it;
if (match[5].matched and match[6].matched) {
try {
auto start = std::stoi(match[5]), end = std::stoi(match[6]);
for (auto p = start; p <= end; p++)
proxys.emplace_back(match[1].str() + match[2].str() + ":" +
std::to_string(p));
} catch (...) {
RING_WARN("Malformed proxy, ignore it");
continue;
}
} else {
proxys.emplace_back(match[0].str());
}
}
if (proxys.empty())
return {};
// Select one of the list as the current proxy.
auto randIt = proxys.begin();
std::advance(randIt, std::rand() % proxys.size());
proxyServerCached_ = *randIt;
// Cache it!
fileutils::check_dir(cachePath_.c_str(), 0700);
std::string proxyCachePath = cachePath_ + DIR_SEPARATOR_STR "dhtproxy";
std::ofstream file(proxyCachePath);
RING_DBG("Cache DHT proxy server: %s", proxyServerCached_.c_str());
if (file.is_open())
file << proxyServerCached_;
else
RING_WARN("Cannot write into %s", proxyCachePath.c_str());
return proxyServerCached_;
}
return proxyServerCached_;
}
void
RingAccount::generateDhParams()
{
......
......@@ -86,7 +86,7 @@ class RingAccount : public SIPAccountBase {
constexpr static const char* const ACCOUNT_TYPE = "RING";
constexpr static const in_port_t DHT_DEFAULT_PORT = 4222;
constexpr static const char* const DHT_DEFAULT_BOOTSTRAP = "bootstrap.jami.net";
constexpr static const char* const DHT_DEFAULT_PROXY = "dhtproxy.jami.net";
constexpr static const char* const DHT_DEFAULT_PROXY = "dhtproxy.jami.net:[80-100]";
constexpr static const char* const DHT_TYPE_NS = "cx.ring";
/* constexpr */ static const std::pair<uint16_t, uint16_t> DHT_PORT_RANGE;
......@@ -635,7 +635,9 @@ class RingAccount : public SIPAccountBase {
*/
bool proxyEnabled_;
std::string proxyServer_;
std::string proxyServerCached_;
std::string deviceKey_;
std::string getDhtProxyServer();
/**
* The TLS settings, used only if tls is chosen as a sip transport.
......
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