diff --git a/src/ice_socket.h b/src/ice_socket.h index cd46a1a8c63bcee2caaa9c64f2b2c45bed3cc4fc..39aa813ef0d8ff0af17fc52c8c8ffc0f894dd828 100644 --- a/src/ice_socket.h +++ b/src/ice_socket.h @@ -49,6 +49,7 @@ class IceSocket ssize_t waitForData(std::chrono::milliseconds timeout); void setOnRecv(IceRecvCb cb); uint16_t getTransportOverhead(); + void setDefaultRemoteAddress(const IpAddr& addr); }; /// ICE transport as a GenericSocket. diff --git a/src/ice_transport.cpp b/src/ice_transport.cpp index a8b165e06d92a518e2ba2c58a0a753f0e64781c9..74ea71322898b8c720aeb0430ad1eaf697db7ed3 100644 --- a/src/ice_transport.cpp +++ b/src/ice_transport.cpp @@ -174,6 +174,9 @@ public: */ void selectUPnPIceCandidates(); + void setDefaultRemoteAddress(int comp_id, const IpAddr& addr); + const IpAddr& getDefaultRemoteAddress(int comp_id) const; + std::unique_ptr<upnp::Controller> upnp_; std::mutex upnpMutex_; @@ -189,6 +192,9 @@ public: std::condition_variable waitDataCv_ = {}; onShutdownCb scb; + + // Default remote adresses + std::vector<IpAddr> iceDefaultRemoteAddr_; }; //============================================================================== @@ -284,6 +290,7 @@ IceTransport::Impl::Impl(const char* name, int component_count, bool master, , compIO_(component_count) , initiatorSession_(master) , thread_() + , iceDefaultRemoteAddr_(component_count) { sip_utils::register_thread(); if (options.upnpEnable) @@ -396,6 +403,9 @@ IceTransport::Impl::Impl(const char* name, int component_count, bool master, } } }); + + // Init to invalid adresses + iceDefaultRemoteAddr_.reserve(component_count); } IceTransport::Impl::~Impl() @@ -825,6 +835,25 @@ IceTransport::Impl::selectUPnPIceCandidates() } } +void +IceTransport::Impl::setDefaultRemoteAddress(int comp_id, const IpAddr& addr) +{ + // Component ID must be valid. + assert(comp_id < component_count_); + + iceDefaultRemoteAddr_[comp_id] = addr; + // The port does not matter. Set it 0 to avoid confusion. + iceDefaultRemoteAddr_[comp_id].setPort(0); +} + +const IpAddr& +IceTransport::Impl::getDefaultRemoteAddress(int comp_id) const +{ + // Component ID must be valid. + assert(comp_id < component_count_); + + return iceDefaultRemoteAddr_[comp_id]; +} void IceTransport::Impl::onReceiveData(unsigned comp_id, void *pkt, pj_size_t size) @@ -1031,6 +1060,16 @@ IceTransport::getLocalAddress(unsigned comp_id) const IpAddr IceTransport::getRemoteAddress(unsigned comp_id) const { + + // Return the default remote address if set. + // Note that the default remote addresses are the addresses + // set in the 'c=' and 'a=rtcp' lines of the received SDP. + // See pj_ice_strans_sendto2() for more details. + + if (pimpl_->getDefaultRemoteAddress(comp_id)) { + return pimpl_->getDefaultRemoteAddress(comp_id); + } + return pimpl_->getRemoteAddress(comp_id); } @@ -1047,7 +1086,6 @@ IceTransport::getLocalCandidates(unsigned comp_id) const pj_ice_sess_cand cand[PJ_ARRAY_SIZE(pimpl_->cand_)]; unsigned cand_cnt = PJ_ARRAY_SIZE(cand); - { std::lock_guard<std::mutex> lk {pimpl_->iceMutex_}; if (!pimpl_->icest_) return res; @@ -1305,6 +1343,7 @@ IceTransport::send(int comp_id, const unsigned char* buf, size_t len) { sip_utils::register_thread(); auto remote = getRemoteAddress(comp_id); + if (!remote) { JAMI_ERR("[ice:%p] can't find remote address for component %d", this, comp_id); errno = EINVAL; @@ -1440,6 +1479,12 @@ IceTransport::parse_SDP(const std::string& sdp_msg, const IceTransport& ice) return res; } +void +IceTransport::setDefaultRemoteAddress(int comp_id, const IpAddr& addr) +{ + pimpl_->setDefaultRemoteAddress(comp_id, addr); +} + //============================================================================== IceTransportFactory::IceTransportFactory() @@ -1607,8 +1652,16 @@ IceSocket::setOnRecv(IceRecvCb cb) } uint16_t -IceSocket::getTransportOverhead(){ +IceSocket::getTransportOverhead() +{ return (ice_transport_->getRemoteAddress(compId_).getFamily() == AF_INET) ? IPV4_HEADER_SIZE : IPV6_HEADER_SIZE; } +void +IceSocket::setDefaultRemoteAddress(const IpAddr& addr) +{ + if (ice_transport_) + ice_transport_->setDefaultRemoteAddress(compId_, addr); +} + } // namespace jami diff --git a/src/ice_transport.h b/src/ice_transport.h index 7ac2f2a40fd3c8ce3b17618b28443ff9e438c21e..3b9ce36453b21ae1954b998c857dd9ed97c50e47 100644 --- a/src/ice_transport.h +++ b/src/ice_transport.h @@ -229,6 +229,8 @@ public: static ICESDP parse_SDP(const std::string& sdp_msg, const IceTransport& ice); + void setDefaultRemoteAddress(int comp_id, const IpAddr& addr); + private: class Impl; std::unique_ptr<Impl> pimpl_; diff --git a/src/media/audio/audio_rtp_session.cpp b/src/media/audio/audio_rtp_session.cpp index c53a717588499ca95d6430cc4de75b7830f11aca..f6325c46a7a498c244da573e8844b6e534e874c1 100644 --- a/src/media/audio/audio_rtp_session.cpp +++ b/src/media/audio/audio_rtp_session.cpp @@ -149,8 +149,13 @@ AudioRtpSession::start(std::unique_ptr<IceSocket> rtp_sock, std::unique_ptr<IceS } try { - if (rtp_sock and rtcp_sock) + if (rtp_sock and rtcp_sock) { + + rtp_sock->setDefaultRemoteAddress(send_.addr); + rtcp_sock->setDefaultRemoteAddress(send_.rtcp_addr); + socketPair_.reset(new SocketPair(std::move(rtp_sock), std::move(rtcp_sock))); + } else socketPair_.reset(new SocketPair(getRemoteRtpUri().c_str(), receive_.addr.getPort())); diff --git a/src/media/media_codec.h b/src/media/media_codec.h index 6068ef33778bab06a7f173fcf673ebc0f9daba45..38034abf0f01afdca9875f5101d8db7e62e78a2e 100644 --- a/src/media/media_codec.h +++ b/src/media/media_codec.h @@ -272,6 +272,9 @@ struct MediaDescription { /** Endpoint socket address */ IpAddr addr {}; + /** RTCP socket address */ + IpAddr rtcp_addr {}; + /** RTP */ std::shared_ptr<AccountCodecInfo> codec {}; unsigned payload_type {}; diff --git a/src/media/video/video_rtp_session.cpp b/src/media/video/video_rtp_session.cpp index f242d9f0937393f2682592626ac2e2836d8c26bf..2d50cb07916785ebcec82b3366cc622e4a934f1b 100644 --- a/src/media/video/video_rtp_session.cpp +++ b/src/media/video/video_rtp_session.cpp @@ -208,8 +208,12 @@ void VideoRtpSession::start(std::unique_ptr<IceSocket> rtp_sock, } try { - if (rtp_sock and rtcp_sock) + if (rtp_sock and rtcp_sock) { + rtp_sock->setDefaultRemoteAddress(send_.addr); + rtcp_sock->setDefaultRemoteAddress(send_.rtcp_addr); + socketPair_.reset(new SocketPair(std::move(rtp_sock), std::move(rtcp_sock))); + } else socketPair_.reset(new SocketPair(getRemoteRtpUri().c_str(), receive_.addr.getPort())); diff --git a/src/sip/sdp.cpp b/src/sip/sdp.cpp index acfa2bac82bfff54297b2f698cfb9cbd92995901..b57a5efbe3947b325dbc2d138c2b7a56b7f001c0 100644 --- a/src/sip/sdp.cpp +++ b/src/sip/sdp.cpp @@ -597,6 +597,18 @@ Sdp::getMediaSlots(const pjmedia_sdp_session* session, bool remote) const descr.addr = std::string(conn->addr.ptr, conn->addr.slen); descr.addr.setPort(media->desc.port); + // Get the "rtcp" address from the SDP if present. Otherwise, + // infere it from endpoint (RTP) address. + auto attr = pjmedia_sdp_attr_find2(media->attr_count, media->attr, "rtcp", NULL); + if (attr) { + pjmedia_sdp_rtcp_attr rtcp; + auto status = pjmedia_sdp_attr_get_rtcp(attr, &rtcp); + if (status == PJ_SUCCESS && rtcp.addr.slen) { + descr.rtcp_addr = std::string(rtcp.addr.ptr, rtcp.addr.slen); + descr.rtcp_addr.setPort(rtcp.port); + } + } + descr.holding = pjmedia_sdp_attr_find2(media->attr_count, media->attr, "sendonly", nullptr) || pjmedia_sdp_attr_find2(media->attr_count, media->attr, "inactive", nullptr);