10#include <sdp/SdpCodec.h>
45#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON
85 RemoteParticipant(partHandle, conversationManager, dum, remoteParticipantDialogSet),
88 InfoLog(<<
"SipXRemoteParticipant created (UAC), handle=" <<
mHandle);
100 InfoLog(<<
"SipXRemoteParticipant created (UAS or forked leg), handle=" <<
mHandle);
112 InfoLog(<<
"SipXRemoteParticipant destroyed, handle=" <<
mHandle);
163 std::unique_ptr<SdpContents> _offer(
new SdpContents);
184 for (std::list<SdpContents::Session::Medium>::iterator mediaIt = offer.
session().
media().begin();
187 if(mediaIt->name() ==
"audio" &&
190#ifdef RTP_SAVPF_FUDGE
195 audioMedium = &(*mediaIt);
204 int highPayloadId = 96;
206 for (std::list<SdpContents::Session::Codec>::iterator codecsIt = sessionCaps.
session().
media().front().codecs().begin();
207 codecsIt != sessionCaps.
session().
media().front().codecs().end(); codecsIt++)
210 bool payloadIdCollision=
false;
211 for (std::list<SdpContents::Session::Codec>::iterator codecsIt2 = audioMedium->
codecs().begin();
212 codecsIt2 != audioMedium->
codecs().end(); codecsIt2++)
214 if(
isEqualNoCase(codecsIt->getName(), codecsIt2->getName()) &&
215 codecsIt->getRate() == codecsIt2->getRate())
219 else if(codecsIt->payloadType() == codecsIt2->payloadType())
221 payloadIdCollision =
true;
224 if(codecsIt2->payloadType() > highPayloadId)
226 highPayloadId = codecsIt2->payloadType();
231 if(payloadIdCollision)
234 codecsIt->payloadType() = highPayloadId;
236 else if(codecsIt->payloadType() > highPayloadId)
238 highPayloadId = codecsIt->payloadType();
261 audioMedium->
port() = 0;
302#ifdef RTP_SAVPF_FUDGE
303 if(mDialogSet.peerExpectsSAVPF())
328 char fingerprint[100];
344 audioMedium->
addAttribute(
"tcap",
"1 UDP/TLS/RTP/SAVP");
380 sdpReady(
true, std::move(_offer));
393#ifdef RTP_SAVPF_FUDGE
401#ifndef RTP_SAVPF_FUDGE
419#ifdef RTP_SAVPF_FUDGE
424 bool supportedCryptoSuite =
false;
425 sdpcontainer::SdpMediaLine::CryptoList::const_iterator itCrypto = sdpMediaLine.
getCryptos().begin();
426 for (; !supportedCryptoSuite && itCrypto != sdpMediaLine.
getCryptos().end(); itCrypto++)
428 Data cryptoKeyB64(itCrypto->getCryptoKeyParams().front().getKeyValue());
431 if (cryptoKey.
size() == SRTP_MASTER_KEY_LEN)
433 switch (itCrypto->getSuite())
437 supportedCryptoSuite =
true;
441 supportedCryptoSuite =
true;
449 InfoLog(<<
"SDES crypto key found in SDP, but is not of correct length after base 64 decode: " << cryptoKey.
size());
452 if (!supportedCryptoSuite && secureMediaRequired)
454 InfoLog(<<
"Secure media stream is required, but there is no supported crypto attributes in the offer - skipping this stream...");
463 bool supportedFingerprint =
false;
472 char fingerprint[100];
487 supportedFingerprint =
true;
489 if (!supportedFingerprint && secureMediaRequired)
491 InfoLog(<<
"Secure media stream is required, but there is no supported fingerprint attributes in the offer - skipping this stream...");
504 sdpcontainer::SdpMediaLine::CodecList::const_iterator itCodec = sdpMediaLine.
getCodecs().begin();
505 for(; itCodec != sdpMediaLine.
getCodecs().end(); itCodec++)
507 unsigned int itCodecRate = itCodec->getRate();
508 if(itCodec->getMimeSubtype() ==
"G722" && itCodecRate != 8000)
510 WarningLog(<<
"Peer is advertising G.722 with rate " << itCodecRate <<
", overriding to 8000 (see RFC 3551 s4.5.2)");
513 std::list<SdpContents::Session::Codec>::iterator bestCapsCodecMatchIt = mediaSessionCaps.
codecs().end();
514 bool modeInOffer = itCodec->getFormatParameters().prefix(
"mode=");
517 for (std::list<SdpContents::Session::Codec>::iterator capsCodecsIt = mediaSessionCaps.
codecs().begin();
518 capsCodecsIt != mediaSessionCaps.
codecs().end(); capsCodecsIt++)
520 if(
isEqualNoCase(capsCodecsIt->getName(), itCodec->getMimeSubtype()) &&
521 (
unsigned int)capsCodecsIt->getRate() == itCodecRate)
523 bool modeInCaps = capsCodecsIt->parameters().prefix(
"mode=");
524 if(!modeInOffer && !modeInCaps)
527 bestCapsCodecMatchIt = capsCodecsIt;
530 else if(modeInOffer && modeInCaps)
532 if(
isEqualNoCase(capsCodecsIt->parameters(), itCodec->getFormatParameters()))
534 bestCapsCodecMatchIt = capsCodecsIt;
543 if(bestCapsCodecMatchIt == mediaSessionCaps.
codecs().end())
545 bestCapsCodecMatchIt = capsCodecsIt;
551 if(bestCapsCodecMatchIt != mediaSessionCaps.
codecs().end())
554 codec.payloadType() = itCodec->getPayloadType();
556 if(!valid && !
isEqualNoCase(bestCapsCodecMatchIt->getName(),
"telephone-event"))
567 if(mediaSessionCaps.
exists(
"ptime"))
573 unsigned int remoteRtpPort = sdpMediaLine.
getConnections().front().getPort();
599SipXRemoteParticipant::buildSdpAnswer(
const SdpContents& offer, CallbackSdpReady sdpReady)
606 std::unique_ptr<SdpContents> _answer(
new SdpContents);
641 sdpcontainer::Sdp::MediaLineList::const_iterator itMediaLine = remoteSdp->getMediaLines().begin();
642 for(; itMediaLine != remoteSdp->getMediaLines().end(); itMediaLine++)
644 bool mediaLineValid =
false;
650 (*itMediaLine)->getTransportProtocolTypeString());
651 if((*itMediaLine)->getCodecs().size() > 0)
654 (*itMediaLine)->getCodecs().front().getRate(),
655 (*itMediaLine)->getCodecs().front().getFormatParameters()));
656 rejmedium.codecs().front().payloadType() = (*itMediaLine)->getCodecs().front().getPayloadType();
663 sdpcontainer::SdpMediaLine::SdpMediaLineList::const_iterator itPotentialMediaLine = (*itMediaLine)->getPotentialMediaViews().begin();
664 for(; itPotentialMediaLine != (*itMediaLine)->getPotentialMediaViews().end(); itPotentialMediaLine++)
666 mediaLineValid = answerMediaLine(mediaSessionCaps, *itPotentialMediaLine, answer,
true);
679 stolen.swap((*itMediaLine)->getPotentialMediaViews());
680 *(*itMediaLine) = *itPotentialMediaLine;
688 mediaLineValid = answerMediaLine(mediaSessionCaps, *(*itMediaLine), answer,
false);
692 (*itMediaLine)->getTransportProtocolTypeString());
693 if((*itMediaLine)->getCodecs().size() > 0)
696 (*itMediaLine)->getCodecs().front().getRate(),
697 (*itMediaLine)->getCodecs().front().getFormatParameters()));
698 rejmedium.codecs().front().payloadType() = (*itMediaLine)->getCodecs().front().getPayloadType();
716 WarningLog( <<
"buildSdpAnswer: unknown exception parsing SDP offer");
727 sdpReady(valid, std::move(_answer));
757 for (std::list<SdpContents::Session::Medium>::const_iterator localMediaIt = localSdp.
session().
media().begin();
758 localMediaIt != localSdp.
session().
media().end(); localMediaIt++)
760 for (std::list<SdpContents::Session::Medium>::const_iterator remoteMediaIt = remoteSdp.
session().
media().begin();
761 remoteMediaIt != remoteSdp.
session().
media().end(); remoteMediaIt++)
763 if(localMediaIt->name() == remoteMediaIt->name() && localMediaIt->protocol() == remoteMediaIt->protocol())
769 for (std::list<SdpContents::Session::Codec>::const_iterator localCodecsIt = localMediaIt->codecs().begin();
770 localCodecsIt != localMediaIt->codecs().end(); localCodecsIt++)
773 for (std::list<SdpContents::Session::Codec>::const_iterator remoteCodecsIt = remoteMediaIt->codecs().begin();
774 remoteCodecsIt != remoteMediaIt->codecs().end(); remoteCodecsIt++)
776 if(
isEqualNoCase(localCodecsIt->getName(), remoteCodecsIt->getName()) &&
777 localCodecsIt->getRate() == remoteCodecsIt->getRate())
781 if(!valid && !
isEqualNoCase(localCodecsIt->getName(),
"telephone-event"))
792 if(localMediaIt->exists(
"ptime"))
794 medium.
addAttribute(
"ptime", localMediaIt->getValues(
"ptime").front());
801 if(remoteMediaIt->exists(
"inactive") ||
802 remoteMediaIt->exists(
"sendonly") ||
803 remoteMediaIt->port() == 0)
814 if(remoteMediaIt->exists(
"inactive") || remoteMediaIt->exists(
"sendonly") || remoteMediaIt->port() == 0 )
827 if(remoteMediaIt->exists(
"inactive") ||
828 (
isHolding() && (remoteMediaIt->exists(
"sendonly") || remoteMediaIt->port() == 0)))
832 else if(remoteMediaIt->exists(
"sendonly") || remoteMediaIt->port() == 0 )
836 else if(remoteMediaIt->exists(
"recvonly") ||
isHolding())
860 WarningLog( <<
"formMidDialogSdpOfferOrAnswer: unknown exception");
873 Data remoteIPAddress;
874 unsigned int remoteRtpPort=0;
875 unsigned int remoteRtcpPort=0;
880 bool supportedCryptoSuite =
false;
881 bool supportedFingerprint =
false;
882 bool localFingerprint =
false;
902 sdpcontainer::Sdp::MediaLineList::const_iterator itMediaLine = localSdp->getMediaLines().begin();
903 for(; itMediaLine != localSdp->getMediaLines().end(); itMediaLine++)
908 ", numConnections=" << (*itMediaLine)->getConnections().size() <<
909 ", port=" << ((*itMediaLine)->getConnections().size() > 0 ? (*itMediaLine)->getConnections().front().getPort() : 0));
913#ifdef RTP_SAVPF_FUDGE
917 (*itMediaLine)->getConnections().size() != 0 &&
918 (*itMediaLine)->getConnections().front().getPort() != 0)
921 localMediaDirection = (*itMediaLine)->getDirection();
922 localCodecs = &(*itMediaLine)->getCodecs();
923 localFingerprint = !(*itMediaLine)->getFingerPrint().empty();
932 sdpcontainer::Sdp::MediaLineList::const_iterator itRemMediaLine = remoteSdp->getMediaLines().begin();
933 for(; itRemMediaLine != remoteSdp->getMediaLines().end(); itRemMediaLine++)
939#ifdef RTP_SAVPF_FUDGE
943 (*itRemMediaLine)->getConnections().size() != 0 &&
944 (*itRemMediaLine)->getConnections().front().getPort() != 0)
947 remoteMediaDirection = (*itRemMediaLine)->getDirection();
948 remoteRtpPort = (*itRemMediaLine)->getConnections().front().getPort();
949 remoteRtcpPort = (*itRemMediaLine)->getRtcpConnections().front().getPort();
950 remoteIPAddress = (*itRemMediaLine)->getConnections().front().getAddress();
951 remoteCodecs = &(*itRemMediaLine)->getCodecs();
956#ifdef RTP_SAVPF_FUDGE
961 DebugLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", process crypto settings");
962 sdpcontainer::SdpMediaLine::CryptoList::const_iterator itCrypto = (*itRemMediaLine)->getCryptos().begin();
963 for(; itCrypto != (*itRemMediaLine)->getCryptos().end(); itCrypto++)
965 Data cryptoKeyB64(itCrypto->getCryptoKeyParams().front().getKeyValue());
968 if(cryptoKey.
size() == SRTP_MASTER_KEY_LEN)
970 switch(itCrypto->getSuite())
974 InfoLog(<<
"Failed creating SRTP session");
975 supportedCryptoSuite =
true;
979 InfoLog(<<
"Failed creating SRTP session");
980 supportedCryptoSuite =
true;
988 InfoLog(<<
"SDES crypto key found in SDP, but is not of correct length after base 64 decode: " << cryptoKey.
size());
990 if(supportedCryptoSuite)
992 StackLog(<<
"Supported crypto suite found");
1009 InfoLog(<<
"Fingerprint retrieved from remote SDP: " << hashFunction <<
" " << (*itRemMediaLine)->getFingerPrint());
1020 supportedFingerprint =
true;
1024 InfoLog(<<
"Fingerprint found, but its hash function is not supported: "
1044 bool broadcastOnly =
false;
1045 ConversationMap::iterator it;
1048 if(it->second->broadcastOnly())
1050 broadcastOnly =
true;
1100 InfoLog(<<
"Secure media is required and no valid support found in remote sdp - ending call.");
1107 bool activeDestinationSet =
false;
1111 activeDestinationSet =
true;
1116 activeDestinationSet && remoteCodecs && localCodecs)
1120 ::SdpCodec** codecs = new ::SdpCodec*[remoteCodecs->size()];
1121 sdpcontainer::SdpMediaLine::CodecList::const_iterator itRemoteCodec = remoteCodecs->begin();
1122 for(; itRemoteCodec != remoteCodecs->end(); itRemoteCodec++)
1125 sdpcontainer::SdpMediaLine::CodecList::const_iterator bestCapsCodecMatchIt = localCodecs->end();
1126 sdpcontainer::SdpMediaLine::CodecList::const_iterator itLocalCodec = localCodecs->begin();
1127 for(; itLocalCodec != localCodecs->end(); itLocalCodec++)
1129 if(
isEqualNoCase(itRemoteCodec->getMimeSubtype(), itLocalCodec->getMimeSubtype()) &&
1130 itRemoteCodec->getRate() == itLocalCodec->getRate())
1132 bool modeInLocal = itLocalCodec->getFormatParameters().prefix(
"mode=");
1133 if(!modeInLocal && !modeInRemote)
1136 bestCapsCodecMatchIt = itLocalCodec;
1139 else if(modeInLocal && modeInRemote)
1141 if(
isEqualNoCase(itRemoteCodec->getFormatParameters(), itLocalCodec->getFormatParameters()))
1143 bestCapsCodecMatchIt = itLocalCodec;
1152 if(bestCapsCodecMatchIt == localCodecs->end())
1154 bestCapsCodecMatchIt = itLocalCodec;
1159 if(bestCapsCodecMatchIt != localCodecs->end())
1161 codecs[numCodecs++] = new ::SdpCodec(itRemoteCodec->getPayloadType(),
1162 itRemoteCodec->getMimeType().c_str(),
1163 itRemoteCodec->getMimeSubtype().c_str(),
1164 itRemoteCodec->getRate(),
1165 itRemoteCodec->getPacketTime(),
1166 itRemoteCodec->getNumChannels(),
1167 itRemoteCodec->getFormatParameters().c_str());
1169 UtlString codecString;
1170 codecs[numCodecs-1]->
toString(codecString);
1172 DebugLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", sending codec: " << codecString.data());
1178 InfoLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", starting to send for " << numCodecs <<
" codecs to destination address " << remoteIPAddress <<
":" <<
1179 remoteRtpPort <<
" (RTCP on " << remoteRtcpPort <<
")");
1181 if(ret != OS_SUCCESS)
1183 InfoLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", failed to start RTP send, ret = " << ret);
1188 WarningLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", something went wrong during SDP negotiations, no common codec found.");
1190 for(
int i = 0; i < numCodecs; i++)
1202 InfoLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", stop sending.");
1214 ::SdpCodec** codecs = new ::SdpCodec*[localCodecs->size()];
1215 sdpcontainer::SdpMediaLine::CodecList::const_iterator itLocalCodec = localCodecs->begin();
1216 for(; itLocalCodec != localCodecs->end(); itLocalCodec++)
1218 codecs[numCodecs++] = new ::SdpCodec(itLocalCodec->getPayloadType(),
1219 itLocalCodec->getMimeType().c_str(),
1220 itLocalCodec->getMimeSubtype().c_str(),
1221 itLocalCodec->getRate(),
1222 itLocalCodec->getPacketTime(),
1223 itLocalCodec->getNumChannels(),
1224 itLocalCodec->getFormatParameters().c_str());
1225 UtlString codecString;
1226 codecs[numCodecs-1]->
toString(codecString);
1227 DebugLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", receiving: " << codecString.data());
1229 InfoLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", starting to receive for " << numCodecs <<
" codecs");
1232 for(
int i = 0; i < numCodecs; i++)
1238 DebugLog(<<
"adjustRTPStreams: handle=" <<
mHandle <<
", receiving...");
1254 WarningLog(<<
"requestKeyframe not implemented for this media stack");
#define WarningLog(args_)
#define resip_assert(x)
This file needs to work for both C and C++ code.
static Data IPV4_ZERO_ADDRESS_STRING("0.0.0.0")
static const char * supportedFingerprintHashFunction(const sdpcontainer::SdpMediaLine &mediaLine)
static sdpcontainer::Sdp * createSdpFromResipSdp(const resip::SdpContents &resipSdp)
void getMyCertFingerprint(char *fingerprint)
static bool isFingerprintHashFunctionSupported(const char *hashFunction)
dtls::DtlsFactory * getDtlsFactory()
This class is one of two main classes of concern to an application using the UserAgent library.
This class extends the resip UserProfile to include Conversation Manager specific settings.
virtual resip::SdpContents & sessionCaps()
Get/Set the session capabilities.
This is the base class for a RemoteParticipant, LocalParticipant and a MediaResourceParticipant.
ConversationMap mConversations
virtual void unregisterFromAllConversations()
ParticipantHandle mHandle
ConversationManager & mConversationManager
This class is used by Invite DialogSets.
std::shared_ptr< ConversationProfile > getConversationProfile()
bool getSecureMediaRequired()
This class represent a remote participant.
void setProposedSdp(const resip::SdpContents &sdp)
void setRemoteSdp(const resip::SdpContents &sdp, bool answer=false)
virtual bool isRemoteHold()
std::function< void(bool sdpOk, std::unique_ptr< resip::SdpContents > sdp)> CallbackSdpReady
void setLocalSdp(const resip::SdpContents &sdp)
std::shared_ptr< resip::SdpContents > getLocalSdp()
std::shared_ptr< resip::SdpContents > getRemoteSdp()
virtual void destroyParticipant() override
virtual resip::InviteSessionHandle & getInviteSessionHandle()
void setRemoteHold(bool remoteHold)
RemoteParticipantDialogSet & getDialogSet()
This is the base class for a SipXRemoteParticipant, SipXLocalParticipant and a SipXMediaResourceParti...
SipXMediaStackAdapter & mSipXMediaStackAdapter
virtual std::shared_ptr< SipXMediaInterface > getMediaInterface()
This class is used by Invite DialogSets.
resip::MediaConstants::SrtpCryptoSuite getSrtpCryptoSuite()
virtual unsigned int getLocalRTPPort()
virtual int getMediaConnectionId()
void setRemoteSDPFingerprint(const resip::Data &hashFunction, const resip::Data &fingerprint)
void setActiveDestination(const char *address, unsigned short rtpPort, unsigned short rtcpPort)
virtual void setPeerExpectsSAVPF(bool value)
virtual int getConnectionPortOnBridge()
const resip::Data & getLocalSrtpSessionKey()
bool createSRTPSession(resip::MediaConstants::SrtpCryptoSuite cryptoSuite, const char *remoteKey, size_t remoteKeyLen)
void startDtlsClient(const char *address, unsigned short rtpPort, unsigned short rtcpPort)
virtual void adjustRTPStreams(bool sendingOffer=false) override
virtual SipXRemoteParticipantDialogSet * getSipXDialogSet()
SipXRemoteParticipant(ParticipantHandle partHandle, ConversationManager &conversationManager, SipXMediaStackAdapter &sipXMediaStackAdapter, resip::DialogUsageManager &dum, RemoteParticipantDialogSet &remoteParticipantDialogSet)
virtual int getMediaConnectionId()
virtual void requestKeyframe() override
virtual unsigned int getLocalRTPPort()
virtual ~SipXRemoteParticipant()
virtual void buildSdpOffer(bool holdSdp, CallbackSdpReady sdpReady, bool preferExistingSdp=false) override
virtual int getConnectionPortOnBridge() override
virtual bool mediaStackPortAvailable() override
The abstract base-class for all exceptions thrown by resip code.
const Data & getMessage() const noexcept
An alternative to std::string, encapsulates an arbitrary buffer of bytes.
Data base64decode() const
Performs RFC 3548 Base 64 decoding of the contents of this data.
const char * c_str() const
Returns a null-terminated string representing.
Data base64encode(bool useUrlSafe=false) const
Performs RFC 3548 Base 64 encoding of the contents of this data.
bool prefix(const Data &pre) const noexcept
Returns true if this Data starts with the bytes indicated by the passed-in Data.
bool empty() const noexcept
Checks whether the Data is empty.
size_type size() const noexcept
Returns the number of bytes in this Data.
const char * data() const noexcept
Returns a pointer to the contents of this Data.
const SdpContents & getLocalSdp() const
parameters for a specific codec are stored in this class.
process m= (media announcement) blocks
void addAttribute(const Data &key, const Data &value=Data::Empty)
add a media attribute line
const std::list< Data > & getValues(const Data &key) const
get the attribute values corresponding to the key - returns the attributes set on this medium,...
bool exists(const Data &key) const
tests if an a= key is present in the media section
int port() const
return the base port
void addCodec(const Codec &codec)
add a codec to the m= line
const CodecContainer & codecs() const
preferred codec/format interface
const Data & protocol() const
return the transport protocol
const Data & name() const
return the media type
void clearAttribute(const Data &key)
erase all attributes for a given key
const uint64_t & getVersion() const
returns the session version
const uint64_t & getSessionId() const
returns the session ID
const std::list< Time > & getTimes() const
return session Time lines
void addMedium(const Medium &medium)
add an m= (Medium) section to session
void addTime(const Time &t)
add a t= (Time) line to session
const Origin & origin() const
return session Origin line
void clearAttribute(const Data &key)
erase all attributes for a given key
const MediumContainer & media() const
return session Media lines
void addAttribute(const Data &key, const Data &value=Data::Empty)
add a session attribute line
Provides an interface to process and generate SDP bodies (MIME content-type application/sdp).
Session & session()
get the parsed SDP
static const char * RTP_AVP
static const char * RTP_SAVP
static const char * RTP_SAVPF
static const char * UDP_TLS_RTP_SAVP
static uint64_t getTimeMicroSec()
Returns the current clock time in microseconds.
const resip::Data & getFormatParameters() const
void toString(resip::Data &sdpCodecString) const
unsigned int ParticipantHandle
dcm! – add UnusedChecking(_enum) below;
bool isEqualNoCase(const Data &left, const Data &right)
unsigned __int64 uint64_t