Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(573)

Side by Side Diff: webrtc/api/quicdatachannel_unittest.cc

Issue 1844803002: Modify PeerConnection for end-to-end QuicDataChannel usage (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Remove webrtcsdp.cc from this CL Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright 2016 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 "webrtc/api/quicdatachannel.h"
12
13 #include <map>
14 #include <sstream>
15 #include <string>
16 #include <vector>
17
18 #include "webrtc/base/bind.h"
19 #include "webrtc/base/gunit.h"
20 #include "webrtc/base/scoped_ptr.h"
21 #include "webrtc/base/scoped_ref_ptr.h"
22 #include "webrtc/p2p/base/faketransportcontroller.h"
23 #include "webrtc/p2p/quic/quictransportchannel.h"
24 #include "webrtc/p2p/quic/reliablequicstream.h"
25
26 using cricket::FakeTransportChannel;
27 using cricket::QuicTransportChannel;
28 using cricket::ReliableQuicStream;
29
30 using webrtc::DataBuffer;
31 using webrtc::DataChannelObserver;
32 using webrtc::DataChannelInit;
33 using webrtc::QuicDataChannel;
34
35 namespace {
36
37 // Timeout for asynchronous operations.
38 static const int kTimeoutMs = 1000; // milliseconds
39
40 // Small messages that can be sent within a single QUIC packet.
41 static const std::string kSmallMessage1 = "Hello, world!";
42 static const std::string kSmallMessage2 = "WebRTC";
43 static const std::string kSmallMessage3 = "1";
44 static const std::string kSmallMessage4 = "abcdefghijklmnopqrstuvwxyz";
45 static const DataBuffer kSmallBuffer1(kSmallMessage1);
46 static const DataBuffer kSmallBuffer2(kSmallMessage2);
47 static const DataBuffer kSmallBuffer3(kSmallMessage3);
48 static const DataBuffer kSmallBuffer4(kSmallMessage4);
49
50 // Large messages (> 1350 bytes) that exceed the max size of a QUIC packet.
51 // These are < 16 KB so they don't exceed the QUIC stream flow control limit.
52 static const std::string kLargeMessage1 = std::string("a", 2000);
53 static const std::string kLargeMessage2 = std::string("a", 4000);
54 static const std::string kLargeMessage3 = std::string("a", 8000);
55 static const std::string kLargeMessage4 = std::string("a", 12000);
56 static const DataBuffer kLargeBuffer1(kLargeMessage1);
57 static const DataBuffer kLargeBuffer2(kLargeMessage2);
58 static const DataBuffer kLargeBuffer3(kLargeMessage3);
59 static const DataBuffer kLargeBuffer4(kLargeMessage4);
60
61 // Oversized message (> 16 KB) that violates the QUIC stream flow control limit.
62 static const std::string kOversizedMessage = std::string("a", 20000);
63 static const DataBuffer kOversizedBuffer(kOversizedMessage);
64
65 // FakeObserver receives messages from the QuicDataChannel.
66 class FakeObserver : public DataChannelObserver {
67 public:
68 FakeObserver()
69 : on_state_change_count_(0), on_buffered_amount_change_count_(0) {}
70
71 void OnStateChange() override { ++on_state_change_count_; }
72
73 void OnBufferedAmountChange(uint64_t previous_amount) override {
74 ++on_buffered_amount_change_count_;
75 }
76
77 void OnMessage(const webrtc::DataBuffer& buffer) override {
78 messages_.push_back(std::string(buffer.data.data<char>(), buffer.size()));
79 }
80
81 const std::vector<std::string>& messages() const { return messages_; }
82
83 size_t messages_received() const { return messages_.size(); }
84
85 size_t on_state_change_count() const { return on_state_change_count_; }
86
87 size_t on_buffered_amount_change_count() const {
88 return on_buffered_amount_change_count_;
89 }
90
91 private:
92 std::vector<std::string> messages_;
93 size_t on_state_change_count_;
94 size_t on_buffered_amount_change_count_;
95 };
96
97 // FakeQuicDataTransport simulates QuicDataTransport by dispatching QUIC
98 // stream messages to data channels and encoding/decoding messages.
99 class FakeQuicDataTransport : public QuicDataChannel::MessageHelper,
100 public sigslot::has_slots<> {
101 public:
102 explicit FakeQuicDataTransport(QuicTransportChannel* quic_transport_channel)
103 : quic_transport_channel_(quic_transport_channel) {
104 quic_transport_channel_->SignalIncomingStream.connect(
105 this, &FakeQuicDataTransport::OnIncomingStream);
106 }
107
108 QuicDataChannel* CreateDataChannel(int id,
109 const std::string& label,
110 const std::string& protocol) {
111 DataChannelInit config;
112 config.id = id;
113 config.protocol = protocol;
114 QuicDataChannel* data_channel = new QuicDataChannel(
115 rtc::Thread::Current(), rtc::Thread::Current(), label, &config, *this);
116 data_channel->SetTransportChannel(quic_transport_channel_);
117 data_channel_by_id_[id] = rtc::scoped_refptr<QuicDataChannel>(data_channel);
118 return data_channel;
119 }
120
121 void OnIncomingStream(cricket::ReliableQuicStream* stream) {
122 incoming_stream_ = stream;
123 incoming_stream_->SignalDataReceived.connect(
124 this, &FakeQuicDataTransport::OnDataReceived);
125 }
126
127 void Encode(const DataBuffer& message,
128 int data_channel_id,
129 uint64_t message_id,
130 rtc::CopyOnWriteBuffer* payload) const override {
131 std::ostringstream oss;
132 oss << data_channel_id << "\n";
133 oss << message_id << "\n";
134 oss << std::string(message.data.data<char>(), message.size());
135 std::string output = oss.str();
136 payload->SetData(output.data(), output.size());
137 }
138
139 private:
140 void OnDataReceived(net::QuicStreamId id, const char* data, size_t len) {
141 ASSERT_EQ(incoming_stream_->id(), id);
142 incoming_stream_->SignalDataReceived.disconnect(this);
143 int data_channel_id;
144 uint64_t message_id;
145 std::string first_bytes;
146 Decode(std::string(data, len), &data_channel_id, &message_id, &first_bytes);
147 const auto& kv = data_channel_by_id_.find(data_channel_id);
148 ASSERT_NE(kv, data_channel_by_id_.end());
149 QuicDataChannel* data_channel = kv->second;
150 Dispatch(data_channel, message_id, first_bytes.data(), first_bytes.size(),
151 incoming_stream_);
152 incoming_stream_ = nullptr;
153 }
154
155 void Decode(std::string input,
156 int* data_channel_id,
157 uint64_t* message_id,
158 std::string* first_bytes) {
159 std::istringstream iss(input);
160 std::string str;
161 std::getline(iss, str);
162 *data_channel_id = std::stoi(str);
163 std::getline(iss, str);
164 *message_id = std::stoul(str);
165 std::getline(iss, *first_bytes);
166 }
167
168 std::map<net::QuicStreamId, rtc::scoped_refptr<QuicDataChannel>>
169 data_channel_by_id_;
170 QuicTransportChannel* const quic_transport_channel_;
171 cricket::ReliableQuicStream* incoming_stream_ = nullptr;
172 };
173
174 // A peer who creates one or more QuicDataChannels to send or receive data.
175 class QuicDataChannelPeer {
176 public:
177 QuicDataChannelPeer()
178 : ice_transport_channel_("data", 0),
179 quic_transport_channel_(&ice_transport_channel_),
180 fake_quic_data_transport_(&quic_transport_channel_) {
181 ice_transport_channel_.SetAsync(true);
182 }
183
184 void GenerateCertificateAndFingerprint() {
185 rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
186 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
187 rtc::SSLIdentity::Generate("cert_name", rtc::KT_DEFAULT)));
188 quic_transport_channel_.SetLocalCertificate(local_cert);
189 local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
190 }
191
192 QuicDataChannel* CreateDataChannel(int id,
193 const std::string& label,
194 const std::string& protocol) {
195 return fake_quic_data_transport_.CreateDataChannel(id, label, protocol);
196 }
197
198 // Connects |ice_transport_channel_| to that of the other peer.
199 void Connect(QuicDataChannelPeer* other_peer) {
200 ice_transport_channel_.Connect();
201 other_peer->ice_transport_channel_.Connect();
202 ice_transport_channel_.SetDestination(&other_peer->ice_transport_channel_);
203 }
204
205 rtc::scoped_ptr<rtc::SSLFingerprint>& local_fingerprint() {
206 return local_fingerprint_;
207 }
208
209 QuicTransportChannel* quic_transport_channel() {
210 return &quic_transport_channel_;
211 }
212
213 private:
214 // Creates a fingerprint from a certificate.
215 rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
216 std::string digest_algorithm;
217 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
218 rtc::scoped_ptr<rtc::SSLFingerprint> fingerprint(
219 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
220 return fingerprint.release();
221 }
222
223 FakeTransportChannel ice_transport_channel_;
224 QuicTransportChannel quic_transport_channel_;
225
226 rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint_;
227
228 FakeQuicDataTransport fake_quic_data_transport_;
229 };
230
231 class QuicDataChannelTest : public testing::Test {
232 public:
233 QuicDataChannelTest() {}
234
235 // Connect the QuicTransportChannels and complete the crypto handshake.
236 void ConnectTransportChannels() {
237 SetCryptoParameters();
238 peer1_.Connect(&peer2_);
239 ASSERT_TRUE_WAIT(peer1_.quic_transport_channel()->writable() &&
240 peer2_.quic_transport_channel()->writable(),
241 kTimeoutMs);
242 }
243
244 // Sets crypto parameters required for the QUIC handshake.
245 void SetCryptoParameters() {
246 peer1_.GenerateCertificateAndFingerprint();
247 peer2_.GenerateCertificateAndFingerprint();
248
249 peer1_.quic_transport_channel()->SetSslRole(rtc::SSL_CLIENT);
250 peer2_.quic_transport_channel()->SetSslRole(rtc::SSL_SERVER);
251
252 rtc::scoped_ptr<rtc::SSLFingerprint>& peer1_fingerprint =
253 peer1_.local_fingerprint();
254 rtc::scoped_ptr<rtc::SSLFingerprint>& peer2_fingerprint =
255 peer2_.local_fingerprint();
256
257 peer1_.quic_transport_channel()->SetRemoteFingerprint(
258 peer2_fingerprint->algorithm,
259 reinterpret_cast<const uint8_t*>(peer2_fingerprint->digest.data()),
260 peer2_fingerprint->digest.size());
261 peer2_.quic_transport_channel()->SetRemoteFingerprint(
262 peer1_fingerprint->algorithm,
263 reinterpret_cast<const uint8_t*>(peer1_fingerprint->digest.data()),
264 peer1_fingerprint->digest.size());
265 }
266
267 protected:
268 QuicDataChannelPeer peer1_;
269 QuicDataChannelPeer peer2_;
270 };
271
272 // Test that QuicDataChannel transfers messages small enough to fit into a
273 // single QUIC stream frame.
274 TEST_F(QuicDataChannelTest, TransferSmallMessage) {
275 ConnectTransportChannels();
276 // Init data channels.
277 int data_channel_id = 2;
278 std::string label = "label";
279 std::string protocol = "protocol";
280 rtc::scoped_refptr<QuicDataChannel> peer1_data_channel =
281 peer1_.CreateDataChannel(data_channel_id, label, protocol);
282 ASSERT_TRUE(peer1_data_channel->state() ==
283 webrtc::DataChannelInterface::kOpen);
284 rtc::scoped_refptr<QuicDataChannel> peer2_data_channel =
285 peer2_.CreateDataChannel(data_channel_id, label, protocol);
286 ASSERT_TRUE(peer2_data_channel->state() ==
287 webrtc::DataChannelInterface::kOpen);
288 FakeObserver peer1_observer;
289 peer1_data_channel->RegisterObserver(&peer1_observer);
290 FakeObserver peer2_observer;
291 peer2_data_channel->RegisterObserver(&peer2_observer);
292 // peer1 -> peer2
293 ASSERT_TRUE(peer1_data_channel->Send(kSmallBuffer1));
294 ASSERT_TRUE_WAIT(peer2_observer.messages_received() == 1, kTimeoutMs);
295 EXPECT_EQ(kSmallMessage1, peer2_observer.messages()[0]);
296 // peer2 -> peer1
297 ASSERT_TRUE(peer2_data_channel->Send(kSmallBuffer2));
298 ASSERT_TRUE_WAIT(peer1_observer.messages_received() == 1, kTimeoutMs);
299 EXPECT_EQ(kSmallMessage2, peer1_observer.messages()[0]);
300 // peer2 -> peer1
301 ASSERT_TRUE(peer2_data_channel->Send(kSmallBuffer3));
302 ASSERT_TRUE_WAIT(peer1_observer.messages_received() == 2, kTimeoutMs);
303 EXPECT_EQ(kSmallMessage3, peer1_observer.messages()[1]);
304 // peer1 -> peer2
305 ASSERT_TRUE(peer1_data_channel->Send(kSmallBuffer4));
306 ASSERT_TRUE_WAIT(peer2_observer.messages_received() == 2, kTimeoutMs);
307 EXPECT_EQ(kSmallMessage4, peer2_observer.messages()[1]);
308 }
309
310 // Test that QuicDataChannel transfers messages large enough to fit into
311 // multiple QUIC stream frames, which don't violate the QUIC flow control limit.
312 // These require buffering by the QuicDataChannel.
313 TEST_F(QuicDataChannelTest, TransferLargeMessage) {
314 ConnectTransportChannels();
315 // Init data channels.
316 int data_channel_id = 347;
317 std::string label = "label";
318 std::string protocol = "protocol";
319 rtc::scoped_refptr<QuicDataChannel> peer1_data_channel =
320 peer1_.CreateDataChannel(data_channel_id, label, protocol);
321 ASSERT_TRUE(peer1_data_channel->state() ==
322 webrtc::DataChannelInterface::kOpen);
323 rtc::scoped_refptr<QuicDataChannel> peer2_data_channel =
324 peer2_.CreateDataChannel(data_channel_id, label, protocol);
325 ASSERT_TRUE(peer2_data_channel->state() ==
326 webrtc::DataChannelInterface::kOpen);
327 FakeObserver peer1_observer;
328 peer1_data_channel->RegisterObserver(&peer1_observer);
329 FakeObserver peer2_observer;
330 peer2_data_channel->RegisterObserver(&peer2_observer);
331 // peer1 -> peer2
332 ASSERT_TRUE(peer1_data_channel->Send(kLargeBuffer1));
333 ASSERT_TRUE_WAIT(peer2_observer.messages_received() == 1, kTimeoutMs);
334 EXPECT_EQ(kLargeMessage1, peer2_observer.messages()[0]);
335 // peer2 -> peer1
336 ASSERT_TRUE(peer2_data_channel->Send(kLargeBuffer2));
337 ASSERT_TRUE_WAIT(peer1_observer.messages_received() == 1, kTimeoutMs);
338 EXPECT_EQ(kLargeMessage2, peer1_observer.messages()[0]);
339 // peer2 -> peer1
340 ASSERT_TRUE(peer2_data_channel->Send(kLargeBuffer3));
341 ASSERT_TRUE_WAIT(peer1_observer.messages_received() == 2, kTimeoutMs);
342 EXPECT_EQ(kLargeMessage3, peer1_observer.messages()[1]);
343 // peer1 -> peer2
344 ASSERT_TRUE(peer1_data_channel->Send(kLargeBuffer4));
345 ASSERT_TRUE_WAIT(peer2_observer.messages_received() == 2, kTimeoutMs);
346 EXPECT_EQ(kLargeMessage4, peer2_observer.messages()[1]);
347 }
348
349 // Test that when a message size exceeds the flow control limit (> 16KB),
350 // QuicDataChannel becomes write blocked. The first 16KB are sent to the remote
351 // peer, while the remaining bytes are buffered until the remote peer sends a
352 // WINDOW_UPDATE frame.
353 TEST_F(QuicDataChannelTest, TransferOversizedMessage) {
354 ConnectTransportChannels();
355 int data_channel_id = 189;
356 std::string label = "label";
357 std::string protocol = "protocol";
358 rtc::scoped_refptr<QuicDataChannel> peer1_data_channel =
359 peer1_.CreateDataChannel(data_channel_id, label, protocol);
360 rtc::scoped_refptr<QuicDataChannel> peer2_data_channel =
361 peer2_.CreateDataChannel(data_channel_id, label, protocol);
362 FakeObserver peer1_observer;
363 peer1_data_channel->RegisterObserver(&peer1_observer);
364 FakeObserver peer2_observer;
365 peer2_data_channel->RegisterObserver(&peer2_observer);
366 ASSERT_TRUE(peer1_data_channel->Send(kOversizedBuffer));
367 EXPECT_EQ(1, peer1_observer.on_buffered_amount_change_count());
368 }
369
370 // Test that QuicDataChannel does not send before it is open.
371 TEST_F(QuicDataChannelTest, TransferDataBeforeChannelOpen) {
372 int data_channel_id = 6;
373 std::string label = "label";
374 std::string protocol = "protocol";
375 rtc::scoped_refptr<QuicDataChannel> data_channel =
376 peer1_.CreateDataChannel(data_channel_id, label, protocol);
377 ASSERT_TRUE(data_channel->state() ==
378 webrtc::DataChannelInterface::kConnecting);
379 EXPECT_FALSE(data_channel->Send(kSmallBuffer1));
380 }
381
382 // Test that QuicDataChannel does not send after it is closed.
383 TEST_F(QuicDataChannelTest, TransferDataAfterChannelClosed) {
384 int data_channel_id = 42;
385 std::string label = "label";
386 std::string protocol = "protocol";
387 rtc::scoped_refptr<QuicDataChannel> data_channel =
388 peer1_.CreateDataChannel(data_channel_id, label, protocol);
389 data_channel->Close();
390 ASSERT_TRUE(data_channel->state() == webrtc::DataChannelInterface::kClosed);
391 EXPECT_FALSE(data_channel->Send(kSmallBuffer1));
392 }
393
394 // If a message is empty, nothing is sent and QuicDataChannel returns true.
395 TEST_F(QuicDataChannelTest, TransferEmptyData) {
396 ConnectTransportChannels();
397 int data_channel_id = 69;
398 std::string label = "label";
399 std::string protocol = "protocol";
400 rtc::scoped_refptr<QuicDataChannel> data_channel =
401 peer1_.CreateDataChannel(data_channel_id, label, protocol);
402 ASSERT_TRUE(data_channel->state() == webrtc::DataChannelInterface::kOpen);
403 EXPECT_TRUE(data_channel->Send(DataBuffer("")));
404 }
405
406 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698