From 5e086184c903e118ad3d7ac6e21741c63698c98e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?S=C3=A9bastien=20Blin?=
 <sebastien.blin@savoirfairelinux.com>
Date: Wed, 22 Apr 2020 10:12:36 -0400
Subject: [PATCH] manager: make manager owns sipvoiplink

The current design describes SIPVoIPLink as a Singleton. This cause
some behaviors where the link is destroyed then immediately created
or vice-versa and its creation/destruction can't really be planned.
This design was made to allow multiple Managers to exist. However,
we never do that, so let's keep it simple, there is only one
Manager and all accounts needs that SIPVoIPLink

This patch change this behavior and the voip link is now owned
by the manager.

Change-Id: I248e41742d342cf452a5503f532fe5ab862166e6
---
 src/jamidht/jamiaccount.cpp | 10 ++++----
 src/manager.cpp             | 16 +++++++++----
 src/manager.h               |  3 +++
 src/sip/pres_sub_client.cpp |  4 ++--
 src/sip/pres_sub_server.cpp |  2 +-
 src/sip/sdp.cpp             |  6 ++---
 src/sip/sipaccount.cpp      | 48 ++++++++++++++++++-------------------
 src/sip/sipaccountbase.cpp  |  2 +-
 src/sip/sipaccountbase.h    |  2 +-
 src/sip/sipcall.cpp         | 18 +++++---------
 src/sip/sippresence.cpp     |  4 ++--
 src/sip/sipvoiplink.cpp     | 26 +++++---------------
 src/sip/sipvoiplink.h       |  4 ----
 13 files changed, 66 insertions(+), 79 deletions(-)

diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 8c077af6f6..ba73164671 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -769,7 +769,7 @@ JamiAccount::SIPStartCall(SIPCall& call, IpAddr target)
     if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, &pjTarget, local_sdp, &dialog, &inv))
         return false;
 
-    inv->mod_data[link_->getModId()] = &call;
+    inv->mod_data[link_.getModId()] = &call;
     call.inv.reset(inv);
 
 /*
@@ -1594,7 +1594,7 @@ JamiAccount::handlePendingCall(PendingCall& pc, bool incoming)
 
     // Following can create a transport that need to be negotiated (TLS).
     // This is a asynchronous task. So we're going to process the SIP after this negotiation.
-    auto transport = link_->sipTransportBroker->getTlsIceTransport(best_transport,
+    auto transport = link_.sipTransportBroker->getTlsIceTransport(best_transport,
                                                                    ICE_COMP_SIP_TRANSPORT,
                                                                    tlsParams);
     if (!transport)
@@ -2785,7 +2785,7 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
         pj_str_t pjTo = pj_str((char*) toURI.c_str());
 
         // Create request.
-        pj_status_t status = pjsip_endpt_create_request(link_->getEndpoint(), &msg_method,
+        pj_status_t status = pjsip_endpt_create_request(link_.getEndpoint(), &msg_method,
                                                         &pjTo, &pjFrom, &pjTo, nullptr, nullptr, -1,
                                                         nullptr, &tdata);
         if (status != PJ_SUCCESS) {
@@ -2850,7 +2850,7 @@ JamiAccount::sendTextMessage(const std::string& to, const std::map<std::string,
 
             sip_utils::register_thread();
 
-            auto status = pjsip_endpt_send_request(shared->link_->getEndpoint(), tdata, -1, ctx.release(),
+            auto status = pjsip_endpt_send_request(shared->link_.getEndpoint(), tdata, -1, ctx.release(),
                 [](void *token, pjsip_event *event)
                 {
                     std::unique_ptr<TextMessageCtx> c{ (TextMessageCtx*)token };
@@ -3292,7 +3292,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket, const s
                 conn++;
         }
     };
-    auto sip_tr = link_->sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown));
+    auto sip_tr = link_.sipTransportBroker->getChanneledTransport(socket, std::move(onShutdown));
     // Store the connection
     sipConnections_[peerId][deviceId].emplace_back(SipConnection {
         std::move(sip_tr),
diff --git a/src/manager.cpp b/src/manager.cpp
index 4db284d3d9..8a837c0eae 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -41,6 +41,7 @@
 #include "account.h"
 #include "string_utils.h"
 #include "jamidht/jamiaccount.h"
+#include "sip/sipvoiplink.h"
 #include <opendht/rng.h>
 using random_device = dht::crypto::random_device;
 
@@ -412,6 +413,8 @@ struct Manager::ManagerPimpl
 #ifdef ENABLE_VIDEO
     std::unique_ptr<VideoManager> videoManager_;
 #endif
+
+    std::unique_ptr<SIPVoIPLink> sipLink_;
 };
 
 Manager::ManagerPimpl::ManagerPimpl(Manager& base)
@@ -741,6 +744,8 @@ Manager::init(const std::string &config_file)
 
     setDhtLogLevel();
 
+    pimpl_->sipLink_ = std::make_unique<SIPVoIPLink>();
+
     check_rename(fileutils::get_cache_dir(PACKAGE_OLD), fileutils::get_cache_dir());
     check_rename(fileutils::get_data_dir(PACKAGE_OLD), fileutils::get_data_dir());
     check_rename(fileutils::get_config_dir(PACKAGE_OLD), fileutils::get_config_dir());
@@ -761,7 +766,6 @@ Manager::init(const std::string &config_file)
         JAMI_ERR("%s", e.what());
         no_errors = false;
     }
-
     // Some VoIP services support SIP/TLS and SRTP, but do not set the
     // correct schema in the INVITE request. For more details, see:
     // https://trac.pjsip.org/repos/ticket/1735
@@ -776,9 +780,6 @@ Manager::init(const std::string &config_file)
         // restore previous configuration
         JAMI_WARN("Restoring last working configuration");
 
-        // keep a reference to sipvoiplink while destroying the accounts
-        const auto sipvoiplink = getSIPVoIPLink();
-
         try {
             // remove accounts from broken configuration
             removeAccounts();
@@ -3074,6 +3075,13 @@ Manager::getLastMessages(const std::string& accountID, const uint64_t& base_time
     return {};
 }
 
+SIPVoIPLink&
+Manager::sipVoIPLink() const
+{
+    return *pimpl_->sipLink_;
+}
+
+
 std::map<std::string, std::string>
 Manager::getNearbyPeers(const std::string& accountID)
 {
diff --git a/src/manager.h b/src/manager.h
index 55cfe2ebda..dd972dfae5 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -60,6 +60,7 @@ class AudioLoop;
 class IceTransportFactory;
 class DataTransferFacade;
 class JamiAccount;
+class SIPVoIPLink;
 
 static constexpr uint64_t DRING_ID_MAX_VAL = 9007199254740992;
 
@@ -900,6 +901,8 @@ class DRING_TESTABLE Manager {
 
         std::vector<DRing::Message> getLastMessages(const std::string& accountID, const uint64_t& base_timestamp);
 
+        SIPVoIPLink& sipVoIPLink() const;
+
 private:
         Manager();
         ~Manager();
diff --git a/src/sip/pres_sub_client.cpp b/src/sip/pres_sub_client.cpp
index 4e78d0526e..47f52b8a2d 100644
--- a/src/sip/pres_sub_client.cpp
+++ b/src/sip/pres_sub_client.cpp
@@ -377,7 +377,7 @@ bool PresSubClient::isTermReason(const std::string &reason)
 void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
 {
     if (timer_.id) {
-        pjsip_endpt_cancel_timer(getSIPVoIPLink()->getEndpoint(), &timer_);
+        pjsip_endpt_cancel_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_);
         timer_.id = PJ_FALSE;
     }
 
@@ -391,7 +391,7 @@ void PresSubClient::rescheduleTimer(bool reschedule, unsigned msec)
         delay.msec = msec;
         pj_time_val_normalize(&delay);
 
-        if (pjsip_endpt_schedule_timer(getSIPVoIPLink()->getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
+        if (pjsip_endpt_schedule_timer(Manager::instance().sipVoIPLink().getEndpoint(), &timer_, &delay) == PJ_SUCCESS) {
             timer_.id = PJ_TRUE;
         }
     }
diff --git a/src/sip/pres_sub_server.cpp b/src/sip/pres_sub_server.cpp
index 27f81e8b79..0e1454c4ab 100644
--- a/src/sip/pres_sub_server.cpp
+++ b/src/sip/pres_sub_server.cpp
@@ -131,7 +131,7 @@ PresSubServer::pres_on_rx_subscribe_request(pjsip_rx_data *rdata)
         return PJ_FALSE;
     }
 
-    pjsip_endpoint *endpt = getSIPVoIPLink()->getEndpoint();
+    pjsip_endpoint *endpt = Manager::instance().sipVoIPLink().getEndpoint();
     SIPPresence * pres = sipaccount->getPresence();
     pres->lock();
 
diff --git a/src/sip/sdp.cpp b/src/sip/sdp.cpp
index f14060fc24..acfa2bac82 100644
--- a/src/sip/sdp.cpp
+++ b/src/sip/sdp.cpp
@@ -64,7 +64,7 @@ Sdp::Sdp(const std::string& id)
     , telephoneEventPayload_(101) // same as asterisk
 {
     sip_utils::register_thread();
-    memPool_.reset(pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory,
+    memPool_.reset(pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory,
                                   id.c_str(), POOL_INITIAL_SIZE,
                                   POOL_INCREMENT_SIZE, NULL));
     if (not memPool_)
@@ -338,7 +338,7 @@ Sdp::printSession(const pjmedia_sdp_session *session, const char* header)
     static constexpr size_t BUF_SZ = 4095;
     sip_utils::register_thread();
     std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&> tmpPool_(
-        pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory, "printSdp", BUF_SZ, BUF_SZ, nullptr),
+        pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory, "printSdp", BUF_SZ, BUF_SZ, nullptr),
         pj_pool_release
     );
 
@@ -494,7 +494,7 @@ Sdp::getFilteredSdp(const pjmedia_sdp_session* session, unsigned media_keep, uns
     sip_utils::register_thread();
     static constexpr size_t BUF_SZ = 4096;
     std::unique_ptr<pj_pool_t, decltype(pj_pool_release)&> tmpPool_(
-        pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory,
+        pj_pool_create(&Manager::instance().sipVoIPLink().getCachingPool()->factory,
                            "tmpSdp", BUF_SZ, BUF_SZ, nullptr),
         pj_pool_release
     );
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 96798b72c0..6b18bc435a 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -202,7 +202,7 @@ SIPAccount::newOutgoingCall(const std::string& toUrl,
 
         // TODO: resolve remote host using SIPVoIPLink::resolveSrvName
         std::shared_ptr<SipTransport> t = isTlsEnabled() ?
-            link_->sipTransportBroker->getTlsTransport(tlsListener_, IpAddr(sip_utils::getHostFromUri(to))) :
+            link_.sipTransportBroker->getTlsTransport(tlsListener_, IpAddr(sip_utils::getHostFromUri(to))) :
             transport_;
         setTransport(t);
         call->setTransport(t);
@@ -362,7 +362,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
     if (!CreateClientDialogAndInvite(&pjFrom, &pjContact, &pjTo, nullptr, local_sdp, &dialog, &inv))
         return false;
 
-    inv->mod_data[link_->getModId()] = call.get();
+    inv->mod_data[link_.getModId()] = call.get();
     call->inv.reset(inv);
 
     updateDialogViaSentBy(dialog);
@@ -382,7 +382,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
         return false;
     }
 
-    const pjsip_tpselector tp_sel = link_->getTransportSelector(transport->get());
+    const pjsip_tpselector tp_sel = link_.getTransportSelector(transport->get());
     if (pjsip_dlg_set_transport(dialog, &tp_sel) != PJ_SUCCESS) {
         JAMI_ERR("Unable to associate transport for invite session dialog");
         return false;
@@ -747,7 +747,7 @@ void SIPAccount::doRegister1_()
         }
     }
 
-    link_->resolveSrvName(
+    link_.resolveSrvName(
         hostname_,
         tlsEnable_ ? PJSIP_TRANSPORT_TLS : PJSIP_TRANSPORT_UDP,
         [w = weak()](std::vector<IpAddr> host_ips) {
@@ -793,7 +793,7 @@ void SIPAccount::doRegister2_()
         initTlsConfiguration();
 
         if (!tlsListener_) {
-            tlsListener_ = link_->sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
+            tlsListener_ = link_.sipTransportBroker->getTlsListener(bindAddress, getTlsSetting());
             if (!tlsListener_) {
                 setRegistrationState(RegistrationState::ERROR_GENERIC);
                 JAMI_ERR("Error creating TLS listener.");
@@ -815,7 +815,7 @@ void SIPAccount::doRegister2_()
     if (isIP2IP()) {
         // If we use Tls for IP2IP, transports will be created on connection.
         if (!tlsEnable_){
-            setTransport(link_->sipTransportBroker->getUdpTransport(bindAddress));
+            setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
         }
         setRegistrationState(RegistrationState::REGISTERED);
         return;
@@ -825,9 +825,9 @@ void SIPAccount::doRegister2_()
         JAMI_WARN("Creating transport");
         transport_.reset();
         if (isTlsEnabled()) {
-            setTransport(link_->sipTransportBroker->getTlsTransport(tlsListener_, hostIp_, tlsServerName_.empty() ? hostname_ : tlsServerName_));
+            setTransport(link_.sipTransportBroker->getTlsTransport(tlsListener_, hostIp_, tlsServerName_.empty() ? hostname_ : tlsServerName_));
         } else {
-            setTransport(link_->sipTransportBroker->getUdpTransport(bindAddress));
+            setTransport(link_.sipTransportBroker->getUdpTransport(bindAddress));
         }
         if (!transport_)
             throw VoipLinkException("Can't create transport");
@@ -914,7 +914,7 @@ void SIPAccount::startKeepAliveTimer()
 
     keepAliveTimerActive_ = true;
 
-    link_->registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
+    link_.registerKeepAliveTimer(keepAliveTimer_, keepAliveDelay_);
 }
 
 void SIPAccount::stopKeepAliveTimer()
@@ -922,7 +922,7 @@ void SIPAccount::stopKeepAliveTimer()
     if (keepAliveTimerActive_) {
         JAMI_DBG("Stop keep alive timer %d for account %s", keepAliveTimer_.id, getAccountID().c_str());
         keepAliveTimerActive_ = false;
-        link_->cancelKeepAliveTimer(keepAliveTimer_);
+        link_.cancelKeepAliveTimer(keepAliveTimer_);
     }
 }
 
@@ -938,7 +938,7 @@ SIPAccount::sendRegister()
     setRegistrationState(RegistrationState::TRYING);
 
     pjsip_regc *regc = nullptr;
-    if (pjsip_regc_create(link_->getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
+    if (pjsip_regc_create(link_.getEndpoint(), (void *) this, &registration_cb, &regc) != PJ_SUCCESS)
         throw VoipLinkException("UserAgent: Unable to create regc structure.");
 
     std::string srvUri(getServerUri());
@@ -977,7 +977,7 @@ SIPAccount::sendRegister()
     }
 
     if (hasServiceRoute())
-        pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
+        pjsip_regc_set_route_set(regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
 
     pjsip_regc_set_credentials(regc, getCredentialCount(), getCredInfo());
 
@@ -987,7 +987,7 @@ SIPAccount::sendRegister()
     auto pJuseragent = CONST_PJ_STR(useragent);
     constexpr pj_str_t STR_USER_AGENT = CONST_PJ_STR("User-Agent");
 
-    pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_->getPool(), &STR_USER_AGENT, &pJuseragent);
+    pjsip_generic_string_hdr *h = pjsip_generic_string_hdr_create(link_.getPool(), &STR_USER_AGENT, &pJuseragent);
     pj_list_push_back(&hdr_list, (pjsip_hdr*) h);
     pjsip_regc_add_headers(regc, &hdr_list);
 
@@ -1068,12 +1068,12 @@ SIPAccount::onRegister(pjsip_regc_cbparam *param)
              */
             // update_rfc5626_status(acc, param->rdata);
 
-            if (checkNATAddress(param, link_->getPool()))
+            if (checkNATAddress(param, link_.getPool()))
                 JAMI_WARN("Contact overwritten");
 
             /* TODO Check and update Service-Route header */
             if (hasServiceRoute())
-                pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_->getPool()));
+                pjsip_regc_set_route_set(param->regc, sip_utils::createRouteSet(getServiceRoute(), link_.getPool()));
 
             // start the periodic registration request based on Expire header
             // account determines itself if a keep alive is required
@@ -1402,7 +1402,7 @@ SIPAccount::getContactHeader(pjsip_transport* t)
     std::string address;
     pj_uint16_t port;
 
-    link_->findLocalAddressFromTransport(
+    link_.findLocalAddressFromTransport(
         t,
         transportType,
         hostname_,
@@ -1418,7 +1418,7 @@ SIPAccount::getContactHeader(pjsip_transport* t)
         port = publishedPort_;
         JAMI_DBG("Using published address %s and port %d", address.c_str(), port);
     } else if (stunEnabled_) {
-        auto success = link_->findLocalAddressFromSTUN(t, &stunServerName_,
+        auto success = link_.findLocalAddressFromSTUN(t, &stunServerName_,
                                                        stunPort_, address, port);
         if (not success)
             emitSignal<DRing::ConfigurationSignal::StunStatusFailed>(getAccountID());
@@ -1467,7 +1467,7 @@ SIPAccount::getHostPortFromSTUN(pj_pool_t *pool)
 {
     std::string addr;
     pj_uint16_t port;
-    auto success = link_->findLocalAddressFromSTUN(
+    auto success = link_.findLocalAddressFromSTUN(
         transport_ ? transport_->get() : nullptr, &stunServerName_, stunPort_,
         addr, port);
     if (not success)
@@ -1955,7 +1955,7 @@ SIPAccount::scheduleReregistration()
     /* Cancel any re-registration timer */
     if (auto_rereg_.timer.id) {
         auto_rereg_.timer.id = PJ_FALSE;
-        pjsip_endpt_cancel_timer(link_->getEndpoint(), &auto_rereg_.timer);
+        pjsip_endpt_cancel_timer(link_.getEndpoint(), &auto_rereg_.timer);
     }
 
     /* Update re-registration flag */
@@ -1984,7 +1984,7 @@ SIPAccount::scheduleReregistration()
 
     JAMI_WARN("Scheduling re-registration retry in %ld seconds..", delay.sec);
     auto_rereg_.timer.id = PJ_TRUE;
-    if (pjsip_endpt_schedule_timer(link_->getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
+    if (pjsip_endpt_schedule_timer(link_.getEndpoint(), &auto_rereg_.timer, &delay) != PJ_SUCCESS)
         auto_rereg_.timer.id = PJ_FALSE;
 }
 
@@ -2032,7 +2032,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
 
     /* Create request. */
     pjsip_tx_data *tdata;
-    pj_status_t status = pjsip_endpt_create_request(link_->getEndpoint(), &msg_method,
+    pj_status_t status = pjsip_endpt_create_request(link_.getEndpoint(), &msg_method,
                                                     &pjTo, &pjFrom, &pjTo, nullptr, nullptr, -1,
                                                     nullptr, &tdata);
     if (status != PJ_SUCCESS) {
@@ -2072,7 +2072,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
     /* Initialize Auth header. */
     auto cred = getCredInfo();
     const_cast<pjsip_cred_info*>(cred)->realm = CONST_PJ_STR(hostname_);
-    status = pjsip_auth_clt_init(t->auth_sess.get(), link_->getEndpoint(), tdata->pool, 0);
+    status = pjsip_auth_clt_init(t->auth_sess.get(), link_.getEndpoint(), tdata->pool, 0);
 
     if (status != PJ_SUCCESS) {
         JAMI_ERR("Unable to initialize auth session: %s", sip_utils::sip_strerror(status).c_str());
@@ -2100,7 +2100,7 @@ SIPAccount::sendTextMessage(const std::string& to, const std::map<std::string, s
     im::fillPJSIPMessageBody(*tdata, payloads);
 
     // Send message request with callback SendMessageOnComplete
-    status = pjsip_endpt_send_request(link_->getEndpoint(), tdata, -1, t.release(), &onComplete);
+    status = pjsip_endpt_send_request(link_.getEndpoint(), tdata, -1, t.release(), &onComplete);
 
     if (status != PJ_SUCCESS) {
         JAMI_ERR("Unable to send request: %s", sip_utils::sip_strerror(status).c_str());
@@ -2139,7 +2139,7 @@ SIPAccount::onComplete(void *token, pjsip_event *event)
             cseq_hdr->cseq += 1;
 
             // Resend request
-            status = pjsip_endpt_send_request(acc->link_->getEndpoint(), new_request, -1, c.release(), &onComplete);
+            status = pjsip_endpt_send_request(acc->link_.getEndpoint(), new_request, -1, c.release(), &onComplete);
 
             if (status != PJ_SUCCESS) {
                 JAMI_ERR("Unable to send request: %s", sip_utils::sip_strerror(status).c_str());
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index f3a5052998..3be80e0c77 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -58,7 +58,7 @@ static constexpr std::chrono::steady_clock::duration COMPOSING_TIMEOUT {std::chr
 SIPAccountBase::SIPAccountBase(const std::string& accountID)
     : Account(accountID),
     messageEngine_(*this, fileutils::get_cache_dir()+DIR_SEPARATOR_STR+getAccountID()+DIR_SEPARATOR_STR "messages"),
-    link_(getSIPVoIPLink())
+    link_(Manager::instance().sipVoIPLink())
 {}
 
 SIPAccountBase::~SIPAccountBase() {}
diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h
index f72651d054..14e3b794d9 100644
--- a/src/sip/sipaccountbase.h
+++ b/src/sip/sipaccountbase.h
@@ -342,7 +342,7 @@ protected:
     /**
      * Voice over IP Link contains a listener thread and calls
      */
-    std::shared_ptr<SIPVoIPLink> link_;
+    SIPVoIPLink& link_;
 
     /**
      * interface name on which this account is bound
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 238189e718..4732252d0a 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -267,7 +267,7 @@ SIPCall::sendSIPInfo(const char *const body, const char *const subtype)
     if (tdata->msg->body == NULL)
         pjsip_tx_data_dec_ref(tdata);
     else
-        pjsip_dlg_send_request(inv->dlg, tdata, getSIPVoIPLink()->getModId(), NULL);
+        pjsip_dlg_send_request(inv->dlg, tdata, Manager::instance().sipVoIPLink().getModId(), NULL);
 }
 
 void
@@ -335,7 +335,7 @@ SIPCall::answer()
         JAMI_WARN("[call:%s] Negotiator is NULL, we've received an INVITE without an SDP",
                   getCallId().c_str());
         pjmedia_sdp_session *dummy = 0;
-        getSIPVoIPLink()->createSDPOffer(inv.get(), &dummy);
+        Manager::instance().sipVoIPLink().createSDPOffer(inv.get(), &dummy);
 
         if (account.isStunEnabled())
             updateSDPFromSTUN();
@@ -416,13 +416,7 @@ SIPCall::refuse()
 static void
 transfer_client_cb(pjsip_evsub *sub, pjsip_event *event)
 {
-    auto link = getSIPVoIPLink();
-    if (not link) {
-        JAMI_ERR("no more VoIP link");
-        return;
-    }
-
-    auto mod_ua_id = link->getModId();
+    auto mod_ua_id = Manager::instance().sipVoIPLink().getModId();
 
     switch (pjsip_evsub_get_state(sub)) {
         case PJSIP_EVSUB_STATE_ACCEPTED:
@@ -513,7 +507,7 @@ SIPCall::transferCommon(const pj_str_t *dst)
      * because after this function, we can no find the cooresponding
      * voiplink from the call any more. But the voiplink is useful!
      */
-    pjsip_evsub_set_mod_data(sub, getSIPVoIPLink()->getModId(), this);
+    pjsip_evsub_set_mod_data(sub, Manager::instance().sipVoIPLink().getModId(), this);
 
     /*
      * Create REFER request.
@@ -1372,7 +1366,7 @@ SIPCall::InvSessionDeleter::operator ()(pjsip_inv_session* inv) const noexcept
     // prevent this from getting accessed in callbacks
     // JAMI_WARN: this is not thread-safe!
     if (!inv) return;
-    inv->mod_data[getSIPVoIPLink()->getModId()] = nullptr;
+    inv->mod_data[Manager::instance().sipVoIPLink().getModId()] = nullptr;
     // NOTE: the counter is incremented by sipvoiplink (transaction_request_cb)
     pjsip_inv_dec_ref(inv);
 }
@@ -1401,7 +1395,7 @@ SIPCall::merge(Call& call)
     std::lock_guard<std::recursive_mutex> lk1 {callMutex_, std::adopt_lock};
     std::lock_guard<std::recursive_mutex> lk2 {subcall.callMutex_, std::adopt_lock};
     inv = std::move(subcall.inv);
-    inv->mod_data[getSIPVoIPLink()->getModId()] = this;
+    inv->mod_data[Manager::instance().sipVoIPLink().getModId()] = this;
     setTransport(std::move(subcall.transport_));
     sdp_ = std::move(subcall.sdp_);
     peerHolding_ = subcall.peerHolding_;
diff --git a/src/sip/sippresence.cpp b/src/sip/sippresence.cpp
index b1a04e98c4..5078c5dc5e 100644
--- a/src/sip/sippresence.cpp
+++ b/src/sip/sippresence.cpp
@@ -93,7 +93,7 @@ pjsip_pres_status * SIPPresence::getStatus()
 
 int SIPPresence::getModId() const
 {
-    return getSIPVoIPLink()->getModId();
+    return Manager::instance().sipVoIPLink().getModId();
 }
 
 pj_pool_t*  SIPPresence::getPool() const
@@ -481,7 +481,7 @@ SIPPresence::publish(SIPPresence *pres)
     pj_status_t status;
     constexpr pj_str_t STR_PRESENCE = CONST_PJ_STR("presence");
     SIPAccount * acc = pres->getAccount();
-    pjsip_endpoint *endpt = getSIPVoIPLink()->getEndpoint();
+    pjsip_endpoint *endpt = Manager::instance().sipVoIPLink().getEndpoint();
 
     /* Create and init client publication session */
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 951a652bde..357b87487f 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -82,8 +82,6 @@ static void outgoing_request_forked_cb(pjsip_inv_session *inv, pjsip_event *e);
 static void transaction_state_changed_cb(pjsip_inv_session *inv, pjsip_transaction *tsx, pjsip_event *e);
 static std::shared_ptr<SIPCall> getCallFromInvite(pjsip_inv_session* inv);
 
-decltype(getGlobalInstance<SIPVoIPLink>)& getSIPVoIPLink = getGlobalInstance<SIPVoIPLink>;
-
 static void
 handleIncomingOptions(pjsip_rx_data *rdata)
 {
@@ -204,13 +202,7 @@ transaction_request_cb(pjsip_rx_data *rdata)
     if (not remote_user.empty() and not remote_hostname.empty())
         peerNumber = remote_user + "@" + remote_hostname;
 
-    auto link = getSIPVoIPLink();
-    if (not link) {
-        JAMI_ERR("no more VoIP link");
-        return PJ_FALSE;
-    }
-
-    auto account(link->guessAccount(toUsername, viaHostname, remote_hostname));
+    auto account(Manager::instance().sipVoIPLink().guessAccount(toUsername, viaHostname, remote_hostname));
     if (!account) {
         JAMI_ERR("NULL account");
         return PJ_FALSE;
@@ -314,7 +306,7 @@ transaction_request_cb(pjsip_rx_data *rdata)
         }
     }
 
-    auto transport = link->sipTransportBroker->addTransport(rdata->tp_info.transport);
+    auto transport = Manager::instance().sipVoIPLink().sipTransportBroker->addTransport(rdata->tp_info.transport);
     auto call = account->newIncomingCall(remote_user, {{"AUDIO_ONLY", (hasVideo ? "false" : "true") }}, transport);
     if (!call) {
         return PJ_FALSE;
@@ -487,16 +479,10 @@ static void
 tp_state_callback(pjsip_transport* tp, pjsip_transport_state state,
                   const pjsip_transport_state_info* info)
 {
-    // There is no way (at writing) to link a user data to a PJSIP transport.
-    // So we obtain it from the global SIPVoIPLink instance that owns it.
-    // Be sure the broker's owner is not deleted during process
-    if (auto sipLink = getSIPVoIPLink()) {
-        if (auto& broker = sipLink->sipTransportBroker)
-            broker->transportStateChanged(tp, state, info);
-        else
-            JAMI_ERR("SIPVoIPLink with invalid SipTransportBroker");
-    } else
-        JAMI_ERR("no more VoIP link");
+    if (auto& broker = Manager::instance().sipVoIPLink().sipTransportBroker)
+        broker->transportStateChanged(tp, state, info);
+    else
+        JAMI_ERR("SIPVoIPLink with invalid SipTransportBroker");
 }
 
 /*************************************************************************************************/
diff --git a/src/sip/sipvoiplink.h b/src/sip/sipvoiplink.h
index 91e25e675c..3664bb527c 100644
--- a/src/sip/sipvoiplink.h
+++ b/src/sip/sipvoiplink.h
@@ -58,13 +58,9 @@ class SipTransportBroker;
 
 typedef std::map<std::string, std::shared_ptr<SIPCall> > SipCallMap;
 
-extern decltype(getGlobalInstance<SIPVoIPLink>)& getSIPVoIPLink;
-
 /**
  * @file sipvoiplink.h
  * @brief Specific VoIPLink for SIP (SIP core for incoming and outgoing events).
- *          This class is based on the singleton design pattern.
- *          One SIPVoIPLink can handle multiple SIP accounts, but all the SIP accounts have all the same SIPVoIPLink
  */
 
 class SIPVoIPLink {
-- 
GitLab