Modified PeerConnection and WebRtcSession for end-to-end QuicDataChannel usage.
To allow end-to-end QuicDataChannel usage with a PeerConnection, RTCConfiguration has been modified to include a boolean for whether to do QUIC, since negotiation of QUIC is not implemented. If one peer does QUIC, then it will be assumed that the other peer must do QUIC or the connection will fail. PeerConnection has been modified to create data channels of type QuicDataChannel when the peer wants to do QUIC. WebRtcSession has ben modified to use a QuicDataTransport instead of a DtlsTransportChannelWrapper/DataChannel when QUIC should be used QuicDataTransport implements the generic functions of BaseChannel to manage the QuicTransportChannel. Review-Url: https://codereview.webrtc.org/2166873002 Cr-Commit-Position: refs/heads/master@{#13645}
This commit is contained in:
@ -907,6 +907,23 @@ PeerConnection::CreateDataChannel(
|
||||
const std::string& label,
|
||||
const DataChannelInit* config) {
|
||||
TRACE_EVENT0("webrtc", "PeerConnection::CreateDataChannel");
|
||||
#ifdef HAVE_QUIC
|
||||
if (session_->data_channel_type() == cricket::DCT_QUIC) {
|
||||
// TODO(zhihuang): Handle case when config is NULL.
|
||||
if (!config) {
|
||||
LOG(LS_ERROR) << "Missing config for QUIC data channel.";
|
||||
return nullptr;
|
||||
}
|
||||
// TODO(zhihuang): Allow unreliable or ordered QUIC data channels.
|
||||
if (!config->reliable || config->ordered) {
|
||||
LOG(LS_ERROR) << "QUIC data channel does not implement unreliable or "
|
||||
"ordered delivery.";
|
||||
return nullptr;
|
||||
}
|
||||
return session_->quic_data_transport()->CreateDataChannel(label, config);
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
bool first_datachannel = !HasDataChannels();
|
||||
|
||||
std::unique_ptr<InternalDataChannelInit> internal_config;
|
||||
@ -1618,8 +1635,8 @@ bool PeerConnection::GetOptionsForOffer(
|
||||
(session_options->has_audio() || session_options->has_video() ||
|
||||
session_options->has_data());
|
||||
|
||||
if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) {
|
||||
session_options->data_channel_type = cricket::DCT_SCTP;
|
||||
if (HasDataChannels()) {
|
||||
session_options->data_channel_type = session_->data_channel_type();
|
||||
}
|
||||
|
||||
session_options->rtcp_cname = rtcp_cname_;
|
||||
@ -1648,9 +1665,7 @@ void PeerConnection::FinishOptionsForAnswer(
|
||||
// RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams
|
||||
// are not signaled in the SDP so does not go through that path and must be
|
||||
// handled here.
|
||||
if (session_->data_channel_type() == cricket::DCT_SCTP) {
|
||||
session_options->data_channel_type = cricket::DCT_SCTP;
|
||||
}
|
||||
session_options->data_channel_type = session_->data_channel_type();
|
||||
session_options->crypto_options = factory_->options().crypto_options;
|
||||
}
|
||||
|
||||
@ -2054,7 +2069,13 @@ rtc::scoped_refptr<DataChannel> PeerConnection::InternalCreateDataChannel(
|
||||
}
|
||||
|
||||
bool PeerConnection::HasDataChannels() const {
|
||||
#ifdef HAVE_QUIC
|
||||
return !rtp_data_channels_.empty() || !sctp_data_channels_.empty() ||
|
||||
(session_->quic_data_transport() &&
|
||||
session_->quic_data_transport()->HasDataChannels());
|
||||
#else
|
||||
return !rtp_data_channels_.empty() || !sctp_data_channels_.empty();
|
||||
#endif // HAVE_QUIC
|
||||
}
|
||||
|
||||
void PeerConnection::AllocateSctpSids(rtc::SSLRole role) {
|
||||
|
||||
@ -174,12 +174,13 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
|
||||
const std::string& id,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const PeerConnectionFactory::Options* options,
|
||||
const PeerConnectionInterface::RTCConfiguration& config,
|
||||
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
|
||||
bool prefer_constraint_apis,
|
||||
rtc::Thread* network_thread,
|
||||
rtc::Thread* worker_thread) {
|
||||
PeerConnectionTestClient* client(new PeerConnectionTestClient(id));
|
||||
if (!client->Init(constraints, options, std::move(cert_generator),
|
||||
if (!client->Init(constraints, options, config, std::move(cert_generator),
|
||||
prefer_constraint_apis, network_thread, worker_thread)) {
|
||||
delete client;
|
||||
return nullptr;
|
||||
@ -191,29 +192,31 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
|
||||
const std::string& id,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const PeerConnectionFactory::Options* options,
|
||||
const PeerConnectionInterface::RTCConfiguration& config,
|
||||
rtc::Thread* network_thread,
|
||||
rtc::Thread* worker_thread) {
|
||||
std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
|
||||
rtc::SSLStreamAdapter::HaveDtlsSrtp() ?
|
||||
new FakeRTCCertificateGenerator() : nullptr);
|
||||
|
||||
return CreateClientWithDtlsIdentityStore(
|
||||
id, constraints, options, std::move(cert_generator), true,
|
||||
network_thread, worker_thread);
|
||||
return CreateClientWithDtlsIdentityStore(id, constraints, options, config,
|
||||
std::move(cert_generator), true,
|
||||
network_thread, worker_thread);
|
||||
}
|
||||
|
||||
static PeerConnectionTestClient* CreateClientPreferNoConstraints(
|
||||
const std::string& id,
|
||||
const PeerConnectionFactory::Options* options,
|
||||
const PeerConnectionInterface::RTCConfiguration& config,
|
||||
rtc::Thread* network_thread,
|
||||
rtc::Thread* worker_thread) {
|
||||
std::unique_ptr<FakeRTCCertificateGenerator> cert_generator(
|
||||
rtc::SSLStreamAdapter::HaveDtlsSrtp() ?
|
||||
new FakeRTCCertificateGenerator() : nullptr);
|
||||
|
||||
return CreateClientWithDtlsIdentityStore(
|
||||
id, nullptr, options, std::move(cert_generator), false,
|
||||
network_thread, worker_thread);
|
||||
return CreateClientWithDtlsIdentityStore(id, nullptr, options, config,
|
||||
std::move(cert_generator), false,
|
||||
network_thread, worker_thread);
|
||||
}
|
||||
|
||||
~PeerConnectionTestClient() {
|
||||
@ -457,8 +460,10 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
|
||||
data_observer_.reset(new MockDataChannelObserver(data_channel));
|
||||
}
|
||||
|
||||
void CreateDataChannel() {
|
||||
data_channel_ = pc()->CreateDataChannel(kDataChannelLabel, nullptr);
|
||||
void CreateDataChannel() { CreateDataChannel(nullptr); }
|
||||
|
||||
void CreateDataChannel(const webrtc::DataChannelInit* init) {
|
||||
data_channel_ = pc()->CreateDataChannel(kDataChannelLabel, init);
|
||||
ASSERT_TRUE(data_channel_.get() != nullptr);
|
||||
data_observer_.reset(new MockDataChannelObserver(data_channel_));
|
||||
}
|
||||
@ -845,6 +850,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
|
||||
bool Init(
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const PeerConnectionFactory::Options* options,
|
||||
const PeerConnectionInterface::RTCConfiguration& config,
|
||||
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator,
|
||||
bool prefer_constraint_apis,
|
||||
rtc::Thread* network_thread,
|
||||
@ -876,21 +882,18 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver,
|
||||
if (options) {
|
||||
peer_connection_factory_->SetOptions(*options);
|
||||
}
|
||||
peer_connection_ = CreatePeerConnection(
|
||||
std::move(port_allocator), constraints, std::move(cert_generator));
|
||||
peer_connection_ =
|
||||
CreatePeerConnection(std::move(port_allocator), constraints, config,
|
||||
std::move(cert_generator));
|
||||
|
||||
return peer_connection_.get() != nullptr;
|
||||
}
|
||||
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
|
||||
std::unique_ptr<cricket::PortAllocator> port_allocator,
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const PeerConnectionInterface::RTCConfiguration& config,
|
||||
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator) {
|
||||
// CreatePeerConnection with RTCConfiguration.
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.uri = "stun:stun.l.google.com:19302";
|
||||
config.servers.push_back(ice_server);
|
||||
|
||||
return peer_connection_factory_->CreatePeerConnection(
|
||||
config, constraints, std::move(port_allocator),
|
||||
std::move(cert_generator), this);
|
||||
@ -1078,6 +1081,9 @@ class P2PTestConductor : public testing::Test {
|
||||
worker_thread_(rtc::Thread::Create()) {
|
||||
RTC_CHECK(network_thread_->Start());
|
||||
RTC_CHECK(worker_thread_->Start());
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.uri = "stun:stun.l.google.com:19302";
|
||||
config_.servers.push_back(ice_server);
|
||||
}
|
||||
|
||||
bool SessionActive() {
|
||||
@ -1187,10 +1193,12 @@ class P2PTestConductor : public testing::Test {
|
||||
bool CreateTestClientsThatPreferNoConstraints() {
|
||||
initiating_client_.reset(
|
||||
PeerConnectionTestClient::CreateClientPreferNoConstraints(
|
||||
"Caller: ", nullptr, network_thread_.get(), worker_thread_.get()));
|
||||
"Caller: ", nullptr, config_, network_thread_.get(),
|
||||
worker_thread_.get()));
|
||||
receiving_client_.reset(
|
||||
PeerConnectionTestClient::CreateClientPreferNoConstraints(
|
||||
"Callee: ", nullptr, network_thread_.get(), worker_thread_.get()));
|
||||
"Callee: ", nullptr, config_, network_thread_.get(),
|
||||
worker_thread_.get()));
|
||||
if (!initiating_client_ || !receiving_client_) {
|
||||
return false;
|
||||
}
|
||||
@ -1210,11 +1218,11 @@ class P2PTestConductor : public testing::Test {
|
||||
MediaConstraintsInterface* recv_constraints,
|
||||
PeerConnectionFactory::Options* recv_options) {
|
||||
initiating_client_.reset(PeerConnectionTestClient::CreateClient(
|
||||
"Caller: ", init_constraints, init_options, network_thread_.get(),
|
||||
worker_thread_.get()));
|
||||
"Caller: ", init_constraints, init_options, config_,
|
||||
network_thread_.get(), worker_thread_.get()));
|
||||
receiving_client_.reset(PeerConnectionTestClient::CreateClient(
|
||||
"Callee: ", recv_constraints, recv_options, network_thread_.get(),
|
||||
worker_thread_.get()));
|
||||
"Callee: ", recv_constraints, recv_options, config_,
|
||||
network_thread_.get(), worker_thread_.get()));
|
||||
if (!initiating_client_ || !receiving_client_) {
|
||||
return false;
|
||||
}
|
||||
@ -1314,7 +1322,7 @@ class P2PTestConductor : public testing::Test {
|
||||
|
||||
// Make sure the new client is using a different certificate.
|
||||
return PeerConnectionTestClient::CreateClientWithDtlsIdentityStore(
|
||||
"New Peer: ", &setup_constraints, nullptr,
|
||||
"New Peer: ", &setup_constraints, nullptr, config_,
|
||||
std::move(cert_generator), prefer_constraint_apis_,
|
||||
network_thread_.get(), worker_thread_.get());
|
||||
}
|
||||
@ -1354,6 +1362,9 @@ class P2PTestConductor : public testing::Test {
|
||||
receiving_client_.reset(client);
|
||||
return old;
|
||||
}
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration* config() {
|
||||
return &config_;
|
||||
}
|
||||
|
||||
bool AllObserversReceived(
|
||||
const std::vector<std::unique_ptr<MockRtpReceiverObserver>>& observers) {
|
||||
@ -1399,6 +1410,7 @@ class P2PTestConductor : public testing::Test {
|
||||
std::unique_ptr<PeerConnectionTestClient> initiating_client_;
|
||||
std::unique_ptr<PeerConnectionTestClient> receiving_client_;
|
||||
bool prefer_constraint_apis_ = true;
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config_;
|
||||
};
|
||||
|
||||
// Disable for TSan v2, see
|
||||
@ -2116,6 +2128,77 @@ TEST_F(P2PTestConductor, EarlyWarmupTest) {
|
||||
kMaxWaitForFramesMs);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
// This test sets up a call between two parties using QUIC instead of DTLS for
|
||||
// audio and video, and a QUIC data channel.
|
||||
TEST_F(P2PTestConductor, LocalP2PTestQuicDataChannel) {
|
||||
config()->enable_quic = true;
|
||||
ASSERT_TRUE(CreateTestClients());
|
||||
webrtc::DataChannelInit init;
|
||||
init.ordered = false;
|
||||
init.reliable = true;
|
||||
init.id = 1;
|
||||
initializing_client()->CreateDataChannel(&init);
|
||||
receiving_client()->CreateDataChannel(&init);
|
||||
LocalP2PTest();
|
||||
ASSERT_NE(nullptr, initializing_client()->data_channel());
|
||||
ASSERT_NE(nullptr, receiving_client()->data_channel());
|
||||
EXPECT_TRUE_WAIT(initializing_client()->data_observer()->IsOpen(),
|
||||
kMaxWaitMs);
|
||||
EXPECT_TRUE_WAIT(receiving_client()->data_observer()->IsOpen(), kMaxWaitMs);
|
||||
|
||||
std::string data = "hello world";
|
||||
|
||||
initializing_client()->data_channel()->Send(DataBuffer(data));
|
||||
EXPECT_EQ_WAIT(data, receiving_client()->data_observer()->last_message(),
|
||||
kMaxWaitMs);
|
||||
|
||||
receiving_client()->data_channel()->Send(DataBuffer(data));
|
||||
EXPECT_EQ_WAIT(data, initializing_client()->data_observer()->last_message(),
|
||||
kMaxWaitMs);
|
||||
}
|
||||
|
||||
// Tests that negotiation of QUIC data channels is completed without error.
|
||||
TEST_F(P2PTestConductor, NegotiateQuicDataChannel) {
|
||||
config()->enable_quic = true;
|
||||
FakeConstraints constraints;
|
||||
constraints.SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true);
|
||||
ASSERT_TRUE(CreateTestClients(&constraints, &constraints));
|
||||
webrtc::DataChannelInit init;
|
||||
init.ordered = false;
|
||||
init.reliable = true;
|
||||
init.id = 1;
|
||||
initializing_client()->CreateDataChannel(&init);
|
||||
initializing_client()->Negotiate(false, false);
|
||||
}
|
||||
|
||||
// This test sets up a JSEP call using QUIC. The callee only receives video.
|
||||
TEST_F(P2PTestConductor, LocalP2PTestVideoOnlyWithQuic) {
|
||||
config()->enable_quic = true;
|
||||
ASSERT_TRUE(CreateTestClients());
|
||||
receiving_client()->SetReceiveAudioVideo(false, true);
|
||||
LocalP2PTest();
|
||||
}
|
||||
|
||||
// This test sets up a JSEP call using QUIC. The callee only receives audio.
|
||||
TEST_F(P2PTestConductor, LocalP2PTestAudioOnlyWithQuic) {
|
||||
config()->enable_quic = true;
|
||||
ASSERT_TRUE(CreateTestClients());
|
||||
receiving_client()->SetReceiveAudioVideo(true, false);
|
||||
LocalP2PTest();
|
||||
}
|
||||
|
||||
// This test sets up a JSEP call using QUIC. The callee rejects both audio and
|
||||
// video.
|
||||
TEST_F(P2PTestConductor, LocalP2PTestNoVideoAudioWithQuic) {
|
||||
config()->enable_quic = true;
|
||||
ASSERT_TRUE(CreateTestClients());
|
||||
receiving_client()->SetReceiveAudioVideo(false, false);
|
||||
LocalP2PTest();
|
||||
}
|
||||
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
TEST_F(P2PTestConductor, ForwardVideoOnlyStream) {
|
||||
ASSERT_TRUE(CreateTestClients());
|
||||
// One-way stream
|
||||
|
||||
@ -56,6 +56,10 @@ class PeerConnectionEndToEndTest
|
||||
"caller", &network_thread_, &worker_thread_);
|
||||
callee_ = new rtc::RefCountedObject<PeerConnectionTestWrapper>(
|
||||
"callee", &network_thread_, &worker_thread_);
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.uri = "stun:stun.l.google.com:19302";
|
||||
config_.servers.push_back(ice_server);
|
||||
|
||||
#ifdef WEBRTC_ANDROID
|
||||
webrtc::InitializeAndroidObjects();
|
||||
#endif
|
||||
@ -66,8 +70,8 @@ class PeerConnectionEndToEndTest
|
||||
}
|
||||
|
||||
void CreatePcs(const MediaConstraintsInterface* pc_constraints) {
|
||||
EXPECT_TRUE(caller_->CreatePc(pc_constraints));
|
||||
EXPECT_TRUE(callee_->CreatePc(pc_constraints));
|
||||
EXPECT_TRUE(caller_->CreatePc(pc_constraints, config_));
|
||||
EXPECT_TRUE(callee_->CreatePc(pc_constraints, config_));
|
||||
PeerConnectionTestWrapper::Connect(caller_.get(), callee_.get());
|
||||
|
||||
caller_->SignalOnDataChannel.connect(
|
||||
@ -162,6 +166,7 @@ class PeerConnectionEndToEndTest
|
||||
rtc::scoped_refptr<PeerConnectionTestWrapper> callee_;
|
||||
DataChannelList caller_signaled_data_channels_;
|
||||
DataChannelList callee_signaled_data_channels_;
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config_;
|
||||
};
|
||||
|
||||
// Disabled for TSan v2, see
|
||||
@ -313,6 +318,82 @@ TEST_F(PeerConnectionEndToEndTest,
|
||||
EXPECT_EQ(1U, dc_2_observer->received_message_count());
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
// Test that QUIC data channels can be used and that messages go to the correct
|
||||
// remote data channel when both peers want to use QUIC. It is assumed that the
|
||||
// application has externally negotiated the data channel parameters.
|
||||
TEST_F(PeerConnectionEndToEndTest, MessageTransferBetweenQuicDataChannels) {
|
||||
config_.enable_quic = true;
|
||||
CreatePcs();
|
||||
|
||||
webrtc::DataChannelInit init_1;
|
||||
init_1.id = 0;
|
||||
init_1.ordered = false;
|
||||
init_1.reliable = true;
|
||||
|
||||
webrtc::DataChannelInit init_2;
|
||||
init_2.id = 1;
|
||||
init_2.ordered = false;
|
||||
init_2.reliable = true;
|
||||
|
||||
rtc::scoped_refptr<DataChannelInterface> caller_dc_1(
|
||||
caller_->CreateDataChannel("data", init_1));
|
||||
ASSERT_NE(nullptr, caller_dc_1);
|
||||
rtc::scoped_refptr<DataChannelInterface> caller_dc_2(
|
||||
caller_->CreateDataChannel("data", init_2));
|
||||
ASSERT_NE(nullptr, caller_dc_2);
|
||||
rtc::scoped_refptr<DataChannelInterface> callee_dc_1(
|
||||
callee_->CreateDataChannel("data", init_1));
|
||||
ASSERT_NE(nullptr, callee_dc_1);
|
||||
rtc::scoped_refptr<DataChannelInterface> callee_dc_2(
|
||||
callee_->CreateDataChannel("data", init_2));
|
||||
ASSERT_NE(nullptr, callee_dc_2);
|
||||
|
||||
Negotiate();
|
||||
WaitForConnection();
|
||||
EXPECT_TRUE_WAIT(caller_dc_1->state() == webrtc::DataChannelInterface::kOpen,
|
||||
kMaxWait);
|
||||
EXPECT_TRUE_WAIT(callee_dc_1->state() == webrtc::DataChannelInterface::kOpen,
|
||||
kMaxWait);
|
||||
EXPECT_TRUE_WAIT(caller_dc_2->state() == webrtc::DataChannelInterface::kOpen,
|
||||
kMaxWait);
|
||||
EXPECT_TRUE_WAIT(callee_dc_2->state() == webrtc::DataChannelInterface::kOpen,
|
||||
kMaxWait);
|
||||
|
||||
std::unique_ptr<webrtc::MockDataChannelObserver> dc_1_observer(
|
||||
new webrtc::MockDataChannelObserver(callee_dc_1.get()));
|
||||
|
||||
std::unique_ptr<webrtc::MockDataChannelObserver> dc_2_observer(
|
||||
new webrtc::MockDataChannelObserver(callee_dc_2.get()));
|
||||
|
||||
const std::string message_1 = "hello 1";
|
||||
const std::string message_2 = "hello 2";
|
||||
|
||||
// Send data from caller to callee.
|
||||
caller_dc_1->Send(webrtc::DataBuffer(message_1));
|
||||
EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
|
||||
|
||||
caller_dc_2->Send(webrtc::DataBuffer(message_2));
|
||||
EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
|
||||
|
||||
EXPECT_EQ(1U, dc_1_observer->received_message_count());
|
||||
EXPECT_EQ(1U, dc_2_observer->received_message_count());
|
||||
|
||||
// Send data from callee to caller.
|
||||
dc_1_observer.reset(new webrtc::MockDataChannelObserver(caller_dc_1.get()));
|
||||
dc_2_observer.reset(new webrtc::MockDataChannelObserver(caller_dc_2.get()));
|
||||
|
||||
callee_dc_1->Send(webrtc::DataBuffer(message_1));
|
||||
EXPECT_EQ_WAIT(message_1, dc_1_observer->last_message(), kMaxWait);
|
||||
|
||||
callee_dc_2->Send(webrtc::DataBuffer(message_2));
|
||||
EXPECT_EQ_WAIT(message_2, dc_2_observer->last_message(), kMaxWait);
|
||||
|
||||
EXPECT_EQ(1U, dc_1_observer->received_message_count());
|
||||
EXPECT_EQ(1U, dc_2_observer->received_message_count());
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
// Verifies that a DataChannel added from an OPEN message functions after
|
||||
// a channel has been previously closed (webrtc issue 3778).
|
||||
// This previously failed because the new channel re-uses the ID of the closed
|
||||
|
||||
@ -296,6 +296,7 @@ class PeerConnectionInterface : public rtc::RefCountInterface {
|
||||
// default applies.
|
||||
bool disable_ipv6 = false;
|
||||
bool enable_rtp_data_channel = false;
|
||||
bool enable_quic = false;
|
||||
rtc::Optional<int> screencast_min_bitrate;
|
||||
rtc::Optional<bool> combined_audio_video_bwe;
|
||||
rtc::Optional<bool> enable_dtls_srtp;
|
||||
|
||||
@ -242,7 +242,6 @@ static const char kSdpStringMs1Video1[] =
|
||||
|
||||
using ::testing::Exactly;
|
||||
using cricket::StreamParams;
|
||||
using rtc::scoped_refptr;
|
||||
using webrtc::AudioSourceInterface;
|
||||
using webrtc::AudioTrack;
|
||||
using webrtc::AudioTrackInterface;
|
||||
@ -535,18 +534,18 @@ class MockPeerConnectionObserver : public PeerConnectionObserver {
|
||||
return "";
|
||||
}
|
||||
|
||||
scoped_refptr<PeerConnectionInterface> pc_;
|
||||
rtc::scoped_refptr<PeerConnectionInterface> pc_;
|
||||
PeerConnectionInterface::SignalingState state_;
|
||||
std::unique_ptr<IceCandidateInterface> last_candidate_;
|
||||
scoped_refptr<DataChannelInterface> last_datachannel_;
|
||||
rtc::scoped_refptr<DataChannelInterface> last_datachannel_;
|
||||
rtc::scoped_refptr<StreamCollection> remote_streams_;
|
||||
bool renegotiation_needed_ = false;
|
||||
bool ice_complete_ = false;
|
||||
bool callback_triggered = false;
|
||||
|
||||
private:
|
||||
scoped_refptr<MediaStreamInterface> last_added_stream_;
|
||||
scoped_refptr<MediaStreamInterface> last_removed_stream_;
|
||||
rtc::scoped_refptr<MediaStreamInterface> last_added_stream_;
|
||||
rtc::scoped_refptr<MediaStreamInterface> last_removed_stream_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@ -664,7 +663,7 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
server.uri = uri;
|
||||
config.servers.push_back(server);
|
||||
|
||||
scoped_refptr<PeerConnectionInterface> pc;
|
||||
rtc::scoped_refptr<PeerConnectionInterface> pc;
|
||||
pc = pc_factory_->CreatePeerConnection(config, nullptr, nullptr, nullptr,
|
||||
&observer_);
|
||||
EXPECT_EQ(nullptr, pc);
|
||||
@ -700,11 +699,11 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
|
||||
void AddVideoStream(const std::string& label) {
|
||||
// Create a local stream.
|
||||
scoped_refptr<MediaStreamInterface> stream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
pc_factory_->CreateLocalMediaStream(label));
|
||||
scoped_refptr<VideoTrackSourceInterface> video_source(
|
||||
rtc::scoped_refptr<VideoTrackSourceInterface> video_source(
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer(), NULL));
|
||||
scoped_refptr<VideoTrackInterface> video_track(
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
pc_factory_->CreateVideoTrack(label + "v0", video_source));
|
||||
stream->AddTrack(video_track.get());
|
||||
EXPECT_TRUE(pc_->AddStream(stream));
|
||||
@ -714,9 +713,9 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
|
||||
void AddVoiceStream(const std::string& label) {
|
||||
// Create a local stream.
|
||||
scoped_refptr<MediaStreamInterface> stream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
pc_factory_->CreateLocalMediaStream(label));
|
||||
scoped_refptr<AudioTrackInterface> audio_track(
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack(label + "a0", NULL));
|
||||
stream->AddTrack(audio_track.get());
|
||||
EXPECT_TRUE(pc_->AddStream(stream));
|
||||
@ -728,13 +727,13 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
const std::string& audio_track_label,
|
||||
const std::string& video_track_label) {
|
||||
// Create a local stream.
|
||||
scoped_refptr<MediaStreamInterface> stream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
pc_factory_->CreateLocalMediaStream(stream_label));
|
||||
scoped_refptr<AudioTrackInterface> audio_track(
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack(
|
||||
audio_track_label, static_cast<AudioSourceInterface*>(NULL)));
|
||||
stream->AddTrack(audio_track.get());
|
||||
scoped_refptr<VideoTrackInterface> video_track(
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
pc_factory_->CreateVideoTrack(
|
||||
video_track_label,
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
@ -1042,9 +1041,9 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
}
|
||||
|
||||
cricket::FakePortAllocator* port_allocator_ = nullptr;
|
||||
scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
|
||||
scoped_refptr<PeerConnectionFactoryForTest> pc_factory_for_test_;
|
||||
scoped_refptr<PeerConnectionInterface> pc_;
|
||||
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
|
||||
rtc::scoped_refptr<PeerConnectionFactoryForTest> pc_factory_for_test_;
|
||||
rtc::scoped_refptr<PeerConnectionInterface> pc_;
|
||||
MockPeerConnectionObserver observer_;
|
||||
rtc::scoped_refptr<StreamCollection> reference_collection_;
|
||||
};
|
||||
@ -1052,7 +1051,7 @@ class PeerConnectionInterfaceTest : public testing::Test {
|
||||
// Test that no callbacks on the PeerConnectionObserver are called after the
|
||||
// PeerConnection is closed.
|
||||
TEST_F(PeerConnectionInterfaceTest, CloseAndTestCallbackFunctions) {
|
||||
scoped_refptr<PeerConnectionInterface> pc(
|
||||
rtc::scoped_refptr<PeerConnectionInterface> pc(
|
||||
pc_factory_for_test_->CreatePeerConnection(
|
||||
PeerConnectionInterface::RTCConfiguration(), nullptr, nullptr,
|
||||
nullptr, &observer_));
|
||||
@ -1170,11 +1169,11 @@ TEST_F(PeerConnectionInterfaceTest, AddStreams) {
|
||||
ASSERT_EQ(2u, pc_->local_streams()->count());
|
||||
|
||||
// Test we can add multiple local streams to one peerconnection.
|
||||
scoped_refptr<MediaStreamInterface> stream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
pc_factory_->CreateLocalMediaStream(kStreamLabel3));
|
||||
scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack(
|
||||
kStreamLabel3, static_cast<AudioSourceInterface*>(NULL)));
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack(kStreamLabel3,
|
||||
static_cast<AudioSourceInterface*>(NULL)));
|
||||
stream->AddTrack(audio_track.get());
|
||||
EXPECT_TRUE(pc_->AddStream(stream));
|
||||
EXPECT_EQ(3u, pc_->local_streams()->count());
|
||||
@ -1252,15 +1251,16 @@ TEST_F(PeerConnectionInterfaceTest, RemoveStream) {
|
||||
TEST_F(PeerConnectionInterfaceTest, AddTrackRemoveTrack) {
|
||||
CreatePeerConnection();
|
||||
// Create a dummy stream, so tracks share a stream label.
|
||||
scoped_refptr<MediaStreamInterface> stream(
|
||||
rtc::scoped_refptr<MediaStreamInterface> stream(
|
||||
pc_factory_->CreateLocalMediaStream(kStreamLabel1));
|
||||
std::vector<MediaStreamInterface*> stream_list;
|
||||
stream_list.push_back(stream.get());
|
||||
scoped_refptr<AudioTrackInterface> audio_track(
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||
scoped_refptr<VideoTrackInterface> video_track(pc_factory_->CreateVideoTrack(
|
||||
"video_track",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
pc_factory_->CreateVideoTrack(
|
||||
"video_track",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
auto audio_sender = pc_->AddTrack(audio_track, stream_list);
|
||||
auto video_sender = pc_->AddTrack(video_track, stream_list);
|
||||
EXPECT_EQ(1UL, audio_sender->stream_ids().size());
|
||||
@ -1326,11 +1326,12 @@ TEST_F(PeerConnectionInterfaceTest, AddTrackRemoveTrack) {
|
||||
TEST_F(PeerConnectionInterfaceTest, AddTrackWithoutStream) {
|
||||
CreatePeerConnection();
|
||||
// Create a dummy stream, so tracks share a stream label.
|
||||
scoped_refptr<AudioTrackInterface> audio_track(
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track(
|
||||
pc_factory_->CreateAudioTrack("audio_track", nullptr));
|
||||
scoped_refptr<VideoTrackInterface> video_track(pc_factory_->CreateVideoTrack(
|
||||
"video_track",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
pc_factory_->CreateVideoTrack(
|
||||
"video_track",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
auto audio_sender =
|
||||
pc_->AddTrack(audio_track, std::vector<MediaStreamInterface*>());
|
||||
auto video_sender =
|
||||
@ -1489,9 +1490,10 @@ TEST_F(PeerConnectionInterfaceTest, AddTrackAfterAddStream) {
|
||||
MediaStreamInterface* stream = pc_->local_streams()->at(0);
|
||||
|
||||
// Add video track to the audio-only stream.
|
||||
scoped_refptr<VideoTrackInterface> video_track(pc_factory_->CreateVideoTrack(
|
||||
"video_label",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track(
|
||||
pc_factory_->CreateVideoTrack(
|
||||
"video_label",
|
||||
pc_factory_->CreateVideoSource(new cricket::FakeVideoCapturer())));
|
||||
stream->AddTrack(video_track.get());
|
||||
|
||||
std::unique_ptr<SessionDescriptionInterface> offer;
|
||||
@ -1543,7 +1545,7 @@ TEST_F(PeerConnectionInterfaceTest, GetStatsForSpecificTrack) {
|
||||
InitiateCall();
|
||||
ASSERT_LT(0u, pc_->remote_streams()->count());
|
||||
ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetAudioTracks().size());
|
||||
scoped_refptr<MediaStreamTrackInterface> remote_audio =
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> remote_audio =
|
||||
pc_->remote_streams()->at(0)->GetAudioTracks()[0];
|
||||
EXPECT_TRUE(DoGetStats(remote_audio));
|
||||
|
||||
@ -1565,7 +1567,7 @@ TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
|
||||
InitiateCall();
|
||||
ASSERT_LT(0u, pc_->remote_streams()->count());
|
||||
ASSERT_LT(0u, pc_->remote_streams()->at(0)->GetVideoTracks().size());
|
||||
scoped_refptr<MediaStreamTrackInterface> remote_video =
|
||||
rtc::scoped_refptr<MediaStreamTrackInterface> remote_video =
|
||||
pc_->remote_streams()->at(0)->GetVideoTracks()[0];
|
||||
EXPECT_TRUE(DoGetStats(remote_video));
|
||||
}
|
||||
@ -1576,7 +1578,7 @@ TEST_F(PeerConnectionInterfaceTest, GetStatsForVideoTrack) {
|
||||
// data is returned for the track.
|
||||
TEST_F(PeerConnectionInterfaceTest, DISABLED_GetStatsForInvalidTrack) {
|
||||
InitiateCall();
|
||||
scoped_refptr<AudioTrackInterface> unknown_audio_track(
|
||||
rtc::scoped_refptr<AudioTrackInterface> unknown_audio_track(
|
||||
pc_factory_->CreateAudioTrack("unknown track", NULL));
|
||||
EXPECT_FALSE(DoGetStats(unknown_audio_track));
|
||||
}
|
||||
@ -1586,9 +1588,9 @@ TEST_F(PeerConnectionInterfaceTest, TestDataChannel) {
|
||||
FakeConstraints constraints;
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
scoped_refptr<DataChannelInterface> data1 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data1 =
|
||||
pc_->CreateDataChannel("test1", NULL);
|
||||
scoped_refptr<DataChannelInterface> data2 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data2 =
|
||||
pc_->CreateDataChannel("test2", NULL);
|
||||
ASSERT_TRUE(data1 != NULL);
|
||||
std::unique_ptr<MockDataChannelObserver> observer1(
|
||||
@ -1633,9 +1635,9 @@ TEST_F(PeerConnectionInterfaceTest, TestSendBinaryOnRtpDataChannel) {
|
||||
FakeConstraints constraints;
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
scoped_refptr<DataChannelInterface> data1 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data1 =
|
||||
pc_->CreateDataChannel("test1", NULL);
|
||||
scoped_refptr<DataChannelInterface> data2 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data2 =
|
||||
pc_->CreateDataChannel("test2", NULL);
|
||||
ASSERT_TRUE(data1 != NULL);
|
||||
std::unique_ptr<MockDataChannelObserver> observer1(
|
||||
@ -1663,7 +1665,7 @@ TEST_F(PeerConnectionInterfaceTest, TestSendOnlyDataChannel) {
|
||||
FakeConstraints constraints;
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
scoped_refptr<DataChannelInterface> data1 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data1 =
|
||||
pc_->CreateDataChannel("test1", NULL);
|
||||
std::unique_ptr<MockDataChannelObserver> observer1(
|
||||
new MockDataChannelObserver(data1));
|
||||
@ -1687,7 +1689,7 @@ TEST_F(PeerConnectionInterfaceTest, TestReceiveOnlyDataChannel) {
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
std::string offer_label = "offer_channel";
|
||||
scoped_refptr<DataChannelInterface> offer_channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> offer_channel =
|
||||
pc_->CreateDataChannel(offer_label, NULL);
|
||||
|
||||
CreateOfferAsLocalDescription();
|
||||
@ -1730,7 +1732,7 @@ TEST_F(PeerConnectionInterfaceTest, CreateReliableRtpDataChannelShouldFail) {
|
||||
std::string label = "test";
|
||||
webrtc::DataChannelInit config;
|
||||
config.reliable = true;
|
||||
scoped_refptr<DataChannelInterface> channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> channel =
|
||||
pc_->CreateDataChannel(label, &config);
|
||||
EXPECT_TRUE(channel == NULL);
|
||||
}
|
||||
@ -1742,11 +1744,11 @@ TEST_F(PeerConnectionInterfaceTest, RtpDuplicatedLabelNotAllowed) {
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
std::string label = "test";
|
||||
scoped_refptr<DataChannelInterface> channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> channel =
|
||||
pc_->CreateDataChannel(label, nullptr);
|
||||
EXPECT_NE(channel, nullptr);
|
||||
|
||||
scoped_refptr<DataChannelInterface> dup_channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> dup_channel =
|
||||
pc_->CreateDataChannel(label, nullptr);
|
||||
EXPECT_EQ(dup_channel, nullptr);
|
||||
}
|
||||
@ -1760,7 +1762,7 @@ TEST_F(PeerConnectionInterfaceTest, CreateSctpDataChannel) {
|
||||
|
||||
webrtc::DataChannelInit config;
|
||||
|
||||
scoped_refptr<DataChannelInterface> channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> channel =
|
||||
pc_->CreateDataChannel("1", &config);
|
||||
EXPECT_TRUE(channel != NULL);
|
||||
EXPECT_TRUE(channel->reliable());
|
||||
@ -1801,7 +1803,7 @@ TEST_F(PeerConnectionInterfaceTest,
|
||||
config.maxRetransmits = 0;
|
||||
config.maxRetransmitTime = 0;
|
||||
|
||||
scoped_refptr<DataChannelInterface> channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> channel =
|
||||
pc_->CreateDataChannel(label, &config);
|
||||
EXPECT_TRUE(channel == NULL);
|
||||
}
|
||||
@ -1815,7 +1817,7 @@ TEST_F(PeerConnectionInterfaceTest,
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
webrtc::DataChannelInit config;
|
||||
scoped_refptr<DataChannelInterface> channel;
|
||||
rtc::scoped_refptr<DataChannelInterface> channel;
|
||||
|
||||
config.id = 1;
|
||||
channel = pc_->CreateDataChannel("1", &config);
|
||||
@ -1843,11 +1845,11 @@ TEST_F(PeerConnectionInterfaceTest, SctpDuplicatedLabelAllowed) {
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
std::string label = "test";
|
||||
scoped_refptr<DataChannelInterface> channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> channel =
|
||||
pc_->CreateDataChannel(label, nullptr);
|
||||
EXPECT_NE(channel, nullptr);
|
||||
|
||||
scoped_refptr<DataChannelInterface> dup_channel =
|
||||
rtc::scoped_refptr<DataChannelInterface> dup_channel =
|
||||
pc_->CreateDataChannel(label, nullptr);
|
||||
EXPECT_NE(dup_channel, nullptr);
|
||||
}
|
||||
@ -1859,12 +1861,12 @@ TEST_F(PeerConnectionInterfaceTest, RenegotiationNeededForNewRtpDataChannel) {
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
scoped_refptr<DataChannelInterface> dc1 =
|
||||
rtc::scoped_refptr<DataChannelInterface> dc1 =
|
||||
pc_->CreateDataChannel("test1", NULL);
|
||||
EXPECT_TRUE(observer_.renegotiation_needed_);
|
||||
observer_.renegotiation_needed_ = false;
|
||||
|
||||
scoped_refptr<DataChannelInterface> dc2 =
|
||||
rtc::scoped_refptr<DataChannelInterface> dc2 =
|
||||
pc_->CreateDataChannel("test2", NULL);
|
||||
EXPECT_TRUE(observer_.renegotiation_needed_);
|
||||
}
|
||||
@ -1875,9 +1877,9 @@ TEST_F(PeerConnectionInterfaceTest, DataChannelCloseWhenPeerConnectionClose) {
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
scoped_refptr<DataChannelInterface> data1 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data1 =
|
||||
pc_->CreateDataChannel("test1", NULL);
|
||||
scoped_refptr<DataChannelInterface> data2 =
|
||||
rtc::scoped_refptr<DataChannelInterface> data2 =
|
||||
pc_->CreateDataChannel("test2", NULL);
|
||||
ASSERT_TRUE(data1 != NULL);
|
||||
std::unique_ptr<MockDataChannelObserver> observer1(
|
||||
@ -1900,7 +1902,7 @@ TEST_F(PeerConnectionInterfaceTest, TestRejectDataChannelInAnswer) {
|
||||
constraints.SetAllowRtpDataChannels();
|
||||
CreatePeerConnection(&constraints);
|
||||
|
||||
scoped_refptr<DataChannelInterface> offer_channel(
|
||||
rtc::scoped_refptr<DataChannelInterface> offer_channel(
|
||||
pc_->CreateDataChannel("offer_channel", NULL));
|
||||
|
||||
CreateOfferAsLocalDescription();
|
||||
@ -2106,8 +2108,8 @@ TEST_F(PeerConnectionInterfaceTest, CloseAndTestStreamsAndStates) {
|
||||
EXPECT_EQ(1u, pc_->local_streams()->count());
|
||||
EXPECT_EQ(1u, pc_->remote_streams()->count());
|
||||
|
||||
scoped_refptr<MediaStreamInterface> remote_stream =
|
||||
pc_->remote_streams()->at(0);
|
||||
rtc::scoped_refptr<MediaStreamInterface> remote_stream =
|
||||
pc_->remote_streams()->at(0);
|
||||
// Track state may be updated asynchronously.
|
||||
EXPECT_EQ_WAIT(MediaStreamTrackInterface::kEnded,
|
||||
remote_stream->GetAudioTracks()[0]->state(), kTimeout);
|
||||
@ -2124,7 +2126,7 @@ TEST_F(PeerConnectionInterfaceTest, CloseAndTestMethods) {
|
||||
CreateAnswerAsLocalDescription();
|
||||
|
||||
ASSERT_EQ(1u, pc_->local_streams()->count());
|
||||
scoped_refptr<MediaStreamInterface> local_stream =
|
||||
rtc::scoped_refptr<MediaStreamInterface> local_stream =
|
||||
pc_->local_streams()->at(0);
|
||||
|
||||
pc_->Close();
|
||||
@ -2217,10 +2219,10 @@ TEST_F(PeerConnectionInterfaceTest,
|
||||
EXPECT_TRUE(DoSetRemoteDescription(desc_ms1_two_tracks.release()));
|
||||
EXPECT_TRUE(CompareStreamCollections(observer_.remote_streams(),
|
||||
reference_collection_));
|
||||
scoped_refptr<AudioTrackInterface> audio_track2 =
|
||||
rtc::scoped_refptr<AudioTrackInterface> audio_track2 =
|
||||
observer_.remote_streams()->at(0)->GetAudioTracks()[1];
|
||||
EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, audio_track2->state());
|
||||
scoped_refptr<VideoTrackInterface> video_track2 =
|
||||
rtc::scoped_refptr<VideoTrackInterface> video_track2 =
|
||||
observer_.remote_streams()->at(0)->GetVideoTracks()[1];
|
||||
EXPECT_EQ(webrtc::MediaStreamTrackInterface::kLive, video_track2->state());
|
||||
|
||||
@ -2641,15 +2643,14 @@ class PeerConnectionMediaConfigTest : public testing::Test {
|
||||
const MediaConstraintsInterface *constraints) {
|
||||
pcf_->create_media_controller_called_ = false;
|
||||
|
||||
scoped_refptr<PeerConnectionInterface> pc(
|
||||
pcf_->CreatePeerConnection(config, constraints, nullptr, nullptr,
|
||||
&observer_));
|
||||
rtc::scoped_refptr<PeerConnectionInterface> pc(pcf_->CreatePeerConnection(
|
||||
config, constraints, nullptr, nullptr, &observer_));
|
||||
EXPECT_TRUE(pc.get());
|
||||
EXPECT_TRUE(pcf_->create_media_controller_called_);
|
||||
return pcf_->create_media_controller_config_;
|
||||
}
|
||||
|
||||
scoped_refptr<PeerConnectionFactoryForTest> pcf_;
|
||||
rtc::scoped_refptr<PeerConnectionFactoryForTest> pcf_;
|
||||
MockPeerConnectionObserver observer_;
|
||||
};
|
||||
|
||||
|
||||
@ -10,24 +10,48 @@
|
||||
|
||||
#include "webrtc/api/quicdatatransport.h"
|
||||
|
||||
#include "webrtc/base/bind.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
#include "webrtc/p2p/quic/quictransportchannel.h"
|
||||
#include "webrtc/p2p/quic/reliablequicstream.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
QuicDataTransport::QuicDataTransport(rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
rtc::Thread* network_thread)
|
||||
QuicDataTransport::QuicDataTransport(
|
||||
rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
rtc::Thread* network_thread,
|
||||
cricket::TransportController* transport_controller)
|
||||
: signaling_thread_(signaling_thread),
|
||||
worker_thread_(worker_thread),
|
||||
network_thread_(network_thread) {
|
||||
network_thread_(network_thread),
|
||||
transport_controller_(transport_controller) {
|
||||
RTC_DCHECK(signaling_thread_);
|
||||
RTC_DCHECK(worker_thread_);
|
||||
RTC_DCHECK(network_thread_);
|
||||
}
|
||||
|
||||
QuicDataTransport::~QuicDataTransport() {}
|
||||
QuicDataTransport::~QuicDataTransport() {
|
||||
DestroyTransportChannel(quic_transport_channel_);
|
||||
LOG(LS_INFO) << "Destroyed the QUIC data transport.";
|
||||
}
|
||||
|
||||
bool QuicDataTransport::SetTransport(const std::string& transport_name) {
|
||||
if (transport_name_ == transport_name) {
|
||||
// Nothing to do if transport name isn't changing
|
||||
return true;
|
||||
}
|
||||
|
||||
cricket::QuicTransportChannel* transport_channel =
|
||||
CreateTransportChannel(transport_name);
|
||||
if (!SetTransportChannel(transport_channel)) {
|
||||
DestroyTransportChannel(transport_channel);
|
||||
return false;
|
||||
}
|
||||
|
||||
transport_name_ = transport_name;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QuicDataTransport::SetTransportChannel(
|
||||
cricket::QuicTransportChannel* channel) {
|
||||
@ -48,7 +72,6 @@ bool QuicDataTransport::SetTransportChannel(
|
||||
quic_transport_channel_ = channel;
|
||||
quic_transport_channel_->SignalIncomingStream.connect(
|
||||
this, &QuicDataTransport::OnIncomingStream);
|
||||
|
||||
bool success = true;
|
||||
for (const auto& kv : data_channel_by_id_) {
|
||||
rtc::scoped_refptr<QuicDataChannel> data_channel = kv.second;
|
||||
@ -147,4 +170,28 @@ void QuicDataTransport::OnDataReceived(net::QuicStreamId id,
|
||||
data_channel->OnIncomingMessage(std::move(message));
|
||||
}
|
||||
|
||||
cricket::QuicTransportChannel* QuicDataTransport::CreateTransportChannel(
|
||||
const std::string& transport_name) {
|
||||
DCHECK(transport_controller_->quic());
|
||||
|
||||
cricket::TransportChannel* transport_channel =
|
||||
network_thread_->Invoke<cricket::TransportChannel*>(
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&cricket::TransportController::CreateTransportChannel_n,
|
||||
transport_controller_, transport_name,
|
||||
cricket::ICE_CANDIDATE_COMPONENT_DEFAULT));
|
||||
return static_cast<cricket::QuicTransportChannel*>(transport_channel);
|
||||
}
|
||||
|
||||
void QuicDataTransport::DestroyTransportChannel(
|
||||
cricket::TransportChannel* transport_channel) {
|
||||
if (transport_channel) {
|
||||
network_thread_->Invoke<void>(
|
||||
RTC_FROM_HERE,
|
||||
rtc::Bind(&cricket::TransportController::DestroyTransportChannel_n,
|
||||
transport_controller_, transport_channel->transport_name(),
|
||||
cricket::ICE_CANDIDATE_COMPONENT_DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include "webrtc/base/scoped_ref_ptr.h"
|
||||
#include "webrtc/base/sigslot.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
#include "webrtc/p2p/base/transportcontroller.h"
|
||||
|
||||
namespace cricket {
|
||||
class QuicTransportChannel;
|
||||
@ -38,14 +39,17 @@ class QuicDataTransport : public sigslot::has_slots<> {
|
||||
public:
|
||||
QuicDataTransport(rtc::Thread* signaling_thread,
|
||||
rtc::Thread* worker_thread,
|
||||
rtc::Thread* network_thread);
|
||||
rtc::Thread* network_thread,
|
||||
cricket::TransportController* transport_controller);
|
||||
~QuicDataTransport() override;
|
||||
|
||||
// Sets the QUIC transport channel for the QuicDataChannels and the
|
||||
// QuicDataTransport. Returns false if a different QUIC transport channel is
|
||||
// already set, the QUIC transport channel cannot be set for any of the
|
||||
// QuicDataChannels, or |channel| is NULL.
|
||||
bool SetTransportChannel(cricket::QuicTransportChannel* channel);
|
||||
// The QuicDataTransport acts like a BaseChannel with these functions.
|
||||
bool SetTransport(const std::string& transport_name);
|
||||
const std::string& transport_name() const { return transport_name_; }
|
||||
const std::string& content_name() const { return content_name_; }
|
||||
void set_content_name(const std::string& content_name) {
|
||||
content_name_ = content_name;
|
||||
}
|
||||
|
||||
// Creates a QuicDataChannel that uses this QuicDataTransport.
|
||||
rtc::scoped_refptr<DataChannelInterface> CreateDataChannel(
|
||||
@ -62,7 +66,17 @@ class QuicDataTransport : public sigslot::has_slots<> {
|
||||
// True if the QuicDataTransport has data channels.
|
||||
bool HasDataChannels() const;
|
||||
|
||||
cricket::QuicTransportChannel* quic_transport_channel() {
|
||||
return quic_transport_channel_;
|
||||
}
|
||||
|
||||
private:
|
||||
// Sets the QUIC transport channel for the QuicDataChannels and the
|
||||
// QuicDataTransport. Returns false if a different QUIC transport channel is
|
||||
// already set, the QUIC transport channel cannot be set for any of the
|
||||
// QuicDataChannels, or |channel| is NULL.
|
||||
bool SetTransportChannel(cricket::QuicTransportChannel* channel);
|
||||
|
||||
// Called from the QuicTransportChannel when a ReliableQuicStream is created
|
||||
// to receive incoming data.
|
||||
void OnIncomingStream(cricket::ReliableQuicStream* stream);
|
||||
@ -74,6 +88,10 @@ class QuicDataTransport : public sigslot::has_slots<> {
|
||||
const char* data,
|
||||
size_t len);
|
||||
|
||||
cricket::QuicTransportChannel* CreateTransportChannel(
|
||||
const std::string& transport_name);
|
||||
void DestroyTransportChannel(cricket::TransportChannel* transport_channel);
|
||||
|
||||
// Map of data channel ID => QUIC data channel values.
|
||||
std::unordered_map<int, rtc::scoped_refptr<QuicDataChannel>>
|
||||
data_channel_by_id_;
|
||||
@ -86,6 +104,10 @@ class QuicDataTransport : public sigslot::has_slots<> {
|
||||
rtc::Thread* const signaling_thread_;
|
||||
rtc::Thread* const worker_thread_;
|
||||
rtc::Thread* const network_thread_;
|
||||
|
||||
cricket::TransportController* transport_controller_;
|
||||
std::string content_name_;
|
||||
std::string transport_name_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -30,6 +30,7 @@ using webrtc::DataChannelObserver;
|
||||
using webrtc::QuicDataChannel;
|
||||
using webrtc::QuicDataTransport;
|
||||
using cricket::FakeTransportChannel;
|
||||
using cricket::FakeTransportController;
|
||||
using cricket::QuicTransportChannel;
|
||||
using cricket::ReliableQuicStream;
|
||||
|
||||
@ -37,6 +38,7 @@ namespace {
|
||||
|
||||
// Timeout for asynchronous operations.
|
||||
static const int kTimeoutMs = 1000; // milliseconds
|
||||
static const char kTransportName[] = "data";
|
||||
|
||||
// FakeObserver receives messages from the data channel.
|
||||
class FakeObserver : public DataChannelObserver {
|
||||
@ -64,11 +66,16 @@ class FakeObserver : public DataChannelObserver {
|
||||
class QuicDataTransportPeer {
|
||||
public:
|
||||
QuicDataTransportPeer()
|
||||
: quic_data_transport_(rtc::Thread::Current(),
|
||||
: fake_transport_controller_(new FakeTransportController()),
|
||||
quic_data_transport_(rtc::Thread::Current(),
|
||||
rtc::Thread::Current(),
|
||||
rtc::Thread::Current()),
|
||||
ice_transport_channel_(new FakeTransportChannel("data", 0)),
|
||||
quic_transport_channel_(ice_transport_channel_) {
|
||||
rtc::Thread::Current(),
|
||||
fake_transport_controller_.get()) {
|
||||
fake_transport_controller_->use_quic();
|
||||
quic_data_transport_.set_content_name("data");
|
||||
quic_data_transport_.SetTransport(kTransportName);
|
||||
ice_transport_channel_ = static_cast<FakeTransportChannel*>(
|
||||
quic_data_transport_.quic_transport_channel()->ice_transport_channel());
|
||||
ice_transport_channel_->SetAsync(true);
|
||||
}
|
||||
|
||||
@ -76,7 +83,8 @@ class QuicDataTransportPeer {
|
||||
rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
|
||||
rtc::RTCCertificate::Create(std::unique_ptr<rtc::SSLIdentity>(
|
||||
rtc::SSLIdentity::Generate("cert_name", rtc::KT_DEFAULT)));
|
||||
quic_transport_channel_.SetLocalCertificate(local_cert);
|
||||
quic_data_transport_.quic_transport_channel()->SetLocalCertificate(
|
||||
local_cert);
|
||||
local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
|
||||
}
|
||||
|
||||
@ -90,14 +98,15 @@ class QuicDataTransportPeer {
|
||||
}
|
||||
|
||||
QuicTransportChannel* quic_transport_channel() {
|
||||
return &quic_transport_channel_;
|
||||
return quic_data_transport_.quic_transport_channel();
|
||||
}
|
||||
|
||||
// Write a messge directly to the ReliableQuicStream.
|
||||
void WriteMessage(int data_channel_id,
|
||||
uint64_t message_id,
|
||||
const std::string& message) {
|
||||
ReliableQuicStream* stream = quic_transport_channel_.CreateQuicStream();
|
||||
ReliableQuicStream* stream =
|
||||
quic_data_transport_.quic_transport_channel()->CreateQuicStream();
|
||||
rtc::CopyOnWriteBuffer payload;
|
||||
webrtc::WriteQuicDataChannelMessageHeader(data_channel_id, message_id,
|
||||
&payload);
|
||||
@ -122,9 +131,9 @@ class QuicDataTransportPeer {
|
||||
return fingerprint.release();
|
||||
}
|
||||
|
||||
std::unique_ptr<FakeTransportController> fake_transport_controller_;
|
||||
QuicDataTransport quic_data_transport_;
|
||||
FakeTransportChannel* ice_transport_channel_;
|
||||
QuicTransportChannel quic_transport_channel_;
|
||||
std::unique_ptr<rtc::SSLFingerprint> local_fingerprint_;
|
||||
};
|
||||
|
||||
@ -140,13 +149,6 @@ class QuicDataTransportTest : public testing::Test {
|
||||
kTimeoutMs);
|
||||
}
|
||||
|
||||
void SetTransportChannels() {
|
||||
ASSERT_TRUE(peer1_.quic_data_transport()->SetTransportChannel(
|
||||
peer1_.quic_transport_channel()));
|
||||
ASSERT_TRUE(peer2_.quic_data_transport()->SetTransportChannel(
|
||||
peer2_.quic_transport_channel()));
|
||||
}
|
||||
|
||||
// Sets crypto parameters required for the QUIC handshake.
|
||||
void SetCryptoParameters() {
|
||||
peer1_.GenerateCertificateAndFingerprint();
|
||||
@ -207,7 +209,7 @@ TEST_F(QuicDataTransportTest, CannotCreateDataChannelsWithSameId) {
|
||||
}
|
||||
|
||||
// Tests that any data channels created by the QuicDataTransport are in state
|
||||
// kConnecting before the QuicTransportChannel is set, then transiton to state
|
||||
// kConnecting before the QuicTransportChannel is set, then transition to state
|
||||
// kOpen when the transport channel becomes writable.
|
||||
TEST_F(QuicDataTransportTest, DataChannelsOpenWhenTransportChannelWritable) {
|
||||
webrtc::DataChannelInit config1;
|
||||
@ -215,7 +217,6 @@ TEST_F(QuicDataTransportTest, DataChannelsOpenWhenTransportChannelWritable) {
|
||||
rtc::scoped_refptr<DataChannelInterface> data_channel1 =
|
||||
peer2_.CreateDataChannel(&config1);
|
||||
EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
|
||||
SetTransportChannels();
|
||||
EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel1->state());
|
||||
webrtc::DataChannelInit config2;
|
||||
config2.id = 14;
|
||||
@ -239,7 +240,6 @@ TEST_F(QuicDataTransportTest, DataChannelsOpenWhenTransportChannelWritable) {
|
||||
// Tests that the QuicTransport dispatches messages for one QuicDataChannel.
|
||||
TEST_F(QuicDataTransportTest, ReceiveMessagesForSingleDataChannel) {
|
||||
ConnectTransportChannels();
|
||||
SetTransportChannels();
|
||||
|
||||
int data_channel_id = 1337;
|
||||
webrtc::DataChannelInit config;
|
||||
@ -269,7 +269,6 @@ TEST_F(QuicDataTransportTest, ReceiveMessagesForSingleDataChannel) {
|
||||
// when multiple are in use.
|
||||
TEST_F(QuicDataTransportTest, ReceiveMessagesForMultipleDataChannels) {
|
||||
ConnectTransportChannels();
|
||||
SetTransportChannels();
|
||||
|
||||
std::vector<rtc::scoped_refptr<DataChannelInterface>> data_channels;
|
||||
for (int data_channel_id = 0; data_channel_id < 5; ++data_channel_id) {
|
||||
@ -299,7 +298,6 @@ TEST_F(QuicDataTransportTest, ReceiveMessagesForMultipleDataChannels) {
|
||||
// send/receive messages using a QuicDataTransport.
|
||||
TEST_F(QuicDataTransportTest, EndToEndSendReceiveMessages) {
|
||||
ConnectTransportChannels();
|
||||
SetTransportChannels();
|
||||
|
||||
std::vector<rtc::scoped_refptr<DataChannelInterface>> peer1_data_channels;
|
||||
std::vector<rtc::scoped_refptr<DataChannelInterface>> peer2_data_channels;
|
||||
@ -339,18 +337,14 @@ TEST_F(QuicDataTransportTest, EndToEndSendReceiveMessages) {
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that SetTransportChannel returns false when setting a NULL transport
|
||||
// channel or a transport channel that is not equivalent to the one already set.
|
||||
TEST_F(QuicDataTransportTest, SetTransportChannelReturnValue) {
|
||||
// Tests that SetTransport returns false when setting a transport that is not
|
||||
// equivalent to the one already set.
|
||||
TEST_F(QuicDataTransportTest, SetTransportReturnValue) {
|
||||
QuicDataTransport* quic_data_transport = peer1_.quic_data_transport();
|
||||
EXPECT_FALSE(quic_data_transport->SetTransportChannel(nullptr));
|
||||
QuicTransportChannel* transport_channel = peer1_.quic_transport_channel();
|
||||
EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
|
||||
EXPECT_TRUE(quic_data_transport->SetTransportChannel(transport_channel));
|
||||
QuicTransportChannel* other_transport_channel =
|
||||
peer2_.quic_transport_channel();
|
||||
EXPECT_FALSE(
|
||||
quic_data_transport->SetTransportChannel(other_transport_channel));
|
||||
// Ignore the same transport name.
|
||||
EXPECT_TRUE(quic_data_transport->SetTransport(kTransportName));
|
||||
// Return false when setting a different transport name.
|
||||
EXPECT_FALSE(quic_data_transport->SetTransport("another transport name"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -58,7 +58,8 @@ PeerConnectionTestWrapper::PeerConnectionTestWrapper(
|
||||
PeerConnectionTestWrapper::~PeerConnectionTestWrapper() {}
|
||||
|
||||
bool PeerConnectionTestWrapper::CreatePc(
|
||||
const MediaConstraintsInterface* constraints) {
|
||||
const MediaConstraintsInterface* constraints,
|
||||
const webrtc::PeerConnectionInterface::RTCConfiguration& config) {
|
||||
std::unique_ptr<cricket::PortAllocator> port_allocator(
|
||||
new cricket::FakePortAllocator(network_thread_, nullptr));
|
||||
|
||||
@ -74,11 +75,6 @@ bool PeerConnectionTestWrapper::CreatePc(
|
||||
return false;
|
||||
}
|
||||
|
||||
// CreatePeerConnection with RTCConfiguration.
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration config;
|
||||
webrtc::PeerConnectionInterface::IceServer ice_server;
|
||||
ice_server.uri = "stun:stun.l.google.com:19302";
|
||||
config.servers.push_back(ice_server);
|
||||
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator(
|
||||
rtc::SSLStreamAdapter::HaveDtlsSrtp() ? new FakeRTCCertificateGenerator()
|
||||
: nullptr);
|
||||
|
||||
@ -32,7 +32,9 @@ class PeerConnectionTestWrapper
|
||||
rtc::Thread* worker_thread);
|
||||
virtual ~PeerConnectionTestWrapper();
|
||||
|
||||
bool CreatePc(const webrtc::MediaConstraintsInterface* constraints);
|
||||
bool CreatePc(
|
||||
const webrtc::MediaConstraintsInterface* constraints,
|
||||
const webrtc::PeerConnectionInterface::RTCConfiguration& config);
|
||||
|
||||
rtc::scoped_refptr<webrtc::DataChannelInterface> CreateDataChannel(
|
||||
const std::string& label,
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "webrtc/api/webrtcsessiondescriptionfactory.h"
|
||||
#include "webrtc/audio_sink.h"
|
||||
#include "webrtc/base/basictypes.h"
|
||||
#include "webrtc/base/bind.h"
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/helpers.h"
|
||||
#include "webrtc/base/logging.h"
|
||||
@ -38,6 +39,10 @@
|
||||
#include "webrtc/pc/channelmanager.h"
|
||||
#include "webrtc/pc/mediasession.h"
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
#include "webrtc/p2p/quic/quictransportchannel.h"
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
using cricket::ContentInfo;
|
||||
using cricket::ContentInfos;
|
||||
using cricket::MediaContentDescription;
|
||||
@ -460,7 +465,8 @@ WebRtcSession::WebRtcSession(
|
||||
rtc::Thread* signaling_thread,
|
||||
cricket::PortAllocator* port_allocator,
|
||||
std::unique_ptr<cricket::TransportController> transport_controller)
|
||||
: worker_thread_(worker_thread),
|
||||
: network_thread_(network_thread),
|
||||
worker_thread_(worker_thread),
|
||||
signaling_thread_(signaling_thread),
|
||||
// RFC 3264: The numeric value of the session id and version in the
|
||||
// o line MUST be representable with a "64 bit signed integer".
|
||||
@ -505,6 +511,11 @@ WebRtcSession::~WebRtcSession() {
|
||||
SignalDataChannelDestroyed();
|
||||
channel_manager_->DestroyDataChannel(data_channel_.release());
|
||||
}
|
||||
#ifdef HAVE_QUIC
|
||||
if (quic_data_transport_) {
|
||||
quic_data_transport_.reset();
|
||||
}
|
||||
#endif
|
||||
SignalDestroyed();
|
||||
|
||||
LOG(LS_INFO) << "Session: " << id() << " is destroyed.";
|
||||
@ -545,7 +556,21 @@ bool WebRtcSession::Initialize(
|
||||
// PeerConnectionFactoryInterface::Options.
|
||||
if (rtc_configuration.enable_rtp_data_channel) {
|
||||
data_channel_type_ = cricket::DCT_RTP;
|
||||
} else {
|
||||
}
|
||||
#ifdef HAVE_QUIC
|
||||
else if (rtc_configuration.enable_quic) {
|
||||
// Use QUIC instead of DTLS when |enable_quic| is true.
|
||||
data_channel_type_ = cricket::DCT_QUIC;
|
||||
transport_controller_->use_quic();
|
||||
if (dtls_enabled_) {
|
||||
LOG(LS_INFO) << "Using QUIC instead of DTLS";
|
||||
}
|
||||
quic_data_transport_.reset(
|
||||
new QuicDataTransport(signaling_thread(), worker_thread(),
|
||||
network_thread(), transport_controller_.get()));
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
else {
|
||||
// DTLS has to be enabled to use SCTP.
|
||||
if (!options.disable_sctp_data_channels && dtls_enabled_) {
|
||||
data_channel_type_ = cricket::DCT_SCTP;
|
||||
@ -1035,6 +1060,15 @@ bool WebRtcSession::EnableBundle(const cricket::ContentGroup& bundle) {
|
||||
const std::string& transport_name = *first_content_name;
|
||||
cricket::BaseChannel* first_channel = GetChannel(transport_name);
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
if (quic_data_transport_ &&
|
||||
bundle.HasContentName(quic_data_transport_->content_name()) &&
|
||||
quic_data_transport_->transport_name() != transport_name) {
|
||||
LOG(LS_ERROR) << "Unable to BUNDLE " << quic_data_transport_->content_name()
|
||||
<< " on " << transport_name << "with QUIC.";
|
||||
}
|
||||
#endif
|
||||
|
||||
auto maybe_set_transport = [this, bundle, transport_name,
|
||||
first_channel](cricket::BaseChannel* ch) {
|
||||
if (!ch || !bundle.HasContentName(ch->content_name())) {
|
||||
@ -1543,9 +1577,17 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) {
|
||||
|
||||
const cricket::ContentInfo* data_info =
|
||||
cricket::GetFirstDataContent(desc);
|
||||
if ((!data_info || data_info->rejected) && data_channel_) {
|
||||
SignalDataChannelDestroyed();
|
||||
channel_manager_->DestroyDataChannel(data_channel_.release());
|
||||
if (!data_info || data_info->rejected) {
|
||||
if (data_channel_) {
|
||||
SignalDataChannelDestroyed();
|
||||
channel_manager_->DestroyDataChannel(data_channel_.release());
|
||||
}
|
||||
#ifdef HAVE_QUIC
|
||||
// Clean up the existing QuicDataTransport and its QuicTransportChannels.
|
||||
if (quic_data_transport_) {
|
||||
quic_data_transport_.reset();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1659,6 +1701,15 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content,
|
||||
|
||||
bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content,
|
||||
const std::string* bundle_transport) {
|
||||
#ifdef HAVE_QUIC
|
||||
if (data_channel_type_ == cricket::DCT_QUIC) {
|
||||
RTC_DCHECK(transport_controller_->quic());
|
||||
const std::string transport_name =
|
||||
bundle_transport ? *bundle_transport : content->name;
|
||||
quic_data_transport_->SetTransport(transport_name);
|
||||
return true;
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
bool sctp = (data_channel_type_ == cricket::DCT_SCTP);
|
||||
bool require_rtcp_mux =
|
||||
rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
|
||||
@ -1842,7 +1893,7 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
const IceCandidateInterface* candidate,
|
||||
const SessionDescriptionInterface* remote_desc,
|
||||
bool* valid) {
|
||||
*valid = true;;
|
||||
*valid = true;
|
||||
|
||||
const SessionDescriptionInterface* current_remote_desc =
|
||||
remote_desc ? remote_desc : remote_desc_.get();
|
||||
@ -1865,13 +1916,12 @@ bool WebRtcSession::ReadyToUseRemoteCandidate(
|
||||
|
||||
cricket::ContentInfo content =
|
||||
current_remote_desc->description()->contents()[mediacontent_index];
|
||||
cricket::BaseChannel* channel = GetChannel(content.name);
|
||||
if (!channel) {
|
||||
|
||||
const std::string transport_name = GetTransportName(content.name);
|
||||
if (transport_name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return transport_controller_->ReadyForRemoteCandidates(
|
||||
channel->transport_name());
|
||||
return transport_controller_->ReadyForRemoteCandidates(transport_name);
|
||||
}
|
||||
|
||||
void WebRtcSession::OnTransportControllerGatheringState(
|
||||
@ -2008,4 +2058,19 @@ void WebRtcSession::OnSentPacket_w(const rtc::SentPacket& sent_packet) {
|
||||
media_controller_->call_w()->OnSentPacket(sent_packet);
|
||||
}
|
||||
|
||||
const std::string WebRtcSession::GetTransportName(
|
||||
const std::string& content_name) {
|
||||
cricket::BaseChannel* channel = GetChannel(content_name);
|
||||
if (!channel) {
|
||||
#ifdef HAVE_QUIC
|
||||
if (data_channel_type_ == cricket::DCT_QUIC && quic_data_transport_ &&
|
||||
content_name == quic_data_transport_->transport_name()) {
|
||||
return quic_data_transport_->transport_name();
|
||||
}
|
||||
#endif
|
||||
// Return an empty string if failed to retrieve the transport name.
|
||||
return "";
|
||||
}
|
||||
return channel->transport_name();
|
||||
}
|
||||
} // namespace webrtc
|
||||
|
||||
@ -30,6 +30,10 @@
|
||||
#include "webrtc/p2p/base/transportcontroller.h"
|
||||
#include "webrtc/pc/mediasession.h"
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
#include "webrtc/api/quicdatatransport.h"
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class ChannelManager;
|
||||
@ -38,6 +42,10 @@ class StatsReport;
|
||||
class VideoChannel;
|
||||
class VoiceChannel;
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
class QuicTransportChannel;
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
} // namespace cricket
|
||||
|
||||
namespace webrtc {
|
||||
@ -146,6 +154,7 @@ class WebRtcSession :
|
||||
virtual ~WebRtcSession();
|
||||
|
||||
// These are const to allow them to be called from const methods.
|
||||
rtc::Thread* network_thread() const { return network_thread_; }
|
||||
rtc::Thread* worker_thread() const { return worker_thread_; }
|
||||
rtc::Thread* signaling_thread() const { return signaling_thread_; }
|
||||
|
||||
@ -301,6 +310,11 @@ class WebRtcSession :
|
||||
// std::string represents the data channel label.
|
||||
sigslot::signal2<const std::string&, const InternalDataChannelInit&>
|
||||
SignalDataChannelOpenMessage;
|
||||
#ifdef HAVE_QUIC
|
||||
QuicDataTransport* quic_data_transport() {
|
||||
return quic_data_transport_.get();
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
private:
|
||||
// Indicates the type of SessionDescription in a call to SetLocalDescription
|
||||
@ -445,6 +459,9 @@ class WebRtcSession :
|
||||
|
||||
void OnSentPacket_w(const rtc::SentPacket& sent_packet);
|
||||
|
||||
const std::string GetTransportName(const std::string& content_name);
|
||||
|
||||
rtc::Thread* const network_thread_;
|
||||
rtc::Thread* const worker_thread_;
|
||||
rtc::Thread* const signaling_thread_;
|
||||
|
||||
@ -496,6 +513,10 @@ class WebRtcSession :
|
||||
bool received_first_video_packet_ = false;
|
||||
bool received_first_audio_packet_ = false;
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
std::unique_ptr<QuicDataTransport> quic_data_transport_;
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
RTC_DISALLOW_COPY_AND_ASSIGN(WebRtcSession);
|
||||
};
|
||||
} // namespace webrtc
|
||||
|
||||
@ -558,6 +558,8 @@ class WebRtcSessionTest
|
||||
|
||||
if (session_->data_channel_type() == cricket::DCT_SCTP && data_channel_) {
|
||||
session_options->data_channel_type = cricket::DCT_SCTP;
|
||||
} else if (session_->data_channel_type() == cricket::DCT_QUIC) {
|
||||
session_options->data_channel_type = cricket::DCT_QUIC;
|
||||
}
|
||||
|
||||
if (with_gcm_) {
|
||||
@ -575,9 +577,7 @@ class WebRtcSessionTest
|
||||
(session_options->has_audio() || session_options->has_video() ||
|
||||
session_options->has_data());
|
||||
|
||||
if (session_->data_channel_type() == cricket::DCT_SCTP) {
|
||||
session_options->data_channel_type = cricket::DCT_SCTP;
|
||||
}
|
||||
session_options->data_channel_type = session_->data_channel_type();
|
||||
|
||||
if (with_gcm_) {
|
||||
session_options->crypto_options.enable_gcm_crypto_suites = true;
|
||||
@ -4212,6 +4212,26 @@ TEST_P(WebRtcSessionTest, TestRenegotiateNewMediaWithCandidatesSeparated) {
|
||||
SetLocalDescriptionWithoutError(answer);
|
||||
}
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
TEST_P(WebRtcSessionTest, TestNegotiateQuic) {
|
||||
configuration_.enable_quic = true;
|
||||
InitWithDtls(GetParam());
|
||||
EXPECT_TRUE(session_->data_channel_type() == cricket::DCT_QUIC);
|
||||
SessionDescriptionInterface* offer = CreateOffer();
|
||||
ASSERT_TRUE(offer);
|
||||
ASSERT_TRUE(offer->description());
|
||||
SetLocalDescriptionWithoutError(offer);
|
||||
cricket::MediaSessionOptions options;
|
||||
options.recv_audio = true;
|
||||
options.recv_video = true;
|
||||
SessionDescriptionInterface* answer =
|
||||
CreateRemoteAnswer(offer, options, cricket::SEC_DISABLED);
|
||||
ASSERT_TRUE(answer);
|
||||
ASSERT_TRUE(answer->description());
|
||||
SetRemoteDescriptionWithoutError(answer);
|
||||
}
|
||||
#endif // HAVE_QUIC
|
||||
|
||||
// Tests that RTX codec is removed from the answer when it isn't supported
|
||||
// by local side.
|
||||
TEST_F(WebRtcSessionTest, TestRtxRemovedByCreateAnswer) {
|
||||
|
||||
@ -168,11 +168,7 @@ class CompositeMediaEngine : public MediaEngineInterface {
|
||||
VIDEO video_;
|
||||
};
|
||||
|
||||
enum DataChannelType {
|
||||
DCT_NONE = 0,
|
||||
DCT_RTP = 1,
|
||||
DCT_SCTP = 2
|
||||
};
|
||||
enum DataChannelType { DCT_NONE = 0, DCT_RTP = 1, DCT_SCTP = 2, DCT_QUIC = 3 };
|
||||
|
||||
class DataEngineInterface {
|
||||
public:
|
||||
|
||||
@ -29,6 +29,10 @@
|
||||
#include "webrtc/base/sslfingerprint.h"
|
||||
#include "webrtc/base/thread.h"
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
#include "webrtc/p2p/quic/quictransport.h"
|
||||
#endif
|
||||
|
||||
namespace cricket {
|
||||
|
||||
class FakeTransport;
|
||||
@ -453,6 +457,21 @@ class FakeTransport : public Transport {
|
||||
rtc::SSLProtocolVersion ssl_max_version_ = rtc::SSL_PROTOCOL_DTLS_12;
|
||||
};
|
||||
|
||||
#ifdef HAVE_QUIC
|
||||
class FakeQuicTransport : public QuicTransport {
|
||||
public:
|
||||
FakeQuicTransport(const std::string& transport_name)
|
||||
: QuicTransport(transport_name, nullptr, nullptr) {}
|
||||
|
||||
protected:
|
||||
QuicTransportChannel* CreateTransportChannel(int component) override {
|
||||
FakeTransportChannel* fake_ice_transport_channel =
|
||||
new FakeTransportChannel(name(), component);
|
||||
return new QuicTransportChannel(fake_ice_transport_channel);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// Fake candidate pair class, which can be passed to BaseChannel for testing
|
||||
// purposes.
|
||||
class FakeCandidatePair : public CandidatePairInterface {
|
||||
@ -541,6 +560,11 @@ class FakeTransportController : public TransportController {
|
||||
|
||||
protected:
|
||||
Transport* CreateTransport_n(const std::string& transport_name) override {
|
||||
#ifdef HAVE_QUIC
|
||||
if (quic()) {
|
||||
return new FakeQuicTransport(transport_name);
|
||||
}
|
||||
#endif
|
||||
return new FakeTransport(transport_name);
|
||||
}
|
||||
|
||||
|
||||
@ -211,6 +211,8 @@ class QuicTransportChannel : public TransportChannelImpl,
|
||||
// Creates a new QUIC stream that can send data.
|
||||
ReliableQuicStream* CreateQuicStream();
|
||||
|
||||
TransportChannelImpl* ice_transport_channel() { return channel_.get(); }
|
||||
|
||||
// Emitted when |quic_| creates a QUIC stream to receive data from the remote
|
||||
// peer, when the stream did not exist previously.
|
||||
sigslot::signal1<ReliableQuicStream*> SignalIncomingStream;
|
||||
|
||||
Reference in New Issue
Block a user