Harald Alvestrand | f8f7b70 | 2022-05-05 13:21:19 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2022 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
| 11 | // This file is intended for PeerConnection integration tests that are |
| 12 | // slow to execute (currently defined as more than 5 seconds per test). |
| 13 | |
| 14 | #include <stdint.h> |
| 15 | |
| 16 | #include <memory> |
| 17 | #include <string> |
| 18 | #include <tuple> |
| 19 | #include <utility> |
| 20 | #include <vector> |
| 21 | |
| 22 | #include "absl/algorithm/container.h" |
| 23 | #include "absl/strings/string_view.h" |
| 24 | #include "absl/types/optional.h" |
| 25 | #include "api/dtmf_sender_interface.h" |
| 26 | #include "api/peer_connection_interface.h" |
| 27 | #include "api/rtp_receiver_interface.h" |
| 28 | #include "api/scoped_refptr.h" |
| 29 | #include "api/units/time_delta.h" |
| 30 | #include "p2p/base/port_allocator.h" |
| 31 | #include "p2p/base/port_interface.h" |
| 32 | #include "p2p/base/stun_server.h" |
| 33 | #include "p2p/base/test_stun_server.h" |
| 34 | #include "pc/test/integration_test_helpers.h" |
| 35 | #include "pc/test/mock_peer_connection_observers.h" |
| 36 | #include "rtc_base/fake_clock.h" |
| 37 | #include "rtc_base/fake_network.h" |
| 38 | #include "rtc_base/firewall_socket_server.h" |
| 39 | #include "rtc_base/gunit.h" |
| 40 | #include "rtc_base/logging.h" |
| 41 | #include "rtc_base/socket_address.h" |
| 42 | #include "rtc_base/ssl_certificate.h" |
| 43 | #include "rtc_base/test_certificate_verifier.h" |
| 44 | #include "test/gmock.h" |
| 45 | #include "test/gtest.h" |
| 46 | |
| 47 | namespace webrtc { |
| 48 | |
| 49 | namespace { |
| 50 | |
| 51 | class PeerConnectionIntegrationTest |
| 52 | : public PeerConnectionIntegrationBaseTest, |
| 53 | public ::testing::WithParamInterface< |
| 54 | std::tuple<SdpSemantics, std::string>> { |
| 55 | protected: |
| 56 | PeerConnectionIntegrationTest() |
| 57 | : PeerConnectionIntegrationBaseTest(std::get<0>(GetParam()), |
| 58 | std::get<1>(GetParam())) {} |
| 59 | }; |
| 60 | |
| 61 | // Fake clock must be set before threads are started to prevent race on |
| 62 | // Set/GetClockForTesting(). |
| 63 | // To achieve that, multiple inheritance is used as a mixin pattern |
| 64 | // where order of construction is finely controlled. |
| 65 | // This also ensures peerconnection is closed before switching back to non-fake |
| 66 | // clock, avoiding other races and DCHECK failures such as in rtp_sender.cc. |
| 67 | class FakeClockForTest : public rtc::ScopedFakeClock { |
| 68 | protected: |
| 69 | FakeClockForTest() { |
| 70 | // Some things use a time of "0" as a special value, so we need to start out |
| 71 | // the fake clock at a nonzero time. |
| 72 | // TODO(deadbeef): Fix this. |
| 73 | AdvanceTime(webrtc::TimeDelta::Seconds(1)); |
| 74 | } |
| 75 | |
| 76 | // Explicit handle. |
| 77 | ScopedFakeClock& FakeClock() { return *this; } |
| 78 | }; |
| 79 | |
| 80 | // Ensure FakeClockForTest is constructed first (see class for rationale). |
| 81 | class PeerConnectionIntegrationTestWithFakeClock |
| 82 | : public FakeClockForTest, |
| 83 | public PeerConnectionIntegrationTest {}; |
| 84 | |
| 85 | class PeerConnectionIntegrationTestPlanB |
| 86 | : public PeerConnectionIntegrationBaseTest { |
| 87 | protected: |
| 88 | PeerConnectionIntegrationTestPlanB() |
| 89 | : PeerConnectionIntegrationBaseTest(SdpSemantics::kPlanB_DEPRECATED) {} |
| 90 | }; |
| 91 | |
| 92 | class PeerConnectionIntegrationTestUnifiedPlan |
| 93 | : public PeerConnectionIntegrationBaseTest { |
| 94 | protected: |
| 95 | PeerConnectionIntegrationTestUnifiedPlan() |
| 96 | : PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {} |
| 97 | }; |
| 98 | |
| 99 | // Test the OnFirstPacketReceived callback from audio/video RtpReceivers. This |
| 100 | // includes testing that the callback is invoked if an observer is connected |
| 101 | // after the first packet has already been received. |
| 102 | TEST_P(PeerConnectionIntegrationTest, |
| 103 | RtpReceiverObserverOnFirstPacketReceived) { |
| 104 | ASSERT_TRUE(CreatePeerConnectionWrappers()); |
| 105 | ConnectFakeSignaling(); |
| 106 | caller()->AddAudioVideoTracks(); |
| 107 | callee()->AddAudioVideoTracks(); |
| 108 | // Start offer/answer exchange and wait for it to complete. |
| 109 | caller()->CreateAndSetAndSignalOffer(); |
| 110 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 111 | // Should be one receiver each for audio/video. |
| 112 | EXPECT_EQ(2U, caller()->rtp_receiver_observers().size()); |
| 113 | EXPECT_EQ(2U, callee()->rtp_receiver_observers().size()); |
| 114 | // Wait for all "first packet received" callbacks to be fired. |
| 115 | EXPECT_TRUE_WAIT( |
| 116 | absl::c_all_of(caller()->rtp_receiver_observers(), |
| 117 | [](const std::unique_ptr<MockRtpReceiverObserver>& o) { |
| 118 | return o->first_packet_received(); |
| 119 | }), |
| 120 | kMaxWaitForFramesMs); |
| 121 | EXPECT_TRUE_WAIT( |
| 122 | absl::c_all_of(callee()->rtp_receiver_observers(), |
| 123 | [](const std::unique_ptr<MockRtpReceiverObserver>& o) { |
| 124 | return o->first_packet_received(); |
| 125 | }), |
| 126 | kMaxWaitForFramesMs); |
| 127 | // If new observers are set after the first packet was already received, the |
| 128 | // callback should still be invoked. |
| 129 | caller()->ResetRtpReceiverObservers(); |
| 130 | callee()->ResetRtpReceiverObservers(); |
| 131 | EXPECT_EQ(2U, caller()->rtp_receiver_observers().size()); |
| 132 | EXPECT_EQ(2U, callee()->rtp_receiver_observers().size()); |
| 133 | EXPECT_TRUE( |
| 134 | absl::c_all_of(caller()->rtp_receiver_observers(), |
| 135 | [](const std::unique_ptr<MockRtpReceiverObserver>& o) { |
| 136 | return o->first_packet_received(); |
| 137 | })); |
| 138 | EXPECT_TRUE( |
| 139 | absl::c_all_of(callee()->rtp_receiver_observers(), |
| 140 | [](const std::unique_ptr<MockRtpReceiverObserver>& o) { |
| 141 | return o->first_packet_received(); |
| 142 | })); |
| 143 | } |
| 144 | |
| 145 | class DummyDtmfObserver : public DtmfSenderObserverInterface { |
| 146 | public: |
| 147 | DummyDtmfObserver() : completed_(false) {} |
| 148 | |
| 149 | // Implements DtmfSenderObserverInterface. |
| 150 | void OnToneChange(const std::string& tone) override { |
| 151 | tones_.push_back(tone); |
| 152 | if (tone.empty()) { |
| 153 | completed_ = true; |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | const std::vector<std::string>& tones() const { return tones_; } |
| 158 | bool completed() const { return completed_; } |
| 159 | |
| 160 | private: |
| 161 | bool completed_; |
| 162 | std::vector<std::string> tones_; |
| 163 | }; |
| 164 | |
| 165 | TEST_P(PeerConnectionIntegrationTest, |
| 166 | SSLCertificateVerifierFailureUsedForTurnConnectionsFailsConnection) { |
| 167 | static const rtc::SocketAddress turn_server_internal_address{"88.88.88.0", |
| 168 | 3478}; |
| 169 | static const rtc::SocketAddress turn_server_external_address{"88.88.88.1", 0}; |
| 170 | |
| 171 | // Enable TCP-TLS for the fake turn server. We need to pass in 88.88.88.0 so |
| 172 | // that host name verification passes on the fake certificate. |
| 173 | CreateTurnServer(turn_server_internal_address, turn_server_external_address, |
| 174 | cricket::PROTO_TLS, "88.88.88.0"); |
| 175 | |
| 176 | webrtc::PeerConnectionInterface::IceServer ice_server; |
| 177 | ice_server.urls.push_back("turns:88.88.88.0:3478?transport=tcp"); |
| 178 | ice_server.username = "test"; |
| 179 | ice_server.password = "test"; |
| 180 | |
| 181 | PeerConnectionInterface::RTCConfiguration client_1_config; |
| 182 | client_1_config.servers.push_back(ice_server); |
| 183 | client_1_config.type = webrtc::PeerConnectionInterface::kRelay; |
| 184 | |
| 185 | PeerConnectionInterface::RTCConfiguration client_2_config; |
| 186 | client_2_config.servers.push_back(ice_server); |
| 187 | // Setting the type to kRelay forces the connection to go through a TURN |
| 188 | // server. |
| 189 | client_2_config.type = webrtc::PeerConnectionInterface::kRelay; |
| 190 | |
| 191 | // Get a copy to the pointer so we can verify calls later. |
| 192 | rtc::TestCertificateVerifier* client_1_cert_verifier = |
| 193 | new rtc::TestCertificateVerifier(); |
| 194 | client_1_cert_verifier->verify_certificate_ = false; |
| 195 | rtc::TestCertificateVerifier* client_2_cert_verifier = |
| 196 | new rtc::TestCertificateVerifier(); |
| 197 | client_2_cert_verifier->verify_certificate_ = false; |
| 198 | |
| 199 | // Create the dependencies with the test certificate verifier. |
| 200 | webrtc::PeerConnectionDependencies client_1_deps(nullptr); |
| 201 | client_1_deps.tls_cert_verifier = |
| 202 | std::unique_ptr<rtc::TestCertificateVerifier>(client_1_cert_verifier); |
| 203 | webrtc::PeerConnectionDependencies client_2_deps(nullptr); |
| 204 | client_2_deps.tls_cert_verifier = |
| 205 | std::unique_ptr<rtc::TestCertificateVerifier>(client_2_cert_verifier); |
| 206 | |
| 207 | ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndDeps( |
| 208 | client_1_config, std::move(client_1_deps), client_2_config, |
| 209 | std::move(client_2_deps))); |
| 210 | ConnectFakeSignaling(); |
| 211 | |
| 212 | // Set "offer to receive audio/video" without adding any tracks, so we just |
| 213 | // set up ICE/DTLS with no media. |
| 214 | PeerConnectionInterface::RTCOfferAnswerOptions options; |
| 215 | options.offer_to_receive_audio = 1; |
| 216 | options.offer_to_receive_video = 1; |
| 217 | caller()->SetOfferAnswerOptions(options); |
| 218 | caller()->CreateAndSetAndSignalOffer(); |
| 219 | bool wait_res = true; |
| 220 | // TODO(bugs.webrtc.org/9219): When IceConnectionState is implemented |
| 221 | // properly, should be able to just wait for a state of "failed" instead of |
| 222 | // waiting a fixed 10 seconds. |
| 223 | WAIT_(DtlsConnected(), kDefaultTimeout, wait_res); |
| 224 | ASSERT_FALSE(wait_res); |
| 225 | |
| 226 | EXPECT_GT(client_1_cert_verifier->call_count_, 0u); |
| 227 | EXPECT_GT(client_2_cert_verifier->call_count_, 0u); |
| 228 | } |
| 229 | |
| 230 | // Test that we can get capture start ntp time. |
| 231 | TEST_P(PeerConnectionIntegrationTest, GetCaptureStartNtpTimeWithOldStatsApi) { |
| 232 | ASSERT_TRUE(CreatePeerConnectionWrappers()); |
| 233 | ConnectFakeSignaling(); |
| 234 | caller()->AddAudioTrack(); |
| 235 | |
| 236 | callee()->AddAudioTrack(); |
| 237 | |
| 238 | // Do offer/answer, wait for the callee to receive some frames. |
| 239 | caller()->CreateAndSetAndSignalOffer(); |
| 240 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 241 | |
| 242 | // Get the remote audio track created on the receiver, so they can be used as |
| 243 | // GetStats filters. |
| 244 | auto receivers = callee()->pc()->GetReceivers(); |
| 245 | ASSERT_EQ(1u, receivers.size()); |
| 246 | auto remote_audio_track = receivers[0]->track(); |
| 247 | |
| 248 | // Get the audio output level stats. Note that the level is not available |
| 249 | // until an RTCP packet has been received. |
| 250 | EXPECT_TRUE_WAIT(callee()->OldGetStatsForTrack(remote_audio_track.get()) |
| 251 | ->CaptureStartNtpTime() > 0, |
| 252 | 2 * kMaxWaitForFramesMs); |
| 253 | } |
| 254 | |
| 255 | // Test that firewalling the ICE connection causes the clients to identify the |
| 256 | // disconnected state and then removing the firewall causes them to reconnect. |
| 257 | class PeerConnectionIntegrationIceStatesTest |
| 258 | : public PeerConnectionIntegrationBaseTest, |
| 259 | public ::testing::WithParamInterface< |
| 260 | std::tuple<SdpSemantics, std::tuple<std::string, uint32_t>>> { |
| 261 | protected: |
| 262 | PeerConnectionIntegrationIceStatesTest() |
| 263 | : PeerConnectionIntegrationBaseTest(std::get<0>(GetParam())) { |
| 264 | port_allocator_flags_ = std::get<1>(std::get<1>(GetParam())); |
| 265 | } |
| 266 | |
| 267 | void StartStunServer(const SocketAddress& server_address) { |
| 268 | stun_server_.reset( |
| 269 | cricket::TestStunServer::Create(firewall(), server_address)); |
| 270 | } |
| 271 | |
| 272 | bool TestIPv6() { |
| 273 | return (port_allocator_flags_ & cricket::PORTALLOCATOR_ENABLE_IPV6); |
| 274 | } |
| 275 | |
| 276 | void SetPortAllocatorFlags() { |
| 277 | PeerConnectionIntegrationBaseTest::SetPortAllocatorFlags( |
| 278 | port_allocator_flags_, port_allocator_flags_); |
| 279 | } |
| 280 | |
| 281 | std::vector<SocketAddress> CallerAddresses() { |
| 282 | std::vector<SocketAddress> addresses; |
| 283 | addresses.push_back(SocketAddress("1.1.1.1", 0)); |
| 284 | if (TestIPv6()) { |
| 285 | addresses.push_back(SocketAddress("1111:0:a:b:c:d:e:f", 0)); |
| 286 | } |
| 287 | return addresses; |
| 288 | } |
| 289 | |
| 290 | std::vector<SocketAddress> CalleeAddresses() { |
| 291 | std::vector<SocketAddress> addresses; |
| 292 | addresses.push_back(SocketAddress("2.2.2.2", 0)); |
| 293 | if (TestIPv6()) { |
| 294 | addresses.push_back(SocketAddress("2222:0:a:b:c:d:e:f", 0)); |
| 295 | } |
| 296 | return addresses; |
| 297 | } |
| 298 | |
| 299 | void SetUpNetworkInterfaces() { |
| 300 | // Remove the default interfaces added by the test infrastructure. |
| 301 | caller()->network_manager()->RemoveInterface(kDefaultLocalAddress); |
| 302 | callee()->network_manager()->RemoveInterface(kDefaultLocalAddress); |
| 303 | |
| 304 | // Add network addresses for test. |
| 305 | for (const auto& caller_address : CallerAddresses()) { |
| 306 | caller()->network_manager()->AddInterface(caller_address); |
| 307 | } |
| 308 | for (const auto& callee_address : CalleeAddresses()) { |
| 309 | callee()->network_manager()->AddInterface(callee_address); |
| 310 | } |
| 311 | } |
| 312 | |
| 313 | private: |
| 314 | uint32_t port_allocator_flags_; |
| 315 | std::unique_ptr<cricket::TestStunServer> stun_server_; |
| 316 | }; |
| 317 | |
| 318 | // Ensure FakeClockForTest is constructed first (see class for rationale). |
| 319 | class PeerConnectionIntegrationIceStatesTestWithFakeClock |
| 320 | : public FakeClockForTest, |
| 321 | public PeerConnectionIntegrationIceStatesTest {}; |
| 322 | |
| 323 | #if !defined(THREAD_SANITIZER) |
| 324 | // This test provokes TSAN errors. bugs.webrtc.org/11282 |
| 325 | |
| 326 | // Tests that the PeerConnection goes through all the ICE gathering/connection |
| 327 | // states over the duration of the call. This includes Disconnected and Failed |
| 328 | // states, induced by putting a firewall between the peers and waiting for them |
| 329 | // to time out. |
| 330 | TEST_P(PeerConnectionIntegrationIceStatesTestWithFakeClock, VerifyIceStates) { |
| 331 | const SocketAddress kStunServerAddress = |
| 332 | SocketAddress("99.99.99.1", cricket::STUN_SERVER_PORT); |
| 333 | StartStunServer(kStunServerAddress); |
| 334 | |
| 335 | PeerConnectionInterface::RTCConfiguration config; |
| 336 | PeerConnectionInterface::IceServer ice_stun_server; |
| 337 | ice_stun_server.urls.push_back( |
| 338 | "stun:" + kStunServerAddress.HostAsURIString() + ":" + |
| 339 | kStunServerAddress.PortAsString()); |
| 340 | config.servers.push_back(ice_stun_server); |
| 341 | |
| 342 | ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(config, config)); |
| 343 | ConnectFakeSignaling(); |
| 344 | SetPortAllocatorFlags(); |
| 345 | SetUpNetworkInterfaces(); |
| 346 | caller()->AddAudioVideoTracks(); |
| 347 | callee()->AddAudioVideoTracks(); |
| 348 | |
| 349 | // Initial state before anything happens. |
| 350 | ASSERT_EQ(PeerConnectionInterface::kIceGatheringNew, |
| 351 | caller()->ice_gathering_state()); |
| 352 | ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew, |
| 353 | caller()->ice_connection_state()); |
| 354 | ASSERT_EQ(PeerConnectionInterface::kIceConnectionNew, |
| 355 | caller()->standardized_ice_connection_state()); |
| 356 | |
| 357 | // Start the call by creating the offer, setting it as the local description, |
| 358 | // then sending it to the peer who will respond with an answer. This happens |
| 359 | // asynchronously so that we can watch the states as it runs in the |
| 360 | // background. |
| 361 | caller()->CreateAndSetAndSignalOffer(); |
| 362 | |
| 363 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted, |
| 364 | caller()->ice_connection_state(), kDefaultTimeout, |
| 365 | FakeClock()); |
| 366 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted, |
| 367 | caller()->standardized_ice_connection_state(), |
| 368 | kDefaultTimeout, FakeClock()); |
| 369 | |
| 370 | // Verify that the observer was notified of the intermediate transitions. |
| 371 | EXPECT_THAT(caller()->ice_connection_state_history(), |
| 372 | ElementsAre(PeerConnectionInterface::kIceConnectionChecking, |
| 373 | PeerConnectionInterface::kIceConnectionConnected, |
| 374 | PeerConnectionInterface::kIceConnectionCompleted)); |
| 375 | EXPECT_THAT(caller()->standardized_ice_connection_state_history(), |
| 376 | ElementsAre(PeerConnectionInterface::kIceConnectionChecking, |
| 377 | PeerConnectionInterface::kIceConnectionConnected, |
| 378 | PeerConnectionInterface::kIceConnectionCompleted)); |
| 379 | EXPECT_THAT( |
| 380 | caller()->peer_connection_state_history(), |
| 381 | ElementsAre(PeerConnectionInterface::PeerConnectionState::kConnecting, |
| 382 | PeerConnectionInterface::PeerConnectionState::kConnected)); |
| 383 | EXPECT_THAT(caller()->ice_gathering_state_history(), |
| 384 | ElementsAre(PeerConnectionInterface::kIceGatheringGathering, |
| 385 | PeerConnectionInterface::kIceGatheringComplete)); |
| 386 | |
| 387 | // Block connections to/from the caller and wait for ICE to become |
| 388 | // disconnected. |
| 389 | for (const auto& caller_address : CallerAddresses()) { |
| 390 | firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address); |
| 391 | } |
| 392 | RTC_LOG(LS_INFO) << "Firewall rules applied"; |
| 393 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, |
| 394 | caller()->ice_connection_state(), kDefaultTimeout, |
| 395 | FakeClock()); |
| 396 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, |
| 397 | caller()->standardized_ice_connection_state(), |
| 398 | kDefaultTimeout, FakeClock()); |
| 399 | |
| 400 | // Let ICE re-establish by removing the firewall rules. |
| 401 | firewall()->ClearRules(); |
| 402 | RTC_LOG(LS_INFO) << "Firewall rules cleared"; |
| 403 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted, |
| 404 | caller()->ice_connection_state(), kDefaultTimeout, |
| 405 | FakeClock()); |
| 406 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionCompleted, |
| 407 | caller()->standardized_ice_connection_state(), |
| 408 | kDefaultTimeout, FakeClock()); |
| 409 | |
| 410 | // According to RFC7675, if there is no response within 30 seconds then the |
| 411 | // peer should consider the other side to have rejected the connection. This |
| 412 | // is signaled by the state transitioning to "failed". |
| 413 | constexpr int kConsentTimeout = 30000; |
| 414 | for (const auto& caller_address : CallerAddresses()) { |
| 415 | firewall()->AddRule(false, rtc::FP_ANY, rtc::FD_ANY, caller_address); |
| 416 | } |
| 417 | RTC_LOG(LS_INFO) << "Firewall rules applied again"; |
| 418 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed, |
| 419 | caller()->ice_connection_state(), kConsentTimeout, |
| 420 | FakeClock()); |
| 421 | ASSERT_EQ_SIMULATED_WAIT(PeerConnectionInterface::kIceConnectionFailed, |
| 422 | caller()->standardized_ice_connection_state(), |
| 423 | kConsentTimeout, FakeClock()); |
| 424 | } |
| 425 | #endif |
| 426 | |
| 427 | // This test sets up a call that's transferred to a new caller with a different |
| 428 | // DTLS fingerprint. |
| 429 | TEST_P(PeerConnectionIntegrationTest, CallTransferredForCallee) { |
| 430 | ASSERT_TRUE(CreatePeerConnectionWrappers()); |
| 431 | ConnectFakeSignaling(); |
| 432 | caller()->AddAudioVideoTracks(); |
| 433 | callee()->AddAudioVideoTracks(); |
| 434 | caller()->CreateAndSetAndSignalOffer(); |
| 435 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 436 | |
| 437 | // Keep the original peer around which will still send packets to the |
| 438 | // receiving client. These SRTP packets will be dropped. |
| 439 | std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer( |
| 440 | SetCallerPcWrapperAndReturnCurrent( |
| 441 | CreatePeerConnectionWrapperWithAlternateKey().release())); |
| 442 | // TODO(deadbeef): Why do we call Close here? That goes against the comment |
| 443 | // directly above. |
| 444 | original_peer->pc()->Close(); |
| 445 | |
| 446 | ConnectFakeSignaling(); |
| 447 | caller()->AddAudioVideoTracks(); |
| 448 | caller()->CreateAndSetAndSignalOffer(); |
| 449 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 450 | // Wait for some additional frames to be transmitted end-to-end. |
| 451 | MediaExpectations media_expectations; |
| 452 | media_expectations.ExpectBidirectionalAudioAndVideo(); |
| 453 | ASSERT_TRUE(ExpectNewFrames(media_expectations)); |
| 454 | } |
| 455 | |
| 456 | // This test sets up a call that's transferred to a new callee with a different |
| 457 | // DTLS fingerprint. |
| 458 | TEST_P(PeerConnectionIntegrationTest, CallTransferredForCaller) { |
| 459 | ASSERT_TRUE(CreatePeerConnectionWrappers()); |
| 460 | ConnectFakeSignaling(); |
| 461 | caller()->AddAudioVideoTracks(); |
| 462 | callee()->AddAudioVideoTracks(); |
| 463 | caller()->CreateAndSetAndSignalOffer(); |
| 464 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 465 | |
| 466 | // Keep the original peer around which will still send packets to the |
| 467 | // receiving client. These SRTP packets will be dropped. |
| 468 | std::unique_ptr<PeerConnectionIntegrationWrapper> original_peer( |
| 469 | SetCalleePcWrapperAndReturnCurrent( |
| 470 | CreatePeerConnectionWrapperWithAlternateKey().release())); |
| 471 | // TODO(deadbeef): Why do we call Close here? That goes against the comment |
| 472 | // directly above. |
| 473 | original_peer->pc()->Close(); |
| 474 | |
| 475 | ConnectFakeSignaling(); |
| 476 | callee()->AddAudioVideoTracks(); |
| 477 | caller()->SetOfferAnswerOptions(IceRestartOfferAnswerOptions()); |
| 478 | caller()->CreateAndSetAndSignalOffer(); |
| 479 | ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); |
| 480 | // Wait for some additional frames to be transmitted end-to-end. |
| 481 | MediaExpectations media_expectations; |
| 482 | media_expectations.ExpectBidirectionalAudioAndVideo(); |
| 483 | ASSERT_TRUE(ExpectNewFrames(media_expectations)); |
| 484 | } |
| 485 | |
| 486 | INSTANTIATE_TEST_SUITE_P( |
| 487 | PeerConnectionIntegrationTest, |
| 488 | PeerConnectionIntegrationTest, |
| 489 | Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan), |
| 490 | Values("WebRTC-FrameBuffer3/arm:FrameBuffer2/", |
| 491 | "WebRTC-FrameBuffer3/arm:FrameBuffer3/", |
| 492 | "WebRTC-FrameBuffer3/arm:SyncDecoding/"))); |
| 493 | |
| 494 | constexpr uint32_t kFlagsIPv4NoStun = cricket::PORTALLOCATOR_DISABLE_TCP | |
| 495 | cricket::PORTALLOCATOR_DISABLE_STUN | |
| 496 | cricket::PORTALLOCATOR_DISABLE_RELAY; |
| 497 | constexpr uint32_t kFlagsIPv6NoStun = |
| 498 | cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_STUN | |
| 499 | cricket::PORTALLOCATOR_ENABLE_IPV6 | cricket::PORTALLOCATOR_DISABLE_RELAY; |
| 500 | constexpr uint32_t kFlagsIPv4Stun = |
| 501 | cricket::PORTALLOCATOR_DISABLE_TCP | cricket::PORTALLOCATOR_DISABLE_RELAY; |
| 502 | |
| 503 | INSTANTIATE_TEST_SUITE_P( |
| 504 | PeerConnectionIntegrationTest, |
| 505 | PeerConnectionIntegrationIceStatesTestWithFakeClock, |
| 506 | Combine(Values(SdpSemantics::kPlanB_DEPRECATED, SdpSemantics::kUnifiedPlan), |
| 507 | Values(std::make_pair("IPv4 no STUN", kFlagsIPv4NoStun), |
| 508 | std::make_pair("IPv6 no STUN", kFlagsIPv6NoStun), |
| 509 | std::make_pair("IPv4 with STUN", kFlagsIPv4Stun)))); |
| 510 | |
| 511 | } // namespace |
| 512 | } // namespace webrtc |