Chromium Code Reviews| Index: webrtc/api/peerconnection_unittest.cc |
| diff --git a/webrtc/api/peerconnection_unittest.cc b/webrtc/api/peerconnection_unittest.cc |
| index 4b06b90d01c6c1c9dd5ed7e9aaf181c9f1fddfb2..b9eb7e4db3f95d3892c30642292524833c8539fb 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) \ |
| @@ -102,6 +104,9 @@ static const char kDataChannelLabel[] = "data_channel"; |
| static const int kDefaultSrtpCryptoSuite = rtc::SRTP_AES128_CM_SHA1_32; |
| #endif |
| +// Used to simulate signaling ICE/SDP between two PeerConnections. |
| +enum { MSG_SDP_MESSAGE, MSG_ICE_MESSAGE }; |
| + |
| static void RemoveLinesFromSdp(const std::string& line_start, |
| std::string* sdp) { |
| const char kSdpLineEnd[] = "\r\n"; |
| @@ -167,18 +172,21 @@ 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 webrtc::PeerConnectionInterface::RTCConfiguration* config, |
| const PeerConnectionFactory::Options* options, |
| 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, config, options, std::move(cert_generator), |
| prefer_constraint_apis, network_thread, worker_thread)) { |
| delete client; |
| return nullptr; |
| @@ -189,6 +197,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
| static PeerConnectionTestClient* CreateClient( |
| const std::string& id, |
| const MediaConstraintsInterface* constraints, |
| + const webrtc::PeerConnectionInterface::RTCConfiguration* config, |
| const PeerConnectionFactory::Options* options, |
| rtc::Thread* network_thread, |
| rtc::Thread* worker_thread) { |
| @@ -196,9 +205,9 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
| rtc::SSLStreamAdapter::HaveDtlsSrtp() ? |
| new FakeRTCCertificateGenerator() : nullptr); |
| - return CreateClientWithDtlsIdentityStore( |
| - id, constraints, options, std::move(cert_generator), true, |
| - network_thread, worker_thread); |
| + return CreateClientWithDtlsIdentityStore(id, constraints, config, options, |
| + std::move(cert_generator), true, |
| + network_thread, worker_thread); |
| } |
| static PeerConnectionTestClient* CreateClientPreferNoConstraints( |
| @@ -210,9 +219,9 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
| rtc::SSLStreamAdapter::HaveDtlsSrtp() ? |
| new FakeRTCCertificateGenerator() : nullptr); |
| - return CreateClientWithDtlsIdentityStore( |
| - id, nullptr, options, std::move(cert_generator), false, |
| - network_thread, worker_thread); |
| + return CreateClientWithDtlsIdentityStore(id, nullptr, nullptr, options, |
| + std::move(cert_generator), false, |
| + network_thread, worker_thread); |
| } |
| ~PeerConnectionTestClient() { |
| @@ -234,8 +243,68 @@ 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); |
| + } |
| + |
| + typedef std::pair<std::string, std::string> SdpMessage; |
| + 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>(SdpMessage(type, msg))); |
| + } |
| + } |
| + |
| + typedef std::tuple<std::string, int, std::string> IceMessage; |
| + 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>( |
| + 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( |
| + std::get<0>(sdp_message->data()), |
| + std::get<1>(sdp_message->data())); |
| + } |
| + 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( |
| + std::get<0>(ice_message->data()), |
| + std::get<1>(ice_message->data()), |
| + std::get<2>(ice_message->data())); |
| + } |
| + delete ice_message; |
| + break; |
| + } |
| + default: |
| + RTC_CHECK(false); |
| + } |
| } |
| // SignalingMessageReceiver callback. |
| @@ -294,8 +363,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 |
| @@ -370,6 +438,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( |
| @@ -388,6 +458,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); |
| @@ -396,15 +469,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; |
| } |
| @@ -843,6 +925,7 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
| bool Init( |
| const MediaConstraintsInterface* constraints, |
| + const webrtc::PeerConnectionInterface::RTCConfiguration* config, |
| const PeerConnectionFactory::Options* options, |
| std::unique_ptr<rtc::RTCCertificateGeneratorInterface> cert_generator, |
| bool prefer_constraint_apis, |
| @@ -855,8 +938,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())); |
|
Taylor Brandstetter
2016/07/12 19:33:34
Switched to using a BasicPortAllocator so we can t
|
| fake_audio_capture_module_ = FakeAudioCaptureModule::Create(); |
| if (fake_audio_capture_module_ == nullptr) { |
| @@ -875,23 +961,26 @@ class PeerConnectionTestClient : public webrtc::PeerConnectionObserver, |
| if (options) { |
| peer_connection_factory_->SetOptions(*options); |
| } |
| - peer_connection_ = CreatePeerConnection( |
| - std::move(port_allocator), constraints, std::move(cert_generator)); |
| + peer_connection_ = |
| + CreatePeerConnection(std::move(port_allocator), constraints, config, |
| + std::move(cert_generator)); |
| return peer_connection_.get() != nullptr; |
| } |
| rtc::scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection( |
| std::unique_ptr<cricket::PortAllocator> port_allocator, |
| const MediaConstraintsInterface* constraints, |
| + const webrtc::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"; |
|
Taylor Brandstetter
2016/07/12 19:33:34
This STUN server wasn't doing anything since the F
|
| - config.servers.push_back(ice_server); |
| + webrtc::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); |
| } |
| @@ -911,10 +1000,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) { |
| @@ -1015,6 +1101,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_; |
| @@ -1043,6 +1131,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. |
| @@ -1179,8 +1268,8 @@ 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() { |
| @@ -1204,16 +1293,24 @@ 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, |
| + const webrtc::PeerConnectionInterface::RTCConfiguration* init_config, |
| + PeerConnectionFactory::Options* init_options, |
| + MediaConstraintsInterface* recv_constraints, |
| + const webrtc::PeerConnectionInterface::RTCConfiguration* recv_config, |
| + PeerConnectionFactory::Options* recv_options) { |
| initiating_client_.reset(PeerConnectionTestClient::CreateClient( |
| - "Caller: ", init_constraints, init_options, network_thread_.get(), |
| - worker_thread_.get())); |
| + "Caller: ", init_constraints, init_config, init_options, |
| + 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_config, recv_options, |
| + network_thread_.get(), worker_thread_.get())); |
| if (!initiating_client_ || !receiving_client_) { |
| return false; |
| } |
| @@ -1313,7 +1410,7 @@ class P2PTestConductor : public testing::Test { |
| // Make sure the new client is using a different certificate. |
| return PeerConnectionTestClient::CreateClientWithDtlsIdentityStore( |
| - "New Peer: ", &setup_constraints, nullptr, |
| + "New Peer: ", &setup_constraints, nullptr, nullptr, |
| std::move(cert_generator), prefer_constraint_apis_, |
| network_thread_.get(), worker_thread_.get()); |
| } |
| @@ -1328,6 +1425,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(); |
| } |
| @@ -1718,8 +1819,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, nullptr, &init_options, nullptr, |
| + nullptr, &recv_options)); |
| rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
| init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
| initializing_client()->pc()->RegisterUMAObserver(init_observer); |
| @@ -1743,8 +1844,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, nullptr, &init_options, nullptr, |
| + nullptr, &recv_options)); |
| rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
| init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
| initializing_client()->pc()->RegisterUMAObserver(init_observer); |
| @@ -1769,8 +1870,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, nullptr, &init_options, nullptr, |
| + nullptr, &recv_options)); |
| rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
| init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
| initializing_client()->pc()->RegisterUMAObserver(init_observer); |
| @@ -1795,8 +1896,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, nullptr, &init_options, nullptr, |
| + nullptr, &recv_options)); |
| rtc::scoped_refptr<webrtc::FakeMetricsObserver> |
| init_observer = new rtc::RefCountedObject<webrtc::FakeMetricsObserver>(); |
| initializing_client()->pc()->RegisterUMAObserver(init_observer); |
| @@ -2106,6 +2207,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 trips we expect to be |
| +// required: |
| +// 1. 2 signaling trip: Signaling offer and offerer's TURN candidate, then |
| +// signaling answer (with DTLS fingerprint). |
| +// 2. 9 media trips: 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_trip_delay_ms = 50; |
| + static constexpr int signaling_trip_delay_ms = 500; |
| + // For explanation of these values, see comment above. |
| + static constexpr int required_media_trips = 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_trip_delay_ms * required_media_trips + |
| + 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); |
| + |
| + webrtc::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; |
| + |
| + webrtc::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, &client_1_config, nullptr, nullptr, |
| + &client_2_config, nullptr)); |
| + // Set up the simulated delays. |
| + SetSignalingDelayMs(signaling_trip_delay_ms); |
| + virtual_socket_server()->set_delay_mean(media_trip_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. |