Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

config: allow for custom SSRC. Added thread safety #185

Merged
merged 1 commit into from
Dec 21, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion include/uvgrtp/media_stream.hh
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@
#include <unordered_map>
#include <memory>
#include <string>

#include <atomic>

#ifndef _WIN32
#include <sys/socket.h>
@@ -345,6 +345,8 @@ namespace uvgrtp {

ssize_t fps_numerator_ = 30;
ssize_t fps_denominator_ = 1;

std::shared_ptr<std::atomic<std::uint32_t>> ssrc_;
};
}

7 changes: 4 additions & 3 deletions include/uvgrtp/rtcp.hh
Original file line number Diff line number Diff line change
@@ -12,6 +12,7 @@
#include <memory>
#include <mutex>
#include <deque>
#include <atomic>

namespace uvgrtp {

@@ -108,8 +109,8 @@ namespace uvgrtp {
class rtcp {
public:
/// \cond DO_NOT_DOCUMENT
rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::string cname, int rce_flags);
rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::string cname, std::shared_ptr<uvgrtp::srtcp> srtcp, int rce_flags);
rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::shared_ptr<std::atomic<std::uint32_t>> ssrc, std::string cname, int rce_flags);
rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::shared_ptr<std::atomic<std::uint32_t>> ssrc, std::string cname, std::shared_ptr<uvgrtp::srtcp> srtcp, int rce_flags);
~rtcp();

/* start the RTCP runner thread
@@ -512,7 +513,7 @@ namespace uvgrtp {
bool initial_;

/* Copy of our own current SSRC */
const uint32_t ssrc_;
std::shared_ptr<std::atomic_uint> ssrc_;

/* NTP timestamp associated with initial RTP timestamp (aka t = 0) */
uint64_t clock_start_;
7 changes: 7 additions & 0 deletions include/uvgrtp/util.hh
Original file line number Diff line number Diff line change
@@ -362,6 +362,13 @@ enum RTP_CTX_CONFIGURATION_FLAGS {
* See RCC_FPS_NUMERATOR for more info.
*/
RCC_FPS_DENOMINATOR = 9,

/** Set the SSRC of the stream manually
*
* By default SSRC is generated randomly
*/
RCC_SSRC = 10,

/// \cond DO_NOT_DOCUMENT
RCC_LAST
/// \endcond
23 changes: 15 additions & 8 deletions src/media_stream.cc
Original file line number Diff line number Diff line change
@@ -45,7 +45,8 @@ uvgrtp::media_stream::media_stream(std::string cname, std::string remote_addr,
holepuncher_(std::unique_ptr<uvgrtp::holepuncher>(new uvgrtp::holepuncher(socket_))),
cname_(cname),
fps_numerator_(30),
fps_denominator_(1)
fps_denominator_(1),
ssrc_(std::make_shared<std::atomic<std::uint32_t>>(uvgrtp::random::generate_32()))
{}

uvgrtp::media_stream::~media_stream()
@@ -257,8 +258,8 @@ rtp_error_t uvgrtp::media_stream::init()

reception_flow_ = std::unique_ptr<uvgrtp::reception_flow> (new uvgrtp::reception_flow());

rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_));
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, cname_, rce_flags_));
rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_, ssrc_));
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, cname_, rce_flags_));

socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);

@@ -277,7 +278,7 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)

reception_flow_ = std::unique_ptr<uvgrtp::reception_flow> (new uvgrtp::reception_flow());

rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_));
rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_, ssrc_));

bool perform_dh = !(rce_flags_ & RCE_ZRTP_MULTISTREAM_MODE);
if (!perform_dh)
@@ -313,7 +314,7 @@ rtp_error_t uvgrtp::media_stream::init(std::shared_ptr<uvgrtp::zrtp> zrtp)

zrtp->dh_has_finished(); // only after the DH stream has gotten its keys, do we let non-DH stream perform ZRTP

rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, cname_, srtcp_, rce_flags_));
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, cname_, srtcp_, rce_flags_));

socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
@@ -345,7 +346,7 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)

reception_flow_ = std::unique_ptr<uvgrtp::reception_flow> (new uvgrtp::reception_flow());

rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_));
rtp_ = std::shared_ptr<uvgrtp::rtp> (new uvgrtp::rtp(fmt_, ssrc_));

srtp_ = std::shared_ptr<uvgrtp::srtp> (new uvgrtp::srtp(rce_flags_));

@@ -362,7 +363,7 @@ rtp_error_t uvgrtp::media_stream::add_srtp_ctx(uint8_t *key, uint8_t *salt)
return free_resources(ret);
}

rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, cname_, srtcp_, rce_flags_));
rtcp_ = std::shared_ptr<uvgrtp::rtcp> (new uvgrtp::rtcp(rtp_, ssrc_, cname_, srtcp_, rce_flags_));

socket_->install_handler(rtcp_.get(), rtcp_->send_packet_handler_vec);
socket_->install_handler(srtp_.get(), srtp_->send_packet_handler);
@@ -660,7 +661,13 @@ rtp_error_t uvgrtp::media_stream::configure_ctx(int rcc_flag, ssize_t value)
media_->set_fps(fps_numerator_, fps_denominator_);
break;
}
case RCC_SSRC: {
if (value <= 0 || value > (ssize_t)UINT32_MAX)
return RTP_INVALID_VALUE;

*ssrc_ = (uint32_t)value;
break;
}
default:
return RTP_INVALID_VALUE;
}
@@ -685,7 +692,7 @@ uint32_t uvgrtp::media_stream::get_ssrc() const
return 0;
}

return rtp_->get_ssrc();
return *ssrc_.get();
}

rtp_error_t uvgrtp::media_stream::init_srtp_with_zrtp(int rce_flags, int type, std::shared_ptr<uvgrtp::base_srtp> srtp,
23 changes: 12 additions & 11 deletions src/rtcp.cc
Original file line number Diff line number Diff line change
@@ -37,12 +37,12 @@ constexpr int ESTIMATED_MAX_RECEPTION_TIME_MS = 10;

const uint32_t MAX_SUPPORTED_PARTICIPANTS = 31;

uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::string cname, int rce_flags):
rce_flags_(rce_flags), our_role_(RECEIVER),
uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::shared_ptr<std::atomic_uint> ssrc, std::string cname, int rce_flags):
rce_flags_(rce_flags), our_role_(RECEIVER),
tp_(0), tc_(0), tn_(0), pmembers_(0),
members_(0), senders_(0), rtcp_bandwidth_(0),
we_sent_(false), avg_rtcp_pkt_pize_(0), rtcp_pkt_count_(0),
rtcp_pkt_sent_count_(0), initial_(true), ssrc_(rtp->get_ssrc()),
rtcp_pkt_sent_count_(0), initial_(true), ssrc_(ssrc),
num_receivers_(0),
sender_hook_(nullptr),
receiver_hook_(nullptr),
@@ -92,9 +92,9 @@ uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::string cname, int rce_
}
}

uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::string cname,
uvgrtp::rtcp::rtcp(std::shared_ptr<uvgrtp::rtp> rtp, std::shared_ptr<std::atomic_uint> ssrc, std::string cname,
std::shared_ptr<uvgrtp::srtcp> srtcp, int rce_flags):
rtcp(rtp, cname, rce_flags)
rtcp(rtp, ssrc, cname, rce_flags)
{
srtcp_ = srtcp;
}
@@ -232,7 +232,7 @@ rtp_error_t uvgrtp::rtcp::stop()
}

/* Send BYE packet with our SSRC to all participants */
return uvgrtp::rtcp::send_bye_packet({ ssrc_ });
return uvgrtp::rtcp::send_bye_packet({ *ssrc_.get() });
}

void uvgrtp::rtcp::rtcp_runner(rtcp* rtcp, int interval)
@@ -1518,7 +1518,7 @@ rtp_error_t uvgrtp::rtcp::send_rtcp_packet_to_participants(uint8_t* frame, uint3
rtp_error_t ret = RTP_OK;

if (encrypt && srtcp_ &&
(ret = srtcp_->handle_rtcp_encryption(rce_flags_, rtcp_pkt_sent_count_, ssrc_, frame, frame_size)) != RTP_OK)
(ret = srtcp_->handle_rtcp_encryption(rce_flags_, rtcp_pkt_sent_count_, *ssrc_.get(), frame, frame_size)) != RTP_OK)
{
UVG_LOG_DEBUG("Encryption failed. Not sending packet");
delete[] frame;
@@ -1643,6 +1643,7 @@ rtp_error_t uvgrtp::rtcp::generate_report()
// see https://datatracker.ietf.org/doc/html/rfc3550#section-6.4.1

size_t write_ptr = 0;
uint32_t ssrc = *ssrc_.get();
if (sr_packet)
{
// sender reports have sender information in addition compared to receiver reports
@@ -1665,7 +1666,7 @@ rtp_error_t uvgrtp::rtcp::generate_report()
uint64_t rtp_ts = expanded_ts_start + ts_since_start;

if (!construct_rtcp_header(frame, write_ptr, sender_report_size, reports, uvgrtp::frame::RTCP_FT_SR) ||
!construct_ssrc(frame, write_ptr, ssrc_) ||
!construct_ssrc(frame, write_ptr, ssrc) ||
!construct_sender_info(frame, write_ptr, ntp_ts, rtp_ts, our_stats.sent_pkts, our_stats.sent_bytes))
{
UVG_LOG_ERROR("Failed to construct SR");
@@ -1678,7 +1679,7 @@ rtp_error_t uvgrtp::rtcp::generate_report()
size_t receiver_report_size = get_rr_packet_size(rce_flags_, reports);

if (!construct_rtcp_header(frame, write_ptr, receiver_report_size, reports, uvgrtp::frame::RTCP_FT_RR) ||
!construct_ssrc(frame, write_ptr, ssrc_))
!construct_ssrc(frame, write_ptr, ssrc))
{
UVG_LOG_ERROR("Failed to construct RR");
return RTP_GENERIC_ERROR;
@@ -1726,7 +1727,7 @@ rtp_error_t uvgrtp::rtcp::generate_report()
{
uvgrtp::frame::rtcp_sdes_chunk chunk;
chunk.items = ourItems_;
chunk.ssrc = ssrc_;
chunk.ssrc = *ssrc_.get();

// add the SDES packet after the SR/RR, mandatory, must contain CNAME
if (!construct_rtcp_header(frame, write_ptr, get_sdes_packet_size(ourItems_), num_receivers_,
@@ -1757,7 +1758,7 @@ rtp_error_t uvgrtp::rtcp::generate_report()

if (!construct_rtcp_header(frame, write_ptr, packet_size, secondField,
uvgrtp::frame::RTCP_FT_APP) ||
!construct_ssrc(frame, write_ptr, ssrc_) ||
!construct_ssrc(frame, write_ptr, ssrc) ||
!construct_app_packet(frame, write_ptr, next_packet.name, next_packet.payload, next_packet.payload_len))
{
UVG_LOG_ERROR("Failed to construct APP packet");
8 changes: 4 additions & 4 deletions src/rtp.cc
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@

#define INVALID_TS UINT64_MAX

uvgrtp::rtp::rtp(rtp_format_t fmt):
ssrc_(uvgrtp::random::generate_32()),
uvgrtp::rtp::rtp(rtp_format_t fmt, std::shared_ptr<std::atomic<std::uint32_t>> ssrc):
ssrc_(ssrc),
ts_(uvgrtp::random::generate_32()),
seq_(uvgrtp::random::generate_32() & 0xffff),
fmt_(fmt),
@@ -40,7 +40,7 @@ uvgrtp::rtp::~rtp()

uint32_t uvgrtp::rtp::get_ssrc() const
{
return ssrc_;
return *ssrc_.get();
}

uint16_t uvgrtp::rtp::get_sequence() const
@@ -145,7 +145,7 @@ void uvgrtp::rtp::fill_header(uint8_t *buffer)
buffer[1] = (payload_ & 0x7f) | (0 << 7);

*(uint16_t *)&buffer[2] = htons(seq_);
*(uint32_t *)&buffer[8] = htonl(ssrc_);
*(uint32_t *)&buffer[8] = htonl(*ssrc_.get());

if (timestamp_ == INVALID_TS) {

6 changes: 4 additions & 2 deletions src/rtp.hh
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
#include "uvgrtp/util.hh"

#include <chrono>
#include <memory>
#include <atomic>

namespace uvgrtp {

@@ -14,7 +16,7 @@ namespace uvgrtp {

class rtp {
public:
rtp(rtp_format_t fmt);
rtp(rtp_format_t fmt, std::shared_ptr<std::atomic<std::uint32_t>> ssrc);
~rtp();

uint32_t get_ssrc() const;
@@ -44,7 +46,7 @@ namespace uvgrtp {

void set_default_clock_rate(rtp_format_t fmt);

uint32_t ssrc_;
std::shared_ptr<std::atomic<std::uint32_t>> ssrc_;
uint32_t ts_;
uint16_t seq_;
rtp_format_t fmt_;