Thanks to visit codestin.com
Credit goes to webrtc.googlesource.com

blob: 71ab9b4b1826003a7c6e3928e885a76c931b1923 [file] [log] [blame]
Harald Alvestranda45c8f42022-05-10 08:44:481/*
2 * Copyright 2022 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include "pc/data_channel_controller.h"
12
Harald Alvestrandf0d5caf2025-04-07 09:08:5113#include <cstddef>
Philip Eliasson17ddd312025-04-08 08:33:4914#include <cstdint>
Harald Alvestranda45c8f42022-05-10 08:44:4815#include <memory>
Harald Alvestrandf0d5caf2025-04-07 09:08:5116#include <optional>
Philip Eliasson17ddd312025-04-08 08:33:4917#include <utility>
18#include <vector>
Harald Alvestranda45c8f42022-05-10 08:44:4819
Philip Eliasson17ddd312025-04-08 08:33:4920#include "api/data_channel_event_observer_interface.h"
Harald Alvestrandf0d5caf2025-04-07 09:08:5121#include "api/data_channel_interface.h"
22#include "api/make_ref_counted.h"
Florent Castelli0012bfa2024-07-26 16:16:4123#include "api/priority.h"
Harald Alvestrandf0d5caf2025-04-07 09:08:5124#include "api/rtc_error.h"
25#include "api/scoped_refptr.h"
26#include "api/transport/data_channel_transport_interface.h"
Philip Eliasson17ddd312025-04-08 08:33:4927#include "api/units/timestamp.h"
Harald Alvestrandf0d5caf2025-04-07 09:08:5128#include "media/sctp/sctp_transport_internal.h"
Harald Alvestranda45c8f42022-05-10 08:44:4829#include "pc/peer_connection_internal.h"
Harald Alvestrand9e5aeb92022-05-11 09:35:3630#include "pc/sctp_data_channel.h"
Philip Eliasson17ddd312025-04-08 08:33:4931#include "pc/sctp_utils.h"
Harald Alvestranda45c8f42022-05-10 08:44:4832#include "pc/test/mock_peer_connection_internal.h"
Harald Alvestrandf0d5caf2025-04-07 09:08:5133#include "rtc_base/copy_on_write_buffer.h"
Philip Eliasson17ddd312025-04-08 08:33:4934#include "rtc_base/fake_clock.h"
Tommi55f72802023-03-27 10:39:3335#include "rtc_base/null_socket_server.h"
Harald Alvestrandf0d5caf2025-04-07 09:08:5136#include "rtc_base/ssl_stream_adapter.h"
37#include "rtc_base/thread.h"
Harald Alvestranda45c8f42022-05-10 08:44:4838#include "test/gmock.h"
39#include "test/gtest.h"
Tommi2a448722023-03-09 22:52:4340#include "test/run_loop.h"
Harald Alvestranda45c8f42022-05-10 08:44:4841
42namespace webrtc {
43
44namespace {
45
Philip Eliasson17ddd312025-04-08 08:33:4946using Message = DataChannelEventObserverInterface::Message;
47using ::testing::ElementsAreArray;
48using ::testing::IsEmpty;
Harald Alvestranda45c8f42022-05-10 08:44:4849using ::testing::NiceMock;
50using ::testing::Return;
Philip Eliasson17ddd312025-04-08 08:33:4951using ::testing::SizeIs;
52
53constexpr uint8_t kSomeData[] = {5, 4, 3, 2, 1};
Harald Alvestranda45c8f42022-05-10 08:44:4854
Harald Alvestranda6544372023-11-13 09:33:5655class MockDataChannelTransport : public DataChannelTransportInterface {
Tommi492296c2023-03-12 15:59:2556 public:
57 ~MockDataChannelTransport() override {}
58
Florent Castelli0012bfa2024-07-26 16:16:4159 MOCK_METHOD(RTCError,
60 OpenChannel,
61 (int channel_id, PriorityValue priority),
62 (override));
Tommi492296c2023-03-12 15:59:2563 MOCK_METHOD(RTCError,
64 SendData,
65 (int channel_id,
66 const SendDataParams& params,
Evan Shrubsole94adaee2025-05-09 10:35:1567 const CopyOnWriteBuffer& buffer),
Tommi492296c2023-03-12 15:59:2568 (override));
69 MOCK_METHOD(RTCError, CloseChannel, (int channel_id), (override));
70 MOCK_METHOD(void, SetDataSink, (DataChannelSink * sink), (override));
71 MOCK_METHOD(bool, IsReadyToSend, (), (const, override));
Victor Boiviefea41f52024-03-11 15:43:3172 MOCK_METHOD(size_t, buffered_amount, (int channel_id), (const, override));
Victor Boiviecdecc4e2024-03-18 12:47:3473 MOCK_METHOD(size_t,
74 buffered_amount_low_threshold,
75 (int channel_id),
76 (const, override));
77 MOCK_METHOD(void,
78 SetBufferedAmountLowThreshold,
79 (int channel_id, size_t bytes),
80 (override));
Tommi492296c2023-03-12 15:59:2581};
82
Philip Eliasson17ddd312025-04-08 08:33:4983class MockDataChannelEventObserver : public DataChannelEventObserverInterface {
84 public:
85 MOCK_METHOD(void,
86 OnMessage,
87 (const DataChannelEventObserverInterface::Message& message),
88 (override));
89};
90
Tommi52719652023-04-04 09:59:5591// Convenience class for tests to ensure that shutdown methods for DCC
92// are consistently called. In practice SdpOfferAnswerHandler will call
93// TeardownDataChannelTransport_n on the network thread when destroying the
94// data channel transport and PeerConnection calls PrepareForShutdown() from
95// within PeerConnection::Close(). The DataChannelControllerForTest class mimics
96// behavior by calling those methods from within its destructor.
97class DataChannelControllerForTest : public DataChannelController {
98 public:
Tommiaa3c9f22023-04-18 10:19:1999 explicit DataChannelControllerForTest(
100 PeerConnectionInternal* pc,
101 DataChannelTransportInterface* transport = nullptr)
102 : DataChannelController(pc) {
103 if (transport) {
104 network_thread()->BlockingCall(
105 [&] { SetupDataChannelTransport_n(transport); });
106 }
107 }
Tommi52719652023-04-04 09:59:55108
109 ~DataChannelControllerForTest() override {
Tommib00d63c2023-04-12 17:49:53110 network_thread()->BlockingCall(
111 [&] { TeardownDataChannelTransport_n(RTCError::OK()); });
Tommi52719652023-04-04 09:59:55112 PrepareForShutdown();
113 }
114};
115
Harald Alvestranda45c8f42022-05-10 08:44:48116class DataChannelControllerTest : public ::testing::Test {
117 protected:
Tommi55f72802023-03-27 10:39:33118 DataChannelControllerTest()
Evan Shrubsole03b68802025-03-18 12:23:05119 : network_thread_(std::make_unique<NullSocketServer>()) {
Tommi55f72802023-03-27 10:39:33120 network_thread_.Start();
Evan Shrubsolee6a1f702025-04-15 14:55:42121 pc_ = make_ref_counted<NiceMock<MockPeerConnectionInternal>>();
Evan Shrubsole6a9a1ae2025-03-21 12:54:15122 ON_CALL(*pc_, signaling_thread).WillByDefault(Return(Thread::Current()));
Tommi55f72802023-03-27 10:39:33123 ON_CALL(*pc_, network_thread).WillByDefault(Return(&network_thread_));
Harald Alvestranda45c8f42022-05-10 08:44:48124 }
125
Tommi55f72802023-03-27 10:39:33126 ~DataChannelControllerTest() override {
127 run_loop_.Flush();
128 network_thread_.Stop();
129 }
Tommi2a448722023-03-09 22:52:43130
Philip Eliasson17ddd312025-04-08 08:33:49131 ScopedBaseFakeClock clock_;
Tommi2a448722023-03-09 22:52:43132 test::RunLoop run_loop_;
Evan Shrubsole6a9a1ae2025-03-21 12:54:15133 Thread network_thread_;
Evan Shrubsolee6a1f702025-04-15 14:55:42134 scoped_refptr<NiceMock<MockPeerConnectionInternal>> pc_;
Harald Alvestranda45c8f42022-05-10 08:44:48135};
136
137TEST_F(DataChannelControllerTest, CreateAndDestroy) {
Tommi52719652023-04-04 09:59:55138 DataChannelControllerForTest dcc(pc_.get());
Harald Alvestranda45c8f42022-05-10 08:44:48139}
140
141TEST_F(DataChannelControllerTest, CreateDataChannelEarlyRelease) {
Tommi52719652023-04-04 09:59:55142 DataChannelControllerForTest dcc(pc_.get());
Tommi4f7ade52023-03-29 18:46:59143 auto ret = dcc.InternalCreateDataChannelWithProxy(
Tommi335d0842023-03-25 09:56:18144 "label", InternalDataChannelInit(DataChannelInit()));
Tommi4f7ade52023-03-29 18:46:59145 ASSERT_TRUE(ret.ok());
146 auto channel = ret.MoveValue();
147 // DCC still holds a reference to the channel. Release this reference early.
148 channel = nullptr;
Harald Alvestranda45c8f42022-05-10 08:44:48149}
150
Harald Alvestrand5da3eb02023-03-15 20:39:42151TEST_F(DataChannelControllerTest, CreateDataChannelEarlyClose) {
Tommi52719652023-04-04 09:59:55152 DataChannelControllerForTest dcc(pc_.get());
Philipp Hancke522380f2023-05-09 07:41:03153 EXPECT_FALSE(dcc.HasDataChannels());
Harald Alvestrand5da3eb02023-03-15 20:39:42154 EXPECT_FALSE(dcc.HasUsedDataChannels());
Tommi4f7ade52023-03-29 18:46:59155 auto ret = dcc.InternalCreateDataChannelWithProxy(
Tommi335d0842023-03-25 09:56:18156 "label", InternalDataChannelInit(DataChannelInit()));
Tommi4f7ade52023-03-29 18:46:59157 ASSERT_TRUE(ret.ok());
158 auto channel = ret.MoveValue();
Philipp Hancke522380f2023-05-09 07:41:03159 EXPECT_TRUE(dcc.HasDataChannels());
Harald Alvestrand5da3eb02023-03-15 20:39:42160 EXPECT_TRUE(dcc.HasUsedDataChannels());
161 channel->Close();
Tommi52719652023-04-04 09:59:55162 run_loop_.Flush();
Philipp Hancke522380f2023-05-09 07:41:03163 EXPECT_FALSE(dcc.HasDataChannels());
Harald Alvestrand5da3eb02023-03-15 20:39:42164 EXPECT_TRUE(dcc.HasUsedDataChannels());
165}
166
Harald Alvestranda45c8f42022-05-10 08:44:48167TEST_F(DataChannelControllerTest, CreateDataChannelLateRelease) {
Tommi52719652023-04-04 09:59:55168 auto dcc = std::make_unique<DataChannelControllerForTest>(pc_.get());
Tommi4f7ade52023-03-29 18:46:59169 auto ret = dcc->InternalCreateDataChannelWithProxy(
Tommi335d0842023-03-25 09:56:18170 "label", InternalDataChannelInit(DataChannelInit()));
Tommi4f7ade52023-03-29 18:46:59171 ASSERT_TRUE(ret.ok());
172 auto channel = ret.MoveValue();
Harald Alvestranda45c8f42022-05-10 08:44:48173 dcc.reset();
174 channel = nullptr;
175}
176
Harald Alvestrand9e5aeb92022-05-11 09:35:36177TEST_F(DataChannelControllerTest, CloseAfterControllerDestroyed) {
Tommi52719652023-04-04 09:59:55178 auto dcc = std::make_unique<DataChannelControllerForTest>(pc_.get());
Tommi4f7ade52023-03-29 18:46:59179 auto ret = dcc->InternalCreateDataChannelWithProxy(
Tommi335d0842023-03-25 09:56:18180 "label", InternalDataChannelInit(DataChannelInit()));
Tommi4f7ade52023-03-29 18:46:59181 ASSERT_TRUE(ret.ok());
182 auto channel = ret.MoveValue();
Harald Alvestrand9e5aeb92022-05-11 09:35:36183 dcc.reset();
184 channel->Close();
185}
186
Tommi492296c2023-03-12 15:59:25187// Allocate the maximum number of data channels and then one more.
188// The last allocation should fail.
189TEST_F(DataChannelControllerTest, MaxChannels) {
190 NiceMock<MockDataChannelTransport> transport;
191 int channel_id = 0;
192
Tommi335d0842023-03-25 09:56:18193 ON_CALL(*pc_, GetSctpSslRole_n).WillByDefault([&]() {
Evan Shrubsoleeb835d02025-03-12 09:41:06194 return std::optional<SSLRole>((channel_id & 1) ? SSL_SERVER : SSL_CLIENT);
Tommi492296c2023-03-12 15:59:25195 });
196
Tommiaa3c9f22023-04-18 10:19:19197 DataChannelControllerForTest dcc(pc_.get(), &transport);
Tommi492296c2023-03-12 15:59:25198
199 // Allocate the maximum number of channels + 1. Inside the loop, the creation
200 // process will allocate a stream id for each channel.
Evan Shrubsole945e5172025-04-08 14:11:45201 for (channel_id = 0; channel_id <= kMaxSctpStreams; ++channel_id) {
Tommi4f7ade52023-03-29 18:46:59202 auto ret = dcc.InternalCreateDataChannelWithProxy(
203 "label", InternalDataChannelInit(DataChannelInit()));
Evan Shrubsole945e5172025-04-08 14:11:45204 if (channel_id == kMaxSctpStreams) {
Tommi492296c2023-03-12 15:59:25205 // We've reached the maximum and the previous call should have failed.
Tommi4f7ade52023-03-29 18:46:59206 EXPECT_FALSE(ret.ok());
Tommi492296c2023-03-12 15:59:25207 } else {
208 // We're still working on saturating the pool. Things should be working.
Tommi4f7ade52023-03-29 18:46:59209 EXPECT_TRUE(ret.ok());
Tommi492296c2023-03-12 15:59:25210 }
211 }
212}
213
Victor Boiviefea41f52024-03-11 15:43:31214TEST_F(DataChannelControllerTest, BufferedAmountIncludesFromTransport) {
215 NiceMock<MockDataChannelTransport> transport;
216 EXPECT_CALL(transport, buffered_amount(0)).WillOnce(Return(4711));
Evan Shrubsoleeb835d02025-03-12 09:41:06217 ON_CALL(*pc_, GetSctpSslRole_n).WillByDefault([&]() { return SSL_CLIENT; });
Victor Boiviefea41f52024-03-11 15:43:31218
219 DataChannelControllerForTest dcc(pc_.get(), &transport);
220 auto dc = dcc.InternalCreateDataChannelWithProxy(
221 "label", InternalDataChannelInit(DataChannelInit()))
222 .MoveValue();
223 EXPECT_EQ(dc->buffered_amount(), 4711u);
224}
225
Tommi4f7ade52023-03-29 18:46:59226// Test that while a data channel is in the `kClosing` state, its StreamId does
227// not get re-used for new channels. Only once the state reaches `kClosed`
228// should a StreamId be available again for allocation.
229TEST_F(DataChannelControllerTest, NoStreamIdReuseWhileClosing) {
Evan Shrubsoleeb835d02025-03-12 09:41:06230 ON_CALL(*pc_, GetSctpSslRole_n).WillByDefault([&]() { return SSL_CLIENT; });
Tommi4f7ade52023-03-29 18:46:59231
Tommi52719652023-04-04 09:59:55232 NiceMock<MockDataChannelTransport> transport; // Wider scope than `dcc`.
Tommiaa3c9f22023-04-18 10:19:19233 DataChannelControllerForTest dcc(pc_.get(), &transport);
Tommi4f7ade52023-03-29 18:46:59234
235 // Create the first channel and check that we got the expected, first sid.
236 auto channel1 = dcc.InternalCreateDataChannelWithProxy(
237 "label", InternalDataChannelInit(DataChannelInit()))
238 .MoveValue();
239 ASSERT_EQ(channel1->id(), 0);
240
241 // Start closing the channel and make sure its state is `kClosing`
242 channel1->Close();
243 ASSERT_EQ(channel1->state(), DataChannelInterface::DataState::kClosing);
244
245 // Create a second channel and make sure we get a new StreamId, not the same
246 // as that of channel1.
247 auto channel2 = dcc.InternalCreateDataChannelWithProxy(
248 "label2", InternalDataChannelInit(DataChannelInit()))
249 .MoveValue();
250 ASSERT_NE(channel2->id(), channel1->id()); // In practice the id will be 2.
251
252 // Simulate the acknowledgement of the channel closing from the transport.
253 // This completes the closing operation of channel1.
254 pc_->network_thread()->BlockingCall([&] { dcc.OnChannelClosed(0); });
255 run_loop_.Flush();
256 ASSERT_EQ(channel1->state(), DataChannelInterface::DataState::kClosed);
257
258 // Now create a third channel. This time, the id of the first channel should
259 // be available again and therefore the ids of the first and third channels
260 // should be the same.
261 auto channel3 = dcc.InternalCreateDataChannelWithProxy(
262 "label3", InternalDataChannelInit(DataChannelInit()))
263 .MoveValue();
264 EXPECT_EQ(channel3->id(), channel1->id());
265}
266
Philip Eliasson17ddd312025-04-08 08:33:49267TEST_F(DataChannelControllerTest, ObserverNotifiedOnStringMessageSent) {
268 NiceMock<MockDataChannelTransport> transport;
269 DataChannelControllerForTest dcc(pc_.get(), &transport);
270
271 std::vector<Message> messages;
272 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
273 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
274 messages.push_back(m);
275 });
276 network_thread_.BlockingCall(
277 [&]() { dcc.SetEventObserver(std::move(observer)); });
278
279 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
280 dcc.InternalCreateDataChannelWithProxy(
281 "TestingSomeSendStuff",
282 InternalDataChannelInit({.negotiated = true, .id = 5}));
283 ASSERT_TRUE(ret.ok());
284 auto channel = ret.MoveValue();
285
286 clock_.SetTime(Timestamp::Millis(123));
287 network_thread_.BlockingCall([&]() {
288 dcc.SendData(StreamId(5), {.type = DataMessageType::kText},
289 CopyOnWriteBuffer(kSomeData));
290 });
291
292 channel->Close();
293 run_loop_.Flush();
294
295 ASSERT_THAT(messages, SizeIs(1));
296 EXPECT_EQ(messages[0].unix_timestamp_ms(), 123);
297 EXPECT_EQ(messages[0].datachannel_id(), 5);
298 EXPECT_EQ(messages[0].label(), "TestingSomeSendStuff");
299 EXPECT_EQ(messages[0].direction(), Message::Direction::kSend);
300 EXPECT_EQ(messages[0].data_type(), Message::DataType::kString);
301 EXPECT_THAT(messages[0].data(), ElementsAreArray(kSomeData));
302}
303
304TEST_F(DataChannelControllerTest, ObserverNotifiedOnBinaryMessageSent) {
305 NiceMock<MockDataChannelTransport> transport;
306 DataChannelControllerForTest dcc(pc_.get(), &transport);
307
308 std::vector<Message> messages;
309 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
310 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
311 messages.push_back(m);
312 });
313 network_thread_.BlockingCall(
314 [&]() { dcc.SetEventObserver(std::move(observer)); });
315
316 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
317 dcc.InternalCreateDataChannelWithProxy(
318 "TestingSomeSendStuff",
319 InternalDataChannelInit({.negotiated = true, .id = 5}));
320 ASSERT_TRUE(ret.ok());
321 auto channel = ret.MoveValue();
322
323 clock_.SetTime(Timestamp::Millis(123));
324 network_thread_.BlockingCall([&]() {
325 dcc.SendData(StreamId(5), {.type = DataMessageType::kBinary},
326 CopyOnWriteBuffer(kSomeData));
327 });
328
329 channel->Close();
330 run_loop_.Flush();
331
332 ASSERT_THAT(messages, SizeIs(1));
333 EXPECT_EQ(messages[0].unix_timestamp_ms(), 123);
334 EXPECT_EQ(messages[0].datachannel_id(), 5);
335 EXPECT_EQ(messages[0].label(), "TestingSomeSendStuff");
336 EXPECT_EQ(messages[0].direction(), Message::Direction::kSend);
337 EXPECT_EQ(messages[0].data_type(), Message::DataType::kBinary);
338 EXPECT_THAT(messages[0].data(), ElementsAreArray(kSomeData));
339}
340
341TEST_F(DataChannelControllerTest, ObserverNotNotifiedOnControlMessageSent) {
342 NiceMock<MockDataChannelTransport> transport;
343 DataChannelControllerForTest dcc(pc_.get(), &transport);
344
345 std::vector<Message> messages;
346 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
347 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
348 messages.push_back(m);
349 });
350 network_thread_.BlockingCall(
351 [&]() { dcc.SetEventObserver(std::move(observer)); });
352
353 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
354 dcc.InternalCreateDataChannelWithProxy(
355 "TestingSomeSendStuff",
356 InternalDataChannelInit({.negotiated = true, .id = 5}));
357 ASSERT_TRUE(ret.ok());
358 auto channel = ret.MoveValue();
359
360 network_thread_.BlockingCall([&]() {
361 dcc.SendData(StreamId(5), {.type = DataMessageType::kControl},
362 CopyOnWriteBuffer(kSomeData));
363 });
364
365 channel->Close();
366 run_loop_.Flush();
367
368 ASSERT_TRUE(messages.empty());
369}
370
371TEST_F(DataChannelControllerTest, ObserverNotNotifiedOnTransportFailed) {
372 NiceMock<MockDataChannelTransport> transport;
373 ON_CALL(transport, SendData)
374 .WillByDefault(Return(RTCError(RTCErrorType::INVALID_STATE)));
375 DataChannelControllerForTest dcc(pc_.get(), &transport);
376
377 std::vector<Message> messages;
378 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
379 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
380 messages.push_back(m);
381 });
382 network_thread_.BlockingCall(
383 [&]() { dcc.SetEventObserver(std::move(observer)); });
384
385 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
386 dcc.InternalCreateDataChannelWithProxy(
387 "TestingSomeSendStuff",
388 InternalDataChannelInit({.negotiated = true, .id = 5}));
389 ASSERT_TRUE(ret.ok());
390 auto channel = ret.MoveValue();
391
392 network_thread_.BlockingCall([&]() {
393 dcc.SendData(StreamId(5), {.type = DataMessageType::kText},
394 CopyOnWriteBuffer(kSomeData));
395 });
396
397 channel->Close();
398 run_loop_.Flush();
399
400 ASSERT_TRUE(messages.empty());
401}
402
403TEST_F(DataChannelControllerTest, ObserverNotifiedOnStringMessageReceived) {
404 NiceMock<MockDataChannelTransport> transport;
405 DataChannelControllerForTest dcc(pc_.get(), &transport);
406
407 std::vector<Message> messages;
408 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
409 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
410 messages.push_back(m);
411 });
412 network_thread_.BlockingCall(
413 [&]() { dcc.SetEventObserver(std::move(observer)); });
414
415 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
416 dcc.InternalCreateDataChannelWithProxy(
417 "TestingSomeReceiveStuff",
418 InternalDataChannelInit({.negotiated = true, .id = 5}));
419 ASSERT_TRUE(ret.ok());
420 auto channel = ret.MoveValue();
421
422 clock_.SetTime(Timestamp::Millis(123));
423 network_thread_.BlockingCall([&]() {
424 dcc.OnDataReceived(5, DataMessageType::kText, CopyOnWriteBuffer(kSomeData));
425 });
426
427 channel->Close();
428 run_loop_.Flush();
429
430 ASSERT_THAT(messages, SizeIs(1));
431 EXPECT_EQ(messages[0].unix_timestamp_ms(), 123);
432 EXPECT_EQ(messages[0].datachannel_id(), 5);
433 EXPECT_EQ(messages[0].label(), "TestingSomeReceiveStuff");
434 EXPECT_EQ(messages[0].direction(), Message::Direction::kReceive);
435 EXPECT_EQ(messages[0].data_type(), Message::DataType::kString);
436 EXPECT_THAT(messages[0].data(), ElementsAreArray(kSomeData));
437}
438
439TEST_F(DataChannelControllerTest, ObserverNotifiedOnBinaryMessageReceived) {
440 NiceMock<MockDataChannelTransport> transport;
441 DataChannelControllerForTest dcc(pc_.get(), &transport);
442
443 std::vector<Message> messages;
444 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
445 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
446 messages.push_back(m);
447 });
448 network_thread_.BlockingCall(
449 [&]() { dcc.SetEventObserver(std::move(observer)); });
450
451 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
452 dcc.InternalCreateDataChannelWithProxy(
453 "TestingSomeReceiveStuff",
454 InternalDataChannelInit({.negotiated = true, .id = 5}));
455 ASSERT_TRUE(ret.ok());
456 auto channel = ret.MoveValue();
457
458 clock_.SetTime(Timestamp::Millis(123));
459 network_thread_.BlockingCall([&]() {
460 dcc.OnDataReceived(5, DataMessageType::kBinary,
461 CopyOnWriteBuffer(kSomeData));
462 });
463
464 channel->Close();
465 run_loop_.Flush();
466
467 ASSERT_THAT(messages, SizeIs(1));
468 EXPECT_EQ(messages[0].unix_timestamp_ms(), 123);
469 EXPECT_EQ(messages[0].datachannel_id(), 5);
470 EXPECT_EQ(messages[0].label(), "TestingSomeReceiveStuff");
471 EXPECT_EQ(messages[0].direction(), Message::Direction::kReceive);
472 EXPECT_EQ(messages[0].data_type(), Message::DataType::kBinary);
473 EXPECT_THAT(messages[0].data(), ElementsAreArray(kSomeData));
474}
475
476TEST_F(DataChannelControllerTest, ObserverNotNotifiedOnControlMessageReceived) {
477 NiceMock<MockDataChannelTransport> transport;
478 DataChannelControllerForTest dcc(pc_.get(), &transport);
479
480 std::vector<Message> messages;
481 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
482 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
483 messages.push_back(m);
484 });
485 network_thread_.BlockingCall(
486 [&]() { dcc.SetEventObserver(std::move(observer)); });
487
488 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
489 dcc.InternalCreateDataChannelWithProxy(
490 "TestingSomeReceiveStuff",
491 InternalDataChannelInit({.negotiated = true, .id = 5}));
492 ASSERT_TRUE(ret.ok());
493 auto channel = ret.MoveValue();
494
495 network_thread_.BlockingCall([&]() {
496 dcc.OnDataReceived(5, DataMessageType::kControl,
497 CopyOnWriteBuffer(kSomeData));
498 });
499
500 channel->Close();
501 run_loop_.Flush();
502
503 EXPECT_THAT(messages, IsEmpty());
504}
505
506TEST_F(DataChannelControllerTest, ObserverNotNotifiedOnUnknownId) {
507 NiceMock<MockDataChannelTransport> transport;
508 DataChannelControllerForTest dcc(pc_.get(), &transport);
509
510 std::vector<Message> messages;
511 auto observer = std::make_unique<NiceMock<MockDataChannelEventObserver>>();
512 ON_CALL(*observer, OnMessage).WillByDefault([&](const Message& m) {
513 messages.push_back(m);
514 });
515 network_thread_.BlockingCall(
516 [&]() { dcc.SetEventObserver(std::move(observer)); });
517
518 RTCErrorOr<scoped_refptr<DataChannelInterface>> ret =
519 dcc.InternalCreateDataChannelWithProxy(
520 "TestingSomeReceiveStuff",
521 InternalDataChannelInit({.negotiated = true, .id = 5}));
522 ASSERT_TRUE(ret.ok());
523 auto channel = ret.MoveValue();
524
525 network_thread_.BlockingCall([&]() {
526 dcc.OnDataReceived(3, DataMessageType::kText, CopyOnWriteBuffer(kSomeData));
527 });
528
529 channel->Close();
530 run_loop_.Flush();
531
532 EXPECT_THAT(messages, IsEmpty());
533}
534
Harald Alvestranda45c8f42022-05-10 08:44:48535} // namespace
536} // namespace webrtc