multiplex: Finalize add_zrtp_ctx() function and set stream remote_ssrc by default to ssrc + 1

Also test add_zrtp_ctx() in ZRTP mux tests
This commit is contained in:
Heikki Tampio 2023-07-31 09:17:29 +03:00
parent e39fc25a5a
commit cb59c55f79
5 changed files with 105 additions and 205 deletions

View File

@ -62,39 +62,6 @@ namespace uvgrtp {
*/
uvgrtp::media_stream *create_stream(uint16_t src_port, uint16_t dst_port, rtp_format_t fmt, int rce_flags);
/**
* \brief Create a uni- or bidirectional media stream
*
* \details
*
* The created object is used for sending and/or receiving media, see documentation
* for uvgrtp::media_stream for more details.
*
* If both addresses were provided when uvgrtp::session was created, by default
* uvgRTP binds itself to local_addr:src_port and sends packets to remote_addr:dst_port.
*
* User can enable and disable functionality of media_stream by OR'ing (using |) RCE_* flags
* together and passing them using the rce_flags parameter. In rce_flags, the RCE_SEND_ONLY flag
* can be used to avoid binding and src_port is thus ignored. Correspondinly RCE_RECEIVE_ONLY flag
* means dst_port is ignored. Without either RCE_SEND_ONLY or RCE_RECEIVE_ONLY,
* and if only one address was provided for session that address is interpreted as remote_addr and
* binding happens to ANY:src_port.
*
* \param remote_port Remote port where uvgRTP sends RTP packets
* \param local_port Local port that uvgRTP listens to for incoming RTP packets
* \param fmt Format of the media stream. see ::RTP_FORMAT for more details
* \param rce_flags RTP context enable flags, see ::RTP_CTX_ENABLE_FLAGS for more details
* \param remote_ssrc Remote SSRC that this stream will receive packets from
* \param local_ssrc Local SSRC that will be present in packets that ´this stream sends
*
* \return RTP media stream object
*
* \retval uvgrtp::media_stream* On success
* \retval nullptr On failure, see print and
*/
uvgrtp::media_stream* create_stream(uint16_t remote_port, uint16_t local_port, rtp_format_t fmt, int rce_flags,
uint32_t remote_ssrc, uint32_t local_ssrc);
/**
* \brief Create a unidirectional media_stream for an RTP session
*

View File

@ -60,7 +60,7 @@ uvgrtp::media_stream::media_stream(std::string cname, std::string remote_addr,
fps_numerator_(30),
fps_denominator_(1),
ssrc_(std::make_shared<std::atomic<std::uint32_t>>(uvgrtp::random::generate_32())),
remote_ssrc_(std::make_shared<std::atomic<std::uint32_t>>(0)),
remote_ssrc_(std::make_shared<std::atomic<std::uint32_t>>(ssrc_.get()->load() + 1)),
snd_buf_size_(-1),
rcv_buf_size_(-1)
{
@ -422,6 +422,57 @@ rtp_error_t uvgrtp::media_stream::init_auto_zrtp(std::shared_ptr<uvgrtp::zrtp> z
rtp_error_t uvgrtp::media_stream::add_zrtp_ctx()
{
if (!zrtp_) {
UVG_LOG_ERROR("ZRTP not found, stream %i", ssrc_.get()->load());
return free_resources(RTP_GENERIC_ERROR);
}
bool perform_dh = !(rce_flags_ & RCE_ZRTP_MULTISTREAM_MODE);
if (!perform_dh)
{
UVG_LOG_DEBUG("Sleeping non-DH performing stream until DH has finished");
std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
while (!zrtp_->has_dh_finished())
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - tp).count() > 10)
{
UVG_LOG_ERROR("Giving up on DH after 10 seconds");
return free_resources(RTP_TIMEOUT);
}
}
}
/* If ZRTP is already performing an MSM negotiation, wait for it to complete before starting a new one */
if (!perform_dh) {
auto start = std::chrono::system_clock::now();
while (zrtp_->is_zrtp_busy()) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
if (std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now() - start).count() > 10)
{
UVG_LOG_ERROR("Giving up on MSM after 10 seconds");
return free_resources(RTP_TIMEOUT);
}
}
}
zrtp_->set_zrtp_busy(true);
rtp_error_t ret = RTP_OK;
if ((ret = zrtp_->init(rtp_->get_ssrc(), socket_, remote_sockaddr_, remote_sockaddr_ip6_, perform_dh, ipv6_)) != RTP_OK) {
UVG_LOG_WARN("Failed to initialize ZRTP for media stream!");
return free_resources(ret);
}
if ((ret = init_srtp_with_zrtp(rce_flags_, SRTP, srtp_, zrtp_)) != RTP_OK)
return free_resources(ret);
if ((ret = init_srtp_with_zrtp(rce_flags_, SRTCP, srtcp_, zrtp_)) != RTP_OK)
return free_resources(ret);
zrtp_->set_zrtp_busy(false);
zrtp_->dh_has_finished(); // only after the DH stream has gotten its keys, do we let non-DH stream perform ZRTP
install_packet_handlers();
return RTP_OK;
}
@ -688,7 +739,7 @@ uvgrtp::frame::rtp_frame *uvgrtp::media_stream::pull_frame(size_t timeout_ms)
return nullptr;
}
// If the remote_ssrc is set, only pull frames that come from this ssrc
if (remote_ssrc_.get()->load() != 0) {
if (remote_ssrc_.get()->load() != ssrc_.get()->load() + 1) {
return reception_flow_->pull_frame(timeout_ms, remote_ssrc_);
}
return reception_flow_->pull_frame(timeout_ms);

View File

@ -369,17 +369,16 @@ void uvgrtp::reception_flow::return_frame(uvgrtp::frame::rtp_frame *frame)
// 1. Check if there exists a hook that this ssrc belongs to
// 2. If not, check if there is a "universal hook"
// 3. If neither is found, push the frame to the queue
if (hooks_.find(ssrc) != hooks_.end()) {
/* Socket multiplexing: Hook found */
receive_pkt_hook pkt_hook = hooks_[ssrc];
if (hooks_.size() == 1) {
/* No socket multiplexing: All packets are given to this hook */
receive_pkt_hook pkt_hook = hooks_.begin()->second;
recv_hook hook = pkt_hook.hook;
void* arg = pkt_hook.arg;
hook(arg, frame);
}
else if (hooks_.find(0) != hooks_.end()) {
/* No socket multiplexing: All packets are given to this hook */
receive_pkt_hook pkt_hook = hooks_[0];
else if (hooks_.find(ssrc) != hooks_.end()) {
/* Socket multiplexing: Hook found */
receive_pkt_hook pkt_hook = hooks_[ssrc];
recv_hook hook = pkt_hook.hook;
void* arg = pkt_hook.arg;
hook(arg, frame);
@ -546,7 +545,11 @@ void uvgrtp::reception_flow::process_packet(int rce_flags)
bool rtcp_pkt = false;
handler* handlers = nullptr;
if (packet_handlers_.find(rtcp_ssrc) != packet_handlers_.end()) {
if (packet_handlers_.size() == 1) {
/* No socket multiplexing: All packets are given to this handler */
handlers = &packet_handlers_.begin()->second;
}
else if (packet_handlers_.find(rtcp_ssrc) != packet_handlers_.end()) {
/* Socket multiplexing: RTCP packet */
handlers = &packet_handlers_[rtcp_ssrc];
rtcp_pkt = true;
@ -555,10 +558,6 @@ void uvgrtp::reception_flow::process_packet(int rce_flags)
/* Socket multiplexing: RTP/ZRTP packet */
handlers = &packet_handlers_[rtp_ssrc];
}
else if (packet_handlers_.find(0) != packet_handlers_.end()) {
/* No socket multiplexing: All packets are given to this handler */
handlers = &packet_handlers_[0];
}
size_t size = (size_t)ring_buffer_[ring_read_index_].read;
uint8_t version = (*(uint8_t*)&ptr[0] >> 6) & 0x3;
@ -712,9 +711,7 @@ void uvgrtp::reception_flow::increase_buffer_size(ssize_t next_write_index)
int uvgrtp::reception_flow::clear_stream_from_flow(std::shared_ptr<std::atomic<std::uint32_t>> remote_ssrc)
{
std::lock_guard<std::mutex> hndl_lg(handlers_mutex_);
std::lock_guard<std::mutex> hook_lg(hooks_mutex_);
std::scoped_lock hlg(hooks_mutex_, handlers_mutex_);
uint32_t ssrc = remote_ssrc.get()->load();
// Clear all the data structures
hooks_.erase(ssrc);
@ -730,8 +727,7 @@ int uvgrtp::reception_flow::clear_stream_from_flow(std::shared_ptr<std::atomic<s
rtp_error_t uvgrtp::reception_flow::update_remote_ssrc(uint32_t old_remote_ssrc, uint32_t new_remote_ssrc)
{
std::lock_guard<std::mutex> hlg(hooks_mutex_);
std::lock_guard<std::mutex> halg(handlers_mutex_);
std::scoped_lock hlg(hooks_mutex_, handlers_mutex_);
if (packet_handlers_.find(old_remote_ssrc) != packet_handlers_.end()) {
handler handlers = packet_handlers_[old_remote_ssrc];
packet_handlers_.erase(old_remote_ssrc);

View File

@ -165,9 +165,11 @@ uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t
}
} else {
UVG_LOG_ERROR("SRTP key management scheme not specified!");
rtp_errno = RTP_INVALID_VALUE;
delete stream;
return nullptr;
if (stream->init(zrtp_) != RTP_OK) {
UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), src_port, dst_port);
delete stream;
return nullptr;
}
}
} else {
if (stream->init(zrtp_) != RTP_OK) {
@ -184,130 +186,6 @@ uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t src_port, uint16_t
return stream;
}
uvgrtp::media_stream* uvgrtp::session::create_stream(uint16_t remote_port, uint16_t local_port, rtp_format_t fmt, int rce_flags,
uint32_t remote_ssrc, uint32_t local_ssrc)
{
if (rce_flags & RCE_OBSOLETE) {
UVG_LOG_WARN("You are using a flag that has either been removed or has been enabled by default. Consider updating RCE flags");
}
if ((rce_flags & RCE_SEND_ONLY) && (rce_flags & RCE_RECEIVE_ONLY)) {
UVG_LOG_ERROR("Cannot both use RCE_SEND_ONLY and RCE_RECEIVE_ONLY!");
rtp_errno = RTP_NOT_SUPPORTED;
return nullptr;
}
// select which address the one address we got as a parameter is
if (generic_address_ != "")
{
if (rce_flags & RCE_RECEIVE_ONLY)
{
local_address_ = generic_address_;
}
else
{
remote_address_ = generic_address_;
}
}
else if ((rce_flags & RCE_RECEIVE_ONLY) && local_address_ == "")
{
UVG_LOG_ERROR("RCE_RECEIVE_ONLY requires local address!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
else if ((rce_flags & RCE_SEND_ONLY) && remote_address_ == "")
{
UVG_LOG_ERROR("RCE_SEND_ONLY requires remote address!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
if ((rce_flags & RCE_RECEIVE_ONLY) && local_port == 0)
{
UVG_LOG_ERROR("RCE_RECEIVE_ONLY requires source port!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
if ((rce_flags & RCE_SEND_ONLY) && remote_port == 0)
{
UVG_LOG_ERROR("RCE_SEND_ONLY requires destination port!");
rtp_errno = RTP_INVALID_VALUE;
return nullptr;
}
uvgrtp::media_stream* stream =
new uvgrtp::media_stream(cname_, remote_address_, local_address_, local_port, remote_port, fmt, sf_, rce_flags);
stream->configure_ctx(RCC_SSRC, local_ssrc);
stream->configure_ctx(RCC_REMOTE_SSRC, remote_ssrc);
if (rce_flags & RCE_SRTP) {
if (!uvgrtp::crypto::enabled()) {
UVG_LOG_ERROR("Recompile uvgRTP with -D__RTP_CRYPTO__");
delete stream;
rtp_errno = RTP_GENERIC_ERROR;
return nullptr;
}
if (rce_flags & RCE_SRTP_REPLAY_PROTECTION)
rce_flags |= RCE_SRTP_AUTHENTICATE_RTP;
session_mtx_.lock();
if (!zrtp_) {
zrtp_ = std::shared_ptr<uvgrtp::zrtp>(new uvgrtp::zrtp());
}
session_mtx_.unlock();
if (rce_flags & RCE_SRTP_KMNGMNT_ZRTP) {
if (rce_flags & (RCE_SRTP_KEYSIZE_192 | RCE_SRTP_KEYSIZE_256)) {
UVG_LOG_ERROR("Only 128-bit keys are supported with ZRTP");
delete stream;
return nullptr;
}
if (!(rce_flags & RCE_ZRTP_DIFFIE_HELLMAN_MODE) &&
!(rce_flags & RCE_ZRTP_MULTISTREAM_MODE)) {
UVG_LOG_INFO("ZRTP mode not selected, using Diffie-Hellman mode");
rce_flags |= RCE_ZRTP_DIFFIE_HELLMAN_MODE;
}
if (stream->init_auto_zrtp(zrtp_) != RTP_OK) {
UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), local_port, remote_port);
delete stream;
return nullptr;
}
}
else if (rce_flags & RCE_SRTP_KMNGMNT_USER) {
UVG_LOG_DEBUG("SRTP with user-managed keys enabled, postpone initialization");
if (stream->init(zrtp_) != RTP_OK) {
UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), local_port, remote_port);
delete stream;
return nullptr;
}
}
else {
UVG_LOG_ERROR("SRTP key management scheme not specified!");
rtp_errno = RTP_INVALID_VALUE;
delete stream;
return nullptr;
}
}
else {
if (stream->init(zrtp_) != RTP_OK) {
UVG_LOG_ERROR("Failed to initialize media stream %s:%d/%d", remote_address_.c_str(), local_port, remote_port);
delete stream;
return nullptr;
}
}
session_mtx_.lock();
streams_.insert(std::make_pair(stream->get_key(), stream));
session_mtx_.unlock();
return stream;
}
rtp_error_t uvgrtp::session::destroy_stream(uvgrtp::media_stream *stream)
{
if (!stream)

View File

@ -17,8 +17,8 @@ constexpr int SALT_SIZE_BYTES = SALT_SIZE / 8;
void user_send_func(uint8_t *key, uint8_t salt[SALT_SIZE_BYTES], uint8_t key_size);
void user_receive_func(uint8_t *key, uint8_t salt[SALT_SIZE_BYTES], uint8_t key_size);
void zrtp_sender_func(uvgrtp::session* sender_session, int sender_port, int receiver_port, unsigned int flags);
void zrtp_receive_func(uvgrtp::session* receiver_session, int sender_port, int receiver_port, unsigned int flags);
void zrtp_sender_func(uvgrtp::session* sender_session, int sender_port, int receiver_port, unsigned int flags, bool mux);
void zrtp_receive_func(uvgrtp::session* receiver_session, int sender_port, int receiver_port, unsigned int flags, bool mux);
void test_user_key(Key_length len);
int received_packets;
@ -196,10 +196,10 @@ TEST(EncryptionTests, zrtp)
received_packets = 0;
std::unique_ptr<std::thread> sender_thread =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags, false));
std::unique_ptr<std::thread> receiver_thread =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags, false));
if (sender_thread && sender_thread->joinable())
{
@ -236,10 +236,10 @@ TEST(EncryptionTests, zrtp_authenticate)
received_packets = 0;
std::unique_ptr<std::thread> sender_thread =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags, false));
std::unique_ptr<std::thread> receiver_thread =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_flags, false));
if (sender_thread && sender_thread->joinable())
{
@ -280,22 +280,22 @@ TEST(EncryptionTests, zrtp_multistream)
uvgrtp::session* receiver_session = ctx.create_session(SENDER_ADDRESS, RECEIVER_ADDRESS);
std::unique_ptr<std::thread> sender_thread1 =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 2, RECEIVER_PORT + 2, zrtp_dh_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 2, RECEIVER_PORT + 2, zrtp_dh_flags, false));
std::unique_ptr<std::thread> receiver_thread1 =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 2, RECEIVER_PORT + 2, zrtp_dh_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 2, RECEIVER_PORT + 2, zrtp_dh_flags, false));
std::unique_ptr<std::thread> sender_thread2 =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 4, RECEIVER_PORT + 4, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 4, RECEIVER_PORT + 4, zrtp_multistream_flags, false));
std::unique_ptr<std::thread> receiver_thread2 =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 4, RECEIVER_PORT + 4, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 4, RECEIVER_PORT + 4, zrtp_multistream_flags, false));
std::unique_ptr<std::thread> sender_thread3 =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 6, RECEIVER_PORT + 6, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT + 6, RECEIVER_PORT + 6, zrtp_multistream_flags, false));
std::unique_ptr<std::thread> receiver_thread3 =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 6, RECEIVER_PORT + 6, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT + 6, RECEIVER_PORT + 6, zrtp_multistream_flags, false));
if (receiver_thread1 && receiver_thread1->joinable())
{
@ -350,27 +350,27 @@ TEST(EncryptionTests, zrtp_multistream_mux)
}
/* Enable SRTP and ZRTP */
unsigned zrtp_dh_flags = RCE_SRTP | RCE_SRTP_KMNGMNT_ZRTP | RCE_ZRTP_DIFFIE_HELLMAN_MODE;
unsigned zrtp_dh_flags = RCE_SRTP | RCE_ZRTP_DIFFIE_HELLMAN_MODE;
// only one of the streams should perform DH
unsigned int zrtp_multistream_flags = RCE_SRTP | RCE_SRTP_KMNGMNT_ZRTP | RCE_ZRTP_MULTISTREAM_MODE;
unsigned int zrtp_multistream_flags = RCE_SRTP | RCE_ZRTP_MULTISTREAM_MODE;
uvgrtp::session* sender_session = send_ctx.create_session(RECEIVER_ADDRESS, SENDER_ADDRESS);
uvgrtp::session* receiver_session = recv_ctx.create_session(SENDER_ADDRESS, RECEIVER_ADDRESS);
std::unique_ptr<std::thread> sender_thread1 =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_dh_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_dh_flags, true));
std::unique_ptr<std::thread> receiver_thread1 =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_dh_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_dh_flags, true));
//std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::unique_ptr<std::thread> sender_thread2 =
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_sender_func, sender_session, SENDER_PORT, RECEIVER_PORT, zrtp_multistream_flags, true));
std::unique_ptr<std::thread> receiver_thread2 =
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_multistream_flags));
std::unique_ptr<std::thread>(new std::thread(zrtp_receive_func, receiver_session, SENDER_PORT, RECEIVER_PORT, zrtp_multistream_flags, true));
if (receiver_thread1 && receiver_thread1->joinable())
{
@ -399,21 +399,25 @@ TEST(EncryptionTests, zrtp_multistream_mux)
cleanup_sess(recv_ctx, receiver_session);
}
void zrtp_sender_func(uvgrtp::session* sender_session, int sender_port, int receiver_port, unsigned int flags)
void zrtp_sender_func(uvgrtp::session* sender_session, int sender_port, int receiver_port, unsigned int flags, bool mux)
{
std::cout << "Starting ZRTP sender thread" << std::endl;
/* See sending.cc for more details about create_stream() */
uvgrtp::media_stream* send = nullptr;
send = sender_session->create_stream(sender_port, receiver_port, RTP_FORMAT_GENERIC, flags);
if (sender_session)
if (sender_session && mux)
{
if (flags & RCE_ZRTP_MULTISTREAM_MODE) {
send = sender_session->create_stream(sender_port, receiver_port, RTP_FORMAT_GENERIC, flags, 11, 22);
send->configure_ctx(RCC_REMOTE_SSRC, 11);
send->configure_ctx(RCC_SSRC, 22);
}
else {
send = sender_session->create_stream(sender_port, receiver_port, RTP_FORMAT_GENERIC, flags, 33, 44);
send->configure_ctx(RCC_REMOTE_SSRC, 33);
send->configure_ctx(RCC_SSRC, 44);
}
send->add_zrtp_ctx();
//send = sender_session->create_stream(sender_port, receiver_port, RTP_FORMAT_GENERIC, flags);
}
//Sleep for a bit so that the receiver is ready to receives
@ -434,21 +438,25 @@ void zrtp_sender_func(uvgrtp::session* sender_session, int sender_port, int rece
cleanup_ms(sender_session, send);
}
void zrtp_receive_func(uvgrtp::session* receiver_session, int sender_port, int receiver_port, unsigned int flags)
void zrtp_receive_func(uvgrtp::session* receiver_session, int sender_port, int receiver_port, unsigned int flags, bool mux)
{
std::cout << "Starting ZRTP receiver thread" << std::endl;
/* See sending.cc for more details about create_stream() */
uvgrtp::media_stream* recv = nullptr;
recv = receiver_session->create_stream(receiver_port, sender_port, RTP_FORMAT_GENERIC, flags);
if (receiver_session)
if (receiver_session && mux)
{
if (flags & RCE_ZRTP_MULTISTREAM_MODE) {
recv = receiver_session->create_stream(receiver_port, sender_port, RTP_FORMAT_GENERIC, flags, 22, 11);
recv->configure_ctx(RCC_REMOTE_SSRC, 22);
recv->configure_ctx(RCC_SSRC, 11);
}
else {
recv = receiver_session->create_stream(receiver_port, sender_port, RTP_FORMAT_GENERIC, flags, 44, 33);
recv->configure_ctx(RCC_REMOTE_SSRC, 44);
recv->configure_ctx(RCC_SSRC, 33);
}
recv->add_zrtp_ctx();
//recv = receiver_session->create_stream(receiver_port, sender_port, RTP_FORMAT_GENERIC, flags);
}