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

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

Powered by Google App Engine
This is Rietveld 408576698