From c04cde48511fdcd7213c271e4c358cc3f5a05f8c Mon Sep 17 00:00:00 2001
From: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com>
Date: Tue, 28 Mar 2017 20:36:35 -0400
Subject: [PATCH] call: move ICE transport into SIPCall class

Just moving all ICE transport related methods from Call class
into the SIPCall call.
This is done in the mind of refactoring media transport system.

Call is agnostic to transport implementation and this stuff
has to be handled by concrete classes of Call that known all about
transport information.

Note: <algorithm> included in audiolayer.cpp to make this patch
buildable on UWP platform.

Change-Id: I04b780dcff3483237a2de3c47ee667df9bba9f97
Reviewed-by: Olivier SOLDANO <olivier.soldano@savoirfairelinux.com>
---
 src/call.cpp                   | 24 ------------
 src/call.h                     | 13 -------
 src/manager.h                  |  1 +
 src/media/audio/audiolayer.cpp |  1 +
 src/ringdht/ringaccount.cpp    |  4 +-
 src/sip/sipaccount.cpp         |  2 +-
 src/sip/sipcall.cpp            | 68 +++++++++++++++++++++-------------
 src/sip/sipcall.h              | 19 +++++++++-
 8 files changed, 66 insertions(+), 66 deletions(-)

diff --git a/src/call.cpp b/src/call.cpp
index 03d433ccf5..c950270d17 100644
--- a/src/call.cpp
+++ b/src/call.cpp
@@ -108,7 +108,6 @@ Call::removeCall()
 {
     auto this_ = shared_from_this();
     Manager::instance().callFactory.removeCall(*this);
-    iceTransport_.reset();
     setState(CallState::OVER);
     recAudio_->closeFile();
 }
@@ -340,28 +339,6 @@ Call::getNullDetails()
     };
 }
 
-bool
-Call::initIceTransport(bool master, unsigned channel_num)
-{
-    auto& iceTransportFactory = Manager::instance().getIceTransportFactory();
-    iceTransport_ = iceTransportFactory.createTransport(getCallId().c_str(),
-                                                        channel_num, master,
-                                                        account_.getIceOptions());
-    return static_cast<bool>(iceTransport_);
-}
-
-bool
-Call::isIceRunning() const
-{
-    return iceTransport_ and iceTransport_->isRunning();
-}
-
-std::unique_ptr<IceSocket>
-Call::newIceSocket(unsigned compId)
-{
-    return std::unique_ptr<IceSocket> {new IceSocket(iceTransport_, compId)};
-}
-
 void
 Call::onTextMessage(std::map<std::string, std::string>&& messages)
 {
@@ -497,7 +474,6 @@ Call::merge(Call& subcall)
         std::lock_guard<std::recursive_mutex> lk1 {callMutex_, std::adopt_lock};
         std::lock_guard<std::recursive_mutex> lk2 {subcall.callMutex_, std::adopt_lock};
         pendingInMessages_ = std::move(subcall.pendingInMessages_);
-        iceTransport_ = std::move(subcall.iceTransport_);
         if (peerNumber_.empty())
             peerNumber_ = std::move(subcall.peerNumber_);
         peerDisplayName_ = std::move(subcall.peerDisplayName_);
diff --git a/src/call.h b/src/call.h
index aeb4838b3d..0d4ac4a0b2 100644
--- a/src/call.h
+++ b/src/call.h
@@ -31,7 +31,6 @@
 
 #include "recordable.h"
 #include "ip_utils.h"
-#include "ice_transport.h"
 
 #include <mutex>
 #include <map>
@@ -289,16 +288,6 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
 
         void onTextMessage(std::map<std::string, std::string>&& messages);
 
-        virtual bool initIceTransport(bool master, unsigned channel_num=4);
-
-        bool isIceRunning() const;
-
-        std::unique_ptr<IceSocket> newIceSocket(unsigned compId);
-
-        std::shared_ptr<IceTransport> getIceTransport() const {
-            return iceTransport_;
-        }
-
         virtual bool useVideoCodec(const AccountVideoCodecInfo* /*codec*/) const {
             return false;
         }
@@ -319,8 +308,6 @@ class Call : public Recordable, public std::enable_shared_from_this<Call> {
 
         // TODO all these members are not protected against multi-thread access
 
-        std::shared_ptr<IceTransport> iceTransport_ {};
-
         bool isAudioMuted_{false};
         bool isVideoMuted_{false};
 
diff --git a/src/manager.h b/src/manager.h
index 79326fa2fe..28f6197563 100644
--- a/src/manager.h
+++ b/src/manager.h
@@ -51,6 +51,7 @@ class RingBufferPool;
 class VideoManager;
 class Conference;
 class AudioLoop;
+class IceTransportFactory;
 
 /** Manager (controller) of Ring daemon */
 class Manager {
diff --git a/src/media/audio/audiolayer.cpp b/src/media/audio/audiolayer.cpp
index 862c074a04..3139363dba 100644
--- a/src/media/audio/audiolayer.cpp
+++ b/src/media/audio/audiolayer.cpp
@@ -29,6 +29,7 @@
 #include "client/ring_signal.h"
 
 #include <ctime>
+#include <algorithm>
 
 namespace ring {
 
diff --git a/src/ringdht/ringaccount.cpp b/src/ringdht/ringaccount.cpp
index 25965dbc73..22aa6f8d37 100644
--- a/src/ringdht/ringaccount.cpp
+++ b/src/ringdht/ringaccount.cpp
@@ -564,13 +564,13 @@ RingAccount::createOutgoingCall(const std::shared_ptr<SIPCall>& call, const std:
 {
     RING_WARN("RingAccount::createOutgoingCall to: %s target: %s",
               to_id.c_str(), target.toString(true).c_str());
-    call->initIceTransport(true);
+    call->initIceMediaTransport(true);
     call->setIPToIP(true);
     call->setPeerNumber(getToUri(to_id+"@"+target.toString(true).c_str()));
     call->initRecFilename(to_id);
 
     const auto localAddress = ip_utils::getInterfaceAddr(getLocalInterface());
-    call->setCallMediaLocal(call->getIceTransport()->getDefaultLocalAddress());
+    call->setCallMediaLocal(call->getIceMediaTransport()->getDefaultLocalAddress());
 
     IpAddr addrSdp;
     if (getUPnPActive()) {
diff --git a/src/sip/sipaccount.cpp b/src/sip/sipaccount.cpp
index 1bafebdd92..8d261e2f7f 100644
--- a/src/sip/sipaccount.cpp
+++ b/src/sip/sipaccount.cpp
@@ -200,7 +200,7 @@ SIPAccount::newOutgoingCall(const std::string& toUrl)
     }
 
     auto toUri = getToUri(to);
-    call->initIceTransport(true);
+    call->initIceMediaTransport(true);
     call->setIPToIP(isIP2IP());
     call->setPeerNumber(toUri);
     call->initRecFilename(to);
diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp
index 881354590c..877e7962ca 100644
--- a/src/sip/sipcall.cpp
+++ b/src/sip/sipcall.cpp
@@ -40,6 +40,7 @@
 #include "dring/call_const.h"
 #include "dring/media_const.h"
 #include "client/ring_signal.h"
+#include "ice_transport.h"
 
 #ifdef RING_VIDEO
 #include "client/videomanager.h"
@@ -232,7 +233,7 @@ SIPCall::SIPSessionReinvite()
                               getState() == CallState::HOLD))
         return !PJ_SUCCESS;
 
-    if (initIceTransport(true))
+    if (initIceMediaTransport(true))
         setupLocalSDPFromIce();
 
     pjsip_tx_data* tdata;
@@ -684,6 +685,7 @@ SIPCall::removeCall()
 {
     RING_WARN("[call:%s] removeCall()", getCallId().c_str());
     Call::removeCall();
+    mediaTransport_.reset();
     inv.reset();
     setTransport({});
 }
@@ -724,25 +726,25 @@ SIPCall::onPeerRinging()
 void
 SIPCall::setupLocalSDPFromIce()
 {
-    if (not iceTransport_) {
+    if (not mediaTransport_) {
         RING_WARN("[call:%s] null icetransport, no attributes added to SDP", getCallId().c_str());
         return;
     }
 
     // we need an initialized ICE to progress further
-    if (iceTransport_->waitForInitialization(DEFAULT_ICE_INIT_TIMEOUT) <= 0) {
+    if (mediaTransport_->waitForInitialization(DEFAULT_ICE_INIT_TIMEOUT) <= 0) {
         RING_ERR("[call:%s] Medias' ICE init failed", getCallId().c_str());
         return;
     }
 
-    sdp_->addIceAttributes(iceTransport_->getLocalAttributes());
+    sdp_->addIceAttributes(mediaTransport_->getLocalAttributes());
 
     // Add video and audio channels
-    sdp_->addIceCandidates(SDP_AUDIO_MEDIA_ID, iceTransport_->getLocalCandidates(ICE_AUDIO_RTP_COMPID));
-    sdp_->addIceCandidates(SDP_AUDIO_MEDIA_ID, iceTransport_->getLocalCandidates(ICE_AUDIO_RTCP_COMPID));
+    sdp_->addIceCandidates(SDP_AUDIO_MEDIA_ID, mediaTransport_->getLocalCandidates(ICE_AUDIO_RTP_COMPID));
+    sdp_->addIceCandidates(SDP_AUDIO_MEDIA_ID, mediaTransport_->getLocalCandidates(ICE_AUDIO_RTCP_COMPID));
 #ifdef RING_VIDEO
-    sdp_->addIceCandidates(SDP_VIDEO_MEDIA_ID, iceTransport_->getLocalCandidates(ICE_VIDEO_RTP_COMPID));
-    sdp_->addIceCandidates(SDP_VIDEO_MEDIA_ID, iceTransport_->getLocalCandidates(ICE_VIDEO_RTCP_COMPID));
+    sdp_->addIceCandidates(SDP_VIDEO_MEDIA_ID, mediaTransport_->getLocalCandidates(ICE_VIDEO_RTP_COMPID));
+    sdp_->addIceCandidates(SDP_VIDEO_MEDIA_ID, mediaTransport_->getLocalCandidates(ICE_VIDEO_RTCP_COMPID));
 #endif
 }
 
@@ -755,7 +757,7 @@ SIPCall::getAllRemoteCandidates()
                                    std::vector<IceCandidate>& out) {
         IceCandidate cand;
         for (auto& line : sdp_->getIceCandidates(sdpMediaId)) {
-            if (iceTransport_->getCandidateFromSDP(line, cand)) {
+            if (mediaTransport_->getCandidateFromSDP(line, cand)) {
                 RING_DBG("[call:%s] add remote ICE candidate: %s", getCallId().c_str(), line.c_str());
                 out.emplace_back(cand);
             }
@@ -773,9 +775,9 @@ SIPCall::getAllRemoteCandidates()
 bool
 SIPCall::startIce()
 {
-    if (not iceTransport_ or iceTransport_->isFailed() or not iceTransport_->isInitialized())
+    if (not mediaTransport_ or mediaTransport_->isFailed() or not mediaTransport_->isInitialized())
         return false;
-    if (iceTransport_->isStarted()) {
+    if (mediaTransport_->isStarted()) {
         RING_DBG("[call:%s] ICE already started", getCallId().c_str());
         return true;
     }
@@ -784,7 +786,7 @@ SIPCall::startIce()
         RING_ERR("[call:%s] ICE empty attributes", getCallId().c_str());
         return false;
     }
-    return iceTransport_->start(rem_ice_attrs, getAllRemoteCandidates());
+    return mediaTransport_->start(rem_ice_attrs, getAllRemoteCandidates());
 }
 
 bool
@@ -965,23 +967,23 @@ SIPCall::onMediaUpdate()
 void
 SIPCall::waitForIceAndStartMedia()
 {
-    auto ice = iceTransport_;
+    auto ice = mediaTransport_;
     auto iceTimeout = std::chrono::steady_clock::now() + std::chrono::seconds(10);
     auto wthis = std::weak_ptr<SIPCall>(std::static_pointer_cast<SIPCall>(shared_from_this()));
     Manager::instance().addTask([wthis,ice,iceTimeout] {
         if (auto sthis = wthis.lock()) {
             auto& this_ = *sthis;
-            if (ice != this_.iceTransport_) {
+            if (ice != this_.mediaTransport_) {
                 RING_WARN("[call:%s] ICE transport replaced", this_.getCallId().c_str());
                 return false;
             }
             /* First step: wait for an ICE transport for SIP channel */
-            if (this_.iceTransport_->isFailed() or std::chrono::steady_clock::now() >= iceTimeout) {
+            if (this_.mediaTransport_->isFailed() or std::chrono::steady_clock::now() >= iceTimeout) {
                 RING_DBG("[call:%s] ICE init failed (or timeout)", this_.getCallId().c_str());
                 this_.onFailure(ETIMEDOUT);
                 return false;
             }
-            if (not this_.iceTransport_->isRunning())
+            if (not this_.mediaTransport_->isRunning())
                 return true;
             this_.startAllMedia();
         }
@@ -1100,16 +1102,19 @@ SIPCall::InvSessionDeleter::operator ()(pjsip_inv_session* inv) const noexcept
 }
 
 bool
-SIPCall::initIceTransport(bool master, unsigned channel_num)
+SIPCall::initIceMediaTransport(bool master, unsigned channel_num)
 {
-    auto result = Call::initIceTransport(master, channel_num);
-    if (result) {
+    auto& iceTransportFactory = Manager::instance().getIceTransportFactory();
+    mediaTransport_ = iceTransportFactory.createTransport(getCallId().c_str(),
+                                                          channel_num, master,
+                                                          getAccount().getIceOptions());
+    if (mediaTransport_) {
         if (const auto& publicIP = getSIPAccount().getPublishedIpAddress()) {
-            for (unsigned compId = 1; compId <= iceTransport_->getComponentCount(); ++compId)
-                iceTransport_->registerPublicIP(compId, publicIP);
+            for (unsigned compId = 1; compId <= mediaTransport_->getComponentCount(); ++compId)
+                mediaTransport_->registerPublicIP(compId, publicIP);
         }
     }
-    return result;
+    return static_cast<bool>(mediaTransport_);
 }
 
 void
@@ -1130,10 +1135,11 @@ SIPCall::merge(Call& call)
     pj_strcpy(&contactHeader_, &subcall.contactHeader_);
     localAudioPort_ = subcall.localAudioPort_;
     localVideoPort_ = subcall.localVideoPort_;
+    mediaTransport_ = std::move(subcall.mediaTransport_);
 
     Call::merge(subcall);
 
-    if (iceTransport_->isStarted())
+    if (mediaTransport_->isStarted())
         waitForIceAndStartMedia();
 }
 
@@ -1145,12 +1151,24 @@ SIPCall::setRemoteSdp(const pjmedia_sdp_session* sdp)
 
     auto ice_attrs = Sdp::getIceAttributes(sdp);
     if (not ice_attrs.ufrag.empty() and not ice_attrs.pwd.empty()) {
-        if (not getIceTransport()) {
+        if (not mediaTransport_) {
             RING_DBG("Initializing ICE transport");
-            initIceTransport(false);
+            initIceMediaTransport(false);
         }
         setupLocalSDPFromIce();
     }
 }
 
+bool
+SIPCall::isIceRunning() const
+{
+    return mediaTransport_ and mediaTransport_->isRunning();
+}
+
+std::unique_ptr<IceSocket>
+SIPCall::newIceSocket(unsigned compId)
+{
+    return std::unique_ptr<IceSocket> {new IceSocket(mediaTransport_, compId)};
+}
+
 } // namespace ring
diff --git a/src/sip/sipcall.h b/src/sip/sipcall.h
index ab0714bb87..09078911f0 100644
--- a/src/sip/sipcall.h
+++ b/src/sip/sipcall.h
@@ -43,6 +43,7 @@
 struct pjsip_evsub;
 struct pjsip_inv_session;
 struct pjmedia_sdp_session;
+struct pj_ice_sess_cand;
 
 namespace ring {
 
@@ -50,6 +51,10 @@ class Sdp;
 class SIPAccountBase;
 class SipTransport;
 class AudioRtpSession;
+class IceTransport;
+class IceSocket;
+
+using IceCandidate = pj_ice_sess_cand;
 
 namespace upnp {
 class Controller;
@@ -99,7 +104,6 @@ public: // overridden
     void restartMediaReceiver() override;
     bool useVideoCodec(const AccountVideoCodecInfo* codec) const override;
     std::map<std::string, std::string> getDetails() const override;
-    bool initIceTransport(bool master, unsigned channel_num=4) override;
 
 public: // SIP related
     /**
@@ -207,6 +211,16 @@ public: // NOT SIP RELATED (good candidates to be moved elsewhere)
         peerRegistredName_ = name;
     }
 
+    bool initIceMediaTransport(bool master, unsigned channel_num=4);
+
+    bool isIceRunning() const;
+
+    std::unique_ptr<IceSocket> newIceSocket(unsigned compId);
+
+    std::shared_ptr<IceTransport> getIceMediaTransport() const {
+        return mediaTransport_;
+    }
+
 private:
     NON_COPYABLE(SIPCall);
 
@@ -265,6 +279,9 @@ private:
 
     /** Local video port, as seen by me. */
     unsigned int localVideoPort_ {0};
+
+    ///< Transport used for media streams
+    std::shared_ptr<IceTransport> mediaTransport_ {};
 };
 
 // Helpers
-- 
GitLab