From cd4d4488e410537f7367f557df8d8a2814ba05e5 Mon Sep 17 00:00:00 2001 From: Tristan Matthews Date: Tue, 11 Jun 2013 15:56:23 -0400 Subject: [PATCH] * #25295: audiortp: get ports from STUN --- .../src/audio/audiortp/audio_rtp_factory.cpp | 2 +- daemon/src/audio/audiortp/audio_rtp_factory.h | 2 +- daemon/src/audio/audiortp/audio_rtp_session.h | 2 +- .../audiortp/audio_symmetric_rtp_session.cpp | 7 ++- .../audiortp/audio_symmetric_rtp_session.h | 2 +- .../src/audio/audiortp/audio_zrtp_session.cpp | 7 ++- .../src/audio/audiortp/audio_zrtp_session.h | 2 +- daemon/src/sip/sdp.cpp | 21 ++++++--- daemon/src/sip/sdp.h | 16 ++++--- daemon/src/sip/siptransport.cpp | 21 +++++++++ daemon/src/sip/siptransport.h | 7 +++ daemon/src/sip/sipvoiplink.cpp | 44 ++++++++++++++++--- 12 files changed, 106 insertions(+), 27 deletions(-) diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.cpp b/daemon/src/audio/audiortp/audio_rtp_factory.cpp index 297232a96..074837880 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.cpp +++ b/daemon/src/audio/audiortp/audio_rtp_factory.cpp @@ -126,7 +126,7 @@ void AudioRtpFactory::initSession() rtpSession_ = new AudioSymmetricRtpSession(*ca_); } -std::pair +std::vector AudioRtpFactory::getSocketDescriptors() const { return rtpSession_->getSocketDescriptors(); diff --git a/daemon/src/audio/audiortp/audio_rtp_factory.h b/daemon/src/audio/audiortp/audio_rtp_factory.h index 08334d91a..8a9ca8221 100644 --- a/daemon/src/audio/audiortp/audio_rtp_factory.h +++ b/daemon/src/audio/audiortp/audio_rtp_factory.h @@ -66,7 +66,7 @@ class AudioRtpFactory { AudioRtpFactory(SIPCall *ca); ~AudioRtpFactory(); - std::pair + std::vector getSocketDescriptors() const; void initConfig(); diff --git a/daemon/src/audio/audiortp/audio_rtp_session.h b/daemon/src/audio/audiortp/audio_rtp_session.h index e8d6c762a..b3f772e99 100644 --- a/daemon/src/audio/audiortp/audio_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_rtp_session.h @@ -73,7 +73,7 @@ class AudioRtpSession : public AudioRtpRecordHandler { virtual std::vector getLocalMasterSalt() const = 0; - virtual std::pair + virtual std::vector getSocketDescriptors() const = 0; private: diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp index 23e0c80bb..31850866d 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.cpp @@ -47,10 +47,13 @@ AudioSymmetricRtpSession::AudioSymmetricRtpSession(SIPCall &call) : audioRtpRecord_.callId_ = call_.getCallId(); } -std::pair +std::vector AudioSymmetricRtpSession::getSocketDescriptors() const { - return std::pair(dso->getRecvSocket(), cso->getRecvSocket()); + std::vector result; + result.push_back(dso->getRecvSocket()); + result.push_back(cso->getRecvSocket()); + return result; } void AudioSymmetricRtpSession::startReceiveThread() diff --git a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h index e1f28f930..acd893c23 100644 --- a/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h +++ b/daemon/src/audio/audiortp/audio_symmetric_rtp_session.h @@ -61,7 +61,7 @@ class AudioSymmetricRtpSession : public ost::SymmetricRTPSession, public AudioRt */ AudioSymmetricRtpSession(SIPCall &call); - std::pair + std::vector getSocketDescriptors() const; virtual bool onRTPPacketRecv(ost::IncomingRTPPkt& pkt) { diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.cpp b/daemon/src/audio/audiortp/audio_zrtp_session.cpp index 70862df60..69535a42f 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.cpp +++ b/daemon/src/audio/audiortp/audio_zrtp_session.cpp @@ -57,10 +57,13 @@ AudioZrtpSession::AudioZrtpSession(SIPCall &call, const std::string &zidFilename audioRtpRecord_.callId_ = call_.getCallId(); } -std::pair +std::vector AudioZrtpSession::getSocketDescriptors() const { - return std::pair(dso->getRecvSocket(), cso->getRecvSocket()); + std::vector result; + result.push_back(dso->getRecvSocket()); + result.push_back(cso->getRecvSocket()); + return result; } void AudioZrtpSession::initializeZid() diff --git a/daemon/src/audio/audiortp/audio_zrtp_session.h b/daemon/src/audio/audiortp/audio_zrtp_session.h index 1df1425e8..bb9d60101 100644 --- a/daemon/src/audio/audiortp/audio_zrtp_session.h +++ b/daemon/src/audio/audiortp/audio_zrtp_session.h @@ -60,7 +60,7 @@ class AudioZrtpSession : public: AudioZrtpSession(SIPCall &call, const std::string& zidFilename); - std::pair + std::vector getSocketDescriptors() const; virtual bool onRTPPacketRecv(ost::IncomingRTPPkt &pkt) { diff --git a/daemon/src/sip/sdp.cpp b/daemon/src/sip/sdp.cpp index 2d1ac6dee..a23ce46a2 100644 --- a/daemon/src/sip/sdp.cpp +++ b/daemon/src/sip/sdp.cpp @@ -62,8 +62,10 @@ Sdp::Sdp(pj_pool_t *pool) , sessionVideoMedia_() , localIpAddr_() , remoteIpAddr_() - , localAudioPort_(0) - , localVideoPort_(0) + , localAudioDataPort_(0) + , localAudioControlPort_(0) + , localVideoDataPort_(0) + , localVideoControlPort_(0) , remoteAudioPort_(0) , remoteVideoPort_(0) , zrtpHelloHash_() @@ -205,7 +207,7 @@ Sdp::setMediaDescriptorLines(bool audio) med->desc.media = audio ? pj_str((char*) "audio") : pj_str((char*) "video"); med->desc.port_count = 1; - med->desc.port = audio ? localAudioPort_ : localVideoPort_; + med->desc.port = audio ? localAudioDataPort_ : localVideoDataPort_; // in case of sdes, media are tagged as "RTP/SAVP", RTP/AVP elsewhere med->desc.transport = pj_str(srtpCrypto_.empty() ? (char*) "RTP/AVP" : (char*) "RTP/SAVP"); @@ -283,10 +285,8 @@ Sdp::setMediaDescriptorLines(bool audio) void Sdp::addRTCPAttribute(pjmedia_sdp_media *med) { - // FIXME: get this from CCRTP directly, don't just assume that the RTCP port is - // RTP + 1 std::ostringstream os; - os << localIpAddr_ << ":" << (localAudioPort_ + 1); + os << localIpAddr_ << ":" << localAudioControlPort_; const std::string str(os.str()); pj_str_t input_str = pj_str((char*) str.c_str()); pj_sockaddr outputAddr; @@ -300,6 +300,15 @@ void Sdp::addRTCPAttribute(pjmedia_sdp_media *med) pjmedia_sdp_attr_add(&med->attr_count, med->attr, attr); } +void +Sdp::updatePorts(const std::vector &sockets) +{ + localAudioDataPort_ = pj_ntohs(sockets[0].sin_port); + localAudioControlPort_ = pj_ntohs(sockets[1].sin_port); + localVideoDataPort_ = pj_ntohs(sockets[2].sin_port); + localVideoControlPort_ = pj_ntohs(sockets[3].sin_port); +} + void Sdp::setTelephoneEventRtpmap(pjmedia_sdp_media *med) { diff --git a/daemon/src/sip/sdp.h b/daemon/src/sip/sdp.h index c4e72551e..1ac680aeb 100644 --- a/daemon/src/sip/sdp.h +++ b/daemon/src/sip/sdp.h @@ -163,13 +163,17 @@ class Sdp { } void setLocalPublishedAudioPort(int port) { - localAudioPort_ = port; + localAudioDataPort_ = port; + localAudioControlPort_ = port + 1; } void setLocalPublishedVideoPort (int port) { - localVideoPort_ = port; + localVideoDataPort_ = port; + localVideoControlPort_ = port + 1; } + void updatePorts(const std::vector &sockets); + /** * Return IP of destination * @return const std:string The remote IP address @@ -203,7 +207,7 @@ class Sdp { } unsigned int getLocalVideoPort() const { - return localVideoPort_; + return localVideoDataPort_; } void addAttributeToLocalAudioMedia(const char *attr); @@ -308,8 +312,10 @@ class Sdp { std::string localIpAddr_; std::string remoteIpAddr_; - int localAudioPort_; - int localVideoPort_; + int localAudioDataPort_; + int localAudioControlPort_; + int localVideoDataPort_; + int localVideoControlPort_; unsigned int remoteAudioPort_; unsigned int remoteVideoPort_; diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp index 3ad5edba5..5e2729781 100644 --- a/daemon/src/sip/siptransport.cpp +++ b/daemon/src/sip/siptransport.cpp @@ -461,6 +461,27 @@ pjsip_tpselector *SipTransport::createTransportSelector(pjsip_transport *transpo return tp; } +std::vector +SipTransport::getSTUNAddresses(const SIPAccount &account, + std::vector &socketDescriptors) const +{ + const pj_str_t serverName = account.getStunServerName(); + const pj_uint16_t port = account.getStunPort(); + + std::vector result(socketDescriptors.size()); + + if (pjstun_get_mapped_addr(&cp_->factory, socketDescriptors.size(), &socketDescriptors[0], + &serverName, port, &serverName, port, &result[0]) != PJ_SUCCESS) + throw std::runtime_error("Can't contact STUN server"); + + for (std::vector::const_iterator it = result.begin(); + it != result.end(); ++it) + WARN("STUN PORTS: %ld", pj_ntohs(it->sin_port)); + + return result; +} + + pjsip_transport *SipTransport::createStunTransport(SIPAccount &account) { #define RETURN_IF_STUN_FAIL(A, M, ...) \ diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h index 98fdafeba..5146f8bf2 100644 --- a/daemon/src/sip/siptransport.h +++ b/daemon/src/sip/siptransport.h @@ -112,6 +112,13 @@ class SipTransport { */ void shutdownSTUNResolver(SIPAccount &account); + /** + * This function returns a list of STUN mapped sockets for + * a given set of socket file descriptors */ + std::vector + getSTUNAddresses(const SIPAccount &account, + std::vector &socks) const; + /** * This function unset the transport for a given account. */ diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 722fd46e7..b40461951 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -189,6 +189,23 @@ pj_bool_t transaction_response_cb(pjsip_rx_data *rdata) return PJ_FALSE; } +void updateSDPFromSTUN(SIPCall &call, const SIPAccount &account, const SipTransport &transport) +{ + std::vector socketDescriptors(call.getAudioRtp().getSocketDescriptors()); + + try { + std::vector stunPorts(transport.getSTUNAddresses(account, socketDescriptors)); + + // FIXME: get video sockets + stunPorts.resize(4); + + call.getLocalSDP()->updatePorts(stunPorts); + } catch (const std::runtime_error &e) { + ERROR("%s", e.what()); + } +} + + pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) { if (!rdata or !rdata->msg_info.msg) { @@ -310,6 +327,9 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata) return PJ_FALSE; } + if (account->isStunEnabled()) + updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport); + if (body and body->len > 0 and call->getAudioRtp().isSdesEnabled()) { std::string sdpOffer(static_cast(body->data), body->len); size_t start = sdpOffer.find("a=crypto:"); @@ -900,6 +920,10 @@ Call *SIPVoIPLink::newRegisteredAccountCall(const std::string& id, const std::st try { call->getAudioRtp().initConfig(); call->getAudioRtp().initSession(); + + if (account->isStunEnabled()) + updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport); + call->getAudioRtp().initLocalCryptoInfo(); call->getAudioRtp().start(audioCodecs); } catch (...) { @@ -1100,6 +1124,13 @@ SIPVoIPLink::offhold(const std::string& id) call->getAudioRtp().initConfig(); call->getAudioRtp().initSession(); + + const std::string account_id(call->getAccountId()); + SIPAccount *account = Manager::instance().getSipAccount(account_id); + + if (account and account->isStunEnabled()) + updateSDPFromSTUN(*call, *account, SIPVoIPLink::instance()->sipTransport); + call->getAudioRtp().restoreLocalContext(); call->getAudioRtp().initLocalCryptoInfoOnOffHold(); call->getAudioRtp().start(audioCodecs); @@ -1830,8 +1861,12 @@ void sdp_media_update_cb(pjsip_inv_session *inv, pj_status_t status) const std::string accountID = call->getAccountId(); SIPAccount *sipaccount = Manager::instance().getSipAccount(accountID); - if (sipaccount and sipaccount->getSrtpFallback()) + if (sipaccount and sipaccount->getSrtpFallback()) { call->getAudioRtp().initSession(); + + if (sipaccount->isStunEnabled()) + updateSDPFromSTUN(*call, *sipaccount, SIPVoIPLink::instance()->sipTransport); + } } #endif // HAVE_SDES @@ -2255,13 +2290,8 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP) // We only want to set ports to new values if they haven't been set if (call->getLocalAudioPort() == 0) { const unsigned callLocalAudioPort = getRandomEvenNumber(10500, 64998); - - const unsigned int callLocalExternAudioPort = account->isStunEnabled() - ? account->getStunPort() - : callLocalAudioPort; - call->setLocalAudioPort(callLocalAudioPort); - call->getLocalSDP()->setLocalPublishedAudioPort(callLocalExternAudioPort); + call->getLocalSDP()->setLocalPublishedAudioPort(callLocalAudioPort); } call->setLocalIp(localIP);