blob: cd7d295f6b17b8c56519bc4311d4df91f4e0a530 [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
Anton Sukhanov4f08faa2019-05-21 11:12:57 -070015#include "api/media_transport_config.h"
Steve Anton10542f22019-01-11 09:11:00 -080016#include "media/base/fake_network_interface.h"
17#include "media/base/media_constants.h"
18#include "media/base/rtp_data_engine.h"
19#include "media/base/rtp_utils.h"
20#include "rtc_base/copy_on_write_buffer.h"
21#include "rtc_base/fake_clock.h"
Yves Gerey3e707812018-11-28 16:47:49 +010022#include "rtc_base/third_party/sigslot/sigslot.h"
Steve Anton10542f22019-01-11 09:11:00 -080023#include "rtc_base/time_utils.h"
Yves Gerey3e707812018-11-28 16:47:49 +010024#include "test/gtest.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000025
henrike@webrtc.org28e20752013-07-10 00:45:36 +000026class FakeDataReceiver : public sigslot::has_slots<> {
27 public:
28 FakeDataReceiver() : has_received_data_(false) {}
29
Yves Gerey665174f2018-06-19 15:03:05 +020030 void OnDataReceived(const cricket::ReceiveDataParams& params,
31 const char* data,
32 size_t len) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033 has_received_data_ = true;
34 last_received_data_ = std::string(data, len);
35 last_received_data_len_ = len;
36 last_received_data_params_ = params;
37 }
38
39 bool has_received_data() const { return has_received_data_; }
40 std::string last_received_data() const { return last_received_data_; }
41 size_t last_received_data_len() const { return last_received_data_len_; }
42 cricket::ReceiveDataParams last_received_data_params() const {
43 return last_received_data_params_;
44 }
45
46 private:
47 bool has_received_data_;
48 std::string last_received_data_;
49 size_t last_received_data_len_;
50 cricket::ReceiveDataParams last_received_data_params_;
51};
52
Mirko Bonadei6a489f22019-04-09 15:11:12 +020053class RtpDataMediaChannelTest : public ::testing::Test {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054 protected:
55 virtual void SetUp() {
56 // Seed needed for each test to satisfy expectations.
57 iface_.reset(new cricket::FakeNetworkInterface());
nissecdf37a92016-09-13 23:41:47 -070058 dme_.reset(CreateEngine());
henrike@webrtc.org28e20752013-07-10 00:45:36 +000059 receiver_.reset(new FakeDataReceiver());
60 }
61
Sebastian Janssond624c392019-04-17 10:36:03 +020062 void SetNow(double now) { clock_.SetTime(webrtc::Timestamp::seconds(now)); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000063
nissecdf37a92016-09-13 23:41:47 -070064 cricket::RtpDataEngine* CreateEngine() {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065 cricket::RtpDataEngine* dme = new cricket::RtpDataEngine();
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066 return dme;
67 }
68
69 cricket::RtpDataMediaChannel* CreateChannel() {
70 return CreateChannel(dme_.get());
71 }
72
73 cricket::RtpDataMediaChannel* CreateChannel(cricket::RtpDataEngine* dme) {
zhihuangebbe4f22016-12-06 10:45:42 -080074 cricket::MediaConfig config;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000075 cricket::RtpDataMediaChannel* channel =
deadbeef953c2ce2017-01-09 14:53:41 -080076 static_cast<cricket::RtpDataMediaChannel*>(dme->CreateChannel(config));
Anton Sukhanov316f3ac2019-05-23 15:50:38 -070077 channel->SetInterface(iface_.get(), webrtc::MediaTransportConfig());
Yves Gerey665174f2018-06-19 15:03:05 +020078 channel->SignalDataReceived.connect(receiver_.get(),
79 &FakeDataReceiver::OnDataReceived);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000080 return channel;
81 }
82
Yves Gerey665174f2018-06-19 15:03:05 +020083 FakeDataReceiver* receiver() { return receiver_.get(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
Yves Gerey665174f2018-06-19 15:03:05 +020085 bool HasReceivedData() { return receiver_->has_received_data(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086
Yves Gerey665174f2018-06-19 15:03:05 +020087 std::string GetReceivedData() { return receiver_->last_received_data(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088
Yves Gerey665174f2018-06-19 15:03:05 +020089 size_t GetReceivedDataLen() { return receiver_->last_received_data_len(); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000090
91 cricket::ReceiveDataParams GetReceivedDataParams() {
92 return receiver_->last_received_data_params();
93 }
94
Yves Gerey665174f2018-06-19 15:03:05 +020095 bool HasSentData(int count) { return (iface_->NumRtpPackets() > count); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000096
97 std::string GetSentData(int index) {
98 // Assume RTP header of length 12
jbaucheec21bd2016-03-20 06:15:43 -070099 std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
henrike@webrtc.org9de257d2013-07-17 14:42:53 +0000100 iface_->GetRtpPacket(index));
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000101 if (packet->size() > 12) {
Karl Wiberg94784372015-04-20 14:03:07 +0200102 return std::string(packet->data<char>() + 12, packet->size() - 12);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000103 } else {
104 return "";
105 }
106 }
107
108 cricket::RtpHeader GetSentDataHeader(int index) {
jbaucheec21bd2016-03-20 06:15:43 -0700109 std::unique_ptr<const rtc::CopyOnWriteBuffer> packet(
henrike@webrtc.org9de257d2013-07-17 14:42:53 +0000110 iface_->GetRtpPacket(index));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000111 cricket::RtpHeader header;
kwiberg@webrtc.orgeebcab52015-03-24 09:19:06 +0000112 GetRtpHeader(packet->data(), packet->size(), &header);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 return header;
114 }
115
116 private:
kwiberg686a8ef2016-02-26 03:00:35 -0800117 std::unique_ptr<cricket::RtpDataEngine> dme_;
nissecdf37a92016-09-13 23:41:47 -0700118 rtc::ScopedFakeClock clock_;
kwiberg686a8ef2016-02-26 03:00:35 -0800119 std::unique_ptr<cricket::FakeNetworkInterface> iface_;
120 std::unique_ptr<FakeDataReceiver> receiver_;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000121};
122
123TEST_F(RtpDataMediaChannelTest, SetUnknownCodecs) {
kwiberg686a8ef2016-02-26 03:00:35 -0800124 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000125
126 cricket::DataCodec known_codec;
127 known_codec.id = 103;
128 known_codec.name = "google-data";
129 cricket::DataCodec unknown_codec;
130 unknown_codec.id = 104;
131 unknown_codec.name = "unknown-data";
132
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200133 cricket::DataSendParameters send_parameters_known;
134 send_parameters_known.codecs.push_back(known_codec);
135 cricket::DataRecvParameters recv_parameters_known;
136 recv_parameters_known.codecs.push_back(known_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200138 cricket::DataSendParameters send_parameters_unknown;
139 send_parameters_unknown.codecs.push_back(unknown_codec);
140 cricket::DataRecvParameters recv_parameters_unknown;
141 recv_parameters_unknown.codecs.push_back(unknown_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000142
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200143 cricket::DataSendParameters send_parameters_mixed;
144 send_parameters_mixed.codecs.push_back(known_codec);
145 send_parameters_mixed.codecs.push_back(unknown_codec);
146 cricket::DataRecvParameters recv_parameters_mixed;
147 recv_parameters_mixed.codecs.push_back(known_codec);
148 recv_parameters_mixed.codecs.push_back(unknown_codec);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200150 EXPECT_TRUE(dmc->SetSendParameters(send_parameters_known));
151 EXPECT_FALSE(dmc->SetSendParameters(send_parameters_unknown));
152 EXPECT_TRUE(dmc->SetSendParameters(send_parameters_mixed));
153 EXPECT_TRUE(dmc->SetRecvParameters(recv_parameters_known));
154 EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_unknown));
155 EXPECT_FALSE(dmc->SetRecvParameters(recv_parameters_mixed));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156}
157
158TEST_F(RtpDataMediaChannelTest, AddRemoveSendStream) {
kwiberg686a8ef2016-02-26 03:00:35 -0800159 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160
161 cricket::StreamParams stream1;
162 stream1.add_ssrc(41);
163 EXPECT_TRUE(dmc->AddSendStream(stream1));
164 cricket::StreamParams stream2;
165 stream2.add_ssrc(42);
166 EXPECT_TRUE(dmc->AddSendStream(stream2));
167
168 EXPECT_TRUE(dmc->RemoveSendStream(41));
169 EXPECT_TRUE(dmc->RemoveSendStream(42));
170 EXPECT_FALSE(dmc->RemoveSendStream(43));
171}
172
173TEST_F(RtpDataMediaChannelTest, AddRemoveRecvStream) {
kwiberg686a8ef2016-02-26 03:00:35 -0800174 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175
176 cricket::StreamParams stream1;
177 stream1.add_ssrc(41);
178 EXPECT_TRUE(dmc->AddRecvStream(stream1));
179 cricket::StreamParams stream2;
180 stream2.add_ssrc(42);
181 EXPECT_TRUE(dmc->AddRecvStream(stream2));
182 EXPECT_FALSE(dmc->AddRecvStream(stream2));
183
184 EXPECT_TRUE(dmc->RemoveRecvStream(41));
185 EXPECT_TRUE(dmc->RemoveRecvStream(42));
186}
187
188TEST_F(RtpDataMediaChannelTest, SendData) {
kwiberg686a8ef2016-02-26 03:00:35 -0800189 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000190
191 cricket::SendDataParams params;
192 params.ssrc = 42;
193 unsigned char data[] = "food";
jbaucheec21bd2016-03-20 06:15:43 -0700194 rtc::CopyOnWriteBuffer payload(data, 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000195 unsigned char padded_data[] = {
Yves Gerey665174f2018-06-19 15:03:05 +0200196 0x00, 0x00, 0x00, 0x00, 'f', 'o', 'o', 'd',
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000197 };
198 cricket::SendDataResult result;
199
200 // Not sending
201 EXPECT_FALSE(dmc->SendData(params, payload, &result));
202 EXPECT_EQ(cricket::SDR_ERROR, result);
203 EXPECT_FALSE(HasSentData(0));
204 ASSERT_TRUE(dmc->SetSend(true));
205
206 // Unknown stream name.
207 EXPECT_FALSE(dmc->SendData(params, payload, &result));
208 EXPECT_EQ(cricket::SDR_ERROR, result);
209 EXPECT_FALSE(HasSentData(0));
210
211 cricket::StreamParams stream;
212 stream.add_ssrc(42);
213 ASSERT_TRUE(dmc->AddSendStream(stream));
214
215 // Unknown codec;
216 EXPECT_FALSE(dmc->SendData(params, payload, &result));
217 EXPECT_EQ(cricket::SDR_ERROR, result);
218 EXPECT_FALSE(HasSentData(0));
219
220 cricket::DataCodec codec;
221 codec.id = 103;
222 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200223 cricket::DataSendParameters parameters;
224 parameters.codecs.push_back(codec);
225 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000226
227 // Length too large;
228 std::string x10000(10000, 'x');
229 EXPECT_FALSE(dmc->SendData(
jbaucheec21bd2016-03-20 06:15:43 -0700230 params, rtc::CopyOnWriteBuffer(x10000.data(), x10000.length()), &result));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231 EXPECT_EQ(cricket::SDR_ERROR, result);
232 EXPECT_FALSE(HasSentData(0));
233
234 // Finally works!
235 EXPECT_TRUE(dmc->SendData(params, payload, &result));
236 EXPECT_EQ(cricket::SDR_SUCCESS, result);
237 ASSERT_TRUE(HasSentData(0));
238 EXPECT_EQ(sizeof(padded_data), GetSentData(0).length());
Yves Gerey665174f2018-06-19 15:03:05 +0200239 EXPECT_EQ(0, memcmp(padded_data, GetSentData(0).data(), sizeof(padded_data)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240 cricket::RtpHeader header0 = GetSentDataHeader(0);
241 EXPECT_NE(0, header0.seq_num);
242 EXPECT_NE(0U, header0.timestamp);
243 EXPECT_EQ(header0.ssrc, 42U);
244 EXPECT_EQ(header0.payload_type, 103);
245
246 // Should bump timestamp by 180000 because the clock rate is 90khz.
247 SetNow(2);
248
249 EXPECT_TRUE(dmc->SendData(params, payload, &result));
250 ASSERT_TRUE(HasSentData(1));
251 EXPECT_EQ(sizeof(padded_data), GetSentData(1).length());
Yves Gerey665174f2018-06-19 15:03:05 +0200252 EXPECT_EQ(0, memcmp(padded_data, GetSentData(1).data(), sizeof(padded_data)));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253 cricket::RtpHeader header1 = GetSentDataHeader(1);
254 EXPECT_EQ(header1.ssrc, 42U);
255 EXPECT_EQ(header1.payload_type, 103);
Peter Boström0c4e06b2015-10-07 12:23:21 +0200256 EXPECT_EQ(static_cast<uint16_t>(header0.seq_num + 1),
257 static_cast<uint16_t>(header1.seq_num));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000258 EXPECT_EQ(header0.timestamp + 180000, header1.timestamp);
259}
260
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000261TEST_F(RtpDataMediaChannelTest, SendDataRate) {
kwiberg686a8ef2016-02-26 03:00:35 -0800262 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000263
264 ASSERT_TRUE(dmc->SetSend(true));
265
266 cricket::DataCodec codec;
267 codec.id = 103;
268 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200269 cricket::DataSendParameters parameters;
270 parameters.codecs.push_back(codec);
271 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000272
273 cricket::StreamParams stream;
274 stream.add_ssrc(42);
275 ASSERT_TRUE(dmc->AddSendStream(stream));
276
277 cricket::SendDataParams params;
278 params.ssrc = 42;
279 unsigned char data[] = "food";
jbaucheec21bd2016-03-20 06:15:43 -0700280 rtc::CopyOnWriteBuffer payload(data, 4);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000281 cricket::SendDataResult result;
282
283 // With rtp overhead of 32 bytes, each one of our packets is 36
284 // bytes, or 288 bits. So, a limit of 872bps will allow 3 packets,
285 // but not four.
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200286 parameters.max_bandwidth_bps = 872;
287 ASSERT_TRUE(dmc->SetSendParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000288
289 EXPECT_TRUE(dmc->SendData(params, payload, &result));
290 EXPECT_TRUE(dmc->SendData(params, payload, &result));
291 EXPECT_TRUE(dmc->SendData(params, payload, &result));
292 EXPECT_FALSE(dmc->SendData(params, payload, &result));
293 EXPECT_FALSE(dmc->SendData(params, payload, &result));
294
295 SetNow(0.9);
296 EXPECT_FALSE(dmc->SendData(params, payload, &result));
297
298 SetNow(1.1);
299 EXPECT_TRUE(dmc->SendData(params, payload, &result));
300 EXPECT_TRUE(dmc->SendData(params, payload, &result));
301 SetNow(1.9);
302 EXPECT_TRUE(dmc->SendData(params, payload, &result));
303
304 SetNow(2.2);
305 EXPECT_TRUE(dmc->SendData(params, payload, &result));
306 EXPECT_TRUE(dmc->SendData(params, payload, &result));
307 EXPECT_TRUE(dmc->SendData(params, payload, &result));
308 EXPECT_FALSE(dmc->SendData(params, payload, &result));
309}
310
311TEST_F(RtpDataMediaChannelTest, ReceiveData) {
312 // PT= 103, SN=2, TS=3, SSRC = 4, data = "abcde"
Yves Gerey665174f2018-06-19 15:03:05 +0200313 unsigned char data[] = {0x80, 0x67, 0x00, 0x02, 0x00, 0x00, 0x00,
314 0x03, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00,
315 0x00, 0x00, 'a', 'b', 'c', 'd', 'e'};
jbaucheec21bd2016-03-20 06:15:43 -0700316 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000317
kwiberg686a8ef2016-02-26 03:00:35 -0800318 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000319
320 // SetReceived not called.
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700321 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000322 EXPECT_FALSE(HasReceivedData());
323
324 dmc->SetReceive(true);
325
326 // Unknown payload id
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700327 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 EXPECT_FALSE(HasReceivedData());
329
330 cricket::DataCodec codec;
331 codec.id = 103;
332 codec.name = cricket::kGoogleRtpDataCodecName;
Fredrik Solenbergb071a192015-09-17 16:42:56 +0200333 cricket::DataRecvParameters parameters;
334 parameters.codecs.push_back(codec);
335 ASSERT_TRUE(dmc->SetRecvParameters(parameters));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000336
337 // Unknown stream
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700338 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000339 EXPECT_FALSE(HasReceivedData());
340
341 cricket::StreamParams stream;
342 stream.add_ssrc(42);
343 ASSERT_TRUE(dmc->AddRecvStream(stream));
344
345 // Finally works!
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700346 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000347 EXPECT_TRUE(HasReceivedData());
348 EXPECT_EQ("abcde", GetReceivedData());
349 EXPECT_EQ(5U, GetReceivedDataLen());
350}
351
352TEST_F(RtpDataMediaChannelTest, InvalidRtpPackets) {
Yves Gerey665174f2018-06-19 15:03:05 +0200353 unsigned char data[] = {0x80, 0x65, 0x00, 0x02};
jbaucheec21bd2016-03-20 06:15:43 -0700354 rtc::CopyOnWriteBuffer packet(data, sizeof(data));
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000355
kwiberg686a8ef2016-02-26 03:00:35 -0800356 std::unique_ptr<cricket::RtpDataMediaChannel> dmc(CreateChannel());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000357
358 // Too short
Amit Hilbuche7a5f7b2019-03-12 11:10:27 -0700359 dmc->OnPacketReceived(packet, /* packet_time_us */ -1);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000360 EXPECT_FALSE(HasReceivedData());
361}