From 445fe3124ab8da51a3272d4e07d9c4360cb47a51 Mon Sep 17 00:00:00 2001
From: Mohamed Chibani <mohamed.chibani@savoirfairelinux.com>
Date: Mon, 3 May 2021 15:24:33 -0400
Subject: [PATCH] ICE: enable/disable ICE for media

Change-Id: I07e13c237af76db0ee197f69ece12ed2461b3b52
---
 src/account.cpp             |  1 -
 src/account.h               |  5 ++++
 src/call.h                  |  5 ++++
 src/jamidht/jamiaccount.cpp |  4 ++-
 src/sip/sipaccount.cpp      | 11 ++++++--
 src/sip/sipcall.cpp         | 55 +++++++++++++++++++++++++++----------
 src/sip/sipcall.h           |  3 ++
 src/sip/sipvoiplink.cpp     |  4 ++-
 8 files changed, 67 insertions(+), 21 deletions(-)

diff --git a/src/account.cpp b/src/account.cpp
index c05dea5bb9..4c6b224909 100644
--- a/src/account.cpp
+++ b/src/account.cpp
@@ -127,7 +127,6 @@ Account::Account(const std::string& accountID)
 #else
     , multiStreamEnabled_(false)
 #endif
-    , iceCompIdRfc5245Compliant_(false)
 {
     // Initialize the codec order, used when creating a new account
     loadDefaultCodecs();
diff --git a/src/account.h b/src/account.h
index 6aa17129d5..f4d915a954 100644
--- a/src/account.h
+++ b/src/account.h
@@ -353,6 +353,10 @@ public:
         allModeratorsEnabled_ = isAllModeratorEnabled;
     }
 
+    // Enable/disable ICE for media
+    bool isIceForMediaEnabled() const { return iceForMediaEnabled_; }
+    void enableIceForMedia(bool enable) { iceForMediaEnabled_ = enable; }
+
     // Enable/disable multi-stream feature.
     // Multi-stream feature changes the callflow of the re-invite process. All
     // clients must support this feature before it can be enabled by default.
@@ -579,6 +583,7 @@ protected:
     bool allModeratorsEnabled_;
 
     bool multiStreamEnabled_ {false};
+    bool iceForMediaEnabled_ {true};
     bool iceCompIdRfc5245Compliant_ {false};
 
     /**
diff --git a/src/call.h b/src/call.h
index 10e3121b0f..8ac8f49ede 100644
--- a/src/call.h
+++ b/src/call.h
@@ -268,6 +268,11 @@ public:
 
     virtual void sendKeyframe() = 0;
 
+    /**
+     * Check wether ICE is enabled for media
+     */
+    virtual bool isIceEnabled() const = 0;
+
     /**
      * Peer has hung up a call
      */
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index dd03af28db..d02084c88c 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -811,7 +811,9 @@ JamiAccount::onConnectedOutgoingCall(const std::shared_ptr<SIPCall>& call,
 bool
 JamiAccount::SIPStartCall(SIPCall& call, IpAddr target)
 {
-    call.addLocalIceAttributes();
+    if (call.isIceEnabled())
+        call.addLocalIceAttributes();
+
     std::string toUri(getToUri(call.getPeerNumber() + "@"
                                + target.toString(true))); // expecting a fully well formed sip uri
 
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index bb7e93f79d..d87c5189d1 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -231,7 +231,9 @@ SIPAccount::newOutgoingCall(std::string_view toUrl,
     }
 
     auto toUri = getToUri(to);
-    call->initIceMediaTransport(true);
+    if (call->isIceEnabled()) {
+        call->initIceMediaTransport(true);
+    }
     call->setPeerNumber(toUri);
     call->setPeerUri(toUri);
 
@@ -321,7 +323,9 @@ SIPAccount::newOutgoingCall(std::string_view toUrl, const std::vector<MediaAttri
     }
 
     auto toUri = getToUri(to);
-    call->initIceMediaTransport(true);
+    if (call->isIceEnabled()) {
+        call->initIceMediaTransport(true);
+    }
     call->setPeerNumber(toUri);
     call->setPeerUri(toUri);
 
@@ -441,7 +445,8 @@ bool
 SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
 {
     // Add Ice headers to local SDP if ice transport exist
-    call->addLocalIceAttributes();
+    if (call->isIceEnabled())
+        call->addLocalIceAttributes();
 
     const std::string& toUri(call->getPeerNumber()); // expecting a fully well formed sip uri
     pj_str_t pjTo = sip_utils::CONST_PJ_STR(toUri);
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index f24b01b6bd..bd73ec1290 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -90,6 +90,7 @@ SIPCall::SIPCall(const std::shared_ptr<SIPAccountBase>& account,
                  const std::map<std::string, std::string>& details)
     : Call(account, callId, type, details)
     , sdp_(new Sdp(callId))
+    , enableIce_(account->isIceForMediaEnabled())
 {
     if (account->getUPnPActive())
         upnp_.reset(new upnp::Controller());
@@ -123,6 +124,7 @@ SIPCall::SIPCall(const std::shared_ptr<SIPAccountBase>& account,
     : Call(account, callId, type)
     , peerSupportMultiStream_(false)
     , sdp_(new Sdp(callId))
+    , enableIce_(account->isIceForMediaEnabled())
 {
     if (account->getUPnPActive())
         upnp_.reset(new upnp::Controller());
@@ -506,8 +508,10 @@ SIPCall::SIPSessionReinvite(const std::vector<MediaAttribute>& mediaAttrList)
     if (not sdp_->createOffer(mediaAttrList))
         return !PJ_SUCCESS;
 
-    if (initIceMediaTransport(true))
-        addLocalIceAttributes();
+    if (isIceEnabled()) {
+        if (initIceMediaTransport(true))
+            addLocalIceAttributes();
+    }
 
     pjsip_tx_data* tdata;
     auto local_sdp = sdp_->getLocalSdpSession();
@@ -891,7 +895,8 @@ SIPCall::answerMediaChangeRequest(const std::vector<MediaAttribute>& mediaAttrLi
         return;
     }
 
-    setupLocalIce();
+    if (isIceEnabled())
+        setupLocalIce();
 
     if (not sdp_->startNegotiation()) {
         JAMI_ERR("[call:%s] Could not start media negotiation for a re-invite request",
@@ -1459,6 +1464,12 @@ SIPCall::sendKeyframe()
 #endif
 }
 
+bool
+SIPCall::isIceEnabled() const
+{
+    return enableIce_;
+}
+
 void
 SIPCall::setPeerUaVersion(std::string_view ua)
 {
@@ -1558,7 +1569,10 @@ SIPCall::addLocalIceAttributes()
     }
 
     JAMI_DBG("[call:%s] fill SDP with ICE transport %p", getCallId().c_str(), media_tr);
-    sdp_->addIceAttributes(media_tr->getLocalAttributes());
+
+    if (isIceEnabled()) {
+        sdp_->addIceAttributes(media_tr->getLocalAttributes());
+    }
 
     if (account->isIceCompIdRfc5245Compliant()) {
         unsigned streamIdx = 0;
@@ -2164,24 +2178,33 @@ SIPCall::onMediaNegotiationComplete()
             JAMI_WARN("[call:%s] media changed", this_->getCallId().c_str());
             // The call is already ended, so we don't need to restart medias
             if (not this_->inviteSession_
-                or this_->inviteSession_->state == PJSIP_INV_STATE_DISCONNECTED or not this_->sdp_)
+                or this_->inviteSession_->state == PJSIP_INV_STATE_DISCONNECTED
+                or not this_->sdp_) {
                 return;
-            // If ICE is not used, start media now
-            auto rem_ice_attrs = this_->sdp_->getIceAttributes();
-            if (rem_ice_attrs.ufrag.empty() or rem_ice_attrs.pwd.empty()) {
-                JAMI_DBG("[call:%s] No ICE, starting media using default ",
-                         this_->getCallId().c_str());
+            }
 
+            bool hasIce = this_->isIceEnabled();
+            if (hasIce) {
+                // If ICE is not used, start medias now
+                auto rem_ice_attrs = this_->sdp_->getIceAttributes();
+                hasIce = not rem_ice_attrs.ufrag.empty() and not rem_ice_attrs.pwd.empty();
+            }
+            if (hasIce) {
+                if (not this_->isSubcall()) {
+                    // Start ICE checks. Media will be started once ICE checks complete.
+                    this_->startIceMedia();
+                }
+            } else {
+                // No ICE, start media now.
+                JAMI_WARN("[call:%s] ICE media disabled, using default media ports",
+                          this_->getCallId().c_str());
                 // Update the negotiated media.
                 this_->updateNegotiatedMedia();
 
                 // Start the media.
                 this_->stopAllMedia();
                 this_->startAllMedia();
-                return;
             }
-            if (not this_->isSubcall())
-                this_->startIceMedia();
         }
     });
 }
@@ -2326,8 +2349,10 @@ SIPCall::onReceiveOffer(const pjmedia_sdp_session* offer, const pjsip_rx_data* r
     // Use current media list.
     sdp_->processIncomingOffer(getMediaAttributeList());
 
-    if (offer)
-        setupLocalIce();
+    if (isIceEnabled()) {
+        if (offer)
+            setupLocalIce();
+    }
     sdp_->startNegotiation();
 
     pjsip_tx_data* tdata = nullptr;
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index f1f6f24433..960f7c7efa 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -147,6 +147,7 @@ public:
     std::shared_ptr<AccountCodecInfo> getAudioCodec() const override;
     std::shared_ptr<AccountCodecInfo> getVideoCodec() const override;
     void sendKeyframe() override;
+    bool isIceEnabled() const override;
     std::map<std::string, std::string> getDetails() const override;
     void enterConference(const std::string& confId) override;
     void exitConference() override;
@@ -426,6 +427,8 @@ private:
     /** Local video port, as seen by me. */
     unsigned int localVideoPort_ {0};
 
+    bool enableIce_ {true};
+
     ///< Transport used for media streams
     std::shared_ptr<IceTransport> mediaTransport_;
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 60ccd5a068..ab8aaea6d2 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -453,8 +453,10 @@ transaction_request_cb(pjsip_rx_data* rdata)
         call->getSDP().setReceivedOffer(r_sdp);
         call->getSDP().processIncomingOffer(mediaList);
     }
-    if (r_sdp)
+
+    if (r_sdp and call->isIceEnabled()) {
         call->setupLocalIce();
+    }
 
     pjsip_dialog* dialog = nullptr;
     if (pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata, nullptr, &dialog)
-- 
GitLab