From ac7f9b109e5977369934ea1035a48da9ca2c80f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com> Date: Tue, 24 Mar 2015 16:21:53 -0400 Subject: [PATCH] ringaccount: use a random port by default Refs #69174 (cherry picked from master, commit e0284a70cf6a72d61c0abdbad2a99c3bf0566456) Change-Id: I4332aa7f3b66b8dbae156ed2f4dc9f9f98ab2a4e --- src/ringdht/ringaccount.cpp | 13 +++++++------ src/ringdht/ringaccount.h | 3 ++- src/sip/sipaccountbase.cpp | 18 +++++++++++++++++- src/sip/sipaccountbase.h | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 8 deletions(-) diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp index b9789e213a..8d7987a8c2 100644 --- a/src/ringdht/ringaccount.cpp +++ b/src/ringdht/ringaccount.cpp @@ -81,6 +81,7 @@ static constexpr int ICE_INIT_TIMEOUT {5}; static constexpr int ICE_NEGOTIATION_TIMEOUT {60}; constexpr const char * const RingAccount::ACCOUNT_TYPE; +constexpr const std::pair<uint16_t, uint16_t> RingAccount::DHT_PORT_RANGE; RingAccount::RingAccount(const std::string& accountID, bool /* presenceEnabled */) : SIPAccountBase(accountID), via_addr_() @@ -402,9 +403,9 @@ void RingAccount::unserialize(const YAML::Node &node) using yaml_utils::parseValue; SIPAccountBase::unserialize(node); - in_port_t port {DHT_DEFAULT_PORT}; - parseValue(node, Conf::DHT_PORT_KEY, port); - dhtPort_ = port ? port : DHT_DEFAULT_PORT; + parseValue(node, Conf::DHT_PORT_KEY, dhtPort_); + if (not dhtPort_) + dhtPort_ = getRandomEvenPort(DHT_PORT_RANGE); dhtPortUsed_ = dhtPort_; checkIdentityPath(); } @@ -498,8 +499,8 @@ void RingAccount::setAccountDetails(const std::map<std::string, std::string> &de if (hostname_ == "") hostname_ = DHT_DEFAULT_BOOTSTRAP; parseInt(details, Conf::CONFIG_DHT_PORT, dhtPort_); - if (dhtPort_ == 0) - dhtPort_ = DHT_DEFAULT_PORT; + if (not dhtPort_) + dhtPort_ = getRandomEvenPort(DHT_PORT_RANGE); dhtPortUsed_ = dhtPort_; checkIdentityPath(); } @@ -672,7 +673,7 @@ void RingAccount::doRegister_() dht_.join(); } auto identity = loadIdentity(); - dht_.run(dhtPortUsed_, identity.second, false, [=](dht::Dht::Status s4, dht::Dht::Status s6) { + dht_.run((in_port_t)dhtPortUsed_, identity.second, false, [=](dht::Dht::Status s4, dht::Dht::Status s6) { RING_WARN("Dht status : IPv4 %s; IPv6 %s", dhtStatusStr(s4), dhtStatusStr(s6)); auto status = std::max(s4, s6); switch(status) { diff --git a/src/ringdht/ringaccount.h b/src/ringdht/ringaccount.h index 84cb1411a5..073d93dbb4 100644 --- a/src/ringdht/ringaccount.h +++ b/src/ringdht/ringaccount.h @@ -79,6 +79,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.ring.cx"; + constexpr static const std::pair<uint16_t, uint16_t> DHT_PORT_RANGE {4000, 8888}; const char* getAccountType() const { return ACCOUNT_TYPE; @@ -340,7 +341,7 @@ class RingAccount : public SIPAccountBase { * selected in the configuration in the case that UPnP is used and the * configured port is already used by another client */ - in_port_t dhtPortUsed_ {DHT_DEFAULT_PORT}; + UsedPort dhtPortUsed_ {DHT_DEFAULT_PORT}; /** * The TLS settings, used only if tls is chosen as a sip transport. diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp index f497069459..7302913c27 100644 --- a/src/sip/sipaccountbase.cpp +++ b/src/sip/sipaccountbase.cpp @@ -247,7 +247,17 @@ SIPAccountBase::getPortsReservation() noexcept -> decltype(getPortsReservation() return portsInUse; } -// returns even number in range [lower, upper] +uint16_t +SIPAccountBase::getRandomEvenPort(const std::pair<uint16_t, uint16_t>& range) const +{ + std::uniform_int_distribution<uint16_t> dist(range.first/2, range.second/2); + uint16_t result; + do { + result = 2 * dist(rand_); + } while (getPortsReservation()[result / 2]); + return result; +} + uint16_t SIPAccountBase::acquireRandomEvenPort(const std::pair<uint16_t, uint16_t>& range) const { @@ -262,6 +272,12 @@ SIPAccountBase::acquireRandomEvenPort(const std::pair<uint16_t, uint16_t>& range return result; } +uint16_t +SIPAccountBase::acquirePort(uint16_t port) +{ + getPortsReservation()[port / 2] = true; +} + void SIPAccountBase::releasePort(uint16_t port) noexcept { diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h index 0874f81cf4..1cef21d25a 100644 --- a/src/sip/sipaccountbase.h +++ b/src/sip/sipaccountbase.h @@ -292,7 +292,43 @@ protected: */ std::pair<uint16_t, uint16_t> videoPortRange_ {49152, (MAX_PORT) - 2}; + struct UsedPort { + UsedPort() {}; + UsedPort(UsedPort&& o) : port_(o.port_) { + o.port_ = 0; + } + UsedPort(in_port_t p) : port_(p) { + if (port_) + acquirePort(port_); + }; + ~UsedPort() { + if (port_) + releasePort(port_); + }; + UsedPort& operator=(UsedPort&& o) { + if (port_) + releasePort(port_); + port_ = o.port_; + o.port_ = 0; + return *this; + } + UsedPort& operator=(in_port_t p) { + if (port_) + releasePort(port_); + port_ = p; + if (port_) + acquirePort(port_); + return *this; + } + explicit operator in_port_t() const { return port_; } + private: + in_port_t port_ {0}; + NON_COPYABLE(UsedPort); + }; + static std::array<bool, HALF_MAX_PORT>& getPortsReservation() noexcept; + static uint16_t acquirePort(uint16_t port); + uint16_t getRandomEvenPort(const std::pair<uint16_t, uint16_t>& range) const; uint16_t acquireRandomEvenPort(const std::pair<uint16_t, uint16_t>& range) const; private: -- GitLab