diff --git a/daemon/src/account.h b/daemon/src/account.h index 6165cc4cfcad61da655ad5d592bdaf3a3f708102..3cb0d25a4c72292ceee7a0c7f48a5e6d3a5ff99a 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -396,7 +396,7 @@ class Account : public Serializable, public std::enable_shared_from_this<Account * Random generator engine * Logical account state shall never rely on the state of the random generator. */ - mutable std::mt19937_64 rand_ {}; + mutable std::mt19937_64 rand_; /** * UPnP IGD controller and the mutex to access it diff --git a/daemon/src/sip/sipaccountbase.cpp b/daemon/src/sip/sipaccountbase.cpp index 110a350b50d1c4af748dd29bf2feccd9f289c74d..cbdd6c928043226e700184fded0b9ebe43c8af67 100644 --- a/daemon/src/sip/sipaccountbase.cpp +++ b/daemon/src/sip/sipaccountbase.cpp @@ -46,8 +46,6 @@ namespace ring { -bool SIPAccountBase::portsInUse_[HALF_MAX_PORT]; - SIPAccountBase::SIPAccountBase(const std::string& accountID) : Account(accountID), link_(getSIPVoIPLink()) {} @@ -69,9 +67,9 @@ validate(std::string &member, const std::string ¶m, const T& valid) } static void -updateRange(int min, int max, std::pair<uint16_t, uint16_t> &range) +updateRange(uint16_t min, uint16_t max, std::pair<uint16_t, uint16_t> &range) { - if (min > 0 and (max > min) and max <= MAX_PORT - 2) { + if (min > 0 and (max > min) and max <= SIPAccountBase::MAX_PORT - 2) { range.first = min; range.second = max; } @@ -319,24 +317,33 @@ SIPAccountBase::setTransport(const std::shared_ptr<SipTransport>& t) transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccountBase::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2)); } +auto +SIPAccountBase::getPortsReservation() noexcept -> decltype(getPortsReservation()) +{ + // Note: static arrays are zero-initialized + static std::remove_reference<decltype(getPortsReservation())>::type portsInUse; + return portsInUse; +} + // returns even number in range [lower, upper] uint16_t SIPAccountBase::acquireRandomEvenPort(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 (portsInUse_[result / 2]); + } while (getPortsReservation()[result / 2]); - portsInUse_[result / 2] = true; + getPortsReservation()[result / 2] = true; return result; } void -SIPAccountBase::releasePort(uint16_t port) +SIPAccountBase::releasePort(uint16_t port) noexcept { - portsInUse_[port / 2] = false; + getPortsReservation()[port / 2] = false; } uint16_t diff --git a/daemon/src/sip/sipaccountbase.h b/daemon/src/sip/sipaccountbase.h index 52841bf20e3ad4cef9ac4a7c42c6f02a6439dda2..bd31dcfb7c233ec3ba3f6e5a24e5cd1f9faef4f6 100644 --- a/daemon/src/sip/sipaccountbase.h +++ b/daemon/src/sip/sipaccountbase.h @@ -101,14 +101,15 @@ class SIPCall; * @file sipaccount.h * @brief A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink) */ -enum {MAX_PORT = 65536}; -enum {HALF_MAX_PORT = MAX_PORT / 2}; + enum class MatchRank {NONE, PARTIAL, FULL}; class SIPAccountBase : public Account { public: constexpr static const char * const OVERRTP_STR = "overrtp"; constexpr static const char * const SIPINFO_STR = "sipinfo"; + constexpr static unsigned MAX_PORT {65536}; + constexpr static unsigned HALF_MAX_PORT {MAX_PORT / 2}; /** * Constructor @@ -248,12 +249,6 @@ public: virtual std::string getServerUri() const = 0; - uint16_t generateAudioPort() const; -#ifdef RING_VIDEO - uint16_t generateVideoPort() const; -#endif - static void releasePort(uint16_t port); - virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr); inline const std::shared_ptr<SipTransport>& getTransport() { @@ -269,6 +264,18 @@ public: */ pjsip_tpselector getTransportSelector(); + /** + * Socket port generators for media + * Note: given ports are application wide, a port cannot be given again + * by any account instances until it's released by the static method + * releasePort(). + */ + uint16_t generateAudioPort() const; +#ifdef RING_VIDEO + uint16_t generateVideoPort() const; +#endif + static void releasePort(uint16_t port) noexcept; + protected: virtual void serialize(YAML::Emitter &out); virtual void serializeTls(YAML::Emitter &out); @@ -362,7 +369,7 @@ protected: */ std::pair<uint16_t, uint16_t> videoPortRange_ {49152, (MAX_PORT) - 2}; - static bool portsInUse_[HALF_MAX_PORT]; + static std::array<bool, HALF_MAX_PORT>& getPortsReservation() noexcept; uint16_t acquireRandomEvenPort(const std::pair<uint16_t, uint16_t>& range) const; static void