diff --git a/src/call.cpp b/src/call.cpp index 03d433ccf50c6ef6938345dbe20c5ac5942f2698..c950270d179e583c855de62b14be1b968c025cee 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 aeb4838b3d6d2556eb4bc31088595e58de710dd3..0d4ac4a0b2201b7cbddfd3593ebbb626b3112427 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 79326fa2fe752832765ece2f11c23f4387bd3097..28f6197563495536ab6f9db608cef363fe08b958 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 862c074a043a7070643f4f6b5f2ab1f66b5d4483..3139363dba97416fa4b99508d680bb0ccb5bf925 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 25965dbc73fd1039d54b188f8b4a6878a12a4d88..22aa6f8d37d9b380bac2248f9a6e8f83ff551f66 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 1bafebdd9279c39d56c39edffa41aa17c865837b..8d261e2f7fc0f970761f43978e498d7b85f5bdfb 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 881354590c6d0a722cb16250590f104c8e01e79d..877e7962cada4c273423c79ac816219d9c64758e 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 ab0714bb87ed585d0a37070657a646d720353349..09078911f0030799b2d72f9b869a2ab7b485124d 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