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.
Committed: https://crrev.com/34b54c36a533dadb6ceb70795119194e6f530ef5
Review-Url: https://codereview.webrtc.org/2166873002
Cr-Original-Commit-Position: refs/heads/master@{#13645}
Cr-Commit-Position: refs/heads/master@{#13657}
diff --git a/webrtc/api/peerconnection.cc b/webrtc/api/peerconnection.cc
index 4ccd6e8..c675015 100644
--- a/webrtc/api/peerconnection.cc
+++ b/webrtc/api/peerconnection.cc
@@ -907,6 +907,23 @@
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,13 @@
(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;
+ // Intentionally unset the data channel type for RTP data channel with the
+ // second condition. Otherwise the RTP data channels would be successfully
+ // negotiated by default and the 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.
+ if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) {
+ session_options->data_channel_type = session_->data_channel_type();
}
session_options->rtcp_cname = rtcp_cname_;
@@ -1648,8 +1670,12 @@
// 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;
+ // Intentionally unset the data channel type for RTP data channel. Otherwise
+ // the RTP data channels would be successfully negotiated by default and the
+ // 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.
+ if (session_->data_channel_type() != cricket::DCT_RTP) {
+ session_options->data_channel_type = session_->data_channel_type();
}
session_options->crypto_options = factory_->options().crypto_options;
}
@@ -2054,7 +2080,13 @@
}
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) {
diff --git a/webrtc/api/peerconnection_unittest.cc b/webrtc/api/peerconnection_unittest.cc
index 18d3606..406fab0 100644
--- a/webrtc/api/peerconnection_unittest.cc
+++ b/webrtc/api/peerconnection_unittest.cc
@@ -174,12 +174,13 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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
diff --git a/webrtc/api/peerconnectionendtoend_unittest.cc b/webrtc/api/peerconnectionendtoend_unittest.cc
index e01daa9..2298cf4 100644
--- a/webrtc/api/peerconnectionendtoend_unittest.cc
+++ b/webrtc/api/peerconnectionendtoend_unittest.cc
@@ -56,6 +56,10 @@
"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 @@
}
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 @@
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 @@
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
diff --git a/webrtc/api/peerconnectioninterface.h b/webrtc/api/peerconnectioninterface.h
index e0eb1a4..fdf9cef 100644
--- a/webrtc/api/peerconnectioninterface.h
+++ b/webrtc/api/peerconnectioninterface.h
@@ -296,6 +296,7 @@
// 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;
diff --git a/webrtc/api/peerconnectioninterface_unittest.cc b/webrtc/api/peerconnectioninterface_unittest.cc
index 419f69c..0b24fcb 100644
--- a/webrtc/api/peerconnectioninterface_unittest.cc
+++ b/webrtc/api/peerconnectioninterface_unittest.cc
@@ -242,7 +242,6 @@
using ::testing::Exactly;
using cricket::StreamParams;
-using rtc::scoped_refptr;
using webrtc::AudioSourceInterface;
using webrtc::AudioTrack;
using webrtc::AudioTrackInterface;
@@ -535,18 +534,18 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
// 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 @@
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, 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, 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 @@
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 @@
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_;
};
diff --git a/webrtc/api/quicdatatransport.cc b/webrtc/api/quicdatatransport.cc
index c1caf54..ff3ac09 100644
--- a/webrtc/api/quicdatatransport.cc
+++ b/webrtc/api/quicdatatransport.cc
@@ -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 @@
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 @@
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
diff --git a/webrtc/api/quicdatatransport.h b/webrtc/api/quicdatatransport.h
index 96fe2a0..b8d3f84 100644
--- a/webrtc/api/quicdatatransport.h
+++ b/webrtc/api/quicdatatransport.h
@@ -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 @@
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 @@
// 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 @@
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 @@
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
diff --git a/webrtc/api/quicdatatransport_unittest.cc b/webrtc/api/quicdatatransport_unittest.cc
index 975898e..a9c605f 100644
--- a/webrtc/api/quicdatatransport_unittest.cc
+++ b/webrtc/api/quicdatatransport_unittest.cc
@@ -30,6 +30,7 @@
using webrtc::QuicDataChannel;
using webrtc::QuicDataTransport;
using cricket::FakeTransportChannel;
+using cricket::FakeTransportController;
using cricket::QuicTransportChannel;
using cricket::ReliableQuicStream;
@@ -37,6 +38,7 @@
// 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 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 @@
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 @@
}
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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 @@
}
}
-// 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
diff --git a/webrtc/api/test/peerconnectiontestwrapper.cc b/webrtc/api/test/peerconnectiontestwrapper.cc
index 450a908..b1eb586 100644
--- a/webrtc/api/test/peerconnectiontestwrapper.cc
+++ b/webrtc/api/test/peerconnectiontestwrapper.cc
@@ -58,7 +58,8 @@
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 @@
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);
diff --git a/webrtc/api/test/peerconnectiontestwrapper.h b/webrtc/api/test/peerconnectiontestwrapper.h
index 0fa0f7c..c56035d 100644
--- a/webrtc/api/test/peerconnectiontestwrapper.h
+++ b/webrtc/api/test/peerconnectiontestwrapper.h
@@ -32,7 +32,9 @@
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,
diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc
index 7497e2c..35a5fab 100644
--- a/webrtc/api/webrtcsession.cc
+++ b/webrtc/api/webrtcsession.cc
@@ -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 @@
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 @@
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 @@
// 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 @@
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 @@
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::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 @@
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 @@
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 @@
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
diff --git a/webrtc/api/webrtcsession.h b/webrtc/api/webrtcsession.h
index 1314c59..3174568 100644
--- a/webrtc/api/webrtcsession.h
+++ b/webrtc/api/webrtcsession.h
@@ -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 VideoChannel;
class VoiceChannel;
+#ifdef HAVE_QUIC
+class QuicTransportChannel;
+#endif // HAVE_QUIC
+
} // namespace cricket
namespace webrtc {
@@ -146,6 +154,7 @@
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 @@
// 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 @@
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_;
@@ -476,6 +493,8 @@
// 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).
+ // The data channel type could be DCT_QUIC if the QUIC data channel is
+ // enabled.
cricket::DataChannelType data_channel_type_;
// List of content names for which the remote side triggered an ICE restart.
std::set<std::string> pending_ice_restarts_;
@@ -496,6 +515,10 @@
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
diff --git a/webrtc/api/webrtcsession_unittest.cc b/webrtc/api/webrtcsession_unittest.cc
index 1aff50f..c0d8a3b 100644
--- a/webrtc/api/webrtcsession_unittest.cc
+++ b/webrtc/api/webrtcsession_unittest.cc
@@ -558,6 +558,8 @@
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,8 +577,8 @@
(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;
+ if (session_->data_channel_type() != cricket::DCT_RTP) {
+ session_options->data_channel_type = session_->data_channel_type();
}
if (with_gcm_) {
@@ -4212,6 +4214,26 @@
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) {