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

Side by Side Diff: webrtc/p2p/quic/quictransportchannel_unittest.cc

Issue 1721673004: Create QuicTransportChannel (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Update documentation before committing Created 4 years, 9 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
« no previous file with comments | « webrtc/p2p/quic/quictransportchannel.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/p2p/quic/quictransportchannel.h"
12
13 #include <set>
14 #include <string>
15 #include <vector>
16
17 #include "webrtc/base/common.h"
18 #include "webrtc/base/gunit.h"
19 #include "webrtc/base/scoped_ptr.h"
20 #include "webrtc/base/sslidentity.h"
21 #include "webrtc/p2p/base/faketransportcontroller.h"
22
23 using cricket::ConnectionRole;
24 using cricket::IceRole;
25 using cricket::QuicTransportChannel;
26 using cricket::TransportChannel;
27 using cricket::TransportDescription;
28
29 // Timeout in milliseconds for asynchronous operations in unit tests.
30 static const int kTimeoutMs = 1000;
31
32 // Export keying material parameters.
33 static const char kExporterLabel[] = "label";
34 static const uint8_t kExporterContext[] = "context";
35 static const size_t kExporterContextLength = sizeof(kExporterContext);
36 static const size_t kOutputKeyLength = 20;
37
38 // Packet size for SRTP.
39 static const size_t kPacketSize = 100;
40
41 // Indicates ICE channel has no write error.
42 static const int kNoWriteError = 0;
43
44 // ICE parameters.
45 static const char kIceUfrag[] = "TESTICEUFRAG0001";
46 static const char kIcePwd[] = "TESTICEPWD00000000000001";
47
48 // QUIC packet parameters.
49 static const net::IPAddressNumber kIpAddress(net::kIPv4AddressSize, 0);
50 static const net::IPEndPoint kIpEndpoint(kIpAddress, 0);
51
52 // Detects incoming RTP packets.
53 static bool IsRtpLeadByte(uint8_t b) {
54 return (b & 0xC0) == 0x80;
55 }
56
57 // Maps SSL role to ICE connection role. The peer with a client role is assumed
58 // to be the one who initiates the connection.
59 static ConnectionRole SslRoleToConnectionRole(rtc::SSLRole ssl_role) {
60 return (ssl_role == rtc::SSL_CLIENT) ? cricket::CONNECTIONROLE_ACTIVE
61 : cricket::CONNECTIONROLE_PASSIVE;
62 }
63
64 // Allows cricket::FakeTransportChannel to simulate write blocked
65 // and write error states.
66 // TODO(mikescarlett): Add this functionality to cricket::FakeTransportChannel.
67 class FailableTransportChannel : public cricket::FakeTransportChannel {
68 public:
69 FailableTransportChannel(const std::string& name, int component)
70 : cricket::FakeTransportChannel(name, component), error_(kNoWriteError) {}
71 int GetError() override { return error_; }
72 void SetError(int error) { error_ = error; }
73 int SendPacket(const char* data,
74 size_t len,
75 const rtc::PacketOptions& options,
76 int flags) override {
77 if (error_ == kNoWriteError) {
78 return cricket::FakeTransportChannel::SendPacket(data, len, options,
79 flags);
80 }
81 return -1;
82 }
83
84 private:
85 int error_;
86 };
87
88 // Peer who establishes a handshake using a QuicTransportChannel, which wraps
89 // a FailableTransportChannel to simulate network connectivity and ICE
90 // negotiation.
91 class QuicTestPeer : public sigslot::has_slots<> {
92 public:
93 explicit QuicTestPeer(const std::string& name)
94 : name_(name),
95 bytes_sent_(0),
96 ice_channel_(name_, 0),
97 quic_channel_(&ice_channel_) {
98 quic_channel_.SignalReadPacket.connect(
99 this, &QuicTestPeer::OnTransportChannelReadPacket);
100 ice_channel_.SetAsync(true);
101 rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
102 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
103 rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT)));
104 quic_channel_.SetLocalCertificate(local_cert);
105 local_fingerprint_.reset(CreateFingerprint(local_cert.get()));
106 }
107
108 // Connects |ice_channel_| to that of the other peer.
109 void Connect(QuicTestPeer* other_peer) {
110 ice_channel_.Connect();
111 other_peer->ice_channel_.Connect();
112 ice_channel_.SetDestination(&other_peer->ice_channel_);
113 }
114
115 // Disconnects |ice_channel_|.
116 void Disconnect() { ice_channel_.SetDestination(nullptr); }
117
118 // Generates ICE credentials and passes them to |quic_channel_|.
119 void SetIceParameters(IceRole local_ice_role,
120 ConnectionRole local_connection_role,
121 ConnectionRole remote_connection_role,
122 rtc::SSLFingerprint* remote_fingerprint) {
123 quic_channel_.SetIceRole(local_ice_role);
124 quic_channel_.SetIceTiebreaker(
125 (local_ice_role == cricket::ICEROLE_CONTROLLING) ? 1 : 2);
126
127 TransportDescription local_desc(
128 std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
129 local_connection_role, local_fingerprint_.get());
130 TransportDescription remote_desc(
131 std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
132 remote_connection_role, remote_fingerprint);
133
134 quic_channel_.SetIceCredentials(local_desc.ice_ufrag, local_desc.ice_pwd);
135 quic_channel_.SetRemoteIceCredentials(remote_desc.ice_ufrag,
136 remote_desc.ice_pwd);
137 }
138
139 // Creates fingerprint from certificate.
140 rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
141 std::string digest_algorithm;
142 bool get_digest_algorithm =
143 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
144 if (!get_digest_algorithm || digest_algorithm.empty()) {
145 return nullptr;
146 }
147 scoped_ptr<rtc::SSLFingerprint> fingerprint(
148 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
149 if (digest_algorithm != rtc::DIGEST_SHA_256) {
150 return nullptr;
151 }
152 return fingerprint.release();
153 }
154
155 // Sends SRTP packet to the other peer via |quic_channel_|.
156 int SendSrtpPacket() {
157 char packet[kPacketSize];
158 packet[0] = 0x80; // Make the packet header look like RTP.
159 int rv = quic_channel_.SendPacket(
160 &packet[0], kPacketSize, rtc::PacketOptions(), cricket::PF_SRTP_BYPASS);
161 bytes_sent_ += rv;
162 return rv;
163 }
164
165 // Sends a non-SRTP packet with the PF_SRTP_BYPASS flag via |quic_channel_|.
166 int SendInvalidSrtpPacket() {
167 char packet[kPacketSize];
168 // Fill the packet with 0 to form an invalid SRTP packet.
169 memset(packet, 0, kPacketSize);
170 return quic_channel_.SendPacket(
171 &packet[0], kPacketSize, rtc::PacketOptions(), cricket::PF_SRTP_BYPASS);
172 }
173
174 // Sends an RTP packet to the other peer via |quic_channel_|, without the SRTP
175 // bypass flag.
176 int SendRtpPacket() {
177 char packet[kPacketSize];
178 packet[0] = 0x80; // Make the packet header look like RTP.
179 return quic_channel_.SendPacket(&packet[0], kPacketSize,
180 rtc::PacketOptions(), 0);
181 }
182
183 void ClearBytesSent() { bytes_sent_ = 0; }
184
185 void ClearBytesReceived() { bytes_received_ = 0; }
186
187 void SetWriteError(int error) { ice_channel_.SetError(error); }
188
189 size_t bytes_received() const { return bytes_received_; }
190
191 size_t bytes_sent() const { return bytes_sent_; }
192
193 FailableTransportChannel* ice_channel() { return &ice_channel_; }
194
195 QuicTransportChannel* quic_channel() { return &quic_channel_; }
196
197 rtc::scoped_ptr<rtc::SSLFingerprint>& local_fingerprint() {
198 return local_fingerprint_;
199 }
200
201 private:
202 // QUIC channel callback.
203 void OnTransportChannelReadPacket(TransportChannel* channel,
204 const char* data,
205 size_t size,
206 const rtc::PacketTime& packet_time,
207 int flags) {
208 bytes_received_ += size;
209 // Only SRTP packets should have the bypass flag set.
210 int expected_flags = IsRtpLeadByte(data[0]) ? cricket::PF_SRTP_BYPASS : 0;
211 ASSERT_EQ(expected_flags, flags);
212 }
213
214 std::string name_; // Channel name.
215 size_t bytes_sent_; // Bytes sent by QUIC channel.
216 size_t bytes_received_; // Bytes received by QUIC channel.
217 FailableTransportChannel ice_channel_; // Simulates an ICE channel.
218 QuicTransportChannel quic_channel_; // QUIC channel to test.
219 rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint_;
220 };
221
222 class QuicTransportChannelTest : public testing::Test {
223 public:
224 QuicTransportChannelTest() : peer1_("P1"), peer2_("P2") {}
225
226 // Performs negotiation before QUIC handshake, then connects the fake
227 // transport channels of each peer. As a side effect, the QUIC channels
228 // start sending handshake messages. |peer1_| has a client role and |peer2_|
229 // has server role in the QUIC handshake.
230 void Connect() {
231 SetIceAndCryptoParameters(rtc::SSL_CLIENT, rtc::SSL_SERVER);
232 peer1_.Connect(&peer2_);
233 }
234
235 // Disconnects the fake transport channels.
236 void Disconnect() {
237 peer1_.Disconnect();
238 peer2_.Disconnect();
239 }
240
241 // Sets up ICE parameters and exchanges fingerprints before QUIC handshake.
242 void SetIceAndCryptoParameters(rtc::SSLRole peer1_ssl_role,
243 rtc::SSLRole peer2_ssl_role) {
244 peer1_.quic_channel()->SetSslRole(peer1_ssl_role);
245 peer2_.quic_channel()->SetSslRole(peer2_ssl_role);
246
247 rtc::scoped_ptr<rtc::SSLFingerprint>& peer1_fingerprint =
248 peer1_.local_fingerprint();
249 rtc::scoped_ptr<rtc::SSLFingerprint>& peer2_fingerprint =
250 peer2_.local_fingerprint();
251
252 peer1_.quic_channel()->SetRemoteFingerprint(
253 peer2_fingerprint->algorithm,
254 reinterpret_cast<const uint8_t*>(peer2_fingerprint->digest.data()),
255 peer2_fingerprint->digest.size());
256 peer2_.quic_channel()->SetRemoteFingerprint(
257 peer1_fingerprint->algorithm,
258 reinterpret_cast<const uint8_t*>(peer1_fingerprint->digest.data()),
259 peer1_fingerprint->digest.size());
260
261 ConnectionRole peer1_connection_role =
262 SslRoleToConnectionRole(peer1_ssl_role);
263 ConnectionRole peer2_connection_role =
264 SslRoleToConnectionRole(peer2_ssl_role);
265
266 peer1_.SetIceParameters(cricket::ICEROLE_CONTROLLED, peer1_connection_role,
267 peer2_connection_role, peer2_fingerprint.get());
268 peer2_.SetIceParameters(cricket::ICEROLE_CONTROLLING, peer2_connection_role,
269 peer1_connection_role, peer1_fingerprint.get());
270 }
271
272 // Checks if QUIC handshake is done.
273 bool quic_connected() {
274 return peer1_.quic_channel()->quic_state() ==
275 cricket::QUIC_TRANSPORT_CONNECTED &&
276 peer2_.quic_channel()->quic_state() ==
277 cricket::QUIC_TRANSPORT_CONNECTED;
278 }
279
280 // Checks if QUIC channels are writable.
281 bool quic_writable() {
282 return peer1_.quic_channel()->writable() &&
283 peer2_.quic_channel()->writable();
284 }
285
286 protected:
287 // QUIC peer with a client role, who initiates the QUIC handshake.
288 QuicTestPeer peer1_;
289 // QUIC peer with a server role, who responds to the client peer.
290 QuicTestPeer peer2_;
291 };
292
293 // Test that the QUIC channel passes ICE parameters to the underlying ICE
294 // channel.
295 TEST_F(QuicTransportChannelTest, ChannelSetupIce) {
296 SetIceAndCryptoParameters(rtc::SSL_CLIENT, rtc::SSL_SERVER);
297 FailableTransportChannel* channel1 = peer1_.ice_channel();
298 FailableTransportChannel* channel2 = peer2_.ice_channel();
299 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole());
300 EXPECT_EQ(2u, channel1->IceTiebreaker());
301 EXPECT_EQ(kIceUfrag, channel1->ice_ufrag());
302 EXPECT_EQ(kIcePwd, channel1->ice_pwd());
303 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
304 EXPECT_EQ(1u, channel2->IceTiebreaker());
305 }
306
307 // Test that export keying material generates identical keys for both peers
308 // after the QUIC handshake.
309 TEST_F(QuicTransportChannelTest, ExportKeyingMaterial) {
310 Connect();
311 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
312 uint8_t key1[kOutputKeyLength];
313 uint8_t key2[kOutputKeyLength];
314
315 bool from_success = peer1_.quic_channel()->ExportKeyingMaterial(
316 kExporterLabel, kExporterContext, kExporterContextLength, true, key1,
317 kOutputKeyLength);
318 ASSERT_TRUE(from_success);
319 bool to_success = peer2_.quic_channel()->ExportKeyingMaterial(
320 kExporterLabel, kExporterContext, kExporterContextLength, true, key2,
321 kOutputKeyLength);
322 ASSERT_TRUE(to_success);
323
324 EXPECT_EQ(0, memcmp(key1, key2, sizeof(key1)));
325 }
326
327 // Test that the QUIC channel is not writable before the QUIC handshake.
328 TEST_F(QuicTransportChannelTest, NotWritableBeforeHandshake) {
329 Connect();
330 EXPECT_FALSE(quic_writable());
331 Disconnect();
332 EXPECT_FALSE(quic_writable());
333 Connect();
334 EXPECT_FALSE(quic_writable());
335 }
336
337 // Test that once handshake begins, QUIC is not writable until its completion.
338 TEST_F(QuicTransportChannelTest, QuicHandshake) {
339 Connect();
340 EXPECT_FALSE(quic_writable());
341 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
342 EXPECT_TRUE(quic_writable());
343 }
344
345 // Test that Non-SRTP data is not sent using SendPacket(), regardless of QUIC
346 // channel state.
347 TEST_F(QuicTransportChannelTest, TransferNonSrtp) {
348 // Send data before ICE channel is connected.
349 peer1_.ClearBytesSent();
350 peer2_.ClearBytesReceived();
351 ASSERT_EQ(-1, peer1_.SendRtpPacket());
352 EXPECT_EQ(0u, peer1_.bytes_sent());
353 // Send data after ICE channel is connected, before QUIC handshake.
354 Connect();
355 peer1_.ClearBytesSent();
356 peer2_.ClearBytesReceived();
357 ASSERT_EQ(-1, peer1_.SendRtpPacket());
358 EXPECT_EQ(0u, peer1_.bytes_sent());
359 // Send data after QUIC handshake.
360 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
361 peer1_.ClearBytesSent();
362 peer2_.ClearBytesReceived();
363 ASSERT_EQ(-1, peer1_.SendRtpPacket());
364 EXPECT_EQ(0u, peer1_.bytes_sent());
365 }
366
367 // Test that SRTP data is always be sent, regardless of QUIC channel state, when
368 // the ICE channel is connected.
369 TEST_F(QuicTransportChannelTest, TransferSrtp) {
370 // Send data after ICE channel is connected, before QUIC handshake.
371 Connect();
372 peer1_.ClearBytesSent();
373 peer2_.ClearBytesReceived();
374 ASSERT_EQ(kPacketSize, static_cast<size_t>(peer1_.SendSrtpPacket()));
375 EXPECT_EQ_WAIT(kPacketSize, peer2_.bytes_received(), kTimeoutMs);
376 EXPECT_EQ(kPacketSize, peer1_.bytes_sent());
377 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
378 // Send data after QUIC handshake.
379 peer1_.ClearBytesSent();
380 peer2_.ClearBytesReceived();
381 ASSERT_EQ(kPacketSize, static_cast<size_t>(peer1_.SendSrtpPacket()));
382 EXPECT_EQ_WAIT(kPacketSize, peer2_.bytes_received(), kTimeoutMs);
383 EXPECT_EQ(kPacketSize, peer1_.bytes_sent());
384 }
385
386 // Test that invalid SRTP (non-SRTP data with
387 // PF_SRTP_BYPASS flag) fails to send with return value -1.
388 TEST_F(QuicTransportChannelTest, TransferInvalidSrtp) {
389 peer1_.ClearBytesSent();
390 peer2_.ClearBytesReceived();
391 EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
392 EXPECT_EQ(0u, peer2_.bytes_received());
393 Connect();
394 peer1_.ClearBytesSent();
395 peer2_.ClearBytesReceived();
396 EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
397 EXPECT_EQ(0u, peer2_.bytes_received());
398 }
399
400 // Test that QuicTransportChannel::WritePacket blocks when the ICE
401 // channel is not writable, and otherwise succeeds.
402 TEST_F(QuicTransportChannelTest, QuicWritePacket) {
403 peer1_.ice_channel()->Connect();
404 peer2_.ice_channel()->Connect();
405 peer1_.ice_channel()->SetDestination(peer2_.ice_channel());
406 std::string packet = "FAKEQUICPACKET";
407
408 // QUIC should be write blocked when the ICE channel is not writable.
409 peer1_.ice_channel()->SetWritable(false);
410 EXPECT_TRUE(peer1_.quic_channel()->IsWriteBlocked());
411 net::WriteResult write_blocked_result = peer1_.quic_channel()->WritePacket(
412 packet.data(), packet.size(), kIpAddress, kIpEndpoint);
413 EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_blocked_result.status);
414 EXPECT_EQ(EWOULDBLOCK, write_blocked_result.error_code);
415
416 // QUIC should ignore errors when the ICE channel is writable.
417 peer1_.ice_channel()->SetWritable(true);
418 EXPECT_FALSE(peer1_.quic_channel()->IsWriteBlocked());
419 peer1_.SetWriteError(EWOULDBLOCK);
420 net::WriteResult ignore_error_result = peer1_.quic_channel()->WritePacket(
421 packet.data(), packet.size(), kIpAddress, kIpEndpoint);
422 EXPECT_EQ(net::WRITE_STATUS_OK, ignore_error_result.status);
423 EXPECT_EQ(0, ignore_error_result.bytes_written);
424
425 peer1_.SetWriteError(kNoWriteError);
426 net::WriteResult no_error_result = peer1_.quic_channel()->WritePacket(
427 packet.data(), packet.size(), kIpAddress, kIpEndpoint);
428 EXPECT_EQ(net::WRITE_STATUS_OK, no_error_result.status);
429 EXPECT_EQ(static_cast<int>(packet.size()), no_error_result.bytes_written);
430 }
431
432 // Test that SSL roles can be reversed before QUIC handshake.
433 TEST_F(QuicTransportChannelTest, QuicRoleReversalBeforeQuic) {
434 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
435 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
436 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
437 }
438
439 // Test that SSL roles cannot be reversed after the QUIC handshake. SetSslRole
440 // returns true if the current SSL role equals the proposed SSL role.
441 TEST_F(QuicTransportChannelTest, QuicRoleReversalAfterQuic) {
442 Connect();
443 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
444 EXPECT_FALSE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
445 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
446 EXPECT_FALSE(peer2_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
447 EXPECT_TRUE(peer2_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
448 }
449
450 // Set the SSL role, then test that GetSslRole returns the same value.
451 TEST_F(QuicTransportChannelTest, SetGetSslRole) {
452 ASSERT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
453 rtc::scoped_ptr<rtc::SSLRole> role(new rtc::SSLRole());
454 ASSERT_TRUE(peer1_.quic_channel()->GetSslRole(role.get()));
455 EXPECT_EQ(rtc::SSL_SERVER, *role);
456 }
457
458 // Test that after the QUIC handshake is complete, the QUIC handshake remains
459 // confirmed even if the ICE channel reconnects.
460 TEST_F(QuicTransportChannelTest, HandshakeConfirmedAfterReconnect) {
461 Connect();
462 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
463 Disconnect();
464 EXPECT_TRUE(quic_connected());
465 Connect();
466 EXPECT_TRUE(quic_connected());
467 }
468
469 // Test that if the ICE channel becomes receiving after the QUIC channel is
470 // connected, then the QUIC channel becomes receiving.
471 TEST_F(QuicTransportChannelTest, IceReceivingAfterConnected) {
472 Connect();
473 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
474 ASSERT_FALSE(peer1_.ice_channel()->receiving());
475 EXPECT_FALSE(peer1_.quic_channel()->receiving());
476 peer1_.ice_channel()->SetReceiving(true);
477 EXPECT_TRUE(peer1_.quic_channel()->receiving());
478 }
479
480 // Test that if the ICE channel becomes receiving before the QUIC channel is
481 // connected, then the QUIC channel becomes receiving.
482 TEST_F(QuicTransportChannelTest, IceReceivingBeforeConnected) {
483 Connect();
484 peer1_.ice_channel()->SetReceiving(true);
485 ASSERT_TRUE(peer1_.ice_channel()->receiving());
486 ASSERT_TRUE_WAIT(quic_connected(), kTimeoutMs);
487 EXPECT_TRUE(peer1_.quic_channel()->receiving());
488 }
OLDNEW
« no previous file with comments | « webrtc/p2p/quic/quictransportchannel.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698