From efff7016e7b314fbccf6a86a886c9b24c2b9c1c1 Mon Sep 17 00:00:00 2001
From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Date: Thu, 26 Feb 2015 12:59:49 -0500
Subject: [PATCH] sipaccountbase: remove portsInUse_ global variable

This patch removes a static global variable initialization order disaster.
(also a coding rules violation)

Refs #67228

Change-Id: Ie8eda34d1049c3c45d476f6b2a2437923c2eeec9
---
 daemon/src/account.h              |  2 +-
 daemon/src/sip/sipaccountbase.cpp | 23 +++++++++++++++--------
 daemon/src/sip/sipaccountbase.h   | 25 ++++++++++++++++---------
 3 files changed, 32 insertions(+), 18 deletions(-)

diff --git a/daemon/src/account.h b/daemon/src/account.h
index 6165cc4cfc..3cb0d25a4c 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 110a350b50..cbdd6c9280 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 &param, 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 52841bf20e..bd31dcfb7c 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
-- 
GitLab