blob: ffb91d7addb8f3b5e5011a3eeda14002ca157b50 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
Yves Gerey3e707812018-11-28 16:47:49 +010011#include <string.h>
kwiberg686a8ef2016-02-26 03:00:35 -080012#include <memory>
henrike@webrtc.org28e20752013-07-10 00:45:36 +000013#include <string>
14
Steve Anton10542f22019-01-11 09:11:00 -080015#include "media/base/fake_network_interface.h"
16#include "media/base/media_constants.h"
17#include "media/base/rtp_data_engine.h"
18#include "media/base/rtp_utils.h"
19#include "rtc_base/copy_on_write_buffer.h"
20#include "rtc_base/fake_clock.h"
Yves Gerey3e707812018-11-28 16:47:49 +010021#include "rtc_base/third_party/sigslot/sigslot.h"
Steve Anton10542f22019-01-11 09:11:00 -080022#include "rtc_base/time_utils.h"
Yves Gerey3e707812018-11-28 16:47:49 +010023#include "test/gtest.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000024
henrike@webrtc.org28e20752013-07-10 00:45:36 +000025class FakeDataReceiver : public sigslot::has_slots<> {
26 public:
27 FakeDataReceiver() : has_received_data_(false) {}
28
Yves Gerey665174f2018-06-19 15:03:05 +020029 void OnDataReceived(const cricket::ReceiveDataParams& params,
30 const char* data,
31 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032 has_received_data_ = true;
33 last_received_data_ = std::string(data, len);
34 last_received_data_len_ = len;
35 last_received_data_params_ = params;
36 }
37
38 bool has_received_data() const { return has_received_data_; }
39 std::string last_received_data() const { return last_received_data_; }
40 size_t last_received_data_len() const { return last_received_data_len_; }
41 cricket::ReceiveDataParams last_received_data_params() const {
42 return last_received_data_params_;
43 }
44
45 private:
46 bool has_received_data_;
47 std::string last_received_data_;
48 size_t last_received_data_len_;
49 cricket::ReceiveDataParams last_received_data_params_;
50};
51
Mirko Bonadei6a489f22019-04-09 15:11:12 +020052class RtpDataMediaChannelTest : public ::testing::Test {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053 protected:
54 virtual void SetUp() {
55 // Seed needed for each test to satisfy expectations.
56 iface_.reset(new cricket::FakeNetworkInterface());
nissecdf37a92016-09-13 23:41:47 -070057 dme_.reset(CreateEngine());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058 receiver_.reset(new FakeDataReceiver());
59 }
60
Sebastian Janssond624c392019-04-17 10:36:03 +020061 void SetNow(double now) { clock_.SetTime(webrtc::Timestamp::seconds(now)); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000062
nissecdf37a92016-09-13 23:41:47 -070063 cricket::RtpDataEngine* CreateEngine() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000064 cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065 return dme;
66 }
67
68 cricket::RtpDataMediaChannel* CreateChannel() {
69 return CreateChannel(dme_.get());
70 }
71
72 cricket::RtpDataMediaChannel* CreateChannel(cricket::RtpDataEngine* dme) {
zhihuangebbe4f22016-12-06 10:45:42 -080073 cricket::MediaConfig config;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000074 cricket::RtpDataMediaChannel* channel =
deadbeef953c2ce2017-01-09 14:53:41 -080075 static_cast<cricket::RtpDataMediaChannel*>(dme->CreateChannel(config));
Anton Sukhanov98a462c2018-10-17 13:15:42 -070076 channel->SetInterface(iface_.get(), /*media_transport=*/nullptr);
Yves Gerey665174f2018-06-19 15:03:05 +020077 channel->SignalDataReceived.connect(receiver_.get(),
78 &FakeDataReceiver::OnDataReceived);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000079 return channel;
80 }
81
Yves Gerey665174f2018-06-19 15:03:05 +020082 FakeDataReceiver* receiver() { return receiver_.get(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000083
Yves Gerey665174f2018-06-19 15:03:05 +020084 bool HasReceivedData() { return receiver_->has_received_data(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000085
Yves Gerey665174f2018-06-19 15:03:05 +020086 std::string GetReceivedData() { return receiver_->last_received_data(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000087
Yves Gerey665174f2018-06-19 15:03:05 +020088 size_t GetReceivedDataLen() { return receiver_->last_received_data_len(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000089
90 cricket::ReceiveDataParams GetReceivedDataParams() {
91 return receiver_->last_received_data_params();
92 }
93
Yves Gerey665174f2018-06-19 15:03:05 +020094 bool HasSentData(int count) { return (iface_->NumRtpPackets() > count); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000095
96 std::string GetSentData(int index) {
97 // Assume RTP header of length 12
jbaucheec21bd2016-03-20 06:15:43 -070098 std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
henrike@webrtc.org9de257d2013-07-17 14:42:53 +000099 iface_->GetRtpPacket(index));
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000100 if (packet->size() > 12) {
Karl Wiberg94784372015-04-20 14:03:07 +0200101 return std::string(packet->data<char>() + 12, packet->size() - 12);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000102 } else {
103 return "";
104 }
105 }
106
107 cricket::RtpHeader GetSentDataHeader(int index) {
jbaucheec21bd2016-03-20 06:15:43 -0700108 std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
henrike@webrtc.org9de257d2013-07-17 14:42:53 +0000109 iface_->GetRtpPacket(index));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000110 cricket::RtpHeader header;
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000111 GetRtpHeader(packet->data(), packet->size(), &header);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000112 return header;
113 }
114
115 private:
kwiberg686a8ef2016-02-26 03:00:35 -0800116 std::unique_ptr<cricket::RtpDataEngine> dme_;
nissecdf37a92016-09-13 23:41:47 -0700117 rtc::ScopedFakeClock clock_;
kwiberg686a8ef2016-02-26 03:00:35 -0800118 std::unique_ptr<cricket::FakeNetworkInterface> iface_;
119 std::unique_ptr<FakeDataReceiver> receiver_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000120};
121
122TEST_F(RtpDataMediaChannelTest, SetUnknownCodecs) {
kwiberg686a8ef2016-02-26 03:00:35 -0800123 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124
125 cricket::DataCodec known_codec;
126 known_codec.id = 103;
127 known_codec.name = "google-data";
128 cricket::DataCodec unknown_codec;
129 unknown_codec.id = 104;
130 unknown_codec.name = "unknown-data";
131
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200132 cricket::DataSendParameters send_parameters_known;
133 send_parameters_known.codecs.push_back(known_codec);
134 cricket::DataRecvParameters recv_parameters_known;
135 recv_parameters_known.codecs.push_back(known_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000136
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200137 cricket::DataSendParameters send_parameters_unknown;
138 send_parameters_unknown.codecs.push_back(unknown_codec);
139 cricket::DataRecvParameters recv_parameters_unknown;
140 recv_parameters_unknown.codecs.push_back(unknown_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000141
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200142 cricket::DataSendParameters send_parameters_mixed;
143 send_parameters_mixed.codecs.push_back(known_codec);
144 send_parameters_mixed.codecs.push_back(unknown_codec);
145 cricket::DataRecvParameters recv_parameters_mixed;
146 recv_parameters_mixed.codecs.push_back(known_codec);
147 recv_parameters_mixed.codecs.push_back(unknown_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200149 EXPECT_TRUE(dmc->SetSendParameters(send_parameters_known));
150 EXPECT_FALSE(dmc->SetSendParameters(send_parameters_unknown));
151 EXPECT_TRUE(dmc->SetSendParameters(send_parameters_mixed));
152 EXPECT_TRUE(dmc->SetRecvParameters(recv_parameters_known));
153 EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_unknown));
154 EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_mixed));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155}
156
157TEST_F(RtpDataMediaChannelTest, AddRemoveSendStream) {
kwiberg686a8ef2016-02-26 03:00:35 -0800158 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000159
160 cricket::StreamParams stream1;
161 stream1.add_ssrc(41);
162 EXPECT_TRUE(dmc->AddSendStream(stream1));
163 cricket::StreamParams stream2;
164 stream2.add_ssrc(42);
165 EXPECT_TRUE(dmc->AddSendStream(stream2));
166
167 EXPECT_TRUE(dmc->RemoveSendStream(41));
168 EXPECT_TRUE(dmc->RemoveSendStream(42));
169 EXPECT_FALSE(dmc->RemoveSendStream(43));
170}
171
172TEST_F(RtpDataMediaChannelTest, AddRemoveRecvStream) {
kwiberg686a8ef2016-02-26 03:00:35 -0800173 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000174
175 cricket::StreamParams stream1;
176 stream1.add_ssrc(41);
177 EXPECT_TRUE(dmc->AddRecvStream(stream1));
178 cricket::StreamParams stream2;
179 stream2.add_ssrc(42);
180 EXPECT_TRUE(dmc->AddRecvStream(stream2));
181 EXPECT_FALSE(dmc->AddRecvStream(stream2));
182
183 EXPECT_TRUE(dmc->RemoveRecvStream(41));
184 EXPECT_TRUE(dmc->RemoveRecvStream(42));
185}
186
187TEST_F(RtpDataMediaChannelTest, SendData) {
kwiberg686a8ef2016-02-26 03:00:35 -0800188 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000189
190 cricket::SendDataParams params;
191 params.ssrc = 42;
192 unsigned char data[] = "food";
jbaucheec21bd2016-03-20 06:15:43 -0700193 rtc::CopyOnWriteBuffer payload(data, 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000194 unsigned char padded_data[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200195 0x00, 0x00, 0x00, 0x00, 'f', 'o', 'o', 'd',
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000196 };
197 cricket::SendDataResult result;
198
199 // Not sending
200 EXPECT_FALSE(dmc->SendData(params, payload, &result));
201 EXPECT_EQ(cricket::SDR_ERROR, result);
202 EXPECT_FALSE(HasSentData(0));
203 ASSERT_TRUE(dmc->SetSend(true));
204
205 // Unknown stream name.
206 EXPECT_FALSE(dmc->SendData(params, payload, &result));
207 EXPECT_EQ(cricket::SDR_ERROR, result);
208 EXPECT_FALSE(HasSentData(0));
209
210 cricket::StreamParams stream;
211 stream.add_ssrc(42);
212 ASSERT_TRUE(dmc->AddSendStream(stream));
213
214 // Unknown codec;
215 EXPECT_FALSE(dmc->SendData(params, payload, &result));
216 EXPECT_EQ(cricket::SDR_ERROR, result);
217 EXPECT_FALSE(HasSentData(0));
218
219 cricket::DataCodec codec;
220 codec.id = 103;
221 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200222 cricket::DataSendParameters parameters;
223 parameters.codecs.push_back(codec);
224 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225
226 // Length too large;
227 std::string x10000(10000, 'x');
228 EXPECT_FALSE(dmc->SendData(
jbaucheec21bd2016-03-20 06:15:43 -0700229 params, rtc::CopyOnWriteBuffer(x10000.data(), x10000.length()), &result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230 EXPECT_EQ(cricket::SDR_ERROR, result);
231 EXPECT_FALSE(HasSentData(0));
232
233 // Finally works!
234 EXPECT_TRUE(dmc->SendData(params, payload, &result));
235 EXPECT_EQ(cricket::SDR_SUCCESS, result);
236 ASSERT_TRUE(HasSentData(0));
237 EXPECT_EQ(sizeof(padded_data), GetSentData(0).length());
Yves Gerey665174f2018-06-19 15:03:05 +0200238 EXPECT_EQ(0, memcmp(padded_data, GetSentData(0).data(), sizeof(padded_data)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239 cricket::RtpHeader header0 = GetSentDataHeader(0);
240 EXPECT_NE(0, header0.seq_num);
241 EXPECT_NE(0U, header0.timestamp);
242 EXPECT_EQ(header0.ssrc, 42U);
243 EXPECT_EQ(header0.payload_type, 103);
244
245 // Should bump timestamp by 180000 because the clock rate is 90khz.
246 SetNow(2);
247
248 EXPECT_TRUE(dmc->SendData(params, payload, &result));
249 ASSERT_TRUE(HasSentData(1));
250 EXPECT_EQ(sizeof(padded_data), GetSentData(1).length());
Yves Gerey665174f2018-06-19 15:03:05 +0200251 EXPECT_EQ(0, memcmp(padded_data, GetSentData(1).data(), sizeof(padded_data)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000252 cricket::RtpHeader header1 = GetSentDataHeader(1);
253 EXPECT_EQ(header1.ssrc, 42U);
254 EXPECT_EQ(header1.payload_type, 103);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200255 EXPECT_EQ(static_cast<uint16_t>(header0.seq_num + 1),
256 static_cast<uint16_t>(header1.seq_num));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 EXPECT_EQ(header0.timestamp + 180000, header1.timestamp);
258}
259
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000260TEST_F(RtpDataMediaChannelTest, SendDataRate) {
kwiberg686a8ef2016-02-26 03:00:35 -0800261 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262
263 ASSERT_TRUE(dmc->SetSend(true));
264
265 cricket::DataCodec codec;
266 codec.id = 103;
267 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200268 cricket::DataSendParameters parameters;
269 parameters.codecs.push_back(codec);
270 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000271
272 cricket::StreamParams stream;
273 stream.add_ssrc(42);
274 ASSERT_TRUE(dmc->AddSendStream(stream));
275
276 cricket::SendDataParams params;
277 params.ssrc = 42;
278 unsigned char data[] = "food";
jbaucheec21bd2016-03-20 06:15:43 -0700279 rtc::CopyOnWriteBuffer payload(data, 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280 cricket::SendDataResult result;
281
282 // With rtp overhead of 32 bytes, each one of our packets is 36
283 // bytes, or 288 bits. So, a limit of 872bps will allow 3 packets,
284 // but not four.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200285 parameters.max_bandwidth_bps = 872;
286 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287
288 EXPECT_TRUE(dmc->SendData(params, payload, &result));
289 EXPECT_TRUE(dmc->SendData(params, payload, &result));
290 EXPECT_TRUE(dmc->SendData(params, payload, &result));
291 EXPECT_FALSE(dmc->SendData(params, payload, &result));
292 EXPECT_FALSE(dmc->SendData(params, payload, &result));
293
294 SetNow(0.9);
295 EXPECT_FALSE(dmc->SendData(params, payload, &result));
296
297 SetNow(1.1);
298 EXPECT_TRUE(dmc->SendData(params, payload, &result));
299 EXPECT_TRUE(dmc->SendData(params, payload, &result));
300 SetNow(1.9);
301 EXPECT_TRUE(dmc->SendData(params, payload, &result));
302
303 SetNow(2.2);
304 EXPECT_TRUE(dmc->SendData(params, payload, &result));
305 EXPECT_TRUE(dmc->SendData(params, payload, &result));
306 EXPECT_TRUE(dmc->SendData(params, payload, &result));
307 EXPECT_FALSE(dmc->SendData(params, payload, &result));
308}
309
310TEST_F(RtpDataMediaChannelTest, ReceiveData) {
311 // PT= 103, SN=2, TS=3, SSRC = 4, data = "abcde"
Yves Gerey665174f2018-06-19 15:03:05 +0200312 unsigned char data[] = {0x80, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00,
313 0x03, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00,
314 0x00, 0x00, 'a', 'b', 'c', 'd', 'e'};
jbaucheec21bd2016-03-20 06:15:43 -0700315 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000316
kwiberg686a8ef2016-02-26 03:00:35 -0800317 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000318
319 // SetReceived not called.
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700320 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 EXPECT_FALSE(HasReceivedData());
322
323 dmc->SetReceive(true);
324
325 // Unknown payload id
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700326 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000327 EXPECT_FALSE(HasReceivedData());
328
329 cricket::DataCodec codec;
330 codec.id = 103;
331 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200332 cricket::DataRecvParameters parameters;
333 parameters.codecs.push_back(codec);
334 ASSERT_TRUE(dmc->SetRecvParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335
336 // Unknown stream
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700337 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000338 EXPECT_FALSE(HasReceivedData());
339
340 cricket::StreamParams stream;
341 stream.add_ssrc(42);
342 ASSERT_TRUE(dmc->AddRecvStream(stream));
343
344 // Finally works!
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700345 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000346 EXPECT_TRUE(HasReceivedData());
347 EXPECT_EQ("abcde", GetReceivedData());
348 EXPECT_EQ(5U, GetReceivedDataLen());
349}
350
351TEST_F(RtpDataMediaChannelTest, InvalidRtpPackets) {
Yves Gerey665174f2018-06-19 15:03:05 +0200352 unsigned char data[] = {0x80, 0x65, 0x00, 0x02};
jbaucheec21bd2016-03-20 06:15:43 -0700353 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000354
kwiberg686a8ef2016-02-26 03:00:35 -0800355 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356
357 // Too short
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700358 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 EXPECT_FALSE(HasReceivedData());
360}