36#include <opendht/rng.h>
57 , publishedIpAddrType_()
58 , telephoneEventPayload_(101)
59 , sessionName_(
"Call ID " +
id)
67 throw std::runtime_error(
"pj_pool_create() failed");
78std::shared_ptr<SystemCodecInfo>
79Sdp::findCodecBySpec(std::string_view codec,
const unsigned clockrate)
const
97std::shared_ptr<SystemCodecInfo>
98Sdp::findCodecByPayload(
const unsigned payloadType)
116 std::uniform_int_distribution<int>
rand_byte {0, std::numeric_limits<uint8_t>::max()};
117 std::random_device
rdev;
124 if (activeLocalSession_ !=
sdp)
125 JAMI_DBG(
"Set active local session to [%p]. Was [%p]",
sdp, activeLocalSession_);
126 activeLocalSession_ =
sdp;
132 if (activeLocalSession_ !=
sdp)
133 JAMI_DBG(
"Set active remote session to [%p]. Was [%p]",
sdp, activeRemoteSession_);
134 activeRemoteSession_ =
sdp;
138Sdp::generateSdesAttribute()
153Sdp::mediaDirection(
const MediaAttribute&
mediaAttr)
214std::vector<std::string>
217 std::vector<std::string> crypto;
218 for (
unsigned j = 0;
j <
media->attr_count;
j++) {
228Sdp::addMediaDescription(
const MediaAttribute&
mediaAttr)
240 med->desc.port =
mediaAttr.enabled_ ? localAudioRtpPort_ : 0;
241 med->desc.fmt_count = audio_codec_list_.size();
245 med->desc.port =
mediaAttr.enabled_ ? localVideoRtpPort_ : 0;
246 med->desc.fmt_count = video_codec_list_.size();
249 throw SdpException(
"Unsupported media type! Only audio and video are supported");
253 med->desc.port_count = 1;
260 for (
unsigned i = 0;
i <
med->desc.fmt_count;
i++) {
264 std::string channels;
269 auto accountAudioCodec = std::static_pointer_cast<SystemAudioCodecInfo>(audio_codec_list_[
i]);
288 rtpmap.clock_rate = 90000;
309 const auto accountVideoCodec = std::static_pointer_cast<SystemVideoCodecInfo>(video_codec_list_[
i]);
320 setTelephoneEventRtpmap(
med);
321 if (localAudioRtcpPort_) {
322 addRTCPAttribute(
med, localAudioRtcpPort_);
325 addRTCPAttribute(
med, localVideoRtcpPort_);
328 char const* direction = mediaDirection(
mediaAttr);
334 throw SdpException(
"Unable to add sdes attribute to media");
343 dhtnet::IpAddr addr {publishedIpAddr_};
353 publishedIpAddr_ = addr;
361 localSession_->conn->addr = localSession_->origin.addr;
376 ++
med->desc.fmt_count;
377 pj_strdup2(memPool_.get(), &
med->desc.fmt[
med->desc.fmt_count - 1], std::to_string(telephoneEventPayload_).c_str());
407 video_codec_list_.erase(std::remove_if(video_codec_list_.begin(),
408 video_codec_list_.end(),
409 [](
const std::shared_ptr<SystemCodecInfo>&
i) {
410 return i->name ==
"H265";
412 video_codec_list_.end());
425constexpr std::string_view
438 static constexpr size_t BUF_SZ = 4095;
447 JAMI_ERROR(
"Unable to clone SDP for printing");
456 std::array<char, BUF_SZ + 1>
buffer;
469 sdpDirection_ = direction;
474 localSession_->origin.version = 0;
481 localSession_->origin.id =
tv.sec + 2208988800UL;
492 localSession_->conn->net_type = localSession_->origin.net_type;
493 localSession_->conn->addr_type = localSession_->origin.addr_type;
494 localSession_->conn->addr = localSession_->origin.addr;
499 localSession_->time.start = 0;
500 localSession_->time.stop = 0;
504Sdp::validateSession()
const
513 throw SdpException(
"Media list size exceeds SDP media maximum size");
520 JAMI_ERR(
"Failed to create initial offer");
524 localSession_->media_count = 0;
527 if (
media.enabled_) {
528 localSession_->media[localSession_->media_count++] = addMediaDescription(
media);
538 JAMI_ERR(
"Failed to create an initial SDP negotiator");
542 printSession(localSession_,
"Local session (initial):", sdpDirection_);
550 if (remote ==
nullptr) {
560 if (
not remoteSession_)
563 JAMI_DEBUG(
"Processing received offer for [{:s}] with {:d} media", sessionName_,
mediaList.size());
569 JAMI_ERR(
"Failed to create local session");
573 localSession_->media_count = 0;
576 if (
media.enabled_) {
577 localSession_->media[localSession_->media_count++] = addMediaDescription(
media);
581 printSession(localSession_,
"Local session:\n", sdpDirection_);
590 JAMI_ERR(
"Failed to initialize media negotiation");
600 JAMI_DBG(
"Starting media negotiation for [%s]", sessionName_.c_str());
602 if (negotiator_ ==
NULL) {
603 JAMI_ERR(
"Unable to start negotiation with invalid negotiator");
611 JAMI_WARN(
"Negotiator not in right state for negotiation");
616 JAMI_ERR(
"Failed to start media negotiation");
621 JAMI_ERR(
"Unable to retrieve local active session");
630 JAMI_ERR(
"Unable to retrieve remote active session");
644 static constexpr size_t BUF_SZ = 4096;
655 for (
unsigned i = 0;
i <
cloned->media_count;
i++)
658 JAMI_ERR(
"Unable to deactivate media");
664 JAMI_DBG(
"No media to keep present in SDP");
669 for (
unsigned i = 0;
i <
cloned->media_count;
i++)
670 if (
cloned->media[
i]->desc.port == 0) {
676 for (
unsigned i = 0;
i <
cloned->media_count;
i++) {
680 for (
unsigned c = 0; c <
media->desc.fmt_count; c++) {
681 auto& pt =
media->desc.fmt[c];
691 std::move(
media->desc.fmt + c + 1,
media->desc.fmt +
media->desc.fmt_count,
media->desc.fmt + c);
692 media->desc.fmt_count--;
707std::vector<MediaDescription>
716std::vector<MediaDescription>
724 std::vector<MediaDescription>
ret;
725 for (
unsigned i = 0;
i <
session->media_count;
i++) {
743 JAMI_ERR(
"Unable to find connection information for media");
746 descr.addr = std::string_view(
conn->addr.ptr,
conn->addr.slen);
756 descr.rtcp_addr = std::string_view(
rtcp.addr.ptr,
rtcp.addr.slen);
773 for (
unsigned j = 0;
j <
media->desc.fmt_count;
j++) {
776 JAMI_ERR(
"Unable to find rtpmap attribute");
777 descr.enabled =
false;
783 descr.enabled =
false;
791 descr.enabled =
false;
800 descr.parameters = std::string(v.ptr, v.ptr + v.slen);
804 descr.enabled =
true;
812 std::vector<std::string> crypto;
813 for (
unsigned j = 0;
j <
media->attr_count;
j++) {
823std::vector<Sdp::MediaSlot>
829 std::vector<MediaSlot> s;
832 s.emplace_back(std::move(
loc[
i]), std::move(
rem[
i]));
840 JAMI_ERR(
"addIceCandidates failed: unable to access media#%u (may be deactivated)",
media_index);
851 throw SdpException(
"Unable to add ICE candidates attribute to media");
855std::vector<std::string>
858 const auto*
remoteSession = activeRemoteSession_ ? activeRemoteSession_ : remoteSession_;
859 const auto*
localSession = activeLocalSession_ ? activeLocalSession_ : localSession_;
861 JAMI_ERR(
"getIceCandidates failed: no remote session");
865 JAMI_ERR(
"getIceCandidates failed: no local session");
869 JAMI_ERR(
"getIceCandidates failed: unable to access media#%u (may be deactivated)",
media_index);
875 JAMI_WARN(
"Media#%u is disabled. Media ports: local %u, remote %u",
884 for (
unsigned i = 0;
i <
media->attr_count;
i++) {
900 throw SdpException(
"Unable to add ICE.ufrag attribute to local SDP");
906 throw SdpException(
"Unable to add ICE.pwd attribute to local SDP");
909dhtnet::IceTransport::Attribute
912 if (
const auto*
session = activeRemoteSession_ ? activeRemoteSession_ : remoteSession_)
917dhtnet::IceTransport::Attribute
920 dhtnet::IceTransport::Attribute
ice_attrs;
924 for (
unsigned i = 0;
i <
session->attr_count;
i++) {
933 for (
unsigned i = 0;
i <
session->media_count;
i++) {
935 for (
unsigned j = 0;
j <
media->attr_count;
j++) {
967 for (
unsigned i = 0;
i <
session->media_count;
i++) {
973std::vector<MediaAttribute>
983 for (
unsigned idx = 0; idx <
sdpSession->media_count; idx++) {
995 JAMI_WARN(
"Media#%u only 'audio' and 'video' types are supported!", idx);
1010 auto direction = getMediaDirection(
media);
1016 JAMI_WARN(
"Media#%u is unable to determine transport type!", idx);
static LIBJAMI_TEST_EXPORT Manager & instance()
static void releasePort(uint16_t port) noexcept
static CryptoAttribute negotiate(const std::vector< std::string > &attributes)
void setReceivedOffer(const pjmedia_sdp_session *remote)
bool processIncomingOffer(const std::vector< MediaAttribute > &mediaList)
Build a new SDP answer using mediaList.
std::vector< MediaDescription > getActiveMediaDescription(bool remote) const
void addIceCandidates(unsigned media_index, const std::vector< std::string > &cands)
bool startNegotiation()
Start the sdp negotiation.
void setLocalMediaCapabilities(MediaType type, const std::vector< std::shared_ptr< SystemCodecInfo > > &selectedCodecs)
Set the local media capabilities.
std::vector< MediaDescription > getMediaDescriptions(const pjmedia_sdp_session *session, bool remote) const
bool createOffer(const std::vector< MediaAttribute > &mediaList)
static std::vector< MediaAttribute > getMediaAttributeListFromSdp(const pjmedia_sdp_session *sdpSession, bool ignoreDisabled=false)
std::vector< std::string > getIceCandidates(unsigned media_index) const
void setPublishedIP(const std::string &addr, pj_uint16_t addr_type=pj_AF_UNSPEC())
void addIceAttributes(const dhtnet::IceTransport::Attribute &&ice_attrs)
dhtnet::IceTransport::Attribute getIceAttributes() const
void setActiveLocalSdpSession(const pjmedia_sdp_session *sdp)
Set the negotiated sdp offer from the sip payload.
Sdp(const std::string &id)
static constexpr std::string_view getSdpDirectionStr(SdpDirection direction)
void setActiveRemoteSdpSession(const pjmedia_sdp_session *sdp)
Retrieve the negotiated sdp offer from the sip payload.
static void printSession(const pjmedia_sdp_session *session, const char *header, SdpDirection direction)
Log the given session.
std::vector< MediaSlot > getMediaSlots() const
#define JAMI_ERROR(formatstr,...)
#define JAMI_DEBUG(formatstr,...)
#define JAMI_LOG(formatstr,...)
std::string encode(std::string_view str)
const char *const DEFAULT_H264_PROFILE_LEVEL_ID
std::unique_ptr< pj_pool_t, PoolDeleter > PoolPtr
constexpr std::string_view as_view(const pj_str_t &str) noexcept
constexpr const pj_str_t CONST_PJ_STR(T(&a)[N]) noexcept
static std::map< MediaDirection, const char * > DIRECTION_STR
void emitSignal(Args... args)
static std::vector< CryptoSuiteDefinition > CryptoSuites
List of accepted Crypto-Suites as defined in RFC4568 (6.2)
static constexpr int POOL_INITIAL_SIZE
static constexpr int POOL_INCREMENT_SIZE
static void randomFill(std::vector< uint8_t > &dest)
A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
Specific VoIPLink for SIP (SIP core for incoming and outgoing events).