Index: webrtc/api/peerconnection_unittest.cc |
diff --git a/webrtc/api/peerconnection_unittest.cc b/webrtc/api/peerconnection_unittest.cc |
index 406fab0d89eb6cc13d397a1ac668a87fca043b6e..a341bb940e7bcac0d4f47e65c6dd660a69405347 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/physicalsocketserver.h" |
#include "webrtc/base/ssladapter.h" |
@@ -37,9 +38,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) \ |
@@ -103,6 +105,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"; |
@@ -168,13 +184,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, |
@@ -192,7 +210,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( |
@@ -207,14 +225,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); |
} |
@@ -238,8 +255,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); |
skvlad
2016/09/06 18:02:09
Is it important to send the message synchronously
Taylor Brandstetter
2016/09/07 00:15:40
Some tests want to ensure that some state changes
|
+ } |
+ } 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. |
@@ -298,8 +371,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 |
@@ -374,6 +446,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( |
@@ -392,6 +466,9 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
bool ExpectIceRestart() const { return expect_ice_restart_; } |
+ // 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); |
@@ -400,15 +477,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; |
} |
@@ -850,7 +936,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, |
@@ -862,8 +948,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) { |
@@ -885,17 +974,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); |
} |
@@ -915,10 +1010,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) { |
@@ -1019,6 +1111,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_; |
@@ -1047,6 +1141,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. |
@@ -1081,9 +1176,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() { |
@@ -1186,19 +1278,17 @@ 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 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; |
} |
@@ -1213,15 +1303,23 @@ class P2PTestConductor : public testing::Test { |
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) { |
+ void SetSignalingDelayMs(int delay_ms) { |
+ initiating_client_->set_signaling_delay_ms(delay_ms); |
+ receiving_client_->set_signaling_delay_ms(delay_ms); |
+ } |
+ |
+ 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; |
@@ -1322,7 +1420,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()); |
} |
@@ -1337,6 +1435,10 @@ class P2PTestConductor : public testing::Test { |
} |
} |
+ rtc::Thread* network_thread() { return network_thread_.get(); } |
+ |
+ rtc::VirtualSocketServer* virtual_socket_server() { return ss_.get(); } |
+ |
PeerConnectionTestClient* initializing_client() { |
return initiating_client_.get(); |
} |
@@ -1362,9 +1464,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) { |
@@ -1382,8 +1481,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>(); |
@@ -1410,7 +1509,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 |
@@ -1753,8 +1851,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); |
@@ -1778,8 +1876,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); |
@@ -1804,8 +1902,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); |
@@ -1830,8 +1928,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); |
@@ -2132,7 +2230,10 @@ 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; |
+ PeerConnectionInterface::RTCConfiguration quic_config; |
+ quic_config.enable_quic = true; |
+ ASSERT_TRUE(CreateTestClients(nullptr, nullptr, &quic_config, nullptr, |
+ nullptr, &quic_config)); |
ASSERT_TRUE(CreateTestClients()); |
webrtc::DataChannelInit init; |
init.ordered = false; |
@@ -2160,7 +2261,10 @@ 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(nullptr, &quic_config, nullptr, nullptr, |
+ &quic_config, nullptr)); |
FakeConstraints constraints; |
constraints.SetMandatory(MediaConstraintsInterface::kEnableDtlsSrtp, true); |
ASSERT_TRUE(CreateTestClients(&constraints, &constraints)); |
@@ -2232,6 +2336,103 @@ 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; |
skvlad
2016/09/06 18:02:09
Is this actually needed with a fake clock? Looks l
Taylor Brandstetter
2016/09/07 00:15:40
The thing is, handling a message can post another
|
+ 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(nullptr, nullptr, &client_1_config, nullptr, |
+ nullptr, &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. |