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