OLD | NEW |
---|---|
(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 } | |
OLD | NEW |