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

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

Powered by Google App Engine
This is Rietveld 408576698