/* * Copyright 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include #include #include #include #include #include "absl/types/optional.h" #include "api/data_channel_interface.h" #include "api/dtmf_sender_interface.h" #include "api/peer_connection_interface.h" #include "api/scoped_refptr.h" #include "api/units/time_delta.h" #include "pc/test/integration_test_helpers.h" #include "pc/test/mock_peer_connection_observers.h" #include "rtc_base/fake_clock.h" #include "rtc_base/gunit.h" #include "rtc_base/ref_counted_object.h" #include "rtc_base/virtual_socket_server.h" namespace webrtc { namespace { class DataChannelIntegrationTest : public PeerConnectionIntegrationBaseTest, public ::testing::WithParamInterface { protected: DataChannelIntegrationTest() : PeerConnectionIntegrationBaseTest(GetParam()) {} }; GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(DataChannelIntegrationTest); // Fake clock must be set before threads are started to prevent race on // Set/GetClockForTesting(). // To achieve that, multiple inheritance is used as a mixin pattern // where order of construction is finely controlled. // This also ensures peerconnection is closed before switching back to non-fake // clock, avoiding other races and DCHECK failures such as in rtp_sender.cc. class FakeClockForTest : public rtc::ScopedFakeClock { protected: FakeClockForTest() { // 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. AdvanceTime(webrtc::TimeDelta::Seconds(1)); } // Explicit handle. ScopedFakeClock& FakeClock() { return *this; } }; // Ensure FakeClockForTest is constructed first (see class for rationale). class DataChannelIntegrationTestWithFakeClock : public FakeClockForTest, public DataChannelIntegrationTest {}; class DataChannelIntegrationTestPlanB : public PeerConnectionIntegrationBaseTest { protected: DataChannelIntegrationTestPlanB() : PeerConnectionIntegrationBaseTest(SdpSemantics::kPlanB) {} }; GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST( DataChannelIntegrationTestWithFakeClock); class DataChannelIntegrationTestUnifiedPlan : public PeerConnectionIntegrationBaseTest { protected: DataChannelIntegrationTestUnifiedPlan() : PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {} }; class DummyDtmfObserver : public DtmfSenderObserverInterface { public: DummyDtmfObserver() : completed_(false) {} // Implements DtmfSenderObserverInterface. void OnToneChange(const std::string& tone) override { tones_.push_back(tone); if (tone.empty()) { completed_ = true; } } const std::vector& tones() const { return tones_; } bool completed() const { return completed_; } private: bool completed_; std::vector tones_; }; #ifdef WEBRTC_HAVE_SCTP // This test causes a PeerConnection to enter Disconnected state, and // sends data on a DataChannel while disconnected. // The data should be surfaced when the connection reestablishes. TEST_P(DataChannelIntegrationTest, DataChannelWhileDisconnected) { CreatePeerConnectionWrappers(); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout); std::string data1 = "hello first"; caller()->data_channel()->Send(DataBuffer(data1)); EXPECT_EQ_WAIT(data1, callee()->data_observer()->last_message(), kDefaultTimeout); // Cause a network outage virtual_socket_server()->set_drop_probability(1.0); EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, caller()->standardized_ice_connection_state(), kDefaultTimeout); std::string data2 = "hello second"; caller()->data_channel()->Send(DataBuffer(data2)); // Remove the network outage. The connection should reestablish. virtual_socket_server()->set_drop_probability(0.0); EXPECT_EQ_WAIT(data2, callee()->data_observer()->last_message(), kDefaultTimeout); } // This test causes a PeerConnection to enter Disconnected state, // sends data on a DataChannel while disconnected, and then triggers // an ICE restart. // The data should be surfaced when the connection reestablishes. TEST_P(DataChannelIntegrationTest, DataChannelWhileDisconnectedIceRestart) { CreatePeerConnectionWrappers(); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout); std::string data1 = "hello first"; caller()->data_channel()->Send(DataBuffer(data1)); EXPECT_EQ_WAIT(data1, callee()->data_observer()->last_message(), kDefaultTimeout); // Cause a network outage virtual_socket_server()->set_drop_probability(1.0); ASSERT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected, caller()->standardized_ice_connection_state(), kDefaultTimeout); std::string data2 = "hello second"; caller()->data_channel()->Send(DataBuffer(data2)); // Trigger an ICE restart. The signaling channel is not affected by // the network outage. caller()->SetOfferAnswerOptions(IceRestartOfferAnswerOptions()); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Remove the network outage. The connection should reestablish. virtual_socket_server()->set_drop_probability(0.0); EXPECT_EQ_WAIT(data2, callee()->data_observer()->last_message(), kDefaultTimeout); } #endif // WEBRTC_HAVE_SCTP // This test sets up a call between two parties with audio, video and an RTP // data channel. TEST_P(DataChannelIntegrationTest, EndToEndCallWithRtpDataChannel) { PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.enable_rtp_data_channel = true; rtc_config.enable_dtls_srtp = false; ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(rtc_config, rtc_config)); ConnectFakeSignaling(); // Expect that data channel created on caller side will show up for callee as // well. caller()->CreateDataChannel(); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Ensure the existence of the RTP data channel didn't impede audio/video. MediaExpectations media_expectations; media_expectations.ExpectBidirectionalAudioAndVideo(); ASSERT_TRUE(ExpectNewFrames(media_expectations)); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_NE(nullptr, callee()->data_channel()); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Ensure data can be sent in both directions. std::string data = "hello world"; SendRtpDataWithRetries(caller()->data_channel(), data, 5); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); SendRtpDataWithRetries(callee()->data_channel(), data, 5); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } TEST_P(DataChannelIntegrationTest, RtpDataChannelWorksAfterRollback) { PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.enable_rtp_data_channel = true; rtc_config.enable_dtls_srtp = false; ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(rtc_config, rtc_config)); ConnectFakeSignaling(); auto data_channel = caller()->pc()->CreateDataChannel("label_1", nullptr); ASSERT_TRUE(data_channel.get() != nullptr); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); caller()->CreateDataChannel("label_2", nullptr); rtc::scoped_refptr observer( new rtc::RefCountedObject()); caller()->pc()->SetLocalDescription(observer, caller()->CreateOfferAndWait().release()); EXPECT_TRUE_WAIT(observer->called(), kDefaultTimeout); caller()->Rollback(); std::string data = "hello world"; SendRtpDataWithRetries(data_channel, data, 5); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); } // Ensure that an RTP data channel is signaled as closed for the caller when // the callee rejects it in a subsequent offer. TEST_P(DataChannelIntegrationTest, RtpDataChannelSignaledClosedInCalleeOffer) { // Same procedure as above test. PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.enable_rtp_data_channel = true; rtc_config.enable_dtls_srtp = false; ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(rtc_config, rtc_config)); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_NE(nullptr, callee()->data_channel()); ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Close the data channel on the callee, and do an updated offer/answer. callee()->data_channel()->Close(); callee()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); EXPECT_FALSE(caller()->data_observer()->IsOpen()); EXPECT_FALSE(callee()->data_observer()->IsOpen()); } #if !defined(THREAD_SANITIZER) // This test provokes TSAN errors. See bugs.webrtc.org/11282 // Tests that data is buffered in an RTP data channel until an observer is // registered for it. // // NOTE: RTP data channels can receive data before the underlying // transport has detected that a channel is writable and thus data can be // received before the data channel state changes to open. That is hard to test // but the same buffering is expected to be used in that case. // // Use fake clock and simulated network delay so that we predictably can wait // until an SCTP message has been delivered without "sleep()"ing. TEST_P(DataChannelIntegrationTestWithFakeClock, DataBufferedUntilRtpDataChannelObserverRegistered) { virtual_socket_server()->set_delay_mean(5); // 5 ms per hop. virtual_socket_server()->UpdateDelayDistribution(); PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.enable_rtp_data_channel = true; rtc_config.enable_dtls_srtp = false; ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(rtc_config, rtc_config)); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE(caller()->data_channel() != nullptr); ASSERT_TRUE_SIMULATED_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout, FakeClock()); ASSERT_TRUE_SIMULATED_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout, FakeClock()); ASSERT_EQ_SIMULATED_WAIT(DataChannelInterface::kOpen, callee()->data_channel()->state(), kDefaultTimeout, FakeClock()); // Unregister the observer which is normally automatically registered. callee()->data_channel()->UnregisterObserver(); // Send data and advance fake clock until it should have been received. std::string data = "hello world"; caller()->data_channel()->Send(DataBuffer(data)); SIMULATED_WAIT(false, 50, FakeClock()); // Attach data channel and expect data to be received immediately. Note that // EXPECT_EQ_WAIT is used, such that the simulated clock is not advanced any // further, but data can be received even if the callback is asynchronous. MockDataChannelObserver new_observer(callee()->data_channel()); EXPECT_EQ_SIMULATED_WAIT(data, new_observer.last_message(), kDefaultTimeout, FakeClock()); } #endif // !defined(THREAD_SANITIZER) // This test sets up a call between two parties with audio, video and but only // the caller client supports RTP data channels. TEST_P(DataChannelIntegrationTest, RtpDataChannelsRejectedByCallee) { PeerConnectionInterface::RTCConfiguration rtc_config_1; rtc_config_1.enable_rtp_data_channel = true; // Must disable DTLS to make negotiation succeed. rtc_config_1.enable_dtls_srtp = false; PeerConnectionInterface::RTCConfiguration rtc_config_2; rtc_config_2.enable_dtls_srtp = false; rtc_config_2.enable_dtls_srtp = false; ASSERT_TRUE( CreatePeerConnectionWrappersWithConfig(rtc_config_1, rtc_config_2)); ConnectFakeSignaling(); caller()->CreateDataChannel(); ASSERT_TRUE(caller()->data_channel() != nullptr); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // The caller should still have a data channel, but it should be closed, and // one should ever have been created for the callee. EXPECT_TRUE(caller()->data_channel() != nullptr); EXPECT_FALSE(caller()->data_observer()->IsOpen()); EXPECT_EQ(nullptr, callee()->data_channel()); } // This test sets up a call between two parties with audio, and video. When // audio and video is setup and flowing, an RTP data channel is negotiated. TEST_P(DataChannelIntegrationTest, AddRtpDataChannelInSubsequentOffer) { PeerConnectionInterface::RTCConfiguration rtc_config; rtc_config.enable_rtp_data_channel = true; rtc_config.enable_dtls_srtp = false; ASSERT_TRUE(CreatePeerConnectionWrappersWithConfig(rtc_config, rtc_config)); ConnectFakeSignaling(); // Do initial offer/answer with audio/video. caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Create data channel and do new offer and answer. caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_NE(nullptr, callee()->data_channel()); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Ensure data can be sent in both directions. std::string data = "hello world"; SendRtpDataWithRetries(caller()->data_channel(), data, 5); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); SendRtpDataWithRetries(callee()->data_channel(), data, 5); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } #ifdef WEBRTC_HAVE_SCTP // This test sets up a call between two parties with audio, video and an SCTP // data channel. TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannel) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); // Expect that data channel created on caller side will show up for callee as // well. caller()->CreateDataChannel(); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Ensure the existence of the SCTP data channel didn't impede audio/video. MediaExpectations media_expectations; media_expectations.ExpectBidirectionalAudioAndVideo(); ASSERT_TRUE(ExpectNewFrames(media_expectations)); // Caller data channel should already exist (it created one). Callee data // channel may not exist yet, since negotiation happens in-band, not in SDP. ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Ensure data can be sent in both directions. std::string data = "hello world"; caller()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } // This test sets up a call between two parties with an SCTP // data channel only, and sends messages of various sizes. TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelVariousSizes) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); // Expect that data channel created on caller side will show up for callee as // well. caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Caller data channel should already exist (it created one). Callee data // channel may not exist yet, since negotiation happens in-band, not in SDP. ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); for (int message_size = 1; message_size < 100000; message_size *= 2) { std::string data(message_size, 'a'); caller()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } // Specifically probe the area around the MTU size. for (int message_size = 1100; message_size < 1300; message_size += 1) { std::string data(message_size, 'a'); caller()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } } TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelLowestSafeMtu) { // The lowest payload size limit that's tested and found safe for this // application. Note that this is not the safe limit under all conditions; // in particular, the default is not the largest DTLS signature, and // this test does not use TURN. const size_t kLowestSafePayloadSizeLimit = 1225; ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); // Expect that data channel created on caller side will show up for callee as // well. caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Caller data channel should already exist (it created one). Callee data // channel may not exist yet, since negotiation happens in-band, not in SDP. ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit); for (int message_size = 1140; message_size < 1240; message_size += 1) { std::string data(message_size, 'a'); caller()->data_channel()->Send(DataBuffer(data)); ASSERT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); ASSERT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } } // This test verifies that lowering the MTU of the connection will cause // the datachannel to not transmit reliably. // The purpose of this test is to ensure that we know how a too-small MTU // error manifests itself. TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelHarmfulMtu) { // The lowest payload size limit that's tested and found safe for this // application in this configuration (see test above). const size_t kLowestSafePayloadSizeLimit = 1225; // The size of the smallest message that fails to be delivered. const size_t kMessageSizeThatIsNotDelivered = 1157; ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit - 1); // Probe for an undelivered or slowly delivered message. The exact // size limit seems to be dependent on the message history, so make the // code easily able to find the current value. bool failure_seen = false; for (size_t message_size = 1110; message_size < 1400; message_size++) { const size_t message_count = callee()->data_observer()->received_message_count(); const std::string data(message_size, 'a'); caller()->data_channel()->Send(DataBuffer(data)); // Wait a very short time for the message to be delivered. WAIT(callee()->data_observer()->received_message_count() > message_count, 10); if (callee()->data_observer()->received_message_count() == message_count) { ASSERT_EQ(kMessageSizeThatIsNotDelivered, message_size); failure_seen = true; break; } } ASSERT_TRUE(failure_seen); } // Ensure that when the callee closes an SCTP data channel, the closing // procedure results in the data channel being closed for the caller as well. TEST_P(DataChannelIntegrationTest, CalleeClosesSctpDataChannel) { // Same procedure as above test. ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Close the data channel on the callee side, and wait for it to reach the // "closed" state on both sides. callee()->data_channel()->Close(); EXPECT_TRUE_WAIT(!caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout); } TEST_P(DataChannelIntegrationTest, SctpDataChannelConfigSentToOtherSide) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); webrtc::DataChannelInit init; init.id = 53; init.maxRetransmits = 52; caller()->CreateDataChannel("data-channel", &init); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Since "negotiated" is false, the "id" parameter should be ignored. EXPECT_NE(init.id, callee()->data_channel()->id()); EXPECT_EQ("data-channel", callee()->data_channel()->label()); EXPECT_EQ(init.maxRetransmits, callee()->data_channel()->maxRetransmits()); EXPECT_FALSE(callee()->data_channel()->negotiated()); } // Test usrsctp's ability to process unordered data stream, where data actually // arrives out of order using simulated delays. Previously there have been some // bugs in this area. TEST_P(DataChannelIntegrationTest, StressTestUnorderedSctpDataChannel) { // Introduce random network delays. // Otherwise it's not a true "unordered" test. virtual_socket_server()->set_delay_mean(20); virtual_socket_server()->set_delay_stddev(5); virtual_socket_server()->UpdateDelayDistribution(); // Normal procedure, but with unordered data channel config. ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); webrtc::DataChannelInit init; init.ordered = false; caller()->CreateDataChannel(&init); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); static constexpr int kNumMessages = 100; // Deliberately chosen to be larger than the MTU so messages get fragmented. static constexpr size_t kMaxMessageSize = 4096; // Create and send random messages. std::vector sent_messages; for (int i = 0; i < kNumMessages; ++i) { size_t length = (rand() % kMaxMessageSize) + 1; // NOLINT (rand_r instead of rand) std::string message; ASSERT_TRUE(rtc::CreateRandomString(length, &message)); caller()->data_channel()->Send(DataBuffer(message)); callee()->data_channel()->Send(DataBuffer(message)); sent_messages.push_back(message); } // Wait for all messages to be received. EXPECT_EQ_WAIT(rtc::checked_cast(kNumMessages), caller()->data_observer()->received_message_count(), kDefaultTimeout); EXPECT_EQ_WAIT(rtc::checked_cast(kNumMessages), callee()->data_observer()->received_message_count(), kDefaultTimeout); // Sort and compare to make sure none of the messages were corrupted. std::vector caller_received_messages = caller()->data_observer()->messages(); std::vector callee_received_messages = callee()->data_observer()->messages(); absl::c_sort(sent_messages); absl::c_sort(caller_received_messages); absl::c_sort(callee_received_messages); EXPECT_EQ(sent_messages, caller_received_messages); EXPECT_EQ(sent_messages, callee_received_messages); } // This test sets up a call between two parties with audio, and video. When // audio and video are setup and flowing, an SCTP data channel is negotiated. TEST_P(DataChannelIntegrationTest, AddSctpDataChannelInSubsequentOffer) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); // Do initial offer/answer with audio/video. caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Create data channel and do new offer and answer. caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Caller data channel should already exist (it created one). Callee data // channel may not exist yet, since negotiation happens in-band, not in SDP. ASSERT_NE(nullptr, caller()->data_channel()); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Ensure data can be sent in both directions. std::string data = "hello world"; caller()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } // Set up a connection initially just using SCTP data channels, later upgrading // to audio/video, ensuring frames are received end-to-end. Effectively the // inverse of the test above. // This was broken in M57; see https://crbug.com/711243 TEST_P(DataChannelIntegrationTest, SctpDataChannelToAudioVideoUpgrade) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); // Do initial offer/answer with just data channel. caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); // Wait until data can be sent over the data channel. ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Do subsequent offer/answer with two-way audio and video. Audio and video // should end up bundled on the DTLS/ICE transport already used for data. caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); MediaExpectations media_expectations; media_expectations.ExpectBidirectionalAudioAndVideo(); ASSERT_TRUE(ExpectNewFrames(media_expectations)); } static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) { cricket::SctpDataContentDescription* dcd_offer = GetFirstSctpDataContentDescription(desc); // See https://crbug.com/webrtc/11211 - this function is a no-op ASSERT_TRUE(dcd_offer); dcd_offer->set_use_sctpmap(false); dcd_offer->set_protocol("UDP/DTLS/SCTP"); } // Test that the data channel works when a spec-compliant SCTP m= section is // offered (using "a=sctp-port" instead of "a=sctpmap", and using // "UDP/DTLS/SCTP" as the protocol). TEST_P(DataChannelIntegrationTest, DataChannelWorksWhenSpecCompliantSctpOfferReceived) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->SetGeneratedSdpMunger(MakeSpecCompliantSctpOffer); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout); EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout); EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); // Ensure data can be sent in both directions. std::string data = "hello world"; caller()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(), kDefaultTimeout); callee()->data_channel()->Send(DataBuffer(data)); EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(), kDefaultTimeout); } #endif // WEBRTC_HAVE_SCTP // Test that after closing PeerConnections, they stop sending any packets (ICE, // DTLS, RTP...). TEST_P(DataChannelIntegrationTest, ClosingConnectionStopsPacketFlow) { // Set up audio/video/data, wait for some frames to be received. ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->AddAudioVideoTracks(); #ifdef WEBRTC_HAVE_SCTP caller()->CreateDataChannel(); #endif caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); MediaExpectations media_expectations; media_expectations.CalleeExpectsSomeAudioAndVideo(); ASSERT_TRUE(ExpectNewFrames(media_expectations)); // Close PeerConnections. ClosePeerConnections(); // Pump messages for a second, and ensure no new packets end up sent. uint32_t sent_packets_a = virtual_socket_server()->sent_packets(); WAIT(false, 1000); uint32_t sent_packets_b = virtual_socket_server()->sent_packets(); EXPECT_EQ(sent_packets_a, sent_packets_b); } // Test that transport stats are generated by the RTCStatsCollector for a // connection that only involves data channels. This is a regression test for // crbug.com/826972. #ifdef WEBRTC_HAVE_SCTP TEST_P(DataChannelIntegrationTest, TransportStatsReportedForDataChannelOnlyConnection) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout); auto caller_report = caller()->NewGetStats(); EXPECT_EQ(1u, caller_report->GetStatsOfType().size()); auto callee_report = callee()->NewGetStats(); EXPECT_EQ(1u, callee_report->GetStatsOfType().size()); } INSTANTIATE_TEST_SUITE_P(DataChannelIntegrationTest, DataChannelIntegrationTest, Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan)); INSTANTIATE_TEST_SUITE_P(DataChannelIntegrationTest, DataChannelIntegrationTestWithFakeClock, Values(SdpSemantics::kPlanB, SdpSemantics::kUnifiedPlan)); TEST_F(DataChannelIntegrationTestUnifiedPlan, EndToEndCallWithBundledSctpDataChannel) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->AddAudioVideoTracks(); callee()->AddAudioVideoTracks(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); network_thread()->Invoke(RTC_FROM_HERE, [this] { ASSERT_EQ_WAIT(SctpTransportState::kConnected, caller()->pc()->GetSctpTransport()->Information().state(), kDefaultTimeout); }); ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); } TEST_F(DataChannelIntegrationTestUnifiedPlan, EndToEndCallWithDataChannelOnlyConnects) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); ASSERT_TRUE(caller()->data_observer()->IsOpen()); } TEST_F(DataChannelIntegrationTestUnifiedPlan, DataChannelClosesWhenClosed) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); caller()->data_channel()->Close(); ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout); } TEST_F(DataChannelIntegrationTestUnifiedPlan, DataChannelClosesWhenClosedReverse) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); callee()->data_channel()->Close(); ASSERT_TRUE_WAIT(!caller()->data_observer()->IsOpen(), kDefaultTimeout); } TEST_F(DataChannelIntegrationTestUnifiedPlan, DataChannelClosesWhenPeerConnectionClosed) { ASSERT_TRUE(CreatePeerConnectionWrappers()); ConnectFakeSignaling(); caller()->CreateDataChannel(); caller()->CreateAndSetAndSignalOffer(); ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout); ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout); caller()->pc()->Close(); ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout); } #endif // WEBRTC_HAVE_SCTP } // namespace } // namespace webrtc