Index: webrtc/api/peerconnection_unittest.cc |
diff --git a/webrtc/api/peerconnection_unittest.cc b/webrtc/api/peerconnection_unittest.cc |
index fb3c1887ba78d0ae95a86dca193b57db0221a68e..981cec778a690108de0b21850e4c3328a035cabe 100644 |
--- a/webrtc/api/peerconnection_unittest.cc |
+++ b/webrtc/api/peerconnection_unittest.cc |
@@ -30,6 +30,7 @@ |
#include "webrtc/api/test/fakertccertificategenerator.h" |
#include "webrtc/api/test/fakevideotrackrenderer.h" |
#include "webrtc/api/test/mockpeerconnectionobservers.h" |
+#include "webrtc/base/fakenetwork.h" |
#include "webrtc/base/gunit.h" |
#include "webrtc/base/helpers.h" |
#include "webrtc/base/physicalsocketserver.h" |
@@ -38,9 +39,10 @@ |
#include "webrtc/base/thread.h" |
#include "webrtc/base/virtualsocketserver.h" |
#include "webrtc/media/engine/fakewebrtcvideoengine.h" |
-#include "webrtc/p2p/base/fakeportallocator.h" |
#include "webrtc/p2p/base/p2pconstants.h" |
#include "webrtc/p2p/base/sessiondescription.h" |
+#include "webrtc/p2p/base/testturnserver.h" |
+#include "webrtc/p2p/client/basicportallocator.h" |
#include "webrtc/pc/mediasession.h" |
#define MAYBE_SKIP_TEST(feature) \ |
@@ -104,6 +106,20 @@ static const int kDefaultSrtpCryptoSuite = rtc::SRTP_AES128_CM_SHA1_32; |
static const int kDefaultSrtpCryptoSuiteGcm = rtc::SRTP_AEAD_AES_256_GCM; |
#endif |
+// Used to simulate signaling ICE/SDP between two PeerConnections. |
+enum Message { MSG_SDP_MESSAGE, MSG_ICE_MESSAGE }; |
+ |
+struct SdpMessage { |
+ std::string type; |
+ std::string msg; |
+}; |
+ |
+struct IceMessage { |
+ std::string sdp_mid; |
+ int sdp_mline_index; |
+ std::string msg; |
+}; |
+ |
static void RemoveLinesFromSdp(const std::string& line_start, |
std::string* sdp) { |
const char kSdpLineEnd[] = "\r\n"; |
@@ -169,13 +185,15 @@ class MockRtpReceiverObserver : public webrtc::RtpReceiverObserverInterface { |
class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
public SignalingMessageReceiver, |
- public ObserverInterface { |
+ public ObserverInterface, |
+ public rtc::MessageHandler { |
public: |
+ // If |config| is not provided, uses a default constructed RTCConfiguration. |
static PeerConnectionTestClient* CreateClientWithDtlsIdentityStore( |
const std::string& id, |
const MediaConstraintsInterface* constraints, |
const PeerConnectionFactory::Options* options, |
- const PeerConnectionInterface::RTCConfiguration& config, |
+ const PeerConnectionInterface::RTCConfiguration* config, |
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, |
bool prefer_constraint_apis, |
rtc::Thread* network_thread, |
@@ -193,7 +211,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
const std::string& id, |
const MediaConstraintsInterface* constraints, |
const PeerConnectionFactory::Options* options, |
- const PeerConnectionInterface::RTCConfiguration& config, |
+ const PeerConnectionInterface::RTCConfiguration* config, |
rtc::Thread* network_thread, |
rtc::Thread* worker_thread) { |
std::unique_ptr<FakeRTCCertificateGenerator> cert_generator( |
@@ -208,14 +226,13 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
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, config, |
+ return CreateClientWithDtlsIdentityStore(id, nullptr, options, nullptr, |
std::move(cert_generator), false, |
network_thread, worker_thread); |
} |
@@ -239,8 +256,64 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
std::string sdp; |
EXPECT_TRUE(offer->ToString(&sdp)); |
EXPECT_TRUE(DoSetLocalDescription(offer.release())); |
- signaling_message_receiver_->ReceiveSdpMessage( |
- webrtc::SessionDescriptionInterface::kOffer, sdp); |
+ SendSdpMessage(webrtc::SessionDescriptionInterface::kOffer, sdp); |
+ } |
+ |
+ void SendSdpMessage(const std::string& type, std::string& msg) { |
+ if (signaling_delay_ms_ == 0) { |
+ if (signaling_message_receiver_) { |
+ signaling_message_receiver_->ReceiveSdpMessage(type, msg); |
+ } |
+ } else { |
+ rtc::Thread::Current()->PostDelayed( |
+ RTC_FROM_HERE, signaling_delay_ms_, this, MSG_SDP_MESSAGE, |
+ new rtc::TypedMessageData<SdpMessage>({type, msg})); |
+ } |
+ } |
+ |
+ void SendIceMessage(const std::string& sdp_mid, |
+ int sdp_mline_index, |
+ const std::string& msg) { |
+ if (signaling_delay_ms_ == 0) { |
+ if (signaling_message_receiver_) { |
+ signaling_message_receiver_->ReceiveIceMessage(sdp_mid, sdp_mline_index, |
+ msg); |
+ } |
+ } else { |
+ rtc::Thread::Current()->PostDelayed(RTC_FROM_HERE, signaling_delay_ms_, |
+ this, MSG_ICE_MESSAGE, |
+ new rtc::TypedMessageData<IceMessage>( |
+ {sdp_mid, sdp_mline_index, msg})); |
+ } |
+ } |
+ |
+ // MessageHandler callback. |
+ void OnMessage(rtc::Message* msg) override { |
+ switch (msg->message_id) { |
+ case MSG_SDP_MESSAGE: { |
+ auto sdp_message = |
+ static_cast<rtc::TypedMessageData<SdpMessage>*>(msg->pdata); |
+ if (signaling_message_receiver_) { |
+ signaling_message_receiver_->ReceiveSdpMessage( |
+ sdp_message->data().type, sdp_message->data().msg); |
+ } |
+ delete sdp_message; |
+ break; |
+ } |
+ case MSG_ICE_MESSAGE: { |
+ auto ice_message = |
+ static_cast<rtc::TypedMessageData<IceMessage>*>(msg->pdata); |
+ if (signaling_message_receiver_) { |
+ signaling_message_receiver_->ReceiveIceMessage( |
+ ice_message->data().sdp_mid, ice_message->data().sdp_mline_index, |
+ ice_message->data().msg); |
+ } |
+ delete ice_message; |
+ break; |
+ } |
+ default: |
+ RTC_CHECK(false); |
+ } |
} |
// SignalingMessageReceiver callback. |
@@ -299,8 +372,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
// Remote party may be deleted. |
return; |
} |
- signaling_message_receiver_->ReceiveIceMessage( |
- candidate->sdp_mid(), candidate->sdp_mline_index(), ice_sdp); |
+ SendIceMessage(candidate->sdp_mid(), candidate->sdp_mline_index(), ice_sdp); |
} |
// MediaStreamInterface callback |
@@ -375,6 +447,8 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
signaling_message_receiver_ = signaling_message_receiver; |
} |
+ void set_signaling_delay_ms(int delay_ms) { signaling_delay_ms_ = delay_ms; } |
+ |
void EnableVideoDecoderFactory() { |
video_decoder_factory_enabled_ = true; |
fake_video_decoder_factory_->AddSupportedVideoCodecType( |
@@ -402,6 +476,9 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
bool ExpectIceRenomination() { return expect_ice_renomination_; } |
bool ExpectRemoteIceRenomination() { return expect_remote_ice_renomination_; } |
+ // The below 3 methods assume streams will be offered. |
+ // Thus they'll only set the "offer to receive" flag to true if it's |
+ // currently false, not if it's just unset. |
void SetReceiveAudioVideo(bool audio, bool video) { |
SetReceiveAudio(audio); |
SetReceiveVideo(video); |
@@ -410,15 +487,24 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
} |
void SetReceiveAudio(bool audio) { |
- if (audio && can_receive_audio()) |
+ if (audio && can_receive_audio()) { |
return; |
+ } |
offer_answer_constraints_.SetMandatoryReceiveAudio(audio); |
offer_answer_options_.offer_to_receive_audio = audio ? 1 : 0; |
} |
void SetReceiveVideo(bool video) { |
- if (video && can_receive_video()) |
+ if (video && can_receive_video()) { |
return; |
+ } |
+ offer_answer_constraints_.SetMandatoryReceiveVideo(video); |
+ offer_answer_options_.offer_to_receive_video = video ? 1 : 0; |
+ } |
+ |
+ void SetOfferToReceiveAudioVideo(bool audio, bool video) { |
+ offer_answer_constraints_.SetMandatoryReceiveAudio(audio); |
+ offer_answer_options_.offer_to_receive_audio = audio ? 1 : 0; |
offer_answer_constraints_.SetMandatoryReceiveVideo(video); |
offer_answer_options_.offer_to_receive_video = video ? 1 : 0; |
} |
@@ -896,7 +982,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
bool Init( |
const MediaConstraintsInterface* constraints, |
const PeerConnectionFactory::Options* options, |
- const PeerConnectionInterface::RTCConfiguration& config, |
+ const PeerConnectionInterface::RTCConfiguration* config, |
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, |
bool prefer_constraint_apis, |
rtc::Thread* network_thread, |
@@ -908,8 +994,11 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
} |
prefer_constraint_apis_ = prefer_constraint_apis; |
+ fake_network_manager_.reset(new rtc::FakeNetworkManager()); |
+ fake_network_manager_->AddInterface(rtc::SocketAddress("192.168.1.1", 0)); |
+ |
std::unique_ptr<cricket::PortAllocator> port_allocator( |
- new cricket::FakePortAllocator(network_thread, nullptr)); |
+ new cricket::BasicPortAllocator(fake_network_manager_.get())); |
fake_audio_capture_module_ = FakeAudioCaptureModule::Create(); |
if (fake_audio_capture_module_ == nullptr) { |
@@ -931,17 +1020,23 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
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, |
+ const PeerConnectionInterface::RTCConfiguration* config, |
std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator) { |
+ // CreatePeerConnection with RTCConfiguration. |
+ PeerConnectionInterface::RTCConfiguration default_config; |
+ |
+ if (!config) { |
+ config = &default_config; |
+ } |
+ |
return peer_connection_factory_->CreatePeerConnection( |
- config, constraints, std::move(port_allocator), |
+ *config, constraints, std::move(port_allocator), |
std::move(cert_generator), this); |
} |
@@ -961,10 +1056,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
std::string sdp; |
EXPECT_TRUE(answer->ToString(&sdp)); |
EXPECT_TRUE(DoSetLocalDescription(answer.release())); |
- if (signaling_message_receiver_) { |
- signaling_message_receiver_->ReceiveSdpMessage( |
- webrtc::SessionDescriptionInterface::kAnswer, sdp); |
- } |
+ SendSdpMessage(webrtc::SessionDescriptionInterface::kAnswer, sdp); |
} |
void HandleIncomingAnswer(const std::string& msg) { |
@@ -1065,6 +1157,8 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
std::string id_; |
+ std::unique_ptr<rtc::FakeNetworkManager> fake_network_manager_; |
+ |
rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_; |
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> |
peer_connection_factory_; |
@@ -1095,6 +1189,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
// For remote peer communication. |
SignalingMessageReceiver* signaling_message_receiver_ = nullptr; |
+ int signaling_delay_ms_ = 0; |
// Store references to the video capturers we've created, so that we can stop |
// them, if required. |
@@ -1129,9 +1224,6 @@ 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() { |
@@ -1234,19 +1326,24 @@ class P2PTestConductor : public testing::Test { |
bool CreateTestClients(MediaConstraintsInterface* init_constraints, |
MediaConstraintsInterface* recv_constraints) { |
- return CreateTestClients(init_constraints, nullptr, recv_constraints, |
- nullptr); |
+ return CreateTestClients(init_constraints, nullptr, nullptr, |
+ recv_constraints, nullptr, nullptr); |
+ } |
+ |
+ bool CreateTestClients( |
+ const PeerConnectionInterface::RTCConfiguration& init_config, |
+ const PeerConnectionInterface::RTCConfiguration& recv_config) { |
+ return CreateTestClients(nullptr, nullptr, &init_config, nullptr, nullptr, |
+ &recv_config); |
} |
bool CreateTestClientsThatPreferNoConstraints() { |
initiating_client_.reset( |
PeerConnectionTestClient::CreateClientPreferNoConstraints( |
- "Caller: ", nullptr, config_, network_thread_.get(), |
- worker_thread_.get())); |
+ "Caller: ", nullptr, network_thread_.get(), worker_thread_.get())); |
receiving_client_.reset( |
PeerConnectionTestClient::CreateClientPreferNoConstraints( |
- "Callee: ", nullptr, config_, network_thread_.get(), |
- worker_thread_.get())); |
+ "Callee: ", nullptr, network_thread_.get(), worker_thread_.get())); |
if (!initiating_client_ || !receiving_client_) { |
return false; |
} |
@@ -1256,20 +1353,18 @@ class P2PTestConductor : public testing::Test { |
return true; |
} |
- void SetSignalingReceivers() { |
- initiating_client_->set_signaling_message_receiver(receiving_client_.get()); |
- receiving_client_->set_signaling_message_receiver(initiating_client_.get()); |
- } |
- |
- bool CreateTestClients(MediaConstraintsInterface* init_constraints, |
- PeerConnectionFactory::Options* init_options, |
- MediaConstraintsInterface* recv_constraints, |
- PeerConnectionFactory::Options* recv_options) { |
+ bool CreateTestClients( |
+ MediaConstraintsInterface* init_constraints, |
+ PeerConnectionFactory::Options* init_options, |
+ const PeerConnectionInterface::RTCConfiguration* init_config, |
+ MediaConstraintsInterface* recv_constraints, |
+ PeerConnectionFactory::Options* recv_options, |
+ const PeerConnectionInterface::RTCConfiguration* recv_config) { |
initiating_client_.reset(PeerConnectionTestClient::CreateClient( |
- "Caller: ", init_constraints, init_options, config_, |
+ "Caller: ", init_constraints, init_options, init_config, |
network_thread_.get(), worker_thread_.get())); |
receiving_client_.reset(PeerConnectionTestClient::CreateClient( |
- "Callee: ", recv_constraints, recv_options, config_, |
+ "Callee: ", recv_constraints, recv_options, recv_config, |
network_thread_.get(), worker_thread_.get())); |
if (!initiating_client_ || !receiving_client_) { |
return false; |
@@ -1278,6 +1373,16 @@ class P2PTestConductor : public testing::Test { |
return true; |
} |
+ void SetSignalingReceivers() { |
+ initiating_client_->set_signaling_message_receiver(receiving_client_.get()); |
+ receiving_client_->set_signaling_message_receiver(initiating_client_.get()); |
+ } |
+ |
+ void SetSignalingDelayMs(int delay_ms) { |
+ initiating_client_->set_signaling_delay_ms(delay_ms); |
+ receiving_client_->set_signaling_delay_ms(delay_ms); |
+ } |
+ |
void SetVideoConstraints(const webrtc::FakeConstraints& init_constraints, |
const webrtc::FakeConstraints& recv_constraints) { |
initiating_client_->SetVideoConstraints(init_constraints); |
@@ -1370,7 +1475,7 @@ class P2PTestConductor : public testing::Test { |
// Make sure the new client is using a different certificate. |
return PeerConnectionTestClient::CreateClientWithDtlsIdentityStore( |
- "New Peer: ", &setup_constraints, nullptr, config_, |
+ "New Peer: ", &setup_constraints, nullptr, nullptr, |
std::move(cert_generator), prefer_constraint_apis_, |
network_thread_.get(), worker_thread_.get()); |
} |
@@ -1385,6 +1490,8 @@ class P2PTestConductor : public testing::Test { |
} |
} |
+ rtc::Thread* network_thread() { return network_thread_.get(); } |
+ |
rtc::VirtualSocketServer* virtual_socket_server() { return ss_.get(); } |
PeerConnectionTestClient* initializing_client() { |
@@ -1412,9 +1519,6 @@ 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) { |
@@ -1432,8 +1536,8 @@ class P2PTestConductor : public testing::Test { |
init_options.crypto_options.enable_gcm_crypto_suites = local_gcm_enabled; |
PeerConnectionFactory::Options recv_options; |
recv_options.crypto_options.enable_gcm_crypto_suites = remote_gcm_enabled; |
- ASSERT_TRUE( |
- CreateTestClients(nullptr, &init_options, nullptr, &recv_options)); |
+ ASSERT_TRUE(CreateTestClients(nullptr, &init_options, nullptr, nullptr, |
+ &recv_options, nullptr)); |
rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
init_observer = |
new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
@@ -1460,7 +1564,6 @@ 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 |
@@ -1803,8 +1906,8 @@ TEST_F(P2PTestConductor, GetDtls12None) { |
init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; |
PeerConnectionFactory::Options recv_options; |
recv_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; |
- ASSERT_TRUE( |
- CreateTestClients(nullptr, &init_options, nullptr, &recv_options)); |
+ ASSERT_TRUE(CreateTestClients(nullptr, &init_options, nullptr, nullptr, |
+ &recv_options, nullptr)); |
rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
initializing_client()->pc()->RegisterUMAObserver(init_observer); |
@@ -1828,8 +1931,8 @@ TEST_F(P2PTestConductor, GetDtls12Both) { |
init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; |
PeerConnectionFactory::Options recv_options; |
recv_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; |
- ASSERT_TRUE( |
- CreateTestClients(nullptr, &init_options, nullptr, &recv_options)); |
+ ASSERT_TRUE(CreateTestClients(nullptr, &init_options, nullptr, nullptr, |
+ &recv_options, nullptr)); |
rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
initializing_client()->pc()->RegisterUMAObserver(init_observer); |
@@ -1854,8 +1957,8 @@ TEST_F(P2PTestConductor, GetDtls12Init) { |
init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; |
PeerConnectionFactory::Options recv_options; |
recv_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; |
- ASSERT_TRUE( |
- CreateTestClients(nullptr, &init_options, nullptr, &recv_options)); |
+ ASSERT_TRUE(CreateTestClients(nullptr, &init_options, nullptr, nullptr, |
+ &recv_options, nullptr)); |
rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
initializing_client()->pc()->RegisterUMAObserver(init_observer); |
@@ -1880,8 +1983,8 @@ TEST_F(P2PTestConductor, GetDtls12Recv) { |
init_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_10; |
PeerConnectionFactory::Options recv_options; |
recv_options.ssl_max_version = rtc::SSL_PROTOCOL_DTLS_12; |
- ASSERT_TRUE( |
- CreateTestClients(nullptr, &init_options, nullptr, &recv_options)); |
+ ASSERT_TRUE(CreateTestClients(nullptr, &init_options, nullptr, nullptr, |
+ &recv_options, nullptr)); |
rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
initializing_client()->pc()->RegisterUMAObserver(init_observer); |
@@ -2176,8 +2279,9 @@ TEST_F(P2PTestConductor, IceRestart) { |
} |
TEST_F(P2PTestConductor, IceRenominationDisabled) { |
- config()->enable_ice_renomination = false; |
- ASSERT_TRUE(CreateTestClients()); |
+ PeerConnectionInterface::RTCConfiguration config; |
+ config.enable_ice_renomination = false; |
+ ASSERT_TRUE(CreateTestClients(config, config)); |
LocalP2PTest(); |
initializing_client()->VerifyLocalIceRenomination(); |
@@ -2187,8 +2291,9 @@ TEST_F(P2PTestConductor, IceRenominationDisabled) { |
} |
TEST_F(P2PTestConductor, IceRenominationEnabled) { |
- config()->enable_ice_renomination = true; |
- ASSERT_TRUE(CreateTestClients()); |
+ PeerConnectionInterface::RTCConfiguration config; |
+ config.enable_ice_renomination = true; |
+ ASSERT_TRUE(CreateTestClients(config, config)); |
initializing_client()->SetExpectIceRenomination(true); |
initializing_client()->SetExpectRemoteIceRenomination(true); |
receiving_client()->SetExpectIceRenomination(true); |
@@ -2268,8 +2373,9 @@ TEST_F(P2PTestConductor, EarlyWarmupTest) { |
// 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()); |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(quic_config, quic_config)); |
webrtc::DataChannelInit init; |
init.ordered = false; |
init.reliable = true; |
@@ -2296,7 +2402,9 @@ TEST_F(P2PTestConductor, LocalP2PTestQuicDataChannel) { |
// Tests that negotiation of QUIC data channels is completed without error. |
TEST_F(P2PTestConductor, NegotiateQuicDataChannel) { |
- config()->enable_quic = true; |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(quic_config, quic_config)); |
FakeConstraints constraints; |
constraints.SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true); |
ASSERT_TRUE(CreateTestClients(&constraints, &constraints)); |
@@ -2310,16 +2418,18 @@ TEST_F(P2PTestConductor, NegotiateQuicDataChannel) { |
// 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()); |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(quic_config, quic_config)); |
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()); |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(quic_config, quic_config)); |
receiving_client()->SetReceiveAudioVideo(true, false); |
LocalP2PTest(); |
} |
@@ -2327,8 +2437,9 @@ TEST_F(P2PTestConductor, LocalP2PTestAudioOnlyWithQuic) { |
// 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()); |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(quic_config, quic_config)); |
receiving_client()->SetReceiveAudioVideo(false, false); |
LocalP2PTest(); |
} |
@@ -2368,6 +2479,102 @@ TEST_F(P2PTestConductor, ForwardVideoOnlyStream) { |
kMaxWaitForFramesMs); |
} |
+// Test that we achieve the expected end-to-end connection time, using a |
+// fake clock and simulated latency on the media and signaling paths. |
+// We use a TURN<->TURN connection because this is usually the quickest to |
+// set up initially, especially when we're confident the connection will work |
+// and can start sending media before we get a STUN response. |
+// |
+// With various optimizations enabled, here are the network delays we expect to |
+// be on the critical path: |
+// 1. 2 signaling trips: Signaling offer and offerer's TURN candidate, then |
+// signaling answer (with DTLS fingerprint). |
+// 2. 9 media hops: Rest of the DTLS handshake. 3 hops in each direction when |
+// using TURN<->TURN pair, and DTLS exchange is 4 packets, |
+// the first of which should have arrived before the answer. |
+TEST_F(P2PTestConductor, EndToEndConnectionTimeWithTurnTurnPair) { |
+ rtc::ScopedFakeClock fake_clock; |
+ // Some things use a time of "0" as a special value, so we need to start out |
+ // the fake clock at a nonzero time. |
+ // TODO(deadbeef): Fix this. |
+ fake_clock.AdvanceTime(rtc::TimeDelta::FromSeconds(1)); |
+ |
+ static constexpr int media_hop_delay_ms = 50; |
+ static constexpr int signaling_trip_delay_ms = 500; |
+ // For explanation of these values, see comment above. |
+ static constexpr int required_media_hops = 9; |
+ static constexpr int required_signaling_trips = 2; |
+ // For internal delays (such as posting an event asychronously). |
+ static constexpr int allowed_internal_delay_ms = 20; |
+ static constexpr int total_connection_time_ms = |
+ media_hop_delay_ms * required_media_hops + |
+ signaling_trip_delay_ms * required_signaling_trips + |
+ allowed_internal_delay_ms; |
+ |
+ static const rtc::SocketAddress turn_server_1_internal_address{"88.88.88.0", |
+ 3478}; |
+ static const rtc::SocketAddress turn_server_1_external_address{"88.88.88.1", |
+ 0}; |
+ static const rtc::SocketAddress turn_server_2_internal_address{"99.99.99.0", |
+ 3478}; |
+ static const rtc::SocketAddress turn_server_2_external_address{"99.99.99.1", |
+ 0}; |
+ cricket::TestTurnServer turn_server_1(network_thread(), |
+ turn_server_1_internal_address, |
+ turn_server_1_external_address); |
+ cricket::TestTurnServer turn_server_2(network_thread(), |
+ turn_server_2_internal_address, |
+ turn_server_2_external_address); |
+ // Bypass permission check on received packets so media can be sent before |
+ // the candidate is signaled. |
+ turn_server_1.set_enable_permission_checks(false); |
+ turn_server_2.set_enable_permission_checks(false); |
+ |
+ PeerConnectionInterface::RTCConfiguration client_1_config; |
+ webrtc::PeerConnectionInterface::IceServer ice_server_1; |
+ ice_server_1.urls.push_back("turn:88.88.88.0:3478"); |
+ ice_server_1.username = "test"; |
+ ice_server_1.password = "test"; |
+ client_1_config.servers.push_back(ice_server_1); |
+ client_1_config.type = webrtc::PeerConnectionInterface::kRelay; |
+ client_1_config.presume_writable_when_fully_relayed = true; |
+ |
+ PeerConnectionInterface::RTCConfiguration client_2_config; |
+ webrtc::PeerConnectionInterface::IceServer ice_server_2; |
+ ice_server_2.urls.push_back("turn:99.99.99.0:3478"); |
+ ice_server_2.username = "test"; |
+ ice_server_2.password = "test"; |
+ client_2_config.servers.push_back(ice_server_2); |
+ client_2_config.type = webrtc::PeerConnectionInterface::kRelay; |
+ client_2_config.presume_writable_when_fully_relayed = true; |
+ |
+ ASSERT_TRUE(CreateTestClients(client_1_config, client_2_config)); |
+ // Set up the simulated delays. |
+ SetSignalingDelayMs(signaling_trip_delay_ms); |
+ virtual_socket_server()->set_delay_mean(media_hop_delay_ms); |
+ virtual_socket_server()->UpdateDelayDistribution(); |
+ |
+ initializing_client()->SetOfferToReceiveAudioVideo(true, true); |
+ initializing_client()->Negotiate(); |
+ // TODO(deadbeef): kIceConnectionConnected currently means both ICE and DTLS |
+ // are connected. This is an important distinction. Once we have separate ICE |
+ // and DTLS state, this check needs to use the DTLS state. |
+ EXPECT_TRUE_SIMULATED_WAIT( |
+ (receiving_client()->ice_connection_state() == |
+ webrtc::PeerConnectionInterface::kIceConnectionConnected || |
+ receiving_client()->ice_connection_state() == |
+ webrtc::PeerConnectionInterface::kIceConnectionCompleted) && |
+ (initializing_client()->ice_connection_state() == |
+ webrtc::PeerConnectionInterface::kIceConnectionConnected || |
+ initializing_client()->ice_connection_state() == |
+ webrtc::PeerConnectionInterface::kIceConnectionCompleted), |
+ total_connection_time_ms, fake_clock); |
+ // Need to free the clients here since they're using things we created on |
+ // the stack. |
+ delete set_initializing_client(nullptr); |
+ delete set_receiving_client(nullptr); |
+} |
+ |
class IceServerParsingTest : public testing::Test { |
public: |
// Convenience for parsing a single URL. |