#define MS_CLASS "RTC::Router"
#include "RTC/Router.hpp"
#include "Logger.hpp"
#include "MediaSoupErrors.hpp"
#include "Utils.hpp"
#include "RTC/ActiveSpeakerObserver.hpp"
#include "RTC/AudioLevelObserver.hpp"
#include "RTC/DirectTransport.hpp"
#include "RTC/PipeTransport.hpp"
#include "RTC/PlainTransport.hpp"
#include "RTC/WebRtcTransport.hpp"
namespace RTC
{
Router::Router(const std::string& id) : id(id)
{
MS_TRACE();
}
Router::~Router()
{
MS_TRACE();
for (auto& kv : this->mapTransports)
{
auto* transport = kv.second;
delete transport;
}
this->mapTransports.clear();
for (auto& kv : this->mapRtpObservers)
{
auto* rtpObserver = kv.second;
delete rtpObserver;
}
this->mapRtpObservers.clear();
this->mapProducerConsumers.clear();
this->mapConsumerProducer.clear();
this->mapProducerRtpObservers.clear();
this->mapProducers.clear();
this->mapDataProducerDataConsumers.clear();
this->mapDataConsumerDataProducer.clear();
this->mapDataProducers.clear();
}
void Router::FillJson(json& jsonObject) const
{
MS_TRACE();
jsonObject["id"] = this->id;
jsonObject["transportIds"] = json::array();
auto jsonTransportIdsIt = jsonObject.find("transportIds");
for (const auto& kv : this->mapTransports)
{
const auto& transportId = kv.first;
jsonTransportIdsIt->emplace_back(transportId);
}
jsonObject["rtpObserverIds"] = json::array();
auto jsonRtpObserverIdsIt = jsonObject.find("rtpObserverIds");
for (const auto& kv : this->mapRtpObservers)
{
const auto& rtpObserverId = kv.first;
jsonRtpObserverIdsIt->emplace_back(rtpObserverId);
}
jsonObject["mapProducerIdConsumerIds"] = json::object();
auto jsonMapProducerConsumersIt = jsonObject.find("mapProducerIdConsumerIds");
for (const auto& kv : this->mapProducerConsumers)
{
auto* producer = kv.first;
const auto& consumers = kv.second;
(*jsonMapProducerConsumersIt)[producer->id] = json::array();
auto jsonProducerIdIt = jsonMapProducerConsumersIt->find(producer->id);
for (auto* consumer : consumers)
{
jsonProducerIdIt->emplace_back(consumer->id);
}
}
jsonObject["mapConsumerIdProducerId"] = json::object();
auto jsonMapConsumerProducerIt = jsonObject.find("mapConsumerIdProducerId");
for (const auto& kv : this->mapConsumerProducer)
{
auto* consumer = kv.first;
auto* producer = kv.second;
(*jsonMapConsumerProducerIt)[consumer->id] = producer->id;
}
jsonObject["mapProducerIdObserverIds"] = json::object();
auto jsonMapProducerRtpObserversIt = jsonObject.find("mapProducerIdObserverIds");
for (const auto& kv : this->mapProducerRtpObservers)
{
auto* producer = kv.first;
const auto& rtpObservers = kv.second;
(*jsonMapProducerRtpObserversIt)[producer->id] = json::array();
auto jsonProducerIdIt = jsonMapProducerRtpObserversIt->find(producer->id);
for (auto* rtpObserver : rtpObservers)
{
jsonProducerIdIt->emplace_back(rtpObserver->id);
}
}
jsonObject["mapDataProducerIdDataConsumerIds"] = json::object();
auto jsonMapDataProducerDataConsumersIt = jsonObject.find("mapDataProducerIdDataConsumerIds");
for (const auto& kv : this->mapDataProducerDataConsumers)
{
auto* dataProducer = kv.first;
const auto& dataConsumers = kv.second;
(*jsonMapDataProducerDataConsumersIt)[dataProducer->id] = json::array();
auto jsonDataProducerIdIt = jsonMapDataProducerDataConsumersIt->find(dataProducer->id);
for (auto* dataConsumer : dataConsumers)
{
jsonDataProducerIdIt->emplace_back(dataConsumer->id);
}
}
jsonObject["mapDataConsumerIdDataProducerId"] = json::object();
auto jsonMapDataConsumerDataProducerIt = jsonObject.find("mapDataConsumerIdDataProducerId");
for (const auto& kv : this->mapDataConsumerDataProducer)
{
auto* dataConsumer = kv.first;
auto* dataProducer = kv.second;
(*jsonMapDataConsumerDataProducerIt)[dataConsumer->id] = dataProducer->id;
}
}
void Router::HandleRequest(Channel::ChannelRequest* request)
{
MS_TRACE();
switch (request->methodId)
{
case Channel::ChannelRequest::MethodId::ROUTER_DUMP:
{
json data = json::object();
FillJson(data);
request->Accept(data);
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_WEBRTC_TRANSPORT:
{
std::string transportId;
SetNewTransportIdFromInternal(request->internal, transportId);
auto* webRtcTransport = new RTC::WebRtcTransport(transportId, this, request->data);
this->mapTransports[transportId] = webRtcTransport;
MS_DEBUG_DEV("WebRtcTransport created [transportId:%s]", transportId.c_str());
json data = json::object();
webRtcTransport->FillJson(data);
request->Accept(data);
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PLAIN_TRANSPORT:
{
std::string transportId;
SetNewTransportIdFromInternal(request->internal, transportId);
auto* plainTransport = new RTC::PlainTransport(transportId, this, request->data);
this->mapTransports[transportId] = plainTransport;
MS_DEBUG_DEV("PlainTransport created [transportId:%s]", transportId.c_str());
json data = json::object();
plainTransport->FillJson(data);
request->Accept(data);
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_PIPE_TRANSPORT:
{
std::string transportId;
SetNewTransportIdFromInternal(request->internal, transportId);
auto* pipeTransport = new RTC::PipeTransport(transportId, this, request->data);
this->mapTransports[transportId] = pipeTransport;
MS_DEBUG_DEV("PipeTransport created [transportId:%s]", transportId.c_str());
json data = json::object();
pipeTransport->FillJson(data);
request->Accept(data);
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_DIRECT_TRANSPORT:
{
std::string transportId;
SetNewTransportIdFromInternal(request->internal, transportId);
auto* directTransport = new RTC::DirectTransport(transportId, this, request->data);
this->mapTransports[transportId] = directTransport;
MS_DEBUG_DEV("DirectTransport created [transportId:%s]", transportId.c_str());
json data = json::object();
directTransport->FillJson(data);
request->Accept(data);
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_ACTIVE_SPEAKER_OBSERVER:
{
std::string rtpObserverId;
SetNewRtpObserverIdFromInternal(request->internal, rtpObserverId);
auto* activeSpeakerObserver = new RTC::ActiveSpeakerObserver(rtpObserverId, request->data);
this->mapRtpObservers[rtpObserverId] = activeSpeakerObserver;
MS_DEBUG_DEV("ActiveSpeakerObserver created [rtpObserverId:%s]", rtpObserverId.c_str());
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::ROUTER_CREATE_AUDIO_LEVEL_OBSERVER:
{
std::string rtpObserverId;
SetNewRtpObserverIdFromInternal(request->internal, rtpObserverId);
auto* audioLevelObserver = new RTC::AudioLevelObserver(rtpObserverId, request->data);
this->mapRtpObservers[rtpObserverId] = audioLevelObserver;
MS_DEBUG_DEV("AudioLevelObserver created [rtpObserverId:%s]", rtpObserverId.c_str());
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::TRANSPORT_CLOSE:
{
RTC::Transport* transport = GetTransportFromInternal(request->internal);
transport->CloseProducersAndConsumers();
this->mapTransports.erase(transport->id);
MS_DEBUG_DEV("Transport closed [transportId:%s]", transport->id.c_str());
delete transport;
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::RTP_OBSERVER_CLOSE:
{
RTC::RtpObserver* rtpObserver = GetRtpObserverFromInternal(request->internal);
this->mapRtpObservers.erase(rtpObserver->id);
for (auto& kv : this->mapProducerRtpObservers)
{
auto& rtpObservers = kv.second;
rtpObservers.erase(rtpObserver);
}
MS_DEBUG_DEV("RtpObserver closed [rtpObserverId:%s]", rtpObserver->id.c_str());
delete rtpObserver;
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::RTP_OBSERVER_PAUSE:
{
RTC::RtpObserver* rtpObserver = GetRtpObserverFromInternal(request->internal);
rtpObserver->Pause();
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::RTP_OBSERVER_RESUME:
{
RTC::RtpObserver* rtpObserver = GetRtpObserverFromInternal(request->internal);
rtpObserver->Resume();
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::RTP_OBSERVER_ADD_PRODUCER:
{
RTC::RtpObserver* rtpObserver = GetRtpObserverFromInternal(request->internal);
RTC::Producer* producer = GetProducerFromData(request->data);
rtpObserver->AddProducer(producer);
this->mapProducerRtpObservers[producer].insert(rtpObserver);
request->Accept();
break;
}
case Channel::ChannelRequest::MethodId::RTP_OBSERVER_REMOVE_PRODUCER:
{
RTC::RtpObserver* rtpObserver = GetRtpObserverFromInternal(request->internal);
RTC::Producer* producer = GetProducerFromData(request->data);
rtpObserver->RemoveProducer(producer);
this->mapProducerRtpObservers[producer].erase(rtpObserver);
request->Accept();
break;
}
default:
{
RTC::Transport* transport = GetTransportFromInternal(request->internal);
transport->HandleRequest(request);
break;
}
}
}
void Router::HandleRequest(PayloadChannel::PayloadChannelRequest* request)
{
MS_TRACE();
RTC::Transport* transport = GetTransportFromInternal(request->internal);
transport->HandleRequest(request);
}
void Router::HandleNotification(PayloadChannel::Notification* notification)
{
MS_TRACE();
RTC::Transport* transport = GetTransportFromInternal(notification->internal);
transport->HandleNotification(notification);
}
void Router::SetNewTransportIdFromInternal(json& internal, std::string& transportId) const
{
MS_TRACE();
auto jsonTransportIdIt = internal.find("transportId");
if (jsonTransportIdIt == internal.end() || !jsonTransportIdIt->is_string())
MS_THROW_ERROR("missing internal.transportId");
transportId.assign(jsonTransportIdIt->get<std::string>());
if (this->mapTransports.find(transportId) != this->mapTransports.end())
MS_THROW_ERROR("a Transport with same transportId already exists");
}
RTC::Transport* Router::GetTransportFromInternal(json& internal) const
{
MS_TRACE();
auto jsonTransportIdIt = internal.find("transportId");
if (jsonTransportIdIt == internal.end() || !jsonTransportIdIt->is_string())
MS_THROW_ERROR("missing internal.transportId");
auto it = this->mapTransports.find(jsonTransportIdIt->get<std::string>());
if (it == this->mapTransports.end())
MS_THROW_ERROR("Transport not found");
RTC::Transport* transport = it->second;
return transport;
}
void Router::SetNewRtpObserverIdFromInternal(json& internal, std::string& rtpObserverId) const
{
MS_TRACE();
auto jsonRtpObserverIdIt = internal.find("rtpObserverId");
if (jsonRtpObserverIdIt == internal.end() || !jsonRtpObserverIdIt->is_string())
MS_THROW_ERROR("missing internal.rtpObserverId");
rtpObserverId.assign(jsonRtpObserverIdIt->get<std::string>());
if (this->mapRtpObservers.find(rtpObserverId) != this->mapRtpObservers.end())
MS_THROW_ERROR("an RtpObserver with same rtpObserverId already exists");
}
RTC::RtpObserver* Router::GetRtpObserverFromInternal(json& internal) const
{
MS_TRACE();
auto jsonRtpObserverIdIt = internal.find("rtpObserverId");
if (jsonRtpObserverIdIt == internal.end() || !jsonRtpObserverIdIt->is_string())
MS_THROW_ERROR("missing internal.rtpObserverId");
auto it = this->mapRtpObservers.find(jsonRtpObserverIdIt->get<std::string>());
if (it == this->mapRtpObservers.end())
MS_THROW_ERROR("RtpObserver not found");
RTC::RtpObserver* rtpObserver = it->second;
return rtpObserver;
}
RTC::Producer* Router::GetProducerFromData(json& data) const
{
MS_TRACE();
auto jsonProducerIdIt = data.find("producerId");
if (jsonProducerIdIt == data.end() || !jsonProducerIdIt->is_string())
MS_THROW_ERROR("missing data.producerId");
auto it = this->mapProducers.find(jsonProducerIdIt->get<std::string>());
if (it == this->mapProducers.end())
MS_THROW_ERROR("Producer not found");
RTC::Producer* producer = it->second;
return producer;
}
inline void Router::OnTransportNewProducer(RTC::Transport* , RTC::Producer* producer)
{
MS_TRACE();
MS_ASSERT(
this->mapProducerConsumers.find(producer) == this->mapProducerConsumers.end(),
"Producer already present in mapProducerConsumers");
if (this->mapProducers.find(producer->id) != this->mapProducers.end())
{
MS_THROW_ERROR("Producer already present in mapProducers [producerId:%s]", producer->id.c_str());
}
this->mapProducers[producer->id] = producer;
this->mapProducerConsumers[producer];
this->mapProducerRtpObservers[producer];
}
inline void Router::OnTransportProducerClosed(RTC::Transport* , RTC::Producer* producer)
{
MS_TRACE();
auto mapProducerConsumersIt = this->mapProducerConsumers.find(producer);
auto mapProducersIt = this->mapProducers.find(producer->id);
auto mapProducerRtpObserversIt = this->mapProducerRtpObservers.find(producer);
MS_ASSERT(
mapProducerConsumersIt != this->mapProducerConsumers.end(),
"Producer not present in mapProducerConsumers");
MS_ASSERT(mapProducersIt != this->mapProducers.end(), "Producer not present in mapProducers");
MS_ASSERT(
mapProducerRtpObserversIt != this->mapProducerRtpObservers.end(),
"Producer not present in mapProducerRtpObservers");
auto& consumers = mapProducerConsumersIt->second;
for (auto* consumer : consumers)
{
consumer->ProducerClosed();
}
auto& rtpObservers = mapProducerRtpObserversIt->second;
for (auto* rtpObserver : rtpObservers)
{
rtpObserver->RemoveProducer(producer);
}
this->mapProducers.erase(mapProducersIt);
this->mapProducerConsumers.erase(mapProducerConsumersIt);
this->mapProducerRtpObservers.erase(mapProducerRtpObserversIt);
}
inline void Router::OnTransportProducerPaused(RTC::Transport* , RTC::Producer* producer)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->ProducerPaused();
}
auto it = this->mapProducerRtpObservers.find(producer);
if (it != this->mapProducerRtpObservers.end())
{
auto& rtpObservers = it->second;
for (auto* rtpObserver : rtpObservers)
{
rtpObserver->ProducerPaused(producer);
}
}
}
inline void Router::OnTransportProducerResumed(RTC::Transport* , RTC::Producer* producer)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->ProducerResumed();
}
auto it = this->mapProducerRtpObservers.find(producer);
if (it != this->mapProducerRtpObservers.end())
{
auto& rtpObservers = it->second;
for (auto* rtpObserver : rtpObservers)
{
rtpObserver->ProducerResumed(producer);
}
}
}
inline void Router::OnTransportProducerNewRtpStream(
RTC::Transport* , RTC::Producer* producer, RTC::RtpStream* rtpStream, uint32_t mappedSsrc)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->ProducerNewRtpStream(rtpStream, mappedSsrc);
}
}
inline void Router::OnTransportProducerRtpStreamScore(
RTC::Transport* ,
RTC::Producer* producer,
RTC::RtpStream* rtpStream,
uint8_t score,
uint8_t previousScore)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->ProducerRtpStreamScore(rtpStream, score, previousScore);
}
}
inline void Router::OnTransportProducerRtcpSenderReport(
RTC::Transport* , RTC::Producer* producer, RTC::RtpStream* rtpStream, bool first)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->ProducerRtcpSenderReport(rtpStream, first);
}
}
inline void Router::OnTransportProducerRtpPacketReceived(
RTC::Transport* , RTC::Producer* producer, RTC::RtpPacket* packet)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
const auto& mid = consumer->GetRtpParameters().mid;
if (!mid.empty())
packet->UpdateMid(mid);
consumer->SendRtpPacket(packet);
}
auto it = this->mapProducerRtpObservers.find(producer);
if (it != this->mapProducerRtpObservers.end())
{
auto& rtpObservers = it->second;
for (auto* rtpObserver : rtpObservers)
{
rtpObserver->ReceiveRtpPacket(producer, packet);
}
}
}
inline void Router::OnTransportNeedWorstRemoteFractionLost(
RTC::Transport* ,
RTC::Producer* producer,
uint32_t mappedSsrc,
uint8_t& worstRemoteFractionLost)
{
MS_TRACE();
auto& consumers = this->mapProducerConsumers.at(producer);
for (auto* consumer : consumers)
{
consumer->NeedWorstRemoteFractionLost(mappedSsrc, worstRemoteFractionLost);
}
}
inline void Router::OnTransportNewConsumer(
RTC::Transport* , RTC::Consumer* consumer, std::string& producerId)
{
MS_TRACE();
auto mapProducersIt = this->mapProducers.find(producerId);
if (mapProducersIt == this->mapProducers.end())
MS_THROW_ERROR("Producer not found [producerId:%s]", producerId.c_str());
auto* producer = mapProducersIt->second;
auto mapProducerConsumersIt = this->mapProducerConsumers.find(producer);
MS_ASSERT(
mapProducerConsumersIt != this->mapProducerConsumers.end(),
"Producer not present in mapProducerConsumers");
MS_ASSERT(
this->mapConsumerProducer.find(consumer) == this->mapConsumerProducer.end(),
"Consumer already present in mapConsumerProducer");
if (producer->IsPaused())
consumer->ProducerPaused();
auto& consumers = mapProducerConsumersIt->second;
consumers.insert(consumer);
this->mapConsumerProducer[consumer] = producer;
for (const auto& kv : producer->GetRtpStreams())
{
auto* rtpStream = kv.first;
uint32_t mappedSsrc = kv.second;
consumer->ProducerRtpStream(rtpStream, mappedSsrc);
}
consumer->ProducerRtpStreamScores(producer->GetRtpStreamScores());
}
inline void Router::OnTransportConsumerClosed(RTC::Transport* , RTC::Consumer* consumer)
{
MS_TRACE();
auto mapConsumerProducerIt = this->mapConsumerProducer.find(consumer);
MS_ASSERT(
mapConsumerProducerIt != this->mapConsumerProducer.end(),
"Consumer not present in mapConsumerProducer");
auto* producer = mapConsumerProducerIt->second;
MS_ASSERT(
this->mapProducerConsumers.find(producer) != this->mapProducerConsumers.end(),
"Producer not present in mapProducerConsumers");
auto& consumers = this->mapProducerConsumers.at(producer);
consumers.erase(consumer);
this->mapConsumerProducer.erase(mapConsumerProducerIt);
}
inline void Router::OnTransportConsumerProducerClosed(
RTC::Transport* , RTC::Consumer* consumer)
{
MS_TRACE();
auto mapConsumerProducerIt = this->mapConsumerProducer.find(consumer);
MS_ASSERT(
mapConsumerProducerIt != this->mapConsumerProducer.end(),
"Consumer not present in mapConsumerProducer");
this->mapConsumerProducer.erase(mapConsumerProducerIt);
}
inline void Router::OnTransportConsumerKeyFrameRequested(
RTC::Transport* , RTC::Consumer* consumer, uint32_t mappedSsrc)
{
MS_TRACE();
auto* producer = this->mapConsumerProducer.at(consumer);
producer->RequestKeyFrame(mappedSsrc);
}
inline void Router::OnTransportNewDataProducer(
RTC::Transport* , RTC::DataProducer* dataProducer)
{
MS_TRACE();
MS_ASSERT(
this->mapDataProducerDataConsumers.find(dataProducer) ==
this->mapDataProducerDataConsumers.end(),
"DataProducer already present in mapDataProducerDataConsumers");
if (this->mapDataProducers.find(dataProducer->id) != this->mapDataProducers.end())
{
MS_THROW_ERROR(
"DataProducer already present in mapDataProducers [dataProducerId:%s]",
dataProducer->id.c_str());
}
this->mapDataProducers[dataProducer->id] = dataProducer;
this->mapDataProducerDataConsumers[dataProducer];
}
inline void Router::OnTransportDataProducerClosed(
RTC::Transport* , RTC::DataProducer* dataProducer)
{
MS_TRACE();
auto mapDataProducerDataConsumersIt = this->mapDataProducerDataConsumers.find(dataProducer);
auto mapDataProducersIt = this->mapDataProducers.find(dataProducer->id);
MS_ASSERT(
mapDataProducerDataConsumersIt != this->mapDataProducerDataConsumers.end(),
"DataProducer not present in mapDataProducerDataConsumers");
MS_ASSERT(
mapDataProducersIt != this->mapDataProducers.end(),
"DataProducer not present in mapDataProducers");
auto& dataConsumers = mapDataProducerDataConsumersIt->second;
for (auto* dataConsumer : dataConsumers)
{
dataConsumer->DataProducerClosed();
}
this->mapDataProducers.erase(mapDataProducersIt);
this->mapDataProducerDataConsumers.erase(mapDataProducerDataConsumersIt);
}
inline void Router::OnTransportDataProducerMessageReceived(
RTC::Transport* ,
RTC::DataProducer* dataProducer,
uint32_t ppid,
const uint8_t* msg,
size_t len)
{
MS_TRACE();
auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer);
for (auto* consumer : dataConsumers)
{
consumer->SendMessage(ppid, msg, len);
}
}
inline void Router::OnTransportNewDataConsumer(
RTC::Transport* , RTC::DataConsumer* dataConsumer, std::string& dataProducerId)
{
MS_TRACE();
auto mapDataProducersIt = this->mapDataProducers.find(dataProducerId);
if (mapDataProducersIt == this->mapDataProducers.end())
MS_THROW_ERROR("DataProducer not found [dataProducerId:%s]", dataProducerId.c_str());
auto* dataProducer = mapDataProducersIt->second;
auto mapDataProducerDataConsumersIt = this->mapDataProducerDataConsumers.find(dataProducer);
MS_ASSERT(
mapDataProducerDataConsumersIt != this->mapDataProducerDataConsumers.end(),
"DataProducer not present in mapDataProducerDataConsumers");
MS_ASSERT(
this->mapDataConsumerDataProducer.find(dataConsumer) == this->mapDataConsumerDataProducer.end(),
"DataConsumer already present in mapDataConsumerDataProducer");
auto& dataConsumers = mapDataProducerDataConsumersIt->second;
dataConsumers.insert(dataConsumer);
this->mapDataConsumerDataProducer[dataConsumer] = dataProducer;
}
inline void Router::OnTransportDataConsumerClosed(
RTC::Transport* , RTC::DataConsumer* dataConsumer)
{
MS_TRACE();
auto mapDataConsumerDataProducerIt = this->mapDataConsumerDataProducer.find(dataConsumer);
MS_ASSERT(
mapDataConsumerDataProducerIt != this->mapDataConsumerDataProducer.end(),
"DataConsumer not present in mapDataConsumerDataProducer");
auto* dataProducer = mapDataConsumerDataProducerIt->second;
MS_ASSERT(
this->mapDataProducerDataConsumers.find(dataProducer) !=
this->mapDataProducerDataConsumers.end(),
"DataProducer not present in mapDataProducerDataConsumers");
auto& dataConsumers = this->mapDataProducerDataConsumers.at(dataProducer);
dataConsumers.erase(dataConsumer);
this->mapDataConsumerDataProducer.erase(mapDataConsumerDataProducerIt);
}
inline void Router::OnTransportDataConsumerDataProducerClosed(
RTC::Transport* , RTC::DataConsumer* dataConsumer)
{
MS_TRACE();
auto mapDataConsumerDataProducerIt = this->mapDataConsumerDataProducer.find(dataConsumer);
MS_ASSERT(
mapDataConsumerDataProducerIt != this->mapDataConsumerDataProducer.end(),
"DataConsumer not present in mapDataConsumerDataProducer");
this->mapDataConsumerDataProducer.erase(mapDataConsumerDataProducerIt);
}
}