diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp index bda5c8ad2a987c722ad2a95bff7b541bdc19edf0..c8c5eedb8264fa5f7e7eb05b604379c9282fe0f3 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp @@ -108,7 +108,7 @@ void AudioRtpFactory::initSession() // TODO: be careful with that. The hello hash is computed asynchronously. Maybe it's // not even available at that point. if (helloHashEnabled_) - call_->getLocalSDP().setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_.get())->getHelloHash()); + call_->getSDP().setZrtpHash(static_cast<AudioZrtpSession *>(rtpSession_.get())->getHelloHash()); break; } #endif @@ -194,7 +194,7 @@ void AudioRtpFactory::initLocalCryptoInfo() AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_.get()); // the context is invalidated and deleted by the call to initLocalCryptoInfo srtp->initLocalCryptoInfo(); - call_->getLocalSDP().setLocalSdpCrypto(srtp->getLocalCryptoInfo()); + call_->getSDP().setLocalSdpCrypto(srtp->getLocalCryptoInfo()); } } @@ -206,7 +206,7 @@ void AudioRtpFactory::initLocalCryptoInfoOnOffHold() AudioSrtpSession *srtp = static_cast<AudioSrtpSession*>(rtpSession_.get()); // the context is invalidated and deleted by the call to initLocalCryptoInfo srtp->initLocalCryptoInfoOnOffhold(); - call_->getLocalSDP().setLocalSdpCrypto(srtp->getLocalCryptoInfo()); + call_->getSDP().setLocalSdpCrypto(srtp->getLocalCryptoInfo()); } } diff --git a/daemon/src/audio/audiortp/audio_rtp_session.cpp b/daemon/src/audio/audiortp/audio_rtp_session.cpp index dbdfda1076aae0bcfc8f16fbecd9aa84edfa0d46..d5f62096c6e828b9c38418fa5ec9210a3a771f4b 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_session.cpp @@ -260,10 +260,10 @@ void AudioRtpSession::updateDestinationIpAddress() #endif ) SFL_DBG("Did not remove previous destination"); - IpAddr remote = {call_.getLocalSDP().getRemoteIP()}; - remote.setPort(call_.getLocalSDP().getRemoteAudioPort()); + IpAddr remote = {call_.getSDP().getRemoteIP()}; + remote.setPort(call_.getSDP().getRemoteAudioPort()); if (!remote) { - SFL_WARN("Target IP address (%s) is not correct!", call_.getLocalSDP().getRemoteIP().c_str()); + SFL_WARN("Target IP address (%s) is not correct!", call_.getSDP().getRemoteIP().c_str()); return; } remoteIp_ = remote; diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp index 3a543ee2b3b53a9caaee95f0a00c7d1ff1ba5b25..94e768119a04945abaeb362fac279ef0997f348d 100644 --- a/daemon/src/ringdht/ringaccount.cpp +++ b/daemon/src/ringdht/ringaccount.cpp @@ -194,14 +194,14 @@ RingAccount::createOutgoingCall(const std::shared_ptr<SIPCall>& call, const std: } // Building the local SDP offer - auto& localSDP = call->getLocalSDP(); + auto& sdp = call->getSDP(); if (getPublishedSameasLocal()) - localSDP.setPublishedIP(addrSdp); + sdp.setPublishedIP(addrSdp); else - localSDP.setPublishedIP(getPublishedAddress()); + sdp.setPublishedIP(getPublishedAddress()); - const bool created = localSDP.createOffer(getActiveAudioCodecs(), getActiveVideoCodecs()); + const bool created = sdp.createOffer(getActiveAudioCodecs(), getActiveVideoCodecs()); if (not created or not SIPStartCall(call)) throw VoipLinkException("Could not send outgoing INVITE request for new call"); @@ -248,7 +248,7 @@ RingAccount::SIPStartCall(const std::shared_ptr<SIPCall>& call) pj_list_push_back(&dialog->inv_hdr, subj_hdr); pjsip_inv_session* inv = nullptr; - if (pjsip_inv_create_uac(dialog, call->getLocalSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { + if (pjsip_inv_create_uac(dialog, call->getSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { SFL_ERR("Unable to create invite session for user agent client"); return false; } diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index ae4920990f2e2e417ee88bed67e5d3f8243870ae..e032de192350c1f3d5eb17cead9a83cebf2b0599 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -249,14 +249,14 @@ SIPAccount::newOutgoingCall(const std::string& id, const std::string& toUrl) } // Building the local SDP offer - auto& localSDP = call->getLocalSDP(); + auto& sdp = call->getSDP(); if (getPublishedSameasLocal()) - localSDP.setPublishedIP(addrSdp); + sdp.setPublishedIP(addrSdp); else - localSDP.setPublishedIP(getPublishedAddress()); + sdp.setPublishedIP(getPublishedAddress()); - const bool created = localSDP.createOffer(getActiveAudioCodecs(), getActiveVideoCodecs()); + const bool created = sdp.createOffer(getActiveAudioCodecs(), getActiveVideoCodecs()); if (not created or not SIPStartCall(call)) throw VoipLinkException("Could not send outgoing INVITE request for new call"); @@ -306,7 +306,7 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call) pj_list_push_back(&dialog->inv_hdr, subj_hdr); pjsip_inv_session* inv = nullptr; - if (pjsip_inv_create_uac(dialog, call->getLocalSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { + if (pjsip_inv_create_uac(dialog, call->getSDP().getLocalSdpSession(), 0, &inv) != PJ_SUCCESS) { SFL_ERR("Unable to create invite session for user agent client"); return false; } diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp index 1a573f2705e4b6ecef47487d27a26e874eed19c6..977107ac26b8b63cacf6c593dc716105696ea664 100644 --- a/daemon/src/sip/sipcall.cpp +++ b/daemon/src/sip/sipcall.cpp @@ -107,7 +107,7 @@ SIPCall::SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType #endif , pool_(pj_pool_create(&getSIPVoIPLink()->getCachingPool()->factory, id.c_str(), INITIAL_SIZE, INCREMENT_SIZE, NULL)) - , local_sdp_(new Sdp(pool_)) + , sdp_(new Sdp(pool_)) {} SIPCall::~SIPCall() @@ -122,7 +122,7 @@ SIPCall::~SIPCall() } // local sdp must be destroyed before pool - local_sdp_.reset(); + sdp_.reset(); pj_pool_release(pool_); } @@ -153,7 +153,7 @@ SIPCall::setCallMediaLocal(const pj_sockaddr& localIP) if (getLocalAudioPort() == 0) { const unsigned callLocalAudioPort = account.generateAudioPort(); setLocalAudioPort(callLocalAudioPort); - local_sdp_->setLocalPublishedAudioPort(callLocalAudioPort); + sdp_->setLocalPublishedAudioPort(callLocalAudioPort); } setLocalIp(localIP); @@ -166,7 +166,7 @@ SIPCall::setCallMediaLocal(const pj_sockaddr& localIP) assert(getLocalAudioPort() != callLocalVideoPort); setLocalVideoPort(callLocalVideoPort); - local_sdp_->setLocalPublishedVideoPort(callLocalVideoPort); + sdp_->setLocalPublishedVideoPort(callLocalVideoPort); } #endif } @@ -193,7 +193,7 @@ SIPCall::createHistoryEntry() const int SIPCall::SIPSessionReinvite() { - pjmedia_sdp_session *local_sdp = local_sdp_->getLocalSdpSession(); + pjmedia_sdp_session *local_sdp = sdp_->getLocalSdpSession(); pjsip_tx_data *tdata; if (local_sdp and inv and inv->pool_prov @@ -253,8 +253,8 @@ SIPCall::updateSDPFromSTUN() account.setPublishedAddress(stunPorts[0]); // published IP MUST be updated first, since RTCP depends on it - local_sdp_->setPublishedIP(account.getPublishedAddress()); - local_sdp_->updatePorts(stunPorts); + sdp_->setPublishedIP(account.getPublishedAddress()); + sdp_->updatePorts(stunPorts); } catch (const std::runtime_error &e) { SFL_ERR("%s", e.what()); } @@ -284,7 +284,7 @@ void SIPCall::answer() throw std::runtime_error("Should only be called for initial answer"); // answer with SDP if no SDP was given in initial invite (i.e. inv->neg is NULL) - if (pjsip_inv_answer(inv.get(), PJSIP_SC_OK, NULL, !inv->neg ? local_sdp_->getLocalSdpSession() : NULL, &tdata) != PJ_SUCCESS) + if (pjsip_inv_answer(inv.get(), PJSIP_SC_OK, NULL, !inv->neg ? sdp_->getLocalSdpSession() : NULL, &tdata) != PJ_SUCCESS) throw std::runtime_error("Could not init invite request answer (200 OK)"); // contactStr must stay in scope as long as tdata @@ -559,14 +559,14 @@ SIPCall::onhold() videortp_.stop(); #endif - local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv"); - local_sdp_->removeAttributeFromLocalAudioMedia("sendonly"); - local_sdp_->addAttributeToLocalAudioMedia("sendonly"); + sdp_->removeAttributeFromLocalAudioMedia("sendrecv"); + sdp_->removeAttributeFromLocalAudioMedia("sendonly"); + sdp_->addAttributeToLocalAudioMedia("sendonly"); #ifdef SFL_VIDEO - local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv"); - local_sdp_->removeAttributeFromLocalVideoMedia("inactive"); - local_sdp_->addAttributeToLocalVideoMedia("inactive"); + sdp_->removeAttributeFromLocalVideoMedia("sendrecv"); + sdp_->removeAttributeFromLocalVideoMedia("inactive"); + sdp_->addAttributeToLocalVideoMedia("inactive"); #endif if (SIPSessionReinvite() != PJ_SUCCESS) @@ -602,7 +602,7 @@ SIPCall::internalOffHold(const std::function<void()> &SDPUpdateFunc) if (not setState(Call::ACTIVE)) return; - std::vector<sfl::AudioCodec*> sessionMedia(local_sdp_->getSessionAudioMedia()); + std::vector<sfl::AudioCodec*> sessionMedia(sdp_->getSessionAudioMedia()); if (sessionMedia.empty()) { SFL_WARN("Session media is empty"); @@ -641,15 +641,15 @@ SIPCall::internalOffHold(const std::function<void()> &SDPUpdateFunc) audiortp_.initLocalCryptoInfoOnOffHold(); audiortp_.start(audioCodecs); - local_sdp_->removeAttributeFromLocalAudioMedia("sendrecv"); - local_sdp_->removeAttributeFromLocalAudioMedia("sendonly"); - local_sdp_->addAttributeToLocalAudioMedia("sendrecv"); + sdp_->removeAttributeFromLocalAudioMedia("sendrecv"); + sdp_->removeAttributeFromLocalAudioMedia("sendonly"); + sdp_->addAttributeToLocalAudioMedia("sendrecv"); #ifdef SFL_VIDEO - local_sdp_->removeAttributeFromLocalVideoMedia("sendrecv"); - local_sdp_->removeAttributeFromLocalVideoMedia("sendonly"); - local_sdp_->removeAttributeFromLocalVideoMedia("inactive"); - local_sdp_->addAttributeToLocalVideoMedia("sendrecv"); + sdp_->removeAttributeFromLocalVideoMedia("sendrecv"); + sdp_->removeAttributeFromLocalVideoMedia("sendonly"); + sdp_->removeAttributeFromLocalVideoMedia("inactive"); + sdp_->addAttributeToLocalVideoMedia("sendrecv"); #endif if (SIPSessionReinvite() != PJ_SUCCESS) { diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h index 4d9332eefa9e0810dc2d560990c666d7b6e31863..eb141666a1b85f6399cac3f072028010e6055afa 100644 --- a/daemon/src/sip/sipcall.h +++ b/daemon/src/sip/sipcall.h @@ -84,10 +84,10 @@ class SIPCall : public Call ~SIPCall(); /** - * Return the local SDP session + * Return the SDP's manager of this call */ - Sdp& getLocalSDP() { - return *local_sdp_; + Sdp& getSDP() { + return *sdp_; } /** @@ -223,7 +223,7 @@ class SIPCall : public Call /** * The SDP session */ - std::unique_ptr<Sdp> local_sdp_; + std::unique_ptr<Sdp> sdp_; char contactBuffer_[PJSIP_MAX_URL_SIZE] {}; pj_str_t contactHeader_ {contactBuffer_, 0}; diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 50b1c5c22c797138e3465fbc7b8059e243883a2e..9ee2577960892614c3e53e61ed81359a2620e685 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -76,7 +76,6 @@ #include <pjsip/sip_endpoint.h> #include <pjsip/sip_uri.h> -#include <pjnath.h> #include <pjsip-simple/presence.h> #include <pjsip-simple/publish.h> @@ -323,7 +322,7 @@ transaction_request_cb(pjsip_rx_data *rdata) call->setDisplayName(displayName); call->initRecFilename(peerNumber); call->setCallMediaLocal(addrToUse); - call->getLocalSDP().setPublishedIP(addrSdp); + call->getSDP().setPublishedIP(addrSdp); call->getAudioRtp().initConfig(); call->setTransport(transport); @@ -369,7 +368,7 @@ transaction_request_cb(pjsip_rx_data *rdata) } } - call->getLocalSDP().receiveOffer(r_sdp, account->getActiveAudioCodecs(), account->getActiveVideoCodecs()); + call->getSDP().receiveOffer(r_sdp, account->getActiveAudioCodecs(), account->getActiveVideoCodecs()); sfl::AudioCodec* ac = Manager::instance().audioCodecFactory.instantiateCodec(PAYLOAD_CODEC_ULAW); @@ -397,7 +396,7 @@ transaction_request_cb(pjsip_rx_data *rdata) } pjsip_inv_session* inv = nullptr; - pjsip_inv_create_uas(dialog, rdata, call->getLocalSDP().getLocalSdpSession(), 0, &inv); + pjsip_inv_create_uas(dialog, rdata, call->getSDP().getLocalSdpSession(), 0, &inv); if (!inv) { SFL_ERR("Call invite is not initialized"); @@ -891,7 +890,7 @@ sdp_request_offer_cb(pjsip_inv_session *inv, const pjmedia_sdp_session *offer) return; const auto& account = call->getSIPAccount(); - auto& localSDP = call->getLocalSDP(); + auto& localSDP = call->getSDP(); localSDP.receiveOffer(offer, account.getActiveAudioCodecs(), account.getActiveVideoCodecs()); localSDP.startNegotiation(); @@ -919,7 +918,7 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) call->setCallMediaLocal(address); - auto& localSDP = call->getLocalSDP(); + auto& localSDP = call->getSDP(); localSDP.setPublishedIP(address); const bool created = localSDP.createOffer(account.getActiveAudioCodecs(), account.getActiveVideoCodecs()); @@ -927,6 +926,57 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer) *p_offer = localSDP.getLocalSdpSession(); } +static void +dump_sdp_session(const pjmedia_sdp_session* sdp_session, const char* header) +{ + char buffer[4096] {}; + + if (pjmedia_sdp_print(sdp_session, buffer, sizeof buffer) == -1) { + SFL_ERR("%sSDP too big for dump", header); + return; + } + + SFL_DBG("%s%s", header, buffer); +} + +static const pjmedia_sdp_session* +get_active_remote_sdp(pjsip_inv_session *inv) +{ + const pjmedia_sdp_session* sdp_session {}; + + if (pjmedia_sdp_neg_get_active_remote(inv->neg, &sdp_session) != PJ_SUCCESS) { + SFL_ERR("Active remote not present"); + return nullptr; + } + + if (pjmedia_sdp_validate(sdp_session) != PJ_SUCCESS) { + SFL_ERR("Invalid remote SDP session"); + return nullptr; + } + + dump_sdp_session(sdp_session, "Remote active SDP Session:\n"); + return sdp_session; +} + +static const pjmedia_sdp_session* +get_active_local_sdp(pjsip_inv_session *inv) +{ + const pjmedia_sdp_session* sdp_session {}; + + if (pjmedia_sdp_neg_get_active_local(inv->neg, &sdp_session) != PJ_SUCCESS) { + SFL_ERR("Active local not present"); + return nullptr; + } + + if (pjmedia_sdp_validate(sdp_session) != PJ_SUCCESS) { + SFL_ERR("Invalid local SDP session"); + return nullptr; + } + + dump_sdp_session(sdp_session, "Local active SDP Session:\n"); + return sdp_session; +} + // This callback is called after SDP offer/answer session has completed. static void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) @@ -957,76 +1007,39 @@ sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) return; } - // Retreive SDP session for this call - auto& sdpSession = call->getLocalSDP(); - - // Get active session sessions - const pjmedia_sdp_session *remoteSDP = 0; - - if (pjmedia_sdp_neg_get_active_remote(inv->neg, &remoteSDP) != PJ_SUCCESS) { - SFL_ERR("Active remote not present"); - return; - } - - if (pjmedia_sdp_validate(remoteSDP) != PJ_SUCCESS) { - SFL_ERR("Invalid remote SDP session"); - return; - } - - const pjmedia_sdp_session *local_sdp; - pjmedia_sdp_neg_get_active_local(inv->neg, &local_sdp); - - if (pjmedia_sdp_validate(local_sdp) != PJ_SUCCESS) { - SFL_ERR("Invalid local SDP session"); - return; - } - - // Print SDP session - char buffer[4096]; - memset(buffer, 0, sizeof buffer); - - if (pjmedia_sdp_print(remoteSDP, buffer, sizeof buffer) == -1) { - SFL_ERR("SDP was too big for buffer"); - return; - } - - SFL_DBG("Remote active SDP Session:\n%s", buffer); + const auto localSDP = get_active_local_sdp(inv); + const auto remoteSDP = get_active_remote_sdp(inv); - memset(buffer, 0, sizeof buffer); - - if (pjmedia_sdp_print(local_sdp, buffer, sizeof buffer) == -1) { - SFL_ERR("SDP was too big for buffer"); - return; - } - - SFL_DBG("Local active SDP Session:\n%s", buffer); + // Update our sdp manager + auto& sdp = call->getSDP(); // Set active SDP sessions - sdpSession.setActiveLocalSdpSession(local_sdp); - sdpSession.setActiveRemoteSdpSession(remoteSDP); + sdp.setActiveLocalSdpSession(localSDP); + sdp.setActiveRemoteSdpSession(remoteSDP); - // Update internal field for - sdpSession.setMediaTransportInfoFromRemoteSdp(); + // Update connection information + sdp.setMediaTransportInfoFromRemoteSdp(); + auto& audioRTP = call->getAudioRtp(); try { - call->getAudioRtp().updateDestinationIpAddress(); + audioRTP.updateDestinationIpAddress(); } catch (const AudioRtpFactoryException &e) { SFL_ERR("%s", e.what()); } - call->getAudioRtp().setDtmfPayloadType(sdpSession.getTelephoneEventType()); + audioRTP.setDtmfPayloadType(sdp.getTelephoneEventType()); + #ifdef SFL_VIDEO - call->getVideoRtp().updateSDP(sdpSession); - call->getVideoRtp().updateDestination(call->getLocalSDP().getRemoteIP(), sdpSession.getRemoteVideoPort()); - auto localPort = sdpSession.getLocalVideoPort(); - if (!localPort) - localPort = sdpSession.getRemoteVideoPort(); - call->getVideoRtp().start(localPort); + auto& videoRTP = call->getVideoRtp(); + videoRTP.updateSDP(sdp); + videoRTP.updateDestination(sdp.getRemoteIP(), sdp.getRemoteVideoPort()); + const auto localVideoPort = sdp.getLocalVideoPort(); + videoRTP.start(localVideoPort ? localVideoPort : sdp.getRemoteVideoPort()); #endif // Get the crypto attribute containing srtp's cryptographic context (keys, cipher) CryptoOffer crypto_offer; - call->getLocalSDP().getRemoteSdpCryptoFromOffer(remoteSDP, crypto_offer); + call->getSDP().getRemoteSdpCryptoFromOffer(remoteSDP, crypto_offer); #if HAVE_SDES bool nego_success = false; @@ -1043,7 +1056,7 @@ sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) nego_success = true; try { - call->getAudioRtp().setRemoteCryptoInfo(sdesnego); + audioRTP.setRemoteCryptoInfo(sdesnego); Manager::instance().getClient()->getCallManager()->secureSdesOn(call->getCallId()); } catch (const AudioRtpFactoryException &e) { SFL_ERR("%s", e.what()); @@ -1058,23 +1071,22 @@ sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) } // We did not find any crypto context for this media, RTP fallback - if (!nego_success && call->getAudioRtp().isSdesEnabled()) { + if (!nego_success && audioRTP.isSdesEnabled()) { SFL_ERR("Negotiation failed but SRTP is enabled, fallback on RTP"); - call->getAudioRtp().stop(); - call->getAudioRtp().setSrtpEnabled(false); + audioRTP.stop(); + audioRTP.setSrtpEnabled(false); const auto& account = call->getSIPAccount(); if (account.getSrtpFallback()) { - call->getAudioRtp().initSession(); + audioRTP.initSession(); if (account.isStunEnabled()) call->updateSDPFromSTUN(); } } - #endif // HAVE_SDES - std::vector<sfl::AudioCodec*> sessionMedia(sdpSession.getSessionAudioMedia()); + std::vector<sfl::AudioCodec*> sessionMedia(sdp.getSessionAudioMedia()); if (sessionMedia.empty()) { SFL_WARN("Session media is empty");