1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3*d9f75844SAndroid Build Coastguard Worker *
4*d9f75844SAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license
5*d9f75844SAndroid Build Coastguard Worker * that can be found in the LICENSE file in the root of the source
6*d9f75844SAndroid Build Coastguard Worker * tree. An additional intellectual property rights grant can be found
7*d9f75844SAndroid Build Coastguard Worker * in the file PATENTS. All contributing project authors may
8*d9f75844SAndroid Build Coastguard Worker * be found in the AUTHORS file in the root of the source tree.
9*d9f75844SAndroid Build Coastguard Worker */
10*d9f75844SAndroid Build Coastguard Worker
11*d9f75844SAndroid Build Coastguard Worker #include <stdint.h>
12*d9f75844SAndroid Build Coastguard Worker
13*d9f75844SAndroid Build Coastguard Worker #include <cstdlib>
14*d9f75844SAndroid Build Coastguard Worker #include <iterator>
15*d9f75844SAndroid Build Coastguard Worker #include <string>
16*d9f75844SAndroid Build Coastguard Worker #include <tuple>
17*d9f75844SAndroid Build Coastguard Worker #include <vector>
18*d9f75844SAndroid Build Coastguard Worker
19*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
20*d9f75844SAndroid Build Coastguard Worker #include "absl/types/optional.h"
21*d9f75844SAndroid Build Coastguard Worker #include "api/data_channel_interface.h"
22*d9f75844SAndroid Build Coastguard Worker #include "api/dtls_transport_interface.h"
23*d9f75844SAndroid Build Coastguard Worker #include "api/peer_connection_interface.h"
24*d9f75844SAndroid Build Coastguard Worker #include "api/scoped_refptr.h"
25*d9f75844SAndroid Build Coastguard Worker #include "api/sctp_transport_interface.h"
26*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtc_stats_report.h"
27*d9f75844SAndroid Build Coastguard Worker #include "api/stats/rtcstats_objects.h"
28*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
29*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_description.h"
30*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/transport_info.h"
31*d9f75844SAndroid Build Coastguard Worker #include "pc/media_session.h"
32*d9f75844SAndroid Build Coastguard Worker #include "pc/session_description.h"
33*d9f75844SAndroid Build Coastguard Worker #include "pc/test/integration_test_helpers.h"
34*d9f75844SAndroid Build Coastguard Worker #include "pc/test/mock_peer_connection_observers.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/copy_on_write_buffer.h"
36*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/fake_clock.h"
37*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/gunit.h"
38*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
39*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
40*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_conversions.h"
41*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/virtual_socket_server.h"
42*d9f75844SAndroid Build Coastguard Worker #include "test/gmock.h"
43*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
44*d9f75844SAndroid Build Coastguard Worker
45*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
46*d9f75844SAndroid Build Coastguard Worker
47*d9f75844SAndroid Build Coastguard Worker namespace {
48*d9f75844SAndroid Build Coastguard Worker
49*d9f75844SAndroid Build Coastguard Worker // All tests in this file require SCTP support.
50*d9f75844SAndroid Build Coastguard Worker #ifdef WEBRTC_HAVE_SCTP
51*d9f75844SAndroid Build Coastguard Worker
52*d9f75844SAndroid Build Coastguard Worker #if defined(WEBRTC_ANDROID)
53*d9f75844SAndroid Build Coastguard Worker // Disable heavy tests running on low-end Android devices.
54*d9f75844SAndroid Build Coastguard Worker #define DISABLED_ON_ANDROID(t) DISABLED_##t
55*d9f75844SAndroid Build Coastguard Worker #else
56*d9f75844SAndroid Build Coastguard Worker #define DISABLED_ON_ANDROID(t) t
57*d9f75844SAndroid Build Coastguard Worker #endif
58*d9f75844SAndroid Build Coastguard Worker
59*d9f75844SAndroid Build Coastguard Worker class DataChannelIntegrationTest
60*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionIntegrationBaseTest,
61*d9f75844SAndroid Build Coastguard Worker public ::testing::WithParamInterface<std::tuple<SdpSemantics, bool>> {
62*d9f75844SAndroid Build Coastguard Worker protected:
DataChannelIntegrationTest()63*d9f75844SAndroid Build Coastguard Worker DataChannelIntegrationTest()
64*d9f75844SAndroid Build Coastguard Worker : PeerConnectionIntegrationBaseTest(std::get<0>(GetParam())),
65*d9f75844SAndroid Build Coastguard Worker allow_media_(std::get<1>(GetParam())) {}
allow_media()66*d9f75844SAndroid Build Coastguard Worker bool allow_media() { return allow_media_; }
67*d9f75844SAndroid Build Coastguard Worker
CreatePeerConnectionWrappers()68*d9f75844SAndroid Build Coastguard Worker bool CreatePeerConnectionWrappers() {
69*d9f75844SAndroid Build Coastguard Worker if (allow_media_) {
70*d9f75844SAndroid Build Coastguard Worker return PeerConnectionIntegrationBaseTest::CreatePeerConnectionWrappers();
71*d9f75844SAndroid Build Coastguard Worker }
72*d9f75844SAndroid Build Coastguard Worker return PeerConnectionIntegrationBaseTest::
73*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappersWithoutMediaEngine();
74*d9f75844SAndroid Build Coastguard Worker }
75*d9f75844SAndroid Build Coastguard Worker
76*d9f75844SAndroid Build Coastguard Worker private:
77*d9f75844SAndroid Build Coastguard Worker // True if media is allowed to be added
78*d9f75844SAndroid Build Coastguard Worker const bool allow_media_;
79*d9f75844SAndroid Build Coastguard Worker };
80*d9f75844SAndroid Build Coastguard Worker
81*d9f75844SAndroid Build Coastguard Worker // Fake clock must be set before threads are started to prevent race on
82*d9f75844SAndroid Build Coastguard Worker // Set/GetClockForTesting().
83*d9f75844SAndroid Build Coastguard Worker // To achieve that, multiple inheritance is used as a mixin pattern
84*d9f75844SAndroid Build Coastguard Worker // where order of construction is finely controlled.
85*d9f75844SAndroid Build Coastguard Worker // This also ensures peerconnection is closed before switching back to non-fake
86*d9f75844SAndroid Build Coastguard Worker // clock, avoiding other races and DCHECK failures such as in rtp_sender.cc.
87*d9f75844SAndroid Build Coastguard Worker class FakeClockForTest : public rtc::ScopedFakeClock {
88*d9f75844SAndroid Build Coastguard Worker protected:
FakeClockForTest()89*d9f75844SAndroid Build Coastguard Worker FakeClockForTest() {
90*d9f75844SAndroid Build Coastguard Worker // Some things use a time of "0" as a special value, so we need to start out
91*d9f75844SAndroid Build Coastguard Worker // the fake clock at a nonzero time.
92*d9f75844SAndroid Build Coastguard Worker // TODO(deadbeef): Fix this.
93*d9f75844SAndroid Build Coastguard Worker AdvanceTime(webrtc::TimeDelta::Seconds(1));
94*d9f75844SAndroid Build Coastguard Worker }
95*d9f75844SAndroid Build Coastguard Worker
96*d9f75844SAndroid Build Coastguard Worker // Explicit handle.
FakeClock()97*d9f75844SAndroid Build Coastguard Worker ScopedFakeClock& FakeClock() { return *this; }
98*d9f75844SAndroid Build Coastguard Worker };
99*d9f75844SAndroid Build Coastguard Worker
100*d9f75844SAndroid Build Coastguard Worker class DataChannelIntegrationTestPlanB
101*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionIntegrationBaseTest {
102*d9f75844SAndroid Build Coastguard Worker protected:
DataChannelIntegrationTestPlanB()103*d9f75844SAndroid Build Coastguard Worker DataChannelIntegrationTestPlanB()
104*d9f75844SAndroid Build Coastguard Worker : PeerConnectionIntegrationBaseTest(SdpSemantics::kPlanB_DEPRECATED) {}
105*d9f75844SAndroid Build Coastguard Worker };
106*d9f75844SAndroid Build Coastguard Worker
107*d9f75844SAndroid Build Coastguard Worker class DataChannelIntegrationTestUnifiedPlan
108*d9f75844SAndroid Build Coastguard Worker : public PeerConnectionIntegrationBaseTest {
109*d9f75844SAndroid Build Coastguard Worker protected:
DataChannelIntegrationTestUnifiedPlan()110*d9f75844SAndroid Build Coastguard Worker DataChannelIntegrationTestUnifiedPlan()
111*d9f75844SAndroid Build Coastguard Worker : PeerConnectionIntegrationBaseTest(SdpSemantics::kUnifiedPlan) {}
112*d9f75844SAndroid Build Coastguard Worker };
113*d9f75844SAndroid Build Coastguard Worker
MakeActiveSctpOffer(cricket::SessionDescription * desc)114*d9f75844SAndroid Build Coastguard Worker void MakeActiveSctpOffer(cricket::SessionDescription* desc) {
115*d9f75844SAndroid Build Coastguard Worker auto& transport_infos = desc->transport_infos();
116*d9f75844SAndroid Build Coastguard Worker for (auto& transport_info : transport_infos) {
117*d9f75844SAndroid Build Coastguard Worker transport_info.description.connection_role = cricket::CONNECTIONROLE_ACTIVE;
118*d9f75844SAndroid Build Coastguard Worker }
119*d9f75844SAndroid Build Coastguard Worker }
120*d9f75844SAndroid Build Coastguard Worker
121*d9f75844SAndroid Build Coastguard Worker // This test causes a PeerConnection to enter Disconnected state, and
122*d9f75844SAndroid Build Coastguard Worker // sends data on a DataChannel while disconnected.
123*d9f75844SAndroid Build Coastguard Worker // The data should be surfaced when the connection reestablishes.
TEST_P(DataChannelIntegrationTest,DataChannelWhileDisconnected)124*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, DataChannelWhileDisconnected) {
125*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
126*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
127*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
128*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
129*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
130*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
131*d9f75844SAndroid Build Coastguard Worker std::string data1 = "hello first";
132*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data1));
133*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data1, callee()->data_observer()->last_message(),
134*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
135*d9f75844SAndroid Build Coastguard Worker // Cause a network outage
136*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
137*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
138*d9f75844SAndroid Build Coastguard Worker caller()->standardized_ice_connection_state(),
139*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
140*d9f75844SAndroid Build Coastguard Worker std::string data2 = "hello second";
141*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data2));
142*d9f75844SAndroid Build Coastguard Worker // Remove the network outage. The connection should reestablish.
143*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
144*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data2, callee()->data_observer()->last_message(),
145*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
146*d9f75844SAndroid Build Coastguard Worker }
147*d9f75844SAndroid Build Coastguard Worker
148*d9f75844SAndroid Build Coastguard Worker // This test causes a PeerConnection to enter Disconnected state,
149*d9f75844SAndroid Build Coastguard Worker // sends data on a DataChannel while disconnected, and then triggers
150*d9f75844SAndroid Build Coastguard Worker // an ICE restart.
151*d9f75844SAndroid Build Coastguard Worker // The data should be surfaced when the connection reestablishes.
TEST_P(DataChannelIntegrationTest,DataChannelWhileDisconnectedIceRestart)152*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, DataChannelWhileDisconnectedIceRestart) {
153*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
154*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
155*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
156*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
157*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
158*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
159*d9f75844SAndroid Build Coastguard Worker std::string data1 = "hello first";
160*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data1));
161*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data1, callee()->data_observer()->last_message(),
162*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
163*d9f75844SAndroid Build Coastguard Worker // Cause a network outage
164*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
165*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(PeerConnectionInterface::kIceConnectionDisconnected,
166*d9f75844SAndroid Build Coastguard Worker caller()->standardized_ice_connection_state(),
167*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
168*d9f75844SAndroid Build Coastguard Worker std::string data2 = "hello second";
169*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data2));
170*d9f75844SAndroid Build Coastguard Worker
171*d9f75844SAndroid Build Coastguard Worker // Trigger an ICE restart. The signaling channel is not affected by
172*d9f75844SAndroid Build Coastguard Worker // the network outage.
173*d9f75844SAndroid Build Coastguard Worker caller()->SetOfferAnswerOptions(IceRestartOfferAnswerOptions());
174*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
175*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
176*d9f75844SAndroid Build Coastguard Worker // Remove the network outage. The connection should reestablish.
177*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
178*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data2, callee()->data_observer()->last_message(),
179*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
180*d9f75844SAndroid Build Coastguard Worker }
181*d9f75844SAndroid Build Coastguard Worker
182*d9f75844SAndroid Build Coastguard Worker // This test sets up a call between two parties with audio, video and an SCTP
183*d9f75844SAndroid Build Coastguard Worker // data channel.
TEST_P(DataChannelIntegrationTest,EndToEndCallWithSctpDataChannel)184*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannel) {
185*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
186*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
187*d9f75844SAndroid Build Coastguard Worker // Expect that data channel created on caller side will show up for callee as
188*d9f75844SAndroid Build Coastguard Worker // well.
189*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
190*d9f75844SAndroid Build Coastguard Worker if (allow_media()) {
191*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
192*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
193*d9f75844SAndroid Build Coastguard Worker }
194*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
195*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
196*d9f75844SAndroid Build Coastguard Worker if (allow_media()) {
197*d9f75844SAndroid Build Coastguard Worker // Ensure the existence of the SCTP data channel didn't impede audio/video.
198*d9f75844SAndroid Build Coastguard Worker MediaExpectations media_expectations;
199*d9f75844SAndroid Build Coastguard Worker media_expectations.ExpectBidirectionalAudioAndVideo();
200*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(ExpectNewFrames(media_expectations));
201*d9f75844SAndroid Build Coastguard Worker }
202*d9f75844SAndroid Build Coastguard Worker // Caller data channel should already exist (it created one). Callee data
203*d9f75844SAndroid Build Coastguard Worker // channel may not exist yet, since negotiation happens in-band, not in SDP.
204*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
205*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
206*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
207*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
208*d9f75844SAndroid Build Coastguard Worker
209*d9f75844SAndroid Build Coastguard Worker // Ensure data can be sent in both directions.
210*d9f75844SAndroid Build Coastguard Worker std::string data = "hello world";
211*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
212*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
213*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
214*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
215*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
216*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
217*d9f75844SAndroid Build Coastguard Worker }
218*d9f75844SAndroid Build Coastguard Worker
219*d9f75844SAndroid Build Coastguard Worker // This test sets up a call between two parties with an SCTP
220*d9f75844SAndroid Build Coastguard Worker // data channel only, and sends messages of various sizes.
TEST_P(DataChannelIntegrationTest,EndToEndCallWithSctpDataChannelVariousSizes)221*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
222*d9f75844SAndroid Build Coastguard Worker EndToEndCallWithSctpDataChannelVariousSizes) {
223*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
224*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
225*d9f75844SAndroid Build Coastguard Worker // Expect that data channel created on caller side will show up for callee as
226*d9f75844SAndroid Build Coastguard Worker // well.
227*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
228*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
229*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
230*d9f75844SAndroid Build Coastguard Worker // Caller data channel should already exist (it created one). Callee data
231*d9f75844SAndroid Build Coastguard Worker // channel may not exist yet, since negotiation happens in-band, not in SDP.
232*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
233*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
234*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
235*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
236*d9f75844SAndroid Build Coastguard Worker
237*d9f75844SAndroid Build Coastguard Worker for (int message_size = 1; message_size < 100000; message_size *= 2) {
238*d9f75844SAndroid Build Coastguard Worker std::string data(message_size, 'a');
239*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
240*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
241*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
242*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
243*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
244*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
245*d9f75844SAndroid Build Coastguard Worker }
246*d9f75844SAndroid Build Coastguard Worker // Specifically probe the area around the MTU size.
247*d9f75844SAndroid Build Coastguard Worker for (int message_size = 1100; message_size < 1300; message_size += 1) {
248*d9f75844SAndroid Build Coastguard Worker std::string data(message_size, 'a');
249*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
250*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
251*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
252*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
253*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
254*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
255*d9f75844SAndroid Build Coastguard Worker }
256*d9f75844SAndroid Build Coastguard Worker }
257*d9f75844SAndroid Build Coastguard Worker
258*d9f75844SAndroid Build Coastguard Worker // This test sets up a call between two parties with an SCTP
259*d9f75844SAndroid Build Coastguard Worker // data channel only, and sends empty messages
TEST_P(DataChannelIntegrationTest,EndToEndCallWithSctpDataChannelEmptyMessages)260*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
261*d9f75844SAndroid Build Coastguard Worker EndToEndCallWithSctpDataChannelEmptyMessages) {
262*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
263*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
264*d9f75844SAndroid Build Coastguard Worker // Expect that data channel created on caller side will show up for callee as
265*d9f75844SAndroid Build Coastguard Worker // well.
266*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
267*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
268*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
269*d9f75844SAndroid Build Coastguard Worker // Caller data channel should already exist (it created one). Callee data
270*d9f75844SAndroid Build Coastguard Worker // channel may not exist yet, since negotiation happens in-band, not in SDP.
271*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
272*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
273*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
274*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
275*d9f75844SAndroid Build Coastguard Worker
276*d9f75844SAndroid Build Coastguard Worker // Ensure data can be sent in both directions.
277*d9f75844SAndroid Build Coastguard Worker // Sending empty string data
278*d9f75844SAndroid Build Coastguard Worker std::string data = "";
279*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
280*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
281*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
282*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee()->data_observer()->last_message().empty());
283*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee()->data_observer()->messages().back().binary);
284*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
285*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(1u, caller()->data_observer()->received_message_count(),
286*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
287*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()->data_observer()->last_message().empty());
288*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(caller()->data_observer()->messages().back().binary);
289*d9f75844SAndroid Build Coastguard Worker
290*d9f75844SAndroid Build Coastguard Worker // Sending empty binary data
291*d9f75844SAndroid Build Coastguard Worker rtc::CopyOnWriteBuffer empty_buffer;
292*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(empty_buffer, true));
293*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(2u, callee()->data_observer()->received_message_count(),
294*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
295*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee()->data_observer()->last_message().empty());
296*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(callee()->data_observer()->messages().back().binary);
297*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(empty_buffer, true));
298*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(2u, caller()->data_observer()->received_message_count(),
299*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
300*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()->data_observer()->last_message().empty());
301*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()->data_observer()->messages().back().binary);
302*d9f75844SAndroid Build Coastguard Worker }
303*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,EndToEndCallWithSctpDataChannelLowestSafeMtu)304*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
305*d9f75844SAndroid Build Coastguard Worker EndToEndCallWithSctpDataChannelLowestSafeMtu) {
306*d9f75844SAndroid Build Coastguard Worker // The lowest payload size limit that's tested and found safe for this
307*d9f75844SAndroid Build Coastguard Worker // application. Note that this is not the safe limit under all conditions;
308*d9f75844SAndroid Build Coastguard Worker // in particular, the default is not the largest DTLS signature, and
309*d9f75844SAndroid Build Coastguard Worker // this test does not use TURN.
310*d9f75844SAndroid Build Coastguard Worker const size_t kLowestSafePayloadSizeLimit = 1225;
311*d9f75844SAndroid Build Coastguard Worker
312*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
313*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
314*d9f75844SAndroid Build Coastguard Worker // Expect that data channel created on caller side will show up for callee as
315*d9f75844SAndroid Build Coastguard Worker // well.
316*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
317*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
318*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
319*d9f75844SAndroid Build Coastguard Worker // Caller data channel should already exist (it created one). Callee data
320*d9f75844SAndroid Build Coastguard Worker // channel may not exist yet, since negotiation happens in-band, not in SDP.
321*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
322*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
323*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
324*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
325*d9f75844SAndroid Build Coastguard Worker
326*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit);
327*d9f75844SAndroid Build Coastguard Worker for (int message_size = 1140; message_size < 1240; message_size += 1) {
328*d9f75844SAndroid Build Coastguard Worker std::string data(message_size, 'a');
329*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
330*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(data, callee()->data_observer()->last_message(),
331*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
332*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
333*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(data, caller()->data_observer()->last_message(),
334*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
335*d9f75844SAndroid Build Coastguard Worker }
336*d9f75844SAndroid Build Coastguard Worker }
337*d9f75844SAndroid Build Coastguard Worker
338*d9f75844SAndroid Build Coastguard Worker // This test verifies that lowering the MTU of the connection will cause
339*d9f75844SAndroid Build Coastguard Worker // the datachannel to not transmit reliably.
340*d9f75844SAndroid Build Coastguard Worker // The purpose of this test is to ensure that we know how a too-small MTU
341*d9f75844SAndroid Build Coastguard Worker // error manifests itself.
TEST_P(DataChannelIntegrationTest,EndToEndCallWithSctpDataChannelHarmfulMtu)342*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, EndToEndCallWithSctpDataChannelHarmfulMtu) {
343*d9f75844SAndroid Build Coastguard Worker // The lowest payload size limit that's tested and found safe for this
344*d9f75844SAndroid Build Coastguard Worker // application in this configuration (see test above).
345*d9f75844SAndroid Build Coastguard Worker const size_t kLowestSafePayloadSizeLimit = 1225;
346*d9f75844SAndroid Build Coastguard Worker // The size of the smallest message that fails to be delivered.
347*d9f75844SAndroid Build Coastguard Worker const size_t kMessageSizeThatIsNotDelivered = 1157;
348*d9f75844SAndroid Build Coastguard Worker
349*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
350*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
351*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
352*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
353*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
354*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
355*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
356*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
357*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
358*d9f75844SAndroid Build Coastguard Worker
359*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_max_udp_payload(kLowestSafePayloadSizeLimit - 1);
360*d9f75844SAndroid Build Coastguard Worker // Probe for an undelivered or slowly delivered message. The exact
361*d9f75844SAndroid Build Coastguard Worker // size limit seems to be dependent on the message history, so make the
362*d9f75844SAndroid Build Coastguard Worker // code easily able to find the current value.
363*d9f75844SAndroid Build Coastguard Worker bool failure_seen = false;
364*d9f75844SAndroid Build Coastguard Worker for (size_t message_size = 1110; message_size < 1400; message_size++) {
365*d9f75844SAndroid Build Coastguard Worker const size_t message_count =
366*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->received_message_count();
367*d9f75844SAndroid Build Coastguard Worker const std::string data(message_size, 'a');
368*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
369*d9f75844SAndroid Build Coastguard Worker // Wait a very short time for the message to be delivered.
370*d9f75844SAndroid Build Coastguard Worker // Note: Waiting only 10 ms is too short for Windows bots; they will
371*d9f75844SAndroid Build Coastguard Worker // flakily fail at a random frame.
372*d9f75844SAndroid Build Coastguard Worker WAIT(callee()->data_observer()->received_message_count() > message_count,
373*d9f75844SAndroid Build Coastguard Worker 100);
374*d9f75844SAndroid Build Coastguard Worker if (callee()->data_observer()->received_message_count() == message_count) {
375*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(kMessageSizeThatIsNotDelivered, message_size);
376*d9f75844SAndroid Build Coastguard Worker failure_seen = true;
377*d9f75844SAndroid Build Coastguard Worker break;
378*d9f75844SAndroid Build Coastguard Worker }
379*d9f75844SAndroid Build Coastguard Worker }
380*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(failure_seen);
381*d9f75844SAndroid Build Coastguard Worker }
382*d9f75844SAndroid Build Coastguard Worker
383*d9f75844SAndroid Build Coastguard Worker // Ensure that when the callee closes an SCTP data channel, the closing
384*d9f75844SAndroid Build Coastguard Worker // procedure results in the data channel being closed for the caller as well.
TEST_P(DataChannelIntegrationTest,CalleeClosesSctpDataChannel)385*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, CalleeClosesSctpDataChannel) {
386*d9f75844SAndroid Build Coastguard Worker // Same procedure as above test.
387*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
388*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
389*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
390*d9f75844SAndroid Build Coastguard Worker if (allow_media()) {
391*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
392*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
393*d9f75844SAndroid Build Coastguard Worker }
394*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
395*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
396*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
397*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
398*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
399*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
400*d9f75844SAndroid Build Coastguard Worker
401*d9f75844SAndroid Build Coastguard Worker // Close the data channel on the callee side, and wait for it to reach the
402*d9f75844SAndroid Build Coastguard Worker // "closed" state on both sides.
403*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Close();
404*d9f75844SAndroid Build Coastguard Worker
405*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState expected_states[] = {
406*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kConnecting,
407*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kOpen,
408*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosing,
409*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosed};
410*d9f75844SAndroid Build Coastguard Worker
411*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(DataChannelInterface::DataState::kClosed,
412*d9f75844SAndroid Build Coastguard Worker caller()->data_observer()->state(), kDefaultTimeout);
413*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(caller()->data_observer()->states(),
414*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray(expected_states));
415*d9f75844SAndroid Build Coastguard Worker
416*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(DataChannelInterface::DataState::kClosed,
417*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->state(), kDefaultTimeout);
418*d9f75844SAndroid Build Coastguard Worker EXPECT_THAT(callee()->data_observer()->states(),
419*d9f75844SAndroid Build Coastguard Worker ::testing::ElementsAreArray(expected_states));
420*d9f75844SAndroid Build Coastguard Worker }
421*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,SctpDataChannelConfigSentToOtherSide)422*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, SctpDataChannelConfigSentToOtherSide) {
423*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
424*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
425*d9f75844SAndroid Build Coastguard Worker webrtc::DataChannelInit init;
426*d9f75844SAndroid Build Coastguard Worker init.id = 53;
427*d9f75844SAndroid Build Coastguard Worker init.maxRetransmits = 52;
428*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel("data-channel", &init);
429*d9f75844SAndroid Build Coastguard Worker if (allow_media()) {
430*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
431*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
432*d9f75844SAndroid Build Coastguard Worker }
433*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
434*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
435*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
436*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
437*d9f75844SAndroid Build Coastguard Worker // Since "negotiated" is false, the "id" parameter should be ignored.
438*d9f75844SAndroid Build Coastguard Worker EXPECT_NE(init.id, callee()->data_channel()->id());
439*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ("data-channel", callee()->data_channel()->label());
440*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(init.maxRetransmits, callee()->data_channel()->maxRetransmits());
441*d9f75844SAndroid Build Coastguard Worker EXPECT_FALSE(callee()->data_channel()->negotiated());
442*d9f75844SAndroid Build Coastguard Worker }
443*d9f75844SAndroid Build Coastguard Worker
444*d9f75844SAndroid Build Coastguard Worker // Test sctp's ability to process unordered data stream, where data actually
445*d9f75844SAndroid Build Coastguard Worker // arrives out of order using simulated delays. Previously there have been some
446*d9f75844SAndroid Build Coastguard Worker // bugs in this area.
TEST_P(DataChannelIntegrationTest,StressTestUnorderedSctpDataChannel)447*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, StressTestUnorderedSctpDataChannel) {
448*d9f75844SAndroid Build Coastguard Worker // Introduce random network delays.
449*d9f75844SAndroid Build Coastguard Worker // Otherwise it's not a true "unordered" test.
450*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_delay_mean(20);
451*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_delay_stddev(5);
452*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->UpdateDelayDistribution();
453*d9f75844SAndroid Build Coastguard Worker // Normal procedure, but with unordered data channel config.
454*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
455*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
456*d9f75844SAndroid Build Coastguard Worker webrtc::DataChannelInit init;
457*d9f75844SAndroid Build Coastguard Worker init.ordered = false;
458*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(&init);
459*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
460*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
461*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
462*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
463*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
464*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
465*d9f75844SAndroid Build Coastguard Worker
466*d9f75844SAndroid Build Coastguard Worker static constexpr int kNumMessages = 100;
467*d9f75844SAndroid Build Coastguard Worker // Deliberately chosen to be larger than the MTU so messages get fragmented.
468*d9f75844SAndroid Build Coastguard Worker static constexpr size_t kMaxMessageSize = 4096;
469*d9f75844SAndroid Build Coastguard Worker // Create and send random messages.
470*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> sent_messages;
471*d9f75844SAndroid Build Coastguard Worker for (int i = 0; i < kNumMessages; ++i) {
472*d9f75844SAndroid Build Coastguard Worker size_t length =
473*d9f75844SAndroid Build Coastguard Worker (rand() % kMaxMessageSize) + 1; // NOLINT (rand_r instead of rand)
474*d9f75844SAndroid Build Coastguard Worker std::string message;
475*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(rtc::CreateRandomString(length, &message));
476*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(message));
477*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(message));
478*d9f75844SAndroid Build Coastguard Worker sent_messages.push_back(message);
479*d9f75844SAndroid Build Coastguard Worker }
480*d9f75844SAndroid Build Coastguard Worker
481*d9f75844SAndroid Build Coastguard Worker // Wait for all messages to be received.
482*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(rtc::checked_cast<size_t>(kNumMessages),
483*d9f75844SAndroid Build Coastguard Worker caller()->data_observer()->received_message_count(),
484*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
485*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(rtc::checked_cast<size_t>(kNumMessages),
486*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->received_message_count(),
487*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
488*d9f75844SAndroid Build Coastguard Worker
489*d9f75844SAndroid Build Coastguard Worker // Sort and compare to make sure none of the messages were corrupted.
490*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> caller_received_messages;
491*d9f75844SAndroid Build Coastguard Worker absl::c_transform(caller()->data_observer()->messages(),
492*d9f75844SAndroid Build Coastguard Worker std::back_inserter(caller_received_messages),
493*d9f75844SAndroid Build Coastguard Worker [](const auto& a) { return a.data; });
494*d9f75844SAndroid Build Coastguard Worker
495*d9f75844SAndroid Build Coastguard Worker std::vector<std::string> callee_received_messages;
496*d9f75844SAndroid Build Coastguard Worker absl::c_transform(callee()->data_observer()->messages(),
497*d9f75844SAndroid Build Coastguard Worker std::back_inserter(callee_received_messages),
498*d9f75844SAndroid Build Coastguard Worker [](const auto& a) { return a.data; });
499*d9f75844SAndroid Build Coastguard Worker
500*d9f75844SAndroid Build Coastguard Worker absl::c_sort(sent_messages);
501*d9f75844SAndroid Build Coastguard Worker absl::c_sort(caller_received_messages);
502*d9f75844SAndroid Build Coastguard Worker absl::c_sort(callee_received_messages);
503*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sent_messages, caller_received_messages);
504*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sent_messages, callee_received_messages);
505*d9f75844SAndroid Build Coastguard Worker }
506*d9f75844SAndroid Build Coastguard Worker
507*d9f75844SAndroid Build Coastguard Worker // Repeatedly open and close data channels on a peer connection to check that
508*d9f75844SAndroid Build Coastguard Worker // the channels are properly negotiated and SCTP stream IDs properly recycled.
TEST_P(DataChannelIntegrationTest,StressTestOpenCloseChannelNoDelay)509*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, StressTestOpenCloseChannelNoDelay) {
510*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
511*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
512*d9f75844SAndroid Build Coastguard Worker
513*d9f75844SAndroid Build Coastguard Worker int channel_id = 0;
514*d9f75844SAndroid Build Coastguard Worker const size_t kChannelCount = 8;
515*d9f75844SAndroid Build Coastguard Worker const size_t kIterations = 10;
516*d9f75844SAndroid Build Coastguard Worker bool has_negotiated = false;
517*d9f75844SAndroid Build Coastguard Worker
518*d9f75844SAndroid Build Coastguard Worker webrtc::DataChannelInit init;
519*d9f75844SAndroid Build Coastguard Worker for (size_t repeats = 0; repeats < kIterations; ++repeats) {
520*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Iteration " << (repeats + 1) << "/" << kIterations;
521*d9f75844SAndroid Build Coastguard Worker
522*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
523*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder sb;
524*d9f75844SAndroid Build Coastguard Worker sb << "channel-" << channel_id++;
525*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(sb.Release(), &init);
526*d9f75844SAndroid Build Coastguard Worker }
527*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(caller()->data_channels().size(), kChannelCount);
528*d9f75844SAndroid Build Coastguard Worker
529*d9f75844SAndroid Build Coastguard Worker if (!has_negotiated) {
530*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
531*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
532*d9f75844SAndroid Build Coastguard Worker has_negotiated = true;
533*d9f75844SAndroid Build Coastguard Worker }
534*d9f75844SAndroid Build Coastguard Worker
535*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
536*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(caller()->data_channels()[i]->state(),
537*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kOpen, kDefaultTimeout);
538*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Caller Channel "
539*d9f75844SAndroid Build Coastguard Worker << caller()->data_channels()[i]->label() << " with id "
540*d9f75844SAndroid Build Coastguard Worker << caller()->data_channels()[i]->id() << " is open.";
541*d9f75844SAndroid Build Coastguard Worker }
542*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels().size(), kChannelCount,
543*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
544*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
545*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels()[i]->state(),
546*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kOpen, kDefaultTimeout);
547*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Callee Channel "
548*d9f75844SAndroid Build Coastguard Worker << callee()->data_channels()[i]->label() << " with id "
549*d9f75844SAndroid Build Coastguard Worker << callee()->data_channels()[i]->id() << " is open.";
550*d9f75844SAndroid Build Coastguard Worker }
551*d9f75844SAndroid Build Coastguard Worker
552*d9f75844SAndroid Build Coastguard Worker // Closing from both sides to attempt creating races.
553*d9f75844SAndroid Build Coastguard Worker // A real application would likely only close from one side.
554*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
555*d9f75844SAndroid Build Coastguard Worker if (i % 3 == 0) {
556*d9f75844SAndroid Build Coastguard Worker callee()->data_channels()[i]->Close();
557*d9f75844SAndroid Build Coastguard Worker caller()->data_channels()[i]->Close();
558*d9f75844SAndroid Build Coastguard Worker } else {
559*d9f75844SAndroid Build Coastguard Worker caller()->data_channels()[i]->Close();
560*d9f75844SAndroid Build Coastguard Worker callee()->data_channels()[i]->Close();
561*d9f75844SAndroid Build Coastguard Worker }
562*d9f75844SAndroid Build Coastguard Worker }
563*d9f75844SAndroid Build Coastguard Worker
564*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
565*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(caller()->data_channels()[i]->state(),
566*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosed, kDefaultTimeout);
567*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels()[i]->state(),
568*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosed, kDefaultTimeout);
569*d9f75844SAndroid Build Coastguard Worker }
570*d9f75844SAndroid Build Coastguard Worker
571*d9f75844SAndroid Build Coastguard Worker caller()->data_channels().clear();
572*d9f75844SAndroid Build Coastguard Worker caller()->data_observers().clear();
573*d9f75844SAndroid Build Coastguard Worker callee()->data_channels().clear();
574*d9f75844SAndroid Build Coastguard Worker callee()->data_observers().clear();
575*d9f75844SAndroid Build Coastguard Worker }
576*d9f75844SAndroid Build Coastguard Worker }
577*d9f75844SAndroid Build Coastguard Worker
578*d9f75844SAndroid Build Coastguard Worker // Repeatedly open and close data channels on a peer connection to check that
579*d9f75844SAndroid Build Coastguard Worker // the channels are properly negotiated and SCTP stream IDs properly recycled.
580*d9f75844SAndroid Build Coastguard Worker // Some delay is added for better coverage.
TEST_P(DataChannelIntegrationTest,StressTestOpenCloseChannelWithDelay)581*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, StressTestOpenCloseChannelWithDelay) {
582*d9f75844SAndroid Build Coastguard Worker // Simulate some network delay
583*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_delay_mean(20);
584*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_delay_stddev(5);
585*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->UpdateDelayDistribution();
586*d9f75844SAndroid Build Coastguard Worker
587*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
588*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
589*d9f75844SAndroid Build Coastguard Worker
590*d9f75844SAndroid Build Coastguard Worker int channel_id = 0;
591*d9f75844SAndroid Build Coastguard Worker const size_t kChannelCount = 8;
592*d9f75844SAndroid Build Coastguard Worker const size_t kIterations = 10;
593*d9f75844SAndroid Build Coastguard Worker bool has_negotiated = false;
594*d9f75844SAndroid Build Coastguard Worker
595*d9f75844SAndroid Build Coastguard Worker webrtc::DataChannelInit init;
596*d9f75844SAndroid Build Coastguard Worker for (size_t repeats = 0; repeats < kIterations; ++repeats) {
597*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Iteration " << (repeats + 1) << "/" << kIterations;
598*d9f75844SAndroid Build Coastguard Worker
599*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
600*d9f75844SAndroid Build Coastguard Worker rtc::StringBuilder sb;
601*d9f75844SAndroid Build Coastguard Worker sb << "channel-" << channel_id++;
602*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(sb.Release(), &init);
603*d9f75844SAndroid Build Coastguard Worker }
604*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(caller()->data_channels().size(), kChannelCount);
605*d9f75844SAndroid Build Coastguard Worker
606*d9f75844SAndroid Build Coastguard Worker if (!has_negotiated) {
607*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
608*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
609*d9f75844SAndroid Build Coastguard Worker has_negotiated = true;
610*d9f75844SAndroid Build Coastguard Worker }
611*d9f75844SAndroid Build Coastguard Worker
612*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
613*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(caller()->data_channels()[i]->state(),
614*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kOpen, kDefaultTimeout);
615*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Caller Channel "
616*d9f75844SAndroid Build Coastguard Worker << caller()->data_channels()[i]->label() << " with id "
617*d9f75844SAndroid Build Coastguard Worker << caller()->data_channels()[i]->id() << " is open.";
618*d9f75844SAndroid Build Coastguard Worker }
619*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels().size(), kChannelCount,
620*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
621*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
622*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels()[i]->state(),
623*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kOpen, kDefaultTimeout);
624*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Callee Channel "
625*d9f75844SAndroid Build Coastguard Worker << callee()->data_channels()[i]->label() << " with id "
626*d9f75844SAndroid Build Coastguard Worker << callee()->data_channels()[i]->id() << " is open.";
627*d9f75844SAndroid Build Coastguard Worker }
628*d9f75844SAndroid Build Coastguard Worker
629*d9f75844SAndroid Build Coastguard Worker // Closing from both sides to attempt creating races.
630*d9f75844SAndroid Build Coastguard Worker // A real application would likely only close from one side.
631*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
632*d9f75844SAndroid Build Coastguard Worker if (i % 3 == 0) {
633*d9f75844SAndroid Build Coastguard Worker callee()->data_channels()[i]->Close();
634*d9f75844SAndroid Build Coastguard Worker caller()->data_channels()[i]->Close();
635*d9f75844SAndroid Build Coastguard Worker } else {
636*d9f75844SAndroid Build Coastguard Worker caller()->data_channels()[i]->Close();
637*d9f75844SAndroid Build Coastguard Worker callee()->data_channels()[i]->Close();
638*d9f75844SAndroid Build Coastguard Worker }
639*d9f75844SAndroid Build Coastguard Worker }
640*d9f75844SAndroid Build Coastguard Worker
641*d9f75844SAndroid Build Coastguard Worker for (size_t i = 0; i < kChannelCount; ++i) {
642*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(caller()->data_channels()[i]->state(),
643*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosed, kDefaultTimeout);
644*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels()[i]->state(),
645*d9f75844SAndroid Build Coastguard Worker DataChannelInterface::DataState::kClosed, kDefaultTimeout);
646*d9f75844SAndroid Build Coastguard Worker }
647*d9f75844SAndroid Build Coastguard Worker
648*d9f75844SAndroid Build Coastguard Worker caller()->data_channels().clear();
649*d9f75844SAndroid Build Coastguard Worker caller()->data_observers().clear();
650*d9f75844SAndroid Build Coastguard Worker callee()->data_channels().clear();
651*d9f75844SAndroid Build Coastguard Worker callee()->data_observers().clear();
652*d9f75844SAndroid Build Coastguard Worker }
653*d9f75844SAndroid Build Coastguard Worker }
654*d9f75844SAndroid Build Coastguard Worker
655*d9f75844SAndroid Build Coastguard Worker // This test sets up a call between two parties with audio, and video. When
656*d9f75844SAndroid Build Coastguard Worker // audio and video are setup and flowing, an SCTP data channel is negotiated.
TEST_P(DataChannelIntegrationTest,AddSctpDataChannelInSubsequentOffer)657*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, AddSctpDataChannelInSubsequentOffer) {
658*d9f75844SAndroid Build Coastguard Worker // This test can't be performed without media.
659*d9f75844SAndroid Build Coastguard Worker if (!allow_media()) {
660*d9f75844SAndroid Build Coastguard Worker return;
661*d9f75844SAndroid Build Coastguard Worker }
662*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
663*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
664*d9f75844SAndroid Build Coastguard Worker // Do initial offer/answer with audio/video.
665*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
666*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
667*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
668*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
669*d9f75844SAndroid Build Coastguard Worker // Create data channel and do new offer and answer.
670*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
671*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
672*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
673*d9f75844SAndroid Build Coastguard Worker // Caller data channel should already exist (it created one). Callee data
674*d9f75844SAndroid Build Coastguard Worker // channel may not exist yet, since negotiation happens in-band, not in SDP.
675*d9f75844SAndroid Build Coastguard Worker ASSERT_NE(nullptr, caller()->data_channel());
676*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
677*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
678*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
679*d9f75844SAndroid Build Coastguard Worker // Ensure data can be sent in both directions.
680*d9f75844SAndroid Build Coastguard Worker std::string data = "hello world";
681*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
682*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
683*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
684*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
685*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
686*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
687*d9f75844SAndroid Build Coastguard Worker }
688*d9f75844SAndroid Build Coastguard Worker
689*d9f75844SAndroid Build Coastguard Worker // Set up a connection initially just using SCTP data channels, later
690*d9f75844SAndroid Build Coastguard Worker // upgrading to audio/video, ensuring frames are received end-to-end.
691*d9f75844SAndroid Build Coastguard Worker // Effectively the inverse of the test above. This was broken in M57; see
692*d9f75844SAndroid Build Coastguard Worker // https://crbug.com/711243
TEST_P(DataChannelIntegrationTest,SctpDataChannelToAudioVideoUpgrade)693*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, SctpDataChannelToAudioVideoUpgrade) {
694*d9f75844SAndroid Build Coastguard Worker // This test can't be performed without media.
695*d9f75844SAndroid Build Coastguard Worker if (!allow_media()) {
696*d9f75844SAndroid Build Coastguard Worker return;
697*d9f75844SAndroid Build Coastguard Worker }
698*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
699*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
700*d9f75844SAndroid Build Coastguard Worker // Do initial offer/answer with just data channel.
701*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
702*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
703*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
704*d9f75844SAndroid Build Coastguard Worker // Wait until data can be sent over the data channel.
705*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
706*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
707*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
708*d9f75844SAndroid Build Coastguard Worker
709*d9f75844SAndroid Build Coastguard Worker // Do subsequent offer/answer with two-way audio and video. Audio and video
710*d9f75844SAndroid Build Coastguard Worker // should end up bundled on the DTLS/ICE transport already used for data.
711*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
712*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
713*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
714*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
715*d9f75844SAndroid Build Coastguard Worker MediaExpectations media_expectations;
716*d9f75844SAndroid Build Coastguard Worker media_expectations.ExpectBidirectionalAudioAndVideo();
717*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(ExpectNewFrames(media_expectations));
718*d9f75844SAndroid Build Coastguard Worker }
719*d9f75844SAndroid Build Coastguard Worker
MakeSpecCompliantSctpOffer(cricket::SessionDescription * desc)720*d9f75844SAndroid Build Coastguard Worker static void MakeSpecCompliantSctpOffer(cricket::SessionDescription* desc) {
721*d9f75844SAndroid Build Coastguard Worker cricket::SctpDataContentDescription* dcd_offer =
722*d9f75844SAndroid Build Coastguard Worker GetFirstSctpDataContentDescription(desc);
723*d9f75844SAndroid Build Coastguard Worker // See https://crbug.com/webrtc/11211 - this function is a no-op
724*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(dcd_offer);
725*d9f75844SAndroid Build Coastguard Worker dcd_offer->set_use_sctpmap(false);
726*d9f75844SAndroid Build Coastguard Worker dcd_offer->set_protocol("UDP/DTLS/SCTP");
727*d9f75844SAndroid Build Coastguard Worker }
728*d9f75844SAndroid Build Coastguard Worker
729*d9f75844SAndroid Build Coastguard Worker // Test that the data channel works when a spec-compliant SCTP m= section is
730*d9f75844SAndroid Build Coastguard Worker // offered (using "a=sctp-port" instead of "a=sctpmap", and using
731*d9f75844SAndroid Build Coastguard Worker // "UDP/DTLS/SCTP" as the protocol).
TEST_P(DataChannelIntegrationTest,DataChannelWorksWhenSpecCompliantSctpOfferReceived)732*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
733*d9f75844SAndroid Build Coastguard Worker DataChannelWorksWhenSpecCompliantSctpOfferReceived) {
734*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
735*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
736*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
737*d9f75844SAndroid Build Coastguard Worker caller()->SetGeneratedSdpMunger(MakeSpecCompliantSctpOffer);
738*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
739*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
740*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel() != nullptr, kDefaultTimeout);
741*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
742*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
743*d9f75844SAndroid Build Coastguard Worker
744*d9f75844SAndroid Build Coastguard Worker // Ensure data can be sent in both directions.
745*d9f75844SAndroid Build Coastguard Worker std::string data = "hello world";
746*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer(data));
747*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, callee()->data_observer()->last_message(),
748*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
749*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Send(DataBuffer(data));
750*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(data, caller()->data_observer()->last_message(),
751*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
752*d9f75844SAndroid Build Coastguard Worker }
753*d9f75844SAndroid Build Coastguard Worker
754*d9f75844SAndroid Build Coastguard Worker // Test that after closing PeerConnections, they stop sending any packets
755*d9f75844SAndroid Build Coastguard Worker // (ICE, DTLS, RTP...).
TEST_P(DataChannelIntegrationTest,ClosingConnectionStopsPacketFlow)756*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, ClosingConnectionStopsPacketFlow) {
757*d9f75844SAndroid Build Coastguard Worker // This test can't be performed without media.
758*d9f75844SAndroid Build Coastguard Worker if (!allow_media()) {
759*d9f75844SAndroid Build Coastguard Worker return;
760*d9f75844SAndroid Build Coastguard Worker }
761*d9f75844SAndroid Build Coastguard Worker // Set up audio/video/data, wait for some frames to be received.
762*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
763*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
764*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
765*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
766*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
767*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
768*d9f75844SAndroid Build Coastguard Worker MediaExpectations media_expectations;
769*d9f75844SAndroid Build Coastguard Worker media_expectations.CalleeExpectsSomeAudioAndVideo();
770*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(ExpectNewFrames(media_expectations));
771*d9f75844SAndroid Build Coastguard Worker // Close PeerConnections.
772*d9f75844SAndroid Build Coastguard Worker ClosePeerConnections();
773*d9f75844SAndroid Build Coastguard Worker // Pump messages for a second, and ensure no new packets end up sent.
774*d9f75844SAndroid Build Coastguard Worker uint32_t sent_packets_a = virtual_socket_server()->sent_packets();
775*d9f75844SAndroid Build Coastguard Worker WAIT(false, 1000);
776*d9f75844SAndroid Build Coastguard Worker uint32_t sent_packets_b = virtual_socket_server()->sent_packets();
777*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(sent_packets_a, sent_packets_b);
778*d9f75844SAndroid Build Coastguard Worker }
779*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,DtlsRoleIsSetNormally)780*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, DtlsRoleIsSetNormally) {
781*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
782*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
783*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
784*d9f75844SAndroid Build Coastguard Worker ASSERT_FALSE(caller()->pc()->GetSctpTransport());
785*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
786*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
787*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
788*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller()->pc()->GetSctpTransport());
789*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(
790*d9f75844SAndroid Build Coastguard Worker caller()->pc()->GetSctpTransport()->Information().dtls_transport());
791*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()
792*d9f75844SAndroid Build Coastguard Worker ->pc()
793*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
794*d9f75844SAndroid Build Coastguard Worker ->Information()
795*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
796*d9f75844SAndroid Build Coastguard Worker ->Information()
797*d9f75844SAndroid Build Coastguard Worker .role());
798*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()
799*d9f75844SAndroid Build Coastguard Worker ->pc()
800*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
801*d9f75844SAndroid Build Coastguard Worker ->Information()
802*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
803*d9f75844SAndroid Build Coastguard Worker ->Information()
804*d9f75844SAndroid Build Coastguard Worker .role(),
805*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kServer);
806*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee()
807*d9f75844SAndroid Build Coastguard Worker ->pc()
808*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
809*d9f75844SAndroid Build Coastguard Worker ->Information()
810*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
811*d9f75844SAndroid Build Coastguard Worker ->Information()
812*d9f75844SAndroid Build Coastguard Worker .role(),
813*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kClient);
814*d9f75844SAndroid Build Coastguard Worker // ID should be assigned according to the odd/even rule based on role;
815*d9f75844SAndroid Build Coastguard Worker // client gets even numbers, server gets odd ones. RFC 8832 section 6.
816*d9f75844SAndroid Build Coastguard Worker // TODO(hta): Test multiple channels.
817*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()->data_channel()->id(), 1);
818*d9f75844SAndroid Build Coastguard Worker }
819*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,DtlsRoleIsSetWhenReversed)820*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, DtlsRoleIsSetWhenReversed) {
821*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
822*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
823*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
824*d9f75844SAndroid Build Coastguard Worker callee()->SetReceivedSdpMunger(MakeActiveSctpOffer);
825*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
826*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
827*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
828*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()
829*d9f75844SAndroid Build Coastguard Worker ->pc()
830*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
831*d9f75844SAndroid Build Coastguard Worker ->Information()
832*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
833*d9f75844SAndroid Build Coastguard Worker ->Information()
834*d9f75844SAndroid Build Coastguard Worker .role());
835*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()
836*d9f75844SAndroid Build Coastguard Worker ->pc()
837*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
838*d9f75844SAndroid Build Coastguard Worker ->Information()
839*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
840*d9f75844SAndroid Build Coastguard Worker ->Information()
841*d9f75844SAndroid Build Coastguard Worker .role(),
842*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kClient);
843*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee()
844*d9f75844SAndroid Build Coastguard Worker ->pc()
845*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
846*d9f75844SAndroid Build Coastguard Worker ->Information()
847*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
848*d9f75844SAndroid Build Coastguard Worker ->Information()
849*d9f75844SAndroid Build Coastguard Worker .role(),
850*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kServer);
851*d9f75844SAndroid Build Coastguard Worker // ID should be assigned according to the odd/even rule based on role;
852*d9f75844SAndroid Build Coastguard Worker // client gets even numbers, server gets odd ones. RFC 8832 section 6.
853*d9f75844SAndroid Build Coastguard Worker // TODO(hta): Test multiple channels.
854*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()->data_channel()->id(), 0);
855*d9f75844SAndroid Build Coastguard Worker }
856*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,DtlsRoleIsSetWhenReversedWithChannelCollision)857*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
858*d9f75844SAndroid Build Coastguard Worker DtlsRoleIsSetWhenReversedWithChannelCollision) {
859*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
860*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
861*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
862*d9f75844SAndroid Build Coastguard Worker
863*d9f75844SAndroid Build Coastguard Worker callee()->SetReceivedSdpMunger([this](cricket::SessionDescription* desc) {
864*d9f75844SAndroid Build Coastguard Worker MakeActiveSctpOffer(desc);
865*d9f75844SAndroid Build Coastguard Worker callee()->CreateDataChannel();
866*d9f75844SAndroid Build Coastguard Worker });
867*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
868*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
869*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->data_observer()->IsOpen(), kDefaultTimeout);
870*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(callee()->data_channels().size(), 2U, kDefaultTimeout);
871*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(caller()->data_channels().size(), 2U, kDefaultTimeout);
872*d9f75844SAndroid Build Coastguard Worker EXPECT_TRUE(caller()
873*d9f75844SAndroid Build Coastguard Worker ->pc()
874*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
875*d9f75844SAndroid Build Coastguard Worker ->Information()
876*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
877*d9f75844SAndroid Build Coastguard Worker ->Information()
878*d9f75844SAndroid Build Coastguard Worker .role());
879*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()
880*d9f75844SAndroid Build Coastguard Worker ->pc()
881*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
882*d9f75844SAndroid Build Coastguard Worker ->Information()
883*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
884*d9f75844SAndroid Build Coastguard Worker ->Information()
885*d9f75844SAndroid Build Coastguard Worker .role(),
886*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kClient);
887*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee()
888*d9f75844SAndroid Build Coastguard Worker ->pc()
889*d9f75844SAndroid Build Coastguard Worker ->GetSctpTransport()
890*d9f75844SAndroid Build Coastguard Worker ->Information()
891*d9f75844SAndroid Build Coastguard Worker .dtls_transport()
892*d9f75844SAndroid Build Coastguard Worker ->Information()
893*d9f75844SAndroid Build Coastguard Worker .role(),
894*d9f75844SAndroid Build Coastguard Worker DtlsTransportTlsRole::kServer);
895*d9f75844SAndroid Build Coastguard Worker // ID should be assigned according to the odd/even rule based on role;
896*d9f75844SAndroid Build Coastguard Worker // client gets even numbers, server gets odd ones. RFC 8832 section 6.
897*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(caller()->data_channels().size(), 2U);
898*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ(callee()->data_channels().size(), 2U);
899*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()->data_channels()[0]->id(), 0);
900*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(caller()->data_channels()[1]->id(), 1);
901*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee()->data_channels()[0]->id(), 1);
902*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(callee()->data_channels()[1]->id(), 0);
903*d9f75844SAndroid Build Coastguard Worker }
904*d9f75844SAndroid Build Coastguard Worker
905*d9f75844SAndroid Build Coastguard Worker // Test that transport stats are generated by the RTCStatsCollector for a
906*d9f75844SAndroid Build Coastguard Worker // connection that only involves data channels. This is a regression test for
907*d9f75844SAndroid Build Coastguard Worker // crbug.com/826972.
TEST_P(DataChannelIntegrationTest,TransportStatsReportedForDataChannelOnlyConnection)908*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
909*d9f75844SAndroid Build Coastguard Worker TransportStatsReportedForDataChannelOnlyConnection) {
910*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
911*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
912*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
913*d9f75844SAndroid Build Coastguard Worker
914*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
915*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
916*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
917*d9f75844SAndroid Build Coastguard Worker
918*d9f75844SAndroid Build Coastguard Worker auto caller_report = caller()->NewGetStats();
919*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, caller_report->GetStatsOfType<RTCTransportStats>().size());
920*d9f75844SAndroid Build Coastguard Worker auto callee_report = callee()->NewGetStats();
921*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, callee_report->GetStatsOfType<RTCTransportStats>().size());
922*d9f75844SAndroid Build Coastguard Worker }
923*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,QueuedPacketsGetDeliveredInReliableMode)924*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDeliveredInReliableMode) {
925*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
926*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
927*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
928*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
929*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
930*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
931*d9f75844SAndroid Build Coastguard Worker
932*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("hello first"));
933*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
934*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
935*d9f75844SAndroid Build Coastguard Worker // Cause a temporary network outage
936*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
937*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= 10; i++) {
938*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
939*d9f75844SAndroid Build Coastguard Worker }
940*d9f75844SAndroid Build Coastguard Worker // Nothing should be delivered during outage. Short wait.
941*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(), 10);
942*d9f75844SAndroid Build Coastguard Worker // Reverse outage
943*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
944*d9f75844SAndroid Build Coastguard Worker // All packets should be delivered.
945*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT(11u, callee()->data_observer()->received_message_count(),
946*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
947*d9f75844SAndroid Build Coastguard Worker }
948*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,QueuedPacketsGetDroppedInUnreliableMode)949*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest, QueuedPacketsGetDroppedInUnreliableMode) {
950*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
951*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
952*d9f75844SAndroid Build Coastguard Worker DataChannelInit init;
953*d9f75844SAndroid Build Coastguard Worker init.maxRetransmits = 0;
954*d9f75844SAndroid Build Coastguard Worker init.ordered = false;
955*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(&init);
956*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
957*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
958*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
959*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("hello first"));
960*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
961*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
962*d9f75844SAndroid Build Coastguard Worker // Cause a temporary network outage
963*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
964*d9f75844SAndroid Build Coastguard Worker // Send a few packets. Note that all get dropped only when all packets
965*d9f75844SAndroid Build Coastguard Worker // fit into the receiver receive window/congestion window, so that they
966*d9f75844SAndroid Build Coastguard Worker // actually get sent.
967*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= 10; i++) {
968*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
969*d9f75844SAndroid Build Coastguard Worker }
970*d9f75844SAndroid Build Coastguard Worker // Nothing should be delivered during outage.
971*d9f75844SAndroid Build Coastguard Worker // We do a short wait to verify that delivery count is still 1.
972*d9f75844SAndroid Build Coastguard Worker WAIT(false, 10);
973*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
974*d9f75844SAndroid Build Coastguard Worker // Reverse the network outage.
975*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
976*d9f75844SAndroid Build Coastguard Worker // Send a new packet, and wait for it to be delivered.
977*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("After block"));
978*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
979*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
980*d9f75844SAndroid Build Coastguard Worker // Some messages should be lost, but first and last message should have
981*d9f75844SAndroid Build Coastguard Worker // been delivered.
982*d9f75844SAndroid Build Coastguard Worker // First, check that the protocol guarantee is preserved.
983*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(11u, callee()->data_observer()->received_message_count());
984*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(2u, callee()->data_observer()->received_message_count());
985*d9f75844SAndroid Build Coastguard Worker // Then, check that observed behavior (lose all messages) has not changed
986*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
987*d9f75844SAndroid Build Coastguard Worker }
988*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,QueuedPacketsGetDroppedInLifetimeLimitedMode)989*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
990*d9f75844SAndroid Build Coastguard Worker QueuedPacketsGetDroppedInLifetimeLimitedMode) {
991*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
992*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
993*d9f75844SAndroid Build Coastguard Worker DataChannelInit init;
994*d9f75844SAndroid Build Coastguard Worker init.maxRetransmitTime = 1;
995*d9f75844SAndroid Build Coastguard Worker init.ordered = false;
996*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(&init);
997*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
998*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
999*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
1000*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("hello first"));
1001*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
1002*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
1003*d9f75844SAndroid Build Coastguard Worker // Cause a temporary network outage
1004*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
1005*d9f75844SAndroid Build Coastguard Worker for (int i = 1; i <= 200; i++) {
1006*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
1007*d9f75844SAndroid Build Coastguard Worker }
1008*d9f75844SAndroid Build Coastguard Worker // Nothing should be delivered during outage.
1009*d9f75844SAndroid Build Coastguard Worker // We do a short wait to verify that delivery count is still 1,
1010*d9f75844SAndroid Build Coastguard Worker // and to make sure max packet lifetime (which is in ms) is exceeded.
1011*d9f75844SAndroid Build Coastguard Worker WAIT(false, 10);
1012*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
1013*d9f75844SAndroid Build Coastguard Worker // Reverse the network outage.
1014*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
1015*d9f75844SAndroid Build Coastguard Worker // Send a new packet, and wait for it to be delivered.
1016*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("After block"));
1017*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
1018*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
1019*d9f75844SAndroid Build Coastguard Worker // Some messages should be lost, but first and last message should have
1020*d9f75844SAndroid Build Coastguard Worker // been delivered.
1021*d9f75844SAndroid Build Coastguard Worker // First, check that the protocol guarantee is preserved.
1022*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(202u, callee()->data_observer()->received_message_count());
1023*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(2u, callee()->data_observer()->received_message_count());
1024*d9f75844SAndroid Build Coastguard Worker // Then, check that observed behavior (lose some messages) has not changed
1025*d9f75844SAndroid Build Coastguard Worker // DcSctp loses all messages. This is correct.
1026*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(2u, callee()->data_observer()->received_message_count());
1027*d9f75844SAndroid Build Coastguard Worker }
1028*d9f75844SAndroid Build Coastguard Worker
TEST_P(DataChannelIntegrationTest,DISABLED_ON_ANDROID (SomeQueuedPacketsGetDroppedInMaxRetransmitsMode))1029*d9f75844SAndroid Build Coastguard Worker TEST_P(DataChannelIntegrationTest,
1030*d9f75844SAndroid Build Coastguard Worker DISABLED_ON_ANDROID(SomeQueuedPacketsGetDroppedInMaxRetransmitsMode)) {
1031*d9f75844SAndroid Build Coastguard Worker CreatePeerConnectionWrappers();
1032*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1033*d9f75844SAndroid Build Coastguard Worker DataChannelInit init;
1034*d9f75844SAndroid Build Coastguard Worker init.maxRetransmits = 0;
1035*d9f75844SAndroid Build Coastguard Worker init.ordered = false;
1036*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel(&init);
1037*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1038*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1039*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
1040*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("hello first"));
1041*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(1u, callee()->data_observer()->received_message_count(),
1042*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
1043*d9f75844SAndroid Build Coastguard Worker // Cause a temporary network outage
1044*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(1.0);
1045*d9f75844SAndroid Build Coastguard Worker // Fill the buffer until queued data starts to build
1046*d9f75844SAndroid Build Coastguard Worker size_t packet_counter = 0;
1047*d9f75844SAndroid Build Coastguard Worker while (caller()->data_channel()->buffered_amount() < 1 &&
1048*d9f75844SAndroid Build Coastguard Worker packet_counter < 10000) {
1049*d9f75844SAndroid Build Coastguard Worker packet_counter++;
1050*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("Sent while blocked"));
1051*d9f75844SAndroid Build Coastguard Worker }
1052*d9f75844SAndroid Build Coastguard Worker if (caller()->data_channel()->buffered_amount()) {
1053*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "Buffered data after " << packet_counter << " packets";
1054*d9f75844SAndroid Build Coastguard Worker } else {
1055*d9f75844SAndroid Build Coastguard Worker RTC_LOG(LS_INFO) << "No buffered data after " << packet_counter
1056*d9f75844SAndroid Build Coastguard Worker << " packets";
1057*d9f75844SAndroid Build Coastguard Worker }
1058*d9f75844SAndroid Build Coastguard Worker // Nothing should be delivered during outage.
1059*d9f75844SAndroid Build Coastguard Worker // We do a short wait to verify that delivery count is still 1.
1060*d9f75844SAndroid Build Coastguard Worker WAIT(false, 10);
1061*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ(1u, callee()->data_observer()->received_message_count());
1062*d9f75844SAndroid Build Coastguard Worker // Reverse the network outage.
1063*d9f75844SAndroid Build Coastguard Worker virtual_socket_server()->set_drop_probability(0.0);
1064*d9f75844SAndroid Build Coastguard Worker // Send a new packet, and wait for it to be delivered.
1065*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Send(DataBuffer("After block"));
1066*d9f75844SAndroid Build Coastguard Worker EXPECT_EQ_WAIT("After block", callee()->data_observer()->last_message(),
1067*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
1068*d9f75844SAndroid Build Coastguard Worker // Some messages should be lost, but first and last message should have
1069*d9f75844SAndroid Build Coastguard Worker // been delivered.
1070*d9f75844SAndroid Build Coastguard Worker // Due to the fact that retransmissions are only counted when the packet
1071*d9f75844SAndroid Build Coastguard Worker // goes on the wire, NOT when they are stalled in queue due to
1072*d9f75844SAndroid Build Coastguard Worker // congestion, we expect some of the packets to be delivered, because
1073*d9f75844SAndroid Build Coastguard Worker // congestion prevented them from being sent.
1074*d9f75844SAndroid Build Coastguard Worker // Citation: https://tools.ietf.org/html/rfc7496#section-3.1
1075*d9f75844SAndroid Build Coastguard Worker
1076*d9f75844SAndroid Build Coastguard Worker // First, check that the protocol guarantee is preserved.
1077*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(packet_counter,
1078*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->received_message_count());
1079*d9f75844SAndroid Build Coastguard Worker EXPECT_LE(2u, callee()->data_observer()->received_message_count());
1080*d9f75844SAndroid Build Coastguard Worker // Then, check that observed behavior (lose between 100 and 200 messages)
1081*d9f75844SAndroid Build Coastguard Worker // has not changed.
1082*d9f75844SAndroid Build Coastguard Worker // Usrsctp behavior is different on Android (177) and other platforms (122).
1083*d9f75844SAndroid Build Coastguard Worker // Dcsctp loses 432 packets.
1084*d9f75844SAndroid Build Coastguard Worker EXPECT_GT(2 + packet_counter - 100,
1085*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->received_message_count());
1086*d9f75844SAndroid Build Coastguard Worker EXPECT_LT(2 + packet_counter - 500,
1087*d9f75844SAndroid Build Coastguard Worker callee()->data_observer()->received_message_count());
1088*d9f75844SAndroid Build Coastguard Worker }
1089*d9f75844SAndroid Build Coastguard Worker
1090*d9f75844SAndroid Build Coastguard Worker INSTANTIATE_TEST_SUITE_P(DataChannelIntegrationTest,
1091*d9f75844SAndroid Build Coastguard Worker DataChannelIntegrationTest,
1092*d9f75844SAndroid Build Coastguard Worker Combine(Values(SdpSemantics::kPlanB_DEPRECATED,
1093*d9f75844SAndroid Build Coastguard Worker SdpSemantics::kUnifiedPlan),
1094*d9f75844SAndroid Build Coastguard Worker testing::Bool()));
1095*d9f75844SAndroid Build Coastguard Worker
TEST_F(DataChannelIntegrationTestUnifiedPlan,EndToEndCallWithBundledSctpDataChannel)1096*d9f75844SAndroid Build Coastguard Worker TEST_F(DataChannelIntegrationTestUnifiedPlan,
1097*d9f75844SAndroid Build Coastguard Worker EndToEndCallWithBundledSctpDataChannel) {
1098*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
1099*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1100*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
1101*d9f75844SAndroid Build Coastguard Worker caller()->AddAudioVideoTracks();
1102*d9f75844SAndroid Build Coastguard Worker callee()->AddAudioVideoTracks();
1103*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1104*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1105*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(caller()->pc()->GetSctpTransport(), kDefaultTimeout);
1106*d9f75844SAndroid Build Coastguard Worker ASSERT_EQ_WAIT(SctpTransportState::kConnected,
1107*d9f75844SAndroid Build Coastguard Worker caller()->pc()->GetSctpTransport()->Information().state(),
1108*d9f75844SAndroid Build Coastguard Worker kDefaultTimeout);
1109*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
1110*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
1111*d9f75844SAndroid Build Coastguard Worker }
1112*d9f75844SAndroid Build Coastguard Worker
TEST_F(DataChannelIntegrationTestUnifiedPlan,EndToEndCallWithDataChannelOnlyConnects)1113*d9f75844SAndroid Build Coastguard Worker TEST_F(DataChannelIntegrationTestUnifiedPlan,
1114*d9f75844SAndroid Build Coastguard Worker EndToEndCallWithDataChannelOnlyConnects) {
1115*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
1116*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1117*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
1118*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1119*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1120*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_channel(), kDefaultTimeout);
1121*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
1122*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(caller()->data_observer()->IsOpen());
1123*d9f75844SAndroid Build Coastguard Worker }
1124*d9f75844SAndroid Build Coastguard Worker
TEST_F(DataChannelIntegrationTestUnifiedPlan,DataChannelClosesWhenClosed)1125*d9f75844SAndroid Build Coastguard Worker TEST_F(DataChannelIntegrationTestUnifiedPlan, DataChannelClosesWhenClosed) {
1126*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
1127*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1128*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
1129*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1130*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1131*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
1132*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
1133*d9f75844SAndroid Build Coastguard Worker caller()->data_channel()->Close();
1134*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout);
1135*d9f75844SAndroid Build Coastguard Worker }
1136*d9f75844SAndroid Build Coastguard Worker
TEST_F(DataChannelIntegrationTestUnifiedPlan,DataChannelClosesWhenClosedReverse)1137*d9f75844SAndroid Build Coastguard Worker TEST_F(DataChannelIntegrationTestUnifiedPlan,
1138*d9f75844SAndroid Build Coastguard Worker DataChannelClosesWhenClosedReverse) {
1139*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
1140*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1141*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
1142*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1143*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1144*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
1145*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
1146*d9f75844SAndroid Build Coastguard Worker callee()->data_channel()->Close();
1147*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(!caller()->data_observer()->IsOpen(), kDefaultTimeout);
1148*d9f75844SAndroid Build Coastguard Worker }
1149*d9f75844SAndroid Build Coastguard Worker
TEST_F(DataChannelIntegrationTestUnifiedPlan,DataChannelClosesWhenPeerConnectionClosed)1150*d9f75844SAndroid Build Coastguard Worker TEST_F(DataChannelIntegrationTestUnifiedPlan,
1151*d9f75844SAndroid Build Coastguard Worker DataChannelClosesWhenPeerConnectionClosed) {
1152*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE(CreatePeerConnectionWrappers());
1153*d9f75844SAndroid Build Coastguard Worker ConnectFakeSignaling();
1154*d9f75844SAndroid Build Coastguard Worker caller()->CreateDataChannel();
1155*d9f75844SAndroid Build Coastguard Worker caller()->CreateAndSetAndSignalOffer();
1156*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
1157*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer(), kDefaultTimeout);
1158*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(callee()->data_observer()->IsOpen(), kDefaultTimeout);
1159*d9f75844SAndroid Build Coastguard Worker caller()->pc()->Close();
1160*d9f75844SAndroid Build Coastguard Worker ASSERT_TRUE_WAIT(!callee()->data_observer()->IsOpen(), kDefaultTimeout);
1161*d9f75844SAndroid Build Coastguard Worker }
1162*d9f75844SAndroid Build Coastguard Worker
1163*d9f75844SAndroid Build Coastguard Worker #endif // WEBRTC_HAVE_SCTP
1164*d9f75844SAndroid Build Coastguard Worker
1165*d9f75844SAndroid Build Coastguard Worker } // namespace
1166*d9f75844SAndroid Build Coastguard Worker
1167*d9f75844SAndroid Build Coastguard Worker } // namespace webrtc
1168