Refactoring DataChannelController from PeerConnection part 4
This CL: - Moved HasDataChannel and data_channel_type_ - Moved rtp_data_channels_ - Moved sctp_data_channels_ - Moved data_channel_controller to its own .h file - Various changes to reduce the coupling between the classes - Removed friendship between DataChannelController and PeerConnection Bug: webrtc:11146 Change-Id: Ib8c395e4c90ce34baf40812d1dade0ffa79f2438 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/161094 Commit-Queue: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#29987}
This commit is contained in:

committed by
Commit Bot

parent
bcce4530d4
commit
05e4d08e35
@ -167,6 +167,7 @@ rtc_library("peerconnection") {
|
|||||||
"data_channel.cc",
|
"data_channel.cc",
|
||||||
"data_channel.h",
|
"data_channel.h",
|
||||||
"data_channel_controller.cc",
|
"data_channel_controller.cc",
|
||||||
|
"data_channel_controller.h",
|
||||||
"dtmf_sender.cc",
|
"dtmf_sender.cc",
|
||||||
"dtmf_sender.h",
|
"dtmf_sender.h",
|
||||||
"ice_server_parsing.cc",
|
"ice_server_parsing.cc",
|
||||||
|
@ -8,22 +8,23 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file contains the implementation of the class
|
#include "pc/data_channel_controller.h"
|
||||||
// webrtc::PeerConnection::DataChannelController.
|
|
||||||
//
|
#include <utility>
|
||||||
// The intent is that this should be webrtc::DataChannelController, but
|
|
||||||
// as a migration stage, it is simpler to have it as an inner class,
|
|
||||||
// declared in the header file pc/peer_connection.h
|
|
||||||
|
|
||||||
#include "pc/peer_connection.h"
|
#include "pc/peer_connection.h"
|
||||||
#include "pc/sctp_utils.h"
|
#include "pc/sctp_utils.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
bool PeerConnection::DataChannelController::SendData(
|
bool DataChannelController::HasDataChannels() const {
|
||||||
const cricket::SendDataParams& params,
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
const rtc::CopyOnWriteBuffer& payload,
|
return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
|
||||||
cricket::SendDataResult* result) {
|
}
|
||||||
|
|
||||||
|
bool DataChannelController::SendData(const cricket::SendDataParams& params,
|
||||||
|
const rtc::CopyOnWriteBuffer& payload,
|
||||||
|
cricket::SendDataResult* result) {
|
||||||
// RTC_DCHECK_RUN_ON(signaling_thread());
|
// RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
SendDataParams send_params;
|
SendDataParams send_params;
|
||||||
@ -59,7 +60,7 @@ bool PeerConnection::DataChannelController::SendData(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerConnection::DataChannelController::ConnectDataChannel(
|
bool DataChannelController::ConnectDataChannel(
|
||||||
DataChannel* webrtc_data_channel) {
|
DataChannel* webrtc_data_channel) {
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
if (!rtp_data_channel() && !data_channel_transport()) {
|
if (!rtp_data_channel() && !data_channel_transport()) {
|
||||||
@ -87,7 +88,7 @@ bool PeerConnection::DataChannelController::ConnectDataChannel(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::DisconnectDataChannel(
|
void DataChannelController::DisconnectDataChannel(
|
||||||
DataChannel* webrtc_data_channel) {
|
DataChannel* webrtc_data_channel) {
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
if (!rtp_data_channel() && !data_channel_transport()) {
|
if (!rtp_data_channel() && !data_channel_transport()) {
|
||||||
@ -108,7 +109,7 @@ void PeerConnection::DataChannelController::DisconnectDataChannel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::AddSctpDataStream(int sid) {
|
void DataChannelController::AddSctpDataStream(int sid) {
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
|
network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
@ -118,7 +119,7 @@ void PeerConnection::DataChannelController::AddSctpDataStream(int sid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::RemoveSctpDataStream(int sid) {
|
void DataChannelController::RemoveSctpDataStream(int sid) {
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
|
network_thread()->Invoke<void>(RTC_FROM_HERE, [this, sid] {
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
@ -128,13 +129,13 @@ void PeerConnection::DataChannelController::RemoveSctpDataStream(int sid) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerConnection::DataChannelController::ReadyToSendData() const {
|
bool DataChannelController::ReadyToSendData() const {
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
return (rtp_data_channel() && rtp_data_channel()->ready_to_send_data()) ||
|
return (rtp_data_channel() && rtp_data_channel()->ready_to_send_data()) ||
|
||||||
(data_channel_transport() && data_channel_transport_ready_to_send_);
|
(data_channel_transport() && data_channel_transport_ready_to_send_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnDataReceived(
|
void DataChannelController::OnDataReceived(
|
||||||
int channel_id,
|
int channel_id,
|
||||||
DataMessageType type,
|
DataMessageType type,
|
||||||
const rtc::CopyOnWriteBuffer& buffer) {
|
const rtc::CopyOnWriteBuffer& buffer) {
|
||||||
@ -151,7 +152,7 @@ void PeerConnection::DataChannelController::OnDataReceived(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnChannelClosing(int channel_id) {
|
void DataChannelController::OnChannelClosing(int channel_id) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_->AsyncInvoke<void>(
|
data_channel_transport_invoker_->AsyncInvoke<void>(
|
||||||
RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
|
RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
|
||||||
@ -160,7 +161,7 @@ void PeerConnection::DataChannelController::OnChannelClosing(int channel_id) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnChannelClosed(int channel_id) {
|
void DataChannelController::OnChannelClosed(int channel_id) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_->AsyncInvoke<void>(
|
data_channel_transport_invoker_->AsyncInvoke<void>(
|
||||||
RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
|
RTC_FROM_HERE, signaling_thread(), [this, channel_id] {
|
||||||
@ -169,7 +170,7 @@ void PeerConnection::DataChannelController::OnChannelClosed(int channel_id) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnReadyToSend() {
|
void DataChannelController::OnReadyToSend() {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_->AsyncInvoke<void>(
|
data_channel_transport_invoker_->AsyncInvoke<void>(
|
||||||
RTC_FROM_HERE, signaling_thread(), [this] {
|
RTC_FROM_HERE, signaling_thread(), [this] {
|
||||||
@ -180,12 +181,12 @@ void PeerConnection::DataChannelController::OnReadyToSend() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::SetupDataChannelTransport_n() {
|
void DataChannelController::SetupDataChannelTransport_n() {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>();
|
data_channel_transport_invoker_ = std::make_unique<rtc::AsyncInvoker>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::TeardownDataChannelTransport_n() {
|
void DataChannelController::TeardownDataChannelTransport_n() {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
data_channel_transport_invoker_ = nullptr;
|
data_channel_transport_invoker_ = nullptr;
|
||||||
if (data_channel_transport()) {
|
if (data_channel_transport()) {
|
||||||
@ -194,7 +195,7 @@ void PeerConnection::DataChannelController::TeardownDataChannelTransport_n() {
|
|||||||
set_data_channel_transport(nullptr);
|
set_data_channel_transport(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnTransportChanged(
|
void DataChannelController::OnTransportChanged(
|
||||||
DataChannelTransportInterface* new_data_channel_transport) {
|
DataChannelTransportInterface* new_data_channel_transport) {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
if (data_channel_transport() &&
|
if (data_channel_transport() &&
|
||||||
@ -211,8 +212,8 @@ void PeerConnection::DataChannelController::OnTransportChanged(
|
|||||||
// necessary when bundling is applied.
|
// necessary when bundling is applied.
|
||||||
data_channel_transport_invoker_->AsyncInvoke<void>(
|
data_channel_transport_invoker_->AsyncInvoke<void>(
|
||||||
RTC_FROM_HERE, signaling_thread(), [this] {
|
RTC_FROM_HERE, signaling_thread(), [this] {
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
for (auto channel : pc_->sctp_data_channels_) {
|
for (auto channel : sctp_data_channels_) {
|
||||||
channel->OnTransportChannelCreated();
|
channel->OnTransportChannelCreated();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -220,7 +221,7 @@ void PeerConnection::DataChannelController::OnTransportChanged(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerConnection::DataChannelController::HandleOpenMessage_s(
|
bool DataChannelController::HandleOpenMessage_s(
|
||||||
const cricket::ReceiveDataParams& params,
|
const cricket::ReceiveDataParams& params,
|
||||||
const rtc::CopyOnWriteBuffer& buffer) {
|
const rtc::CopyOnWriteBuffer& buffer) {
|
||||||
if (params.type == cricket::DMT_CONTROL && IsOpenMessage(buffer)) {
|
if (params.type == cricket::DMT_CONTROL && IsOpenMessage(buffer)) {
|
||||||
@ -241,7 +242,7 @@ bool PeerConnection::DataChannelController::HandleOpenMessage_s(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnDataChannelOpenMessage(
|
void DataChannelController::OnDataChannelOpenMessage(
|
||||||
const std::string& label,
|
const std::string& label,
|
||||||
const InternalDataChannelInit& config) {
|
const InternalDataChannelInit& config) {
|
||||||
rtc::scoped_refptr<DataChannel> channel(
|
rtc::scoped_refptr<DataChannel> channel(
|
||||||
@ -253,29 +254,26 @@ void PeerConnection::DataChannelController::OnDataChannelOpenMessage(
|
|||||||
|
|
||||||
rtc::scoped_refptr<DataChannelInterface> proxy_channel =
|
rtc::scoped_refptr<DataChannelInterface> proxy_channel =
|
||||||
DataChannelProxy::Create(signaling_thread(), channel);
|
DataChannelProxy::Create(signaling_thread(), channel);
|
||||||
{
|
pc_->Observer()->OnDataChannel(std::move(proxy_channel));
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
pc_->NoteDataAddedEvent();
|
||||||
pc_->Observer()->OnDataChannel(std::move(proxy_channel));
|
|
||||||
pc_->NoteUsageEvent(UsageEvent::DATA_ADDED);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<DataChannel>
|
rtc::scoped_refptr<DataChannel>
|
||||||
PeerConnection::DataChannelController::InternalCreateDataChannel(
|
DataChannelController::InternalCreateDataChannel(
|
||||||
const std::string& label,
|
const std::string& label,
|
||||||
const InternalDataChannelInit* config) {
|
const InternalDataChannelInit* config) {
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
if (pc_->IsClosed()) {
|
if (pc_->IsClosed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (pc_->data_channel_type() == cricket::DCT_NONE) {
|
if (data_channel_type_ == cricket::DCT_NONE) {
|
||||||
RTC_LOG(LS_ERROR)
|
RTC_LOG(LS_ERROR)
|
||||||
<< "InternalCreateDataChannel: Data is not supported in this call.";
|
<< "InternalCreateDataChannel: Data is not supported in this call.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
InternalDataChannelInit new_config =
|
InternalDataChannelInit new_config =
|
||||||
config ? (*config) : InternalDataChannelInit();
|
config ? (*config) : InternalDataChannelInit();
|
||||||
if (DataChannel::IsSctpLike(pc_->data_channel_type_)) {
|
if (DataChannel::IsSctpLike(data_channel_type_)) {
|
||||||
if (new_config.id < 0) {
|
if (new_config.id < 0) {
|
||||||
rtc::SSLRole role;
|
rtc::SSLRole role;
|
||||||
if ((pc_->GetSctpSslRole(&role)) &&
|
if ((pc_->GetSctpSslRole(&role)) &&
|
||||||
@ -292,36 +290,33 @@ PeerConnection::DataChannelController::InternalCreateDataChannel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rtc::scoped_refptr<DataChannel> channel(
|
rtc::scoped_refptr<DataChannel> channel(
|
||||||
DataChannel::Create(this, pc_->data_channel_type(), label, new_config));
|
DataChannel::Create(this, data_channel_type(), label, new_config));
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
sid_allocator_.ReleaseSid(new_config.id);
|
sid_allocator_.ReleaseSid(new_config.id);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (channel->data_channel_type() == cricket::DCT_RTP) {
|
if (channel->data_channel_type() == cricket::DCT_RTP) {
|
||||||
if (pc_->rtp_data_channels_.find(channel->label()) !=
|
if (rtp_data_channels_.find(channel->label()) != rtp_data_channels_.end()) {
|
||||||
pc_->rtp_data_channels_.end()) {
|
|
||||||
RTC_LOG(LS_ERROR) << "DataChannel with label " << channel->label()
|
RTC_LOG(LS_ERROR) << "DataChannel with label " << channel->label()
|
||||||
<< " already exists.";
|
<< " already exists.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pc_->rtp_data_channels_[channel->label()] = channel;
|
rtp_data_channels_[channel->label()] = channel;
|
||||||
} else {
|
} else {
|
||||||
RTC_DCHECK(DataChannel::IsSctpLike(pc_->data_channel_type_));
|
RTC_DCHECK(DataChannel::IsSctpLike(data_channel_type_));
|
||||||
pc_->sctp_data_channels_.push_back(channel);
|
sctp_data_channels_.push_back(channel);
|
||||||
channel->SignalClosed.connect(pc_,
|
channel->SignalClosed.connect(pc_,
|
||||||
&PeerConnection::OnSctpDataChannelClosed);
|
&PeerConnection::OnSctpDataChannelClosed);
|
||||||
}
|
}
|
||||||
|
SignalDataChannelCreated_(channel.get());
|
||||||
pc_->SignalDataChannelCreated_(channel.get());
|
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::AllocateSctpSids(
|
void DataChannelController::AllocateSctpSids(rtc::SSLRole role) {
|
||||||
rtc::SSLRole role) {
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
|
||||||
std::vector<rtc::scoped_refptr<DataChannel>> channels_to_close;
|
std::vector<rtc::scoped_refptr<DataChannel>> channels_to_close;
|
||||||
for (const auto& channel : pc_->sctp_data_channels_) {
|
for (const auto& channel : sctp_data_channels_) {
|
||||||
if (channel->id() < 0) {
|
if (channel->id() < 0) {
|
||||||
int sid;
|
int sid;
|
||||||
if (!sid_allocator_.AllocateSid(role, &sid)) {
|
if (!sid_allocator_.AllocateSid(role, &sid)) {
|
||||||
@ -339,11 +334,10 @@ void PeerConnection::DataChannelController::AllocateSctpSids(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::DataChannelController::OnSctpDataChannelClosed(
|
void DataChannelController::OnSctpDataChannelClosed(DataChannel* channel) {
|
||||||
DataChannel* channel) {
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
RTC_DCHECK_RUN_ON(pc_->signaling_thread());
|
for (auto it = sctp_data_channels_.begin(); it != sctp_data_channels_.end();
|
||||||
for (auto it = pc_->sctp_data_channels_.begin();
|
++it) {
|
||||||
it != pc_->sctp_data_channels_.end(); ++it) {
|
|
||||||
if (it->get() == channel) {
|
if (it->get() == channel) {
|
||||||
if (channel->id() >= 0) {
|
if (channel->id() >= 0) {
|
||||||
// After the closing procedure is done, it's safe to use this ID for
|
// After the closing procedure is done, it's safe to use this ID for
|
||||||
@ -352,12 +346,138 @@ void PeerConnection::DataChannelController::OnSctpDataChannelClosed(
|
|||||||
}
|
}
|
||||||
// Since this method is triggered by a signal from the DataChannel,
|
// Since this method is triggered by a signal from the DataChannel,
|
||||||
// we can't free it directly here; we need to free it asynchronously.
|
// we can't free it directly here; we need to free it asynchronously.
|
||||||
pc_->sctp_data_channels_to_free_.push_back(*it);
|
sctp_data_channels_to_free_.push_back(*it);
|
||||||
pc_->sctp_data_channels_.erase(it);
|
sctp_data_channels_.erase(it);
|
||||||
pc_->SignalFreeDataChannels();
|
pc_->SignalFreeDataChannels();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DataChannelController::OnTransportChannelClosed() {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
// Use a temporary copy of the RTP/SCTP DataChannel list because the
|
||||||
|
// DataChannel may callback to us and try to modify the list.
|
||||||
|
std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
|
||||||
|
temp_rtp_dcs.swap(rtp_data_channels_);
|
||||||
|
for (const auto& kv : temp_rtp_dcs) {
|
||||||
|
kv.second->OnTransportChannelClosed();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
|
||||||
|
temp_sctp_dcs.swap(sctp_data_channels_);
|
||||||
|
for (const auto& channel : temp_sctp_dcs) {
|
||||||
|
channel->OnTransportChannelClosed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DataChannel* DataChannelController::FindDataChannelBySid(int sid) const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
for (const auto& channel : sctp_data_channels_) {
|
||||||
|
if (channel->id() == sid) {
|
||||||
|
return channel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataChannelController::UpdateLocalRtpDataChannels(
|
||||||
|
const cricket::StreamParamsVec& streams) {
|
||||||
|
std::vector<std::string> existing_channels;
|
||||||
|
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
// Find new and active data channels.
|
||||||
|
for (const cricket::StreamParams& params : streams) {
|
||||||
|
// |it->sync_label| is actually the data channel label. The reason is that
|
||||||
|
// we use the same naming of data channels as we do for
|
||||||
|
// MediaStreams and Tracks.
|
||||||
|
// For MediaStreams, the sync_label is the MediaStream label and the
|
||||||
|
// track label is the same as |streamid|.
|
||||||
|
const std::string& channel_label = params.first_stream_id();
|
||||||
|
auto data_channel_it = rtp_data_channels()->find(channel_label);
|
||||||
|
if (data_channel_it == rtp_data_channels()->end()) {
|
||||||
|
RTC_LOG(LS_ERROR) << "channel label not found";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Set the SSRC the data channel should use for sending.
|
||||||
|
data_channel_it->second->SetSendSsrc(params.first_ssrc());
|
||||||
|
existing_channels.push_back(data_channel_it->first);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateClosingRtpDataChannels(existing_channels, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataChannelController::UpdateRemoteRtpDataChannels(
|
||||||
|
const cricket::StreamParamsVec& streams) {
|
||||||
|
std::vector<std::string> existing_channels;
|
||||||
|
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
// Find new and active data channels.
|
||||||
|
for (const cricket::StreamParams& params : streams) {
|
||||||
|
// The data channel label is either the mslabel or the SSRC if the mslabel
|
||||||
|
// does not exist. Ex a=ssrc:444330170 mslabel:test1.
|
||||||
|
std::string label = params.first_stream_id().empty()
|
||||||
|
? rtc::ToString(params.first_ssrc())
|
||||||
|
: params.first_stream_id();
|
||||||
|
auto data_channel_it = rtp_data_channels()->find(label);
|
||||||
|
if (data_channel_it == rtp_data_channels()->end()) {
|
||||||
|
// This is a new data channel.
|
||||||
|
CreateRemoteRtpDataChannel(label, params.first_ssrc());
|
||||||
|
} else {
|
||||||
|
data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
|
||||||
|
}
|
||||||
|
existing_channels.push_back(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateClosingRtpDataChannels(existing_channels, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataChannelController::UpdateClosingRtpDataChannels(
|
||||||
|
const std::vector<std::string>& active_channels,
|
||||||
|
bool is_local_update) {
|
||||||
|
auto it = rtp_data_channels_.begin();
|
||||||
|
while (it != rtp_data_channels_.end()) {
|
||||||
|
DataChannel* data_channel = it->second;
|
||||||
|
if (absl::c_linear_search(active_channels, data_channel->label())) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_local_update) {
|
||||||
|
data_channel->SetSendSsrc(0);
|
||||||
|
} else {
|
||||||
|
data_channel->RemotePeerRequestClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_channel->state() == DataChannel::kClosed) {
|
||||||
|
rtp_data_channels_.erase(it);
|
||||||
|
it = rtp_data_channels_.begin();
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataChannelController::CreateRemoteRtpDataChannel(const std::string& label,
|
||||||
|
uint32_t remote_ssrc) {
|
||||||
|
rtc::scoped_refptr<DataChannel> channel(
|
||||||
|
InternalCreateDataChannel(label, nullptr));
|
||||||
|
if (!channel.get()) {
|
||||||
|
RTC_LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
|
||||||
|
"CreateDataChannel failed.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
channel->SetReceiveSsrc(remote_ssrc);
|
||||||
|
rtc::scoped_refptr<DataChannelInterface> proxy_channel =
|
||||||
|
DataChannelProxy::Create(signaling_thread(), channel);
|
||||||
|
pc_->Observer()->OnDataChannel(std::move(proxy_channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc::Thread* DataChannelController::network_thread() const {
|
||||||
|
return pc_->network_thread();
|
||||||
|
}
|
||||||
|
rtc::Thread* DataChannelController::signaling_thread() const {
|
||||||
|
return pc_->signaling_thread();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
214
pc/data_channel_controller.h
Normal file
214
pc/data_channel_controller.h
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2019 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PC_DATA_CHANNEL_CONTROLLER_H_
|
||||||
|
#define PC_DATA_CHANNEL_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "pc/channel.h"
|
||||||
|
#include "pc/data_channel.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
class PeerConnection;
|
||||||
|
|
||||||
|
class DataChannelController : public DataChannelProviderInterface,
|
||||||
|
public DataChannelSink {
|
||||||
|
public:
|
||||||
|
explicit DataChannelController(PeerConnection* pc) : pc_(pc) {}
|
||||||
|
|
||||||
|
// Implements DataChannelProviderInterface.
|
||||||
|
bool SendData(const cricket::SendDataParams& params,
|
||||||
|
const rtc::CopyOnWriteBuffer& payload,
|
||||||
|
cricket::SendDataResult* result) override;
|
||||||
|
bool ConnectDataChannel(DataChannel* webrtc_data_channel) override;
|
||||||
|
void DisconnectDataChannel(DataChannel* webrtc_data_channel) override;
|
||||||
|
void AddSctpDataStream(int sid) override;
|
||||||
|
void RemoveSctpDataStream(int sid) override;
|
||||||
|
bool ReadyToSendData() const override;
|
||||||
|
|
||||||
|
// Implements DataChannelSink.
|
||||||
|
void OnDataReceived(int channel_id,
|
||||||
|
DataMessageType type,
|
||||||
|
const rtc::CopyOnWriteBuffer& buffer) override;
|
||||||
|
void OnChannelClosing(int channel_id) override;
|
||||||
|
void OnChannelClosed(int channel_id) override;
|
||||||
|
void OnReadyToSend() override;
|
||||||
|
|
||||||
|
// Called from PeerConnection::SetupDataChannelTransport_n
|
||||||
|
void SetupDataChannelTransport_n();
|
||||||
|
// Called from PeerConnection::TeardownDataChannelTransport_n
|
||||||
|
void TeardownDataChannelTransport_n();
|
||||||
|
|
||||||
|
// Called from PeerConnection::OnTransportChanged
|
||||||
|
// to make required changes to datachannels' transports.
|
||||||
|
void OnTransportChanged(
|
||||||
|
DataChannelTransportInterface* data_channel_transport);
|
||||||
|
|
||||||
|
// Creates channel and adds it to the collection of DataChannels that will
|
||||||
|
// be offered in a SessionDescription.
|
||||||
|
rtc::scoped_refptr<DataChannel> InternalCreateDataChannel(
|
||||||
|
const std::string& label,
|
||||||
|
const InternalDataChannelInit*
|
||||||
|
config) /* RTC_RUN_ON(signaling_thread()) */;
|
||||||
|
void AllocateSctpSids(rtc::SSLRole role);
|
||||||
|
|
||||||
|
DataChannel* FindDataChannelBySid(int sid) const;
|
||||||
|
|
||||||
|
// Checks if any data channel has been added.
|
||||||
|
bool HasDataChannels() const;
|
||||||
|
bool HasSctpDataChannels() const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return !sctp_data_channels_.empty();
|
||||||
|
}
|
||||||
|
bool HasRtpDataChannels() const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return !rtp_data_channels_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when it's appropriate to delete released datachannels.
|
||||||
|
void FreeDataChannels() {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
sctp_data_channels_to_free_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams);
|
||||||
|
void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams);
|
||||||
|
|
||||||
|
// Accessors
|
||||||
|
cricket::DataChannelType data_channel_type() const {
|
||||||
|
return data_channel_type_;
|
||||||
|
}
|
||||||
|
void set_data_channel_type(cricket::DataChannelType type) {
|
||||||
|
data_channel_type_ = type;
|
||||||
|
}
|
||||||
|
cricket::RtpDataChannel* rtp_data_channel() const {
|
||||||
|
return rtp_data_channel_;
|
||||||
|
}
|
||||||
|
void set_rtp_data_channel(cricket::RtpDataChannel* channel) {
|
||||||
|
rtp_data_channel_ = channel;
|
||||||
|
}
|
||||||
|
DataChannelTransportInterface* data_channel_transport() const {
|
||||||
|
return data_channel_transport_;
|
||||||
|
}
|
||||||
|
void set_data_channel_transport(DataChannelTransportInterface* transport) {
|
||||||
|
data_channel_transport_ = transport;
|
||||||
|
}
|
||||||
|
const std::map<std::string, rtc::scoped_refptr<DataChannel>>*
|
||||||
|
rtp_data_channels() const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return &rtp_data_channels_;
|
||||||
|
}
|
||||||
|
const std::vector<rtc::scoped_refptr<DataChannel>>* sctp_data_channels()
|
||||||
|
const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return &sctp_data_channels_;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigslot::signal1<DataChannel*>& SignalDataChannelCreated() {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return SignalDataChannelCreated_;
|
||||||
|
}
|
||||||
|
// Called when the transport for the data channels is closed or destroyed.
|
||||||
|
void OnTransportChannelClosed();
|
||||||
|
|
||||||
|
void OnSctpDataChannelClosed(DataChannel* channel);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Parses and handles open messages. Returns true if the message is an open
|
||||||
|
// message, false otherwise.
|
||||||
|
bool HandleOpenMessage_s(const cricket::ReceiveDataParams& params,
|
||||||
|
const rtc::CopyOnWriteBuffer& buffer)
|
||||||
|
RTC_RUN_ON(signaling_thread());
|
||||||
|
// Called when a valid data channel OPEN message is received.
|
||||||
|
void OnDataChannelOpenMessage(const std::string& label,
|
||||||
|
const InternalDataChannelInit& config)
|
||||||
|
RTC_RUN_ON(signaling_thread());
|
||||||
|
|
||||||
|
void CreateRemoteRtpDataChannel(const std::string& label,
|
||||||
|
uint32_t remote_ssrc)
|
||||||
|
RTC_RUN_ON(signaling_thread());
|
||||||
|
|
||||||
|
void UpdateClosingRtpDataChannels(
|
||||||
|
const std::vector<std::string>& active_channels,
|
||||||
|
bool is_local_update) RTC_RUN_ON(signaling_thread());
|
||||||
|
|
||||||
|
rtc::Thread* network_thread() const;
|
||||||
|
rtc::Thread* signaling_thread() const;
|
||||||
|
|
||||||
|
// Specifies which kind of data channel is allowed. This is controlled
|
||||||
|
// by the chrome command-line flag and constraints:
|
||||||
|
// 1. If chrome command-line switch 'enable-sctp-data-channels' is enabled,
|
||||||
|
// constraint kEnableDtlsSrtp is true, and constaint kEnableRtpDataChannels is
|
||||||
|
// not set or false, SCTP is allowed (DCT_SCTP);
|
||||||
|
// 2. If constraint kEnableRtpDataChannels is true, RTP is allowed (DCT_RTP);
|
||||||
|
// 3. If both 1&2 are false, data channel is not allowed (DCT_NONE).
|
||||||
|
cricket::DataChannelType data_channel_type_ =
|
||||||
|
cricket::DCT_NONE; // TODO(bugs.webrtc.org/9987): Accessed on both
|
||||||
|
// signaling and network thread.
|
||||||
|
|
||||||
|
// Plugin transport used for data channels. Pointer may be accessed and
|
||||||
|
// checked from any thread, but the object may only be touched on the
|
||||||
|
// network thread.
|
||||||
|
// TODO(bugs.webrtc.org/9987): Accessed on both signaling and network
|
||||||
|
// thread.
|
||||||
|
DataChannelTransportInterface* data_channel_transport_ = nullptr;
|
||||||
|
|
||||||
|
// Cached value of whether the data channel transport is ready to send.
|
||||||
|
bool data_channel_transport_ready_to_send_
|
||||||
|
RTC_GUARDED_BY(signaling_thread()) = false;
|
||||||
|
|
||||||
|
// |rtp_data_channel_| is used if in RTP data channel mode,
|
||||||
|
// |data_channel_transport_| when using SCTP.
|
||||||
|
cricket::RtpDataChannel* rtp_data_channel_ = nullptr;
|
||||||
|
// TODO(bugs.webrtc.org/9987): Accessed on both
|
||||||
|
// signaling and some other thread.
|
||||||
|
|
||||||
|
SctpSidAllocator sid_allocator_ /* RTC_GUARDED_BY(signaling_thread()) */;
|
||||||
|
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_to_free_
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
|
||||||
|
// Map of label -> DataChannel
|
||||||
|
std::map<std::string, rtc::scoped_refptr<DataChannel>> rtp_data_channels_
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
|
||||||
|
// Signals from |data_channel_transport_|. These are invoked on the
|
||||||
|
// signaling thread.
|
||||||
|
sigslot::signal1<bool> SignalDataChannelTransportWritable_s
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
sigslot::signal2<const cricket::ReceiveDataParams&,
|
||||||
|
const rtc::CopyOnWriteBuffer&>
|
||||||
|
SignalDataChannelTransportReceivedData_s
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
sigslot::signal1<int> SignalDataChannelTransportChannelClosing_s
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
sigslot::signal1<int> SignalDataChannelTransportChannelClosed_s
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
|
||||||
|
sigslot::signal1<DataChannel*> SignalDataChannelCreated_
|
||||||
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
|
||||||
|
// Used to invoke data channel transport signals on the signaling thread.
|
||||||
|
std::unique_ptr<rtc::AsyncInvoker> data_channel_transport_invoker_
|
||||||
|
RTC_GUARDED_BY(network_thread());
|
||||||
|
|
||||||
|
// Owning PeerConnection.
|
||||||
|
PeerConnection* const pc_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // PC_DATA_CHANNEL_CONTROLLER_H_
|
@ -1306,21 +1306,23 @@ bool PeerConnection::Initialize(
|
|||||||
}
|
}
|
||||||
if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) {
|
if (configuration.enable_dtls_srtp && !*configuration.enable_dtls_srtp) {
|
||||||
RTC_LOG(LS_INFO) << "Using data channel transport with no fallback";
|
RTC_LOG(LS_INFO) << "Using data channel transport with no fallback";
|
||||||
data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT;
|
data_channel_controller_.set_data_channel_type(
|
||||||
|
cricket::DCT_DATA_CHANNEL_TRANSPORT);
|
||||||
} else {
|
} else {
|
||||||
RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP";
|
RTC_LOG(LS_INFO) << "Using data channel transport with fallback to SCTP";
|
||||||
data_channel_type_ = cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP;
|
data_channel_controller_.set_data_channel_type(
|
||||||
|
cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP);
|
||||||
config.sctp_factory = sctp_factory_.get();
|
config.sctp_factory = sctp_factory_.get();
|
||||||
}
|
}
|
||||||
} else if (configuration.enable_rtp_data_channel) {
|
} else if (configuration.enable_rtp_data_channel) {
|
||||||
// Enable creation of RTP data channels if the kEnableRtpDataChannels is
|
// Enable creation of RTP data channels if the kEnableRtpDataChannels is
|
||||||
// set. It takes precendence over the disable_sctp_data_channels
|
// set. It takes precendence over the disable_sctp_data_channels
|
||||||
// PeerConnectionFactoryInterface::Options.
|
// PeerConnectionFactoryInterface::Options.
|
||||||
data_channel_type_ = cricket::DCT_RTP;
|
data_channel_controller_.set_data_channel_type(cricket::DCT_RTP);
|
||||||
} else {
|
} else {
|
||||||
// DTLS has to be enabled to use SCTP.
|
// DTLS has to be enabled to use SCTP.
|
||||||
if (!options.disable_sctp_data_channels && dtls_enabled_) {
|
if (!options.disable_sctp_data_channels && dtls_enabled_) {
|
||||||
data_channel_type_ = cricket::DCT_SCTP;
|
data_channel_controller_.set_data_channel_type(cricket::DCT_SCTP);
|
||||||
config.sctp_factory = sctp_factory_.get();
|
config.sctp_factory = sctp_factory_.get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2159,7 +2161,7 @@ rtc::scoped_refptr<DataChannelInterface> PeerConnection::CreateDataChannel(
|
|||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
|
TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
|
||||||
|
|
||||||
bool first_datachannel = !HasDataChannels();
|
bool first_datachannel = !data_channel_controller_.HasDataChannels();
|
||||||
|
|
||||||
std::unique_ptr<InternalDataChannelInit> internal_config;
|
std::unique_ptr<InternalDataChannelInit> internal_config;
|
||||||
if (config) {
|
if (config) {
|
||||||
@ -2766,7 +2768,7 @@ RTCError PeerConnection::ApplyLocalDescription(
|
|||||||
// If setting the description decided our SSL role, allocate any necessary
|
// If setting the description decided our SSL role, allocate any necessary
|
||||||
// SCTP sids.
|
// SCTP sids.
|
||||||
rtc::SSLRole role;
|
rtc::SSLRole role;
|
||||||
if (DataChannel::IsSctpLike(data_channel_type_) && GetSctpSslRole(&role)) {
|
if (DataChannel::IsSctpLike(data_channel_type()) && GetSctpSslRole(&role)) {
|
||||||
data_channel_controller_.AllocateSctpSids(role);
|
data_channel_controller_.AllocateSctpSids(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2830,7 +2832,8 @@ RTCError PeerConnection::ApplyLocalDescription(
|
|||||||
data_content->media_description()->as_rtp_data();
|
data_content->media_description()->as_rtp_data();
|
||||||
// rtp_data_desc will be null if this is an SCTP description.
|
// rtp_data_desc will be null if this is an SCTP description.
|
||||||
if (rtp_data_desc) {
|
if (rtp_data_desc) {
|
||||||
UpdateLocalRtpDataChannels(rtp_data_desc->streams());
|
data_channel_controller_.UpdateLocalRtpDataChannels(
|
||||||
|
rtp_data_desc->streams());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3204,7 +3207,7 @@ RTCError PeerConnection::ApplyRemoteDescription(
|
|||||||
// If setting the description decided our SSL role, allocate any necessary
|
// If setting the description decided our SSL role, allocate any necessary
|
||||||
// SCTP sids.
|
// SCTP sids.
|
||||||
rtc::SSLRole role;
|
rtc::SSLRole role;
|
||||||
if (DataChannel::IsSctpLike(data_channel_type_) && GetSctpSslRole(&role)) {
|
if (DataChannel::IsSctpLike(data_channel_type()) && GetSctpSslRole(&role)) {
|
||||||
data_channel_controller_.AllocateSctpSids(role);
|
data_channel_controller_.AllocateSctpSids(role);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3385,7 +3388,8 @@ RTCError PeerConnection::ApplyRemoteDescription(
|
|||||||
// If this is an RTP data transport, update the DataChannels with the
|
// If this is an RTP data transport, update the DataChannels with the
|
||||||
// information from the remote peer.
|
// information from the remote peer.
|
||||||
if (rtp_data_desc) {
|
if (rtp_data_desc) {
|
||||||
UpdateRemoteRtpDataChannels(GetActiveStreams(rtp_data_desc));
|
data_channel_controller_.UpdateRemoteRtpDataChannels(
|
||||||
|
GetActiveStreams(rtp_data_desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate new_streams and notify the observer about new MediaStreams.
|
// Iterate new_streams and notify the observer about new MediaStreams.
|
||||||
@ -3584,7 +3588,7 @@ RTCError PeerConnection::UpdateDataChannel(
|
|||||||
cricket::ContentSource source,
|
cricket::ContentSource source,
|
||||||
const cricket::ContentInfo& content,
|
const cricket::ContentInfo& content,
|
||||||
const cricket::ContentGroup* bundle_group) {
|
const cricket::ContentGroup* bundle_group) {
|
||||||
if (data_channel_type_ == cricket::DCT_NONE) {
|
if (data_channel_type() == cricket::DCT_NONE) {
|
||||||
// If data channels are disabled, ignore this media section. CreateAnswer
|
// If data channels are disabled, ignore this media section. CreateAnswer
|
||||||
// will take care of rejecting it.
|
// will take care of rejecting it.
|
||||||
return RTCError::OK();
|
return RTCError::OK();
|
||||||
@ -3604,7 +3608,8 @@ RTCError PeerConnection::UpdateDataChannel(
|
|||||||
if (source == cricket::CS_REMOTE) {
|
if (source == cricket::CS_REMOTE) {
|
||||||
const MediaContentDescription* data_desc = content.media_description();
|
const MediaContentDescription* data_desc = content.media_description();
|
||||||
if (data_desc && cricket::IsRtpProtocol(data_desc->protocol())) {
|
if (data_desc && cricket::IsRtpProtocol(data_desc->protocol())) {
|
||||||
UpdateRemoteRtpDataChannels(GetActiveStreams(data_desc));
|
data_channel_controller_.UpdateRemoteRtpDataChannels(
|
||||||
|
GetActiveStreams(data_desc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4492,7 +4497,7 @@ void PeerConnection::OnMessage(rtc::Message* msg) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_FREE_DATACHANNELS: {
|
case MSG_FREE_DATACHANNELS: {
|
||||||
sctp_data_channels_to_free_.clear();
|
data_channel_controller_.FreeDataChannels();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MSG_REPORT_USAGE_PATTERN: {
|
case MSG_REPORT_USAGE_PATTERN: {
|
||||||
@ -4874,7 +4879,8 @@ void PeerConnection::GetOptionsForOffer(
|
|||||||
// negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
|
// negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
|
||||||
// when building with chromium. We want to leave RTP data channels broken, so
|
// when building with chromium. We want to leave RTP data channels broken, so
|
||||||
// people won't try to use them.
|
// people won't try to use them.
|
||||||
if (!rtp_data_channels_.empty() || data_channel_type() != cricket::DCT_RTP) {
|
if (data_channel_controller_.HasRtpDataChannels() ||
|
||||||
|
data_channel_type() != cricket::DCT_RTP) {
|
||||||
session_options->data_channel_type = data_channel_type();
|
session_options->data_channel_type = data_channel_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4937,7 +4943,7 @@ void PeerConnection::GetOptionsForPlanBOffer(
|
|||||||
// By default, only offer a new m= section if we have media to send with it.
|
// By default, only offer a new m= section if we have media to send with it.
|
||||||
bool offer_new_audio_description = send_audio;
|
bool offer_new_audio_description = send_audio;
|
||||||
bool offer_new_video_description = send_video;
|
bool offer_new_video_description = send_video;
|
||||||
bool offer_new_data_description = HasDataChannels();
|
bool offer_new_data_description = data_channel_controller_.HasDataChannels();
|
||||||
|
|
||||||
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
// The "offer_to_receive_X" options allow those defaults to be overridden.
|
||||||
if (offer_answer_options.offer_to_receive_audio !=
|
if (offer_answer_options.offer_to_receive_audio !=
|
||||||
@ -5175,7 +5181,7 @@ void PeerConnection::GetOptionsForUnifiedPlanOffer(
|
|||||||
}
|
}
|
||||||
// Lastly, add a m-section if we have local data channels and an m section
|
// Lastly, add a m-section if we have local data channels and an m section
|
||||||
// does not already exist.
|
// does not already exist.
|
||||||
if (!GetDataMid() && HasDataChannels()) {
|
if (!GetDataMid() && data_channel_controller_.HasDataChannels()) {
|
||||||
session_options->media_description_options.push_back(
|
session_options->media_description_options.push_back(
|
||||||
GetMediaDescriptionOptionsForActiveData(mid_generator_()));
|
GetMediaDescriptionOptionsForActiveData(mid_generator_()));
|
||||||
}
|
}
|
||||||
@ -5196,7 +5202,8 @@ void PeerConnection::GetOptionsForAnswer(
|
|||||||
// the RTP data channels would be successfully negotiated by default and the
|
// the RTP data channels would be successfully negotiated by default and the
|
||||||
// unit tests in WebRtcDataBrowserTest will fail when building with chromium.
|
// unit tests in WebRtcDataBrowserTest will fail when building with chromium.
|
||||||
// We want to leave RTP data channels broken, so people won't try to use them.
|
// We want to leave RTP data channels broken, so people won't try to use them.
|
||||||
if (!rtp_data_channels_.empty() || data_channel_type() != cricket::DCT_RTP) {
|
if (data_channel_controller_.HasRtpDataChannels() ||
|
||||||
|
data_channel_type() != cricket::DCT_RTP) {
|
||||||
session_options->data_channel_type = data_channel_type();
|
session_options->data_channel_type = data_channel_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5303,7 +5310,7 @@ void PeerConnection::GetOptionsForUnifiedPlanAnswer(
|
|||||||
// Reject all data sections if data channels are disabled.
|
// Reject all data sections if data channels are disabled.
|
||||||
// Reject a data section if it has already been rejected.
|
// Reject a data section if it has already been rejected.
|
||||||
// Reject all data sections except for the first one.
|
// Reject all data sections except for the first one.
|
||||||
if (data_channel_type_ == cricket::DCT_NONE || content.rejected ||
|
if (data_channel_type() == cricket::DCT_NONE || content.rejected ||
|
||||||
content.name != *GetDataMid()) {
|
content.name != *GetDataMid()) {
|
||||||
session_options->media_description_options.push_back(
|
session_options->media_description_options.push_back(
|
||||||
GetMediaDescriptionOptionsForRejectedData(content.name));
|
GetMediaDescriptionOptionsForRejectedData(content.name));
|
||||||
@ -5378,7 +5385,8 @@ PeerConnection::GetMediaDescriptionOptionsForActiveData(
|
|||||||
cricket::MediaDescriptionOptions options(cricket::MEDIA_TYPE_DATA, mid,
|
cricket::MediaDescriptionOptions options(cricket::MEDIA_TYPE_DATA, mid,
|
||||||
RtpTransceiverDirection::kSendRecv,
|
RtpTransceiverDirection::kSendRecv,
|
||||||
/*stopped=*/false);
|
/*stopped=*/false);
|
||||||
AddRtpDataChannelOptions(rtp_data_channels_, &options);
|
AddRtpDataChannelOptions(*data_channel_controller_.rtp_data_channels(),
|
||||||
|
&options);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5388,12 +5396,13 @@ PeerConnection::GetMediaDescriptionOptionsForRejectedData(
|
|||||||
cricket::MediaDescriptionOptions options(cricket::MEDIA_TYPE_DATA, mid,
|
cricket::MediaDescriptionOptions options(cricket::MEDIA_TYPE_DATA, mid,
|
||||||
RtpTransceiverDirection::kInactive,
|
RtpTransceiverDirection::kInactive,
|
||||||
/*stopped=*/true);
|
/*stopped=*/true);
|
||||||
AddRtpDataChannelOptions(rtp_data_channels_, &options);
|
AddRtpDataChannelOptions(*data_channel_controller_.rtp_data_channels(),
|
||||||
|
&options);
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<std::string> PeerConnection::GetDataMid() const {
|
absl::optional<std::string> PeerConnection::GetDataMid() const {
|
||||||
switch (data_channel_type_) {
|
switch (data_channel_type()) {
|
||||||
case cricket::DCT_RTP:
|
case cricket::DCT_RTP:
|
||||||
if (!data_channel_controller_.rtp_data_channel()) {
|
if (!data_channel_controller_.rtp_data_channel()) {
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
@ -5661,100 +5670,6 @@ void PeerConnection::OnLocalSenderRemoved(const RtpSenderInfo& sender_info,
|
|||||||
sender->internal()->SetSsrc(0);
|
sender->internal()->SetSsrc(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::UpdateLocalRtpDataChannels(
|
|
||||||
const cricket::StreamParamsVec& streams) {
|
|
||||||
std::vector<std::string> existing_channels;
|
|
||||||
|
|
||||||
// Find new and active data channels.
|
|
||||||
for (const cricket::StreamParams& params : streams) {
|
|
||||||
// |it->sync_label| is actually the data channel label. The reason is that
|
|
||||||
// we use the same naming of data channels as we do for
|
|
||||||
// MediaStreams and Tracks.
|
|
||||||
// For MediaStreams, the sync_label is the MediaStream label and the
|
|
||||||
// track label is the same as |streamid|.
|
|
||||||
const std::string& channel_label = params.first_stream_id();
|
|
||||||
auto data_channel_it = rtp_data_channels_.find(channel_label);
|
|
||||||
if (data_channel_it == rtp_data_channels_.end()) {
|
|
||||||
RTC_LOG(LS_ERROR) << "channel label not found";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Set the SSRC the data channel should use for sending.
|
|
||||||
data_channel_it->second->SetSendSsrc(params.first_ssrc());
|
|
||||||
existing_channels.push_back(data_channel_it->first);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateClosingRtpDataChannels(existing_channels, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerConnection::UpdateRemoteRtpDataChannels(
|
|
||||||
const cricket::StreamParamsVec& streams) {
|
|
||||||
std::vector<std::string> existing_channels;
|
|
||||||
|
|
||||||
// Find new and active data channels.
|
|
||||||
for (const cricket::StreamParams& params : streams) {
|
|
||||||
// The data channel label is either the mslabel or the SSRC if the mslabel
|
|
||||||
// does not exist. Ex a=ssrc:444330170 mslabel:test1.
|
|
||||||
std::string label = params.first_stream_id().empty()
|
|
||||||
? rtc::ToString(params.first_ssrc())
|
|
||||||
: params.first_stream_id();
|
|
||||||
auto data_channel_it = rtp_data_channels_.find(label);
|
|
||||||
if (data_channel_it == rtp_data_channels_.end()) {
|
|
||||||
// This is a new data channel.
|
|
||||||
CreateRemoteRtpDataChannel(label, params.first_ssrc());
|
|
||||||
} else {
|
|
||||||
data_channel_it->second->SetReceiveSsrc(params.first_ssrc());
|
|
||||||
}
|
|
||||||
existing_channels.push_back(label);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateClosingRtpDataChannels(existing_channels, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerConnection::UpdateClosingRtpDataChannels(
|
|
||||||
const std::vector<std::string>& active_channels,
|
|
||||||
bool is_local_update) {
|
|
||||||
auto it = rtp_data_channels_.begin();
|
|
||||||
while (it != rtp_data_channels_.end()) {
|
|
||||||
DataChannel* data_channel = it->second;
|
|
||||||
if (absl::c_linear_search(active_channels, data_channel->label())) {
|
|
||||||
++it;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_local_update) {
|
|
||||||
data_channel->SetSendSsrc(0);
|
|
||||||
} else {
|
|
||||||
data_channel->RemotePeerRequestClose();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_channel->state() == DataChannel::kClosed) {
|
|
||||||
rtp_data_channels_.erase(it);
|
|
||||||
it = rtp_data_channels_.begin();
|
|
||||||
} else {
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerConnection::CreateRemoteRtpDataChannel(const std::string& label,
|
|
||||||
uint32_t remote_ssrc) {
|
|
||||||
rtc::scoped_refptr<DataChannel> channel(
|
|
||||||
data_channel_controller_.InternalCreateDataChannel(label, nullptr));
|
|
||||||
if (!channel.get()) {
|
|
||||||
RTC_LOG(LS_WARNING) << "Remote peer requested a DataChannel but"
|
|
||||||
"CreateDataChannel failed.";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
channel->SetReceiveSsrc(remote_ssrc);
|
|
||||||
rtc::scoped_refptr<DataChannelInterface> proxy_channel =
|
|
||||||
DataChannelProxy::Create(signaling_thread(), channel);
|
|
||||||
Observer()->OnDataChannel(std::move(proxy_channel));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PeerConnection::HasDataChannels() const {
|
|
||||||
return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
|
void PeerConnection::OnSctpDataChannelClosed(DataChannel* channel) {
|
||||||
// Since data_channel_controller doesn't do signals, this
|
// Since data_channel_controller doesn't do signals, this
|
||||||
// signal is relayed here.
|
// signal is relayed here.
|
||||||
@ -5765,22 +5680,6 @@ void PeerConnection::SignalFreeDataChannels() {
|
|||||||
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FREE_DATACHANNELS, nullptr);
|
signaling_thread()->Post(RTC_FROM_HERE, this, MSG_FREE_DATACHANNELS, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerConnection::OnTransportChannelClosed() {
|
|
||||||
// Use a temporary copy of the RTP/SCTP DataChannel list because the
|
|
||||||
// DataChannel may callback to us and try to modify the list.
|
|
||||||
std::map<std::string, rtc::scoped_refptr<DataChannel>> temp_rtp_dcs;
|
|
||||||
temp_rtp_dcs.swap(rtp_data_channels_);
|
|
||||||
for (const auto& kv : temp_rtp_dcs) {
|
|
||||||
kv.second->OnTransportChannelClosed();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<rtc::scoped_refptr<DataChannel>> temp_sctp_dcs;
|
|
||||||
temp_sctp_dcs.swap(sctp_data_channels_);
|
|
||||||
for (const auto& channel : temp_sctp_dcs) {
|
|
||||||
channel->OnTransportChannelClosed();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
|
||||||
PeerConnection::GetAudioTransceiver() const {
|
PeerConnection::GetAudioTransceiver() const {
|
||||||
// This method only works with Plan B SDP, where there is a single
|
// This method only works with Plan B SDP, where there is a single
|
||||||
@ -5891,12 +5790,7 @@ const PeerConnection::RtpSenderInfo* PeerConnection::FindSenderInfo(
|
|||||||
}
|
}
|
||||||
|
|
||||||
DataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
|
DataChannel* PeerConnection::FindDataChannelBySid(int sid) const {
|
||||||
for (const auto& channel : sctp_data_channels_) {
|
return data_channel_controller_.FindDataChannelBySid(sid);
|
||||||
if (channel->id() == sid) {
|
|
||||||
return channel;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnection::InitializePortAllocatorResult
|
PeerConnection::InitializePortAllocatorResult
|
||||||
@ -6370,7 +6264,7 @@ std::unique_ptr<rtc::SSLCertChain> PeerConnection::GetRemoteSSLCertChain(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cricket::DataChannelType PeerConnection::data_channel_type() const {
|
cricket::DataChannelType PeerConnection::data_channel_type() const {
|
||||||
return data_channel_type_;
|
return data_channel_controller_.data_channel_type();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PeerConnection::IceRestartPending(const std::string& content_name) const {
|
bool PeerConnection::IceRestartPending(const std::string& content_name) const {
|
||||||
@ -6692,7 +6586,7 @@ RTCError PeerConnection::CreateChannels(const SessionDescription& desc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cricket::ContentInfo* data = cricket::GetFirstDataContent(&desc);
|
const cricket::ContentInfo* data = cricket::GetFirstDataContent(&desc);
|
||||||
if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected &&
|
if (data_channel_type() != cricket::DCT_NONE && data && !data->rejected &&
|
||||||
!data_channel_controller_.rtp_data_channel() &&
|
!data_channel_controller_.rtp_data_channel() &&
|
||||||
!data_channel_controller_.data_channel_transport()) {
|
!data_channel_controller_.data_channel_transport()) {
|
||||||
if (!CreateDataChannel(data->name)) {
|
if (!CreateDataChannel(data->name)) {
|
||||||
@ -6752,7 +6646,7 @@ cricket::VideoChannel* PeerConnection::CreateVideoChannel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PeerConnection::CreateDataChannel(const std::string& mid) {
|
bool PeerConnection::CreateDataChannel(const std::string& mid) {
|
||||||
switch (data_channel_type_) {
|
switch (data_channel_type()) {
|
||||||
case cricket::DCT_SCTP:
|
case cricket::DCT_SCTP:
|
||||||
case cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP:
|
case cricket::DCT_DATA_CHANNEL_TRANSPORT_SCTP:
|
||||||
case cricket::DCT_DATA_CHANNEL_TRANSPORT:
|
case cricket::DCT_DATA_CHANNEL_TRANSPORT:
|
||||||
@ -6764,7 +6658,8 @@ bool PeerConnection::CreateDataChannel(const std::string& mid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// All non-RTP data channels must initialize |sctp_data_channels_|.
|
// All non-RTP data channels must initialize |sctp_data_channels_|.
|
||||||
for (const auto& channel : sctp_data_channels_) {
|
for (const auto& channel :
|
||||||
|
*data_channel_controller_.sctp_data_channels()) {
|
||||||
channel->OnTransportChannelCreated();
|
channel->OnTransportChannelCreated();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -7379,7 +7274,7 @@ void PeerConnection::DestroyTransceiverChannel(
|
|||||||
|
|
||||||
void PeerConnection::DestroyDataChannelTransport() {
|
void PeerConnection::DestroyDataChannelTransport() {
|
||||||
if (data_channel_controller_.rtp_data_channel()) {
|
if (data_channel_controller_.rtp_data_channel()) {
|
||||||
OnTransportChannelClosed();
|
data_channel_controller_.OnTransportChannelClosed();
|
||||||
DestroyChannelInterface(data_channel_controller_.rtp_data_channel());
|
DestroyChannelInterface(data_channel_controller_.rtp_data_channel());
|
||||||
data_channel_controller_.set_rtp_data_channel(nullptr);
|
data_channel_controller_.set_rtp_data_channel(nullptr);
|
||||||
}
|
}
|
||||||
@ -7391,7 +7286,7 @@ void PeerConnection::DestroyDataChannelTransport() {
|
|||||||
// rtc::Bind will cause "Pure virtual function called" error to appear.
|
// rtc::Bind will cause "Pure virtual function called" error to appear.
|
||||||
|
|
||||||
if (sctp_mid_) {
|
if (sctp_mid_) {
|
||||||
OnTransportChannelClosed();
|
data_channel_controller_.OnTransportChannelClosed();
|
||||||
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
network_thread()->Invoke<void>(RTC_FROM_HERE, [this] {
|
||||||
RTC_DCHECK_RUN_ON(network_thread());
|
RTC_DCHECK_RUN_ON(network_thread());
|
||||||
TeardownDataChannelTransport_n();
|
TeardownDataChannelTransport_n();
|
||||||
@ -7445,12 +7340,8 @@ void PeerConnection::OnSetStreams() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionObserver* PeerConnection::Observer() const {
|
PeerConnectionObserver* PeerConnection::Observer() const {
|
||||||
// In earlier production code, the pointer was not cleared on close,
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
// which might have led to undefined behavior if the observer was not
|
RTC_DCHECK(observer_);
|
||||||
// deallocated, or strange crashes if it was.
|
|
||||||
// We use CHECK in order to catch such behavior if it exists.
|
|
||||||
// TODO(hta): Remove or replace with DCHECK if nothing is found.
|
|
||||||
RTC_CHECK(observer_);
|
|
||||||
return observer_;
|
return observer_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7534,7 +7425,7 @@ bool PeerConnection::CheckIfNegotiationIsNeeded() {
|
|||||||
|
|
||||||
// 4. If connection has created any RTCDataChannels, and no m= section in
|
// 4. If connection has created any RTCDataChannels, and no m= section in
|
||||||
// description has been negotiated yet for data, return true.
|
// description has been negotiated yet for data, return true.
|
||||||
if (!sctp_data_channels_.empty()) {
|
if (data_channel_controller_.HasSctpDataChannels()) {
|
||||||
if (!cricket::GetFirstDataContent(description->description()->contents()))
|
if (!cricket::GetFirstDataContent(description->description()->contents()))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "api/peer_connection_interface.h"
|
#include "api/peer_connection_interface.h"
|
||||||
#include "api/transport/data_channel_transport_interface.h"
|
#include "api/transport/data_channel_transport_interface.h"
|
||||||
#include "api/turn_customizer.h"
|
#include "api/turn_customizer.h"
|
||||||
|
#include "pc/data_channel_controller.h"
|
||||||
#include "pc/ice_server_parsing.h"
|
#include "pc/ice_server_parsing.h"
|
||||||
#include "pc/jsep_transport_controller.h"
|
#include "pc/jsep_transport_controller.h"
|
||||||
#include "pc/peer_connection_factory.h"
|
#include "pc/peer_connection_factory.h"
|
||||||
@ -269,7 +270,7 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
}
|
}
|
||||||
|
|
||||||
sigslot::signal1<DataChannel*>& SignalDataChannelCreated() override {
|
sigslot::signal1<DataChannel*>& SignalDataChannelCreated() override {
|
||||||
return SignalDataChannelCreated_;
|
return data_channel_controller_.SignalDataChannelCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
cricket::RtpDataChannel* rtp_data_channel() const override {
|
cricket::RtpDataChannel* rtp_data_channel() const override {
|
||||||
@ -279,7 +280,7 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels()
|
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels()
|
||||||
const override {
|
const override {
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
return sctp_data_channels_;
|
return *data_channel_controller_.sctp_data_channels();
|
||||||
}
|
}
|
||||||
|
|
||||||
absl::optional<std::string> sctp_content_name() const override {
|
absl::optional<std::string> sctp_content_name() const override {
|
||||||
@ -304,6 +305,22 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
bool NeedsIceRestart(const std::string& content_name) const override;
|
bool NeedsIceRestart(const std::string& content_name) const override;
|
||||||
bool GetSslRole(const std::string& content_name, rtc::SSLRole* role) override;
|
bool GetSslRole(const std::string& content_name, rtc::SSLRole* role) override;
|
||||||
|
|
||||||
|
// Functions needed by DataChannelController
|
||||||
|
void NoteDataAddedEvent() { NoteUsageEvent(UsageEvent::DATA_ADDED); }
|
||||||
|
// Returns the observer. Will crash on CHECK if the observer is removed.
|
||||||
|
PeerConnectionObserver* Observer() const;
|
||||||
|
bool IsClosed() const {
|
||||||
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
|
return signaling_state_ == PeerConnectionInterface::kClosed;
|
||||||
|
}
|
||||||
|
// Get current SSL role used by SCTP's underlying transport.
|
||||||
|
bool GetSctpSslRole(rtc::SSLRole* role);
|
||||||
|
// Handler for the "channel closed" signal
|
||||||
|
void OnSctpDataChannelClosed(DataChannel* channel);
|
||||||
|
// Sends the MSG_FREE_DATACHANNELS signal
|
||||||
|
void SignalFreeDataChannels();
|
||||||
|
|
||||||
|
// Functions made public for testing.
|
||||||
void ReturnHistogramVeryQuicklyForTesting() {
|
void ReturnHistogramVeryQuicklyForTesting() {
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
RTC_DCHECK_RUN_ON(signaling_thread());
|
||||||
return_histogram_very_quickly_ = true;
|
return_histogram_very_quickly_ = true;
|
||||||
@ -318,6 +335,7 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
friend class ImplicitCreateSessionDescriptionObserver;
|
friend class ImplicitCreateSessionDescriptionObserver;
|
||||||
class SetRemoteDescriptionObserverAdapter;
|
class SetRemoteDescriptionObserverAdapter;
|
||||||
friend class SetRemoteDescriptionObserverAdapter;
|
friend class SetRemoteDescriptionObserverAdapter;
|
||||||
|
|
||||||
// Represents the [[LocalIceCredentialsToReplace]] internal slot in the spec.
|
// Represents the [[LocalIceCredentialsToReplace]] internal slot in the spec.
|
||||||
// It makes the next CreateOffer() produce new ICE credentials even if
|
// It makes the next CreateOffer() produce new ICE credentials even if
|
||||||
// RTCOfferAnswerOptions::ice_restart is false.
|
// RTCOfferAnswerOptions::ice_restart is false.
|
||||||
@ -395,120 +413,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
FieldTrialFlag receive_only;
|
FieldTrialFlag receive_only;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Controller for datachannels. Intended to be separated out; placed here as a
|
|
||||||
// first stage in refactoring.
|
|
||||||
class DataChannelController : public DataChannelProviderInterface,
|
|
||||||
public DataChannelSink {
|
|
||||||
public:
|
|
||||||
explicit DataChannelController(PeerConnection* pc) : pc_(pc) {}
|
|
||||||
~DataChannelController() { data_channel_transport_invoker_.reset(); }
|
|
||||||
|
|
||||||
// Implements DataChannelProviderInterface.
|
|
||||||
bool SendData(const cricket::SendDataParams& params,
|
|
||||||
const rtc::CopyOnWriteBuffer& payload,
|
|
||||||
cricket::SendDataResult* result) override;
|
|
||||||
bool ConnectDataChannel(DataChannel* webrtc_data_channel) override;
|
|
||||||
void DisconnectDataChannel(DataChannel* webrtc_data_channel) override;
|
|
||||||
void AddSctpDataStream(int sid) override;
|
|
||||||
void RemoveSctpDataStream(int sid) override;
|
|
||||||
bool ReadyToSendData() const override;
|
|
||||||
|
|
||||||
// Implements DataChannelSink.
|
|
||||||
void OnDataReceived(int channel_id,
|
|
||||||
DataMessageType type,
|
|
||||||
const rtc::CopyOnWriteBuffer& buffer) override;
|
|
||||||
void OnChannelClosing(int channel_id) override;
|
|
||||||
void OnChannelClosed(int channel_id) override;
|
|
||||||
void OnReadyToSend() override;
|
|
||||||
|
|
||||||
// Called from PeerConnection::SetupDataChannelTransport_n
|
|
||||||
void SetupDataChannelTransport_n();
|
|
||||||
// Called from PeerConnection::TeardownDataChannelTransport_n
|
|
||||||
void TeardownDataChannelTransport_n();
|
|
||||||
|
|
||||||
// Called from PeerConnection::OnTransportChanged
|
|
||||||
// to make required changes to datachannels' transports.
|
|
||||||
void OnTransportChanged(
|
|
||||||
DataChannelTransportInterface* data_channel_transport);
|
|
||||||
|
|
||||||
// Parses and handles open messages. Returns true if the message is an open
|
|
||||||
// message, false otherwise.
|
|
||||||
bool HandleOpenMessage_s(const cricket::ReceiveDataParams& params,
|
|
||||||
const rtc::CopyOnWriteBuffer& buffer)
|
|
||||||
RTC_RUN_ON(signaling_thread());
|
|
||||||
// Called when a valid data channel OPEN message is received.
|
|
||||||
void OnDataChannelOpenMessage(const std::string& label,
|
|
||||||
const InternalDataChannelInit& config)
|
|
||||||
RTC_RUN_ON(signaling_thread());
|
|
||||||
|
|
||||||
// Creates channel and adds it to the collection of DataChannels that will
|
|
||||||
// be offered in a SessionDescription.
|
|
||||||
rtc::scoped_refptr<DataChannel> InternalCreateDataChannel(
|
|
||||||
const std::string& label,
|
|
||||||
const InternalDataChannelInit*
|
|
||||||
config) /* RTC_RUN_ON(signaling_thread()) */;
|
|
||||||
void AllocateSctpSids(
|
|
||||||
rtc::SSLRole role) /* RTC_RUN_ON(signaling_thread()) */;
|
|
||||||
void OnSctpDataChannelClosed(DataChannel* channel);
|
|
||||||
/* RTC_RUN_ON(signaling_thread() */
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
cricket::RtpDataChannel* rtp_data_channel() const {
|
|
||||||
return rtp_data_channel_;
|
|
||||||
}
|
|
||||||
void set_rtp_data_channel(cricket::RtpDataChannel* channel) {
|
|
||||||
rtp_data_channel_ = channel;
|
|
||||||
}
|
|
||||||
DataChannelTransportInterface* data_channel_transport() const {
|
|
||||||
return data_channel_transport_;
|
|
||||||
}
|
|
||||||
void set_data_channel_transport(DataChannelTransportInterface* transport) {
|
|
||||||
data_channel_transport_ = transport;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
rtc::Thread* network_thread() const { return pc_->network_thread(); }
|
|
||||||
rtc::Thread* signaling_thread() const { return pc_->signaling_thread(); }
|
|
||||||
// Plugin transport used for data channels. Pointer may be accessed and
|
|
||||||
// checked from any thread, but the object may only be touched on the
|
|
||||||
// network thread.
|
|
||||||
// TODO(bugs.webrtc.org/9987): Accessed on both signaling and network
|
|
||||||
// thread.
|
|
||||||
DataChannelTransportInterface* data_channel_transport_ = nullptr;
|
|
||||||
|
|
||||||
// Cached value of whether the data channel transport is ready to send.
|
|
||||||
bool data_channel_transport_ready_to_send_
|
|
||||||
RTC_GUARDED_BY(signaling_thread()) = false;
|
|
||||||
|
|
||||||
// |rtp_data_channel_| is used if in RTP data channel mode,
|
|
||||||
// |data_channel_transport_| when using SCTP.
|
|
||||||
cricket::RtpDataChannel* rtp_data_channel_ = nullptr;
|
|
||||||
// TODO(bugs.webrtc.org/9987): Accessed on both
|
|
||||||
// signaling and some other thread.
|
|
||||||
|
|
||||||
SctpSidAllocator sid_allocator_ /* RTC_GUARDED_BY(signaling_thread()) */;
|
|
||||||
|
|
||||||
// Signals from |data_channel_transport_|. These are invoked on the
|
|
||||||
// signaling thread.
|
|
||||||
sigslot::signal1<bool> SignalDataChannelTransportWritable_s
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
sigslot::signal2<const cricket::ReceiveDataParams&,
|
|
||||||
const rtc::CopyOnWriteBuffer&>
|
|
||||||
SignalDataChannelTransportReceivedData_s
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
sigslot::signal1<int> SignalDataChannelTransportChannelClosing_s
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
sigslot::signal1<int> SignalDataChannelTransportChannelClosed_s
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
|
|
||||||
// Used to invoke data channel transport signals on the signaling thread.
|
|
||||||
std::unique_ptr<rtc::AsyncInvoker> data_channel_transport_invoker_
|
|
||||||
RTC_GUARDED_BY(network_thread());
|
|
||||||
|
|
||||||
// Owning PeerConnection.
|
|
||||||
PeerConnection* pc_;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Captures partial state to be used for rollback. Applicable only in
|
// Captures partial state to be used for rollback. Applicable only in
|
||||||
// Unified Plan.
|
// Unified Plan.
|
||||||
class TransceiverStableState {
|
class TransceiverStableState {
|
||||||
@ -807,11 +711,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
|
|
||||||
void OnNegotiationNeeded();
|
void OnNegotiationNeeded();
|
||||||
|
|
||||||
bool IsClosed() const {
|
|
||||||
RTC_DCHECK_RUN_ON(signaling_thread());
|
|
||||||
return signaling_state_ == PeerConnectionInterface::kClosed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a MediaSessionOptions struct with options decided by |options|,
|
// Returns a MediaSessionOptions struct with options decided by |options|,
|
||||||
// the local MediaStreams and DataChannels.
|
// the local MediaStreams and DataChannels.
|
||||||
void GetOptionsForOffer(const PeerConnectionInterface::RTCOfferAnswerOptions&
|
void GetOptionsForOffer(const PeerConnectionInterface::RTCOfferAnswerOptions&
|
||||||
@ -944,27 +843,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
cricket::MediaType media_type)
|
cricket::MediaType media_type)
|
||||||
RTC_RUN_ON(signaling_thread());
|
RTC_RUN_ON(signaling_thread());
|
||||||
|
|
||||||
void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams)
|
|
||||||
RTC_RUN_ON(signaling_thread());
|
|
||||||
void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams)
|
|
||||||
RTC_RUN_ON(signaling_thread());
|
|
||||||
void UpdateClosingRtpDataChannels(
|
|
||||||
const std::vector<std::string>& active_channels,
|
|
||||||
bool is_local_update) RTC_RUN_ON(signaling_thread());
|
|
||||||
void CreateRemoteRtpDataChannel(const std::string& label,
|
|
||||||
uint32_t remote_ssrc)
|
|
||||||
RTC_RUN_ON(signaling_thread());
|
|
||||||
|
|
||||||
// Checks if any data channel has been added.
|
|
||||||
bool HasDataChannels() const RTC_RUN_ON(signaling_thread());
|
|
||||||
// Handler for the "channel closed" signal
|
|
||||||
void OnSctpDataChannelClosed(DataChannel* channel);
|
|
||||||
// Sends the MSG_FREE_DATACHANNELS signal
|
|
||||||
void SignalFreeDataChannels();
|
|
||||||
|
|
||||||
// Called when the transport for the data channels is closed or destroyed.
|
|
||||||
void OnTransportChannelClosed() RTC_RUN_ON(signaling_thread());
|
|
||||||
|
|
||||||
// Returns true if the PeerConnection is configured to use Unified Plan
|
// Returns true if the PeerConnection is configured to use Unified Plan
|
||||||
// semantics for creating offers/answers and setting local/remote
|
// semantics for creating offers/answers and setting local/remote
|
||||||
// descriptions. If this is true the RtpTransceiver API will also be available
|
// descriptions. If this is true the RtpTransceiver API will also be available
|
||||||
@ -1065,9 +943,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
|
|
||||||
cricket::ChannelInterface* GetChannel(const std::string& content_name);
|
cricket::ChannelInterface* GetChannel(const std::string& content_name);
|
||||||
|
|
||||||
// Get current SSL role used by SCTP's underlying transport.
|
|
||||||
bool GetSctpSslRole(rtc::SSLRole* role);
|
|
||||||
|
|
||||||
cricket::IceConfig ParseIceConfig(
|
cricket::IceConfig ParseIceConfig(
|
||||||
const PeerConnectionInterface::RTCConfiguration& config) const;
|
const PeerConnectionInterface::RTCConfiguration& config) const;
|
||||||
|
|
||||||
@ -1283,9 +1158,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
// RtpSenderBase::SetStreamsObserver override.
|
// RtpSenderBase::SetStreamsObserver override.
|
||||||
void OnSetStreams() override;
|
void OnSetStreams() override;
|
||||||
|
|
||||||
// Returns the observer. Will crash on CHECK if the observer is removed.
|
|
||||||
PeerConnectionObserver* Observer() const RTC_RUN_ON(signaling_thread());
|
|
||||||
|
|
||||||
// Returns the CryptoOptions for this PeerConnection. This will always
|
// Returns the CryptoOptions for this PeerConnection. This will always
|
||||||
// return the RTCConfiguration.crypto_options if set and will only default
|
// return the RTCConfiguration.crypto_options if set and will only default
|
||||||
// back to the PeerConnectionFactory settings if nothing was set.
|
// back to the PeerConnectionFactory settings if nothing was set.
|
||||||
@ -1305,9 +1177,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
// | sdp_type | is the type of the SDP that caused the rollback.
|
// | sdp_type | is the type of the SDP that caused the rollback.
|
||||||
RTCError Rollback(SdpType sdp_type);
|
RTCError Rollback(SdpType sdp_type);
|
||||||
|
|
||||||
sigslot::signal1<DataChannel*> SignalDataChannelCreated_
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
|
|
||||||
// Storing the factory as a scoped reference pointer ensures that the memory
|
// Storing the factory as a scoped reference pointer ensures that the memory
|
||||||
// in the PeerConnectionFactoryImpl remains available as long as the
|
// in the PeerConnectionFactoryImpl remains available as long as the
|
||||||
// PeerConnection is running. It is passed to PeerConnection as a raw pointer.
|
// PeerConnection is running. It is passed to PeerConnection as a raw pointer.
|
||||||
@ -1406,14 +1275,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
std::vector<RtpSenderInfo> local_video_sender_infos_
|
std::vector<RtpSenderInfo> local_video_sender_infos_
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
|
|
||||||
// label -> DataChannel
|
|
||||||
std::map<std::string, rtc::scoped_refptr<DataChannel>> rtp_data_channels_
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
std::vector<rtc::scoped_refptr<DataChannel>> sctp_data_channels_to_free_
|
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
|
||||||
|
|
||||||
bool remote_peer_supports_msid_ RTC_GUARDED_BY(signaling_thread()) = false;
|
bool remote_peer_supports_msid_ RTC_GUARDED_BY(signaling_thread()) = false;
|
||||||
|
|
||||||
// The unique_ptr belongs to the worker thread, but the Call object manages
|
// The unique_ptr belongs to the worker thread, but the Call object manages
|
||||||
@ -1489,16 +1350,6 @@ class PeerConnection : public PeerConnectionInternal,
|
|||||||
std::unique_ptr<SessionDescriptionInterface> pending_remote_description_
|
std::unique_ptr<SessionDescriptionInterface> pending_remote_description_
|
||||||
RTC_GUARDED_BY(signaling_thread());
|
RTC_GUARDED_BY(signaling_thread());
|
||||||
bool dtls_enabled_ RTC_GUARDED_BY(signaling_thread()) = false;
|
bool dtls_enabled_ RTC_GUARDED_BY(signaling_thread()) = false;
|
||||||
// Specifies which kind of data channel is allowed. This is controlled
|
|
||||||
// by the chrome command-line flag and constraints:
|
|
||||||
// 1. If chrome command-line switch 'enable-sctp-data-channels' is enabled,
|
|
||||||
// constraint kEnableDtlsSrtp is true, and constaint kEnableRtpDataChannels is
|
|
||||||
// not set or false, SCTP is allowed (DCT_SCTP);
|
|
||||||
// 2. If constraint kEnableRtpDataChannels is true, RTP is allowed (DCT_RTP);
|
|
||||||
// 3. If both 1&2 are false, data channel is not allowed (DCT_NONE).
|
|
||||||
cricket::DataChannelType data_channel_type_ =
|
|
||||||
cricket::DCT_NONE; // TODO(bugs.webrtc.org/9987): Accessed on both
|
|
||||||
// signaling and network thread.
|
|
||||||
|
|
||||||
// List of content names for which the remote side triggered an ICE restart.
|
// List of content names for which the remote side triggered an ICE restart.
|
||||||
std::set<std::string> pending_ice_restarts_
|
std::set<std::string> pending_ice_restarts_
|
||||||
|
Reference in New Issue
Block a user