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/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; | |
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 FakeTransportChannel : public cricket::FakeTransportChannel { | |
pthatcher1
2016/03/01 22:46:52
Can you give it a different name to avoid confusti
mikescarlett
2016/03/02 02:34:19
Done.
| |
72 public: | |
73 FakeTransportChannel(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 FakeTransportChannel to simulate network connectivity and ICE negotiation. | |
94 class QuicTestPeer : public sigslot::has_slots<> { | |
95 public: | |
96 explicit QuicTestPeer(const std::string& name) | |
97 : name_(name), | |
98 bytes_sent_(0), | |
99 fake_channel_(name_, 0), | |
100 quic_channel_(&fake_channel_) { | |
101 quic_channel_.SignalReadPacket.connect( | |
102 this, &QuicTestPeer::OnTransportChannelReadPacket); | |
103 fake_channel_.SetAsync(true); | |
104 SetLocalCertificate(); | |
105 } | |
106 | |
107 // Connects |fake_channel_| to that of the other peer. | |
108 void Connect(QuicTestPeer* peer) { | |
109 fake_channel_.Connect(); | |
110 peer->fake_channel_.Connect(); | |
111 fake_channel_.SetDestination(&peer->fake_channel_); | |
112 } | |
113 | |
114 // Disconnects |fake_channel_|. | |
115 void Disconnect() { fake_channel_.SetDestination(nullptr); } | |
116 | |
117 // Simulates the fingerprint exchange and ICE parameter negotiation | |
118 // which is done before QUIC handshake is started. Peer certificates must be | |
119 // set first. | |
120 void NegotiateBeforeQuic(QuicTestPeer* peer, | |
pthatcher1
2016/03/01 22:46:52
It might be more clear to call it "remote_peer"
mikescarlett
2016/03/02 02:34:19
Done.
| |
121 IceRole ice_role, | |
pthatcher1
2016/03/01 22:46:52
Might as well call it local_ice_role to be clear.
mikescarlett
2016/03/02 02:34:19
Done.
| |
122 rtc::SSLRole local_ssl_role, | |
123 rtc::SSLRole remote_ssl_role) { | |
124 rtc::scoped_refptr<rtc::RTCCertificate> local_cert = | |
125 quic_channel()->GetLocalCertificate(); | |
126 ASSERT_TRUE(local_cert); | |
127 rtc::scoped_refptr<rtc::RTCCertificate> remote_cert = | |
128 peer->quic_channel()->GetLocalCertificate(); | |
129 ASSERT_TRUE(remote_cert); | |
130 // Create fingerprints from certificates. | |
131 rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint; | |
132 rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint; | |
133 local_fingerprint.reset(CreateFingerprint(local_cert.get())); | |
134 ASSERT_NE(local_fingerprint, nullptr); | |
135 remote_fingerprint.reset(CreateFingerprint(remote_cert.get())); | |
136 ASSERT_NE(remote_fingerprint, nullptr); | |
137 // Pass the ICE credentials to the underlying channel. | |
138 SetIceCredentials(ice_role, local_fingerprint.get(), | |
139 remote_fingerprint.get(), local_ssl_role, | |
140 remote_ssl_role); | |
141 // Set SSL and fingerprint parameters for QUIC channel. | |
142 quic_channel_.SetSslRole(local_ssl_role); | |
143 quic_channel_.SetRemoteFingerprint( | |
144 remote_fingerprint->algorithm, | |
145 reinterpret_cast<const uint8_t*>(remote_fingerprint->digest.data()), | |
146 remote_fingerprint->digest.size()); | |
147 } | |
148 | |
149 // Generates ICE credentials and passes them to |quic_channel_|. | |
150 void SetIceCredentials(IceRole ice_role, | |
151 rtc::SSLFingerprint* local_fingerprint, | |
152 rtc::SSLFingerprint* remote_fingerprint, | |
153 rtc::SSLRole local_ssl_role, | |
154 rtc::SSLRole remote_ssl_role) { | |
155 quic_channel_.SetIceRole(ice_role); | |
156 quic_channel_.SetIceTiebreaker( | |
157 (ice_role == cricket::ICEROLE_CONTROLLING) ? 1 : 2); | |
158 | |
159 ConnectionRole local_connection_role = | |
160 SslRoleToConnectionRole(local_ssl_role); | |
161 ConnectionRole remote_connection_role = | |
162 SslRoleToConnectionRole(remote_ssl_role); | |
163 | |
164 TransportDescription local_desc(std::vector<std::string>(), kIceUfrag, | |
165 kIcePwd, cricket::ICEMODE_FULL, | |
166 local_connection_role, local_fingerprint); | |
167 TransportDescription remote_desc( | |
168 std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL, | |
169 remote_connection_role, remote_fingerprint); | |
170 | |
171 quic_channel_.SetIceCredentials(local_desc.ice_ufrag, local_desc.ice_pwd); | |
172 quic_channel_.SetRemoteIceCredentials(remote_desc.ice_ufrag, | |
173 remote_desc.ice_pwd); | |
174 } | |
175 | |
176 // Sets certificate for |quic_channel_|. | |
177 void SetLocalCertificate() { | |
178 quic_channel_.SetLocalCertificate( | |
179 rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>( | |
180 rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT)))); | |
181 } | |
182 | |
183 // Creates fingerprint from certificate. | |
184 rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) { | |
185 std::string digest_algorithm; | |
186 bool get_digest_algorithm = | |
187 cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm); | |
188 if (!get_digest_algorithm || digest_algorithm.empty()) { | |
189 return nullptr; | |
190 } | |
191 scoped_ptr<rtc::SSLFingerprint> fingerprint( | |
192 rtc::SSLFingerprint::Create(digest_algorithm, cert->identity())); | |
193 if (digest_algorithm != rtc::DIGEST_SHA_256) { | |
194 return nullptr; | |
195 } | |
196 return fingerprint.release(); | |
197 } | |
198 | |
199 // Send packets to the other peer via |quic_channel_|. | |
200 void SendPackets(size_t count, bool srtp, bool expect_success) { | |
201 char packet[kPacketSize]; | |
202 for (size_t sent = 0; sent < count; ++sent) { | |
203 // If |srtp| is true, make this packet look like SRTP. | |
204 packet[0] = (srtp) ? 0x80 : 0x00; | |
205 // Set the bypass flag if we're sending SRTP. | |
206 int flags = srtp ? cricket::PF_SRTP_BYPASS : 0; | |
207 rtc::PacketOptions packet_options; | |
208 int rv = quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options, | |
209 flags); | |
210 if (rv > 0) { | |
211 ASSERT_TRUE(expect_success); | |
212 ASSERT_EQ(kPacketSize, static_cast<size_t>(rv)); | |
213 bytes_sent_ += rv; | |
214 } else { | |
215 ASSERT_FALSE(expect_success); | |
216 ASSERT_EQ(-1, rv); | |
217 } | |
218 } | |
219 } | |
220 | |
221 // Sends a non-SRTP packet with the PF_SRTP_BYPASS flag. | |
222 int SendInvalidSrtpPacket() { | |
223 char packet[kPacketSize]; | |
224 // Fill the packet with 0 to form an invalid SRTP packet. | |
225 memset(packet, 0, kPacketSize); | |
226 rtc::PacketOptions packet_options; | |
227 return quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options, | |
228 cricket::PF_SRTP_BYPASS); | |
229 } | |
230 | |
231 net::WriteResult WriteQuicPacket(std::string packet) { | |
232 return quic_channel_.WritePacket(packet.data(), packet.size(), kIpAddress, | |
233 kIpEndpoint); | |
234 } | |
235 | |
236 bool handshake_confirmed() const { | |
237 return quic_channel_.quic_state() == cricket::QUIC_TRANSPORT_CONNECTED; | |
238 } | |
239 | |
240 void ClearBytesSent() { bytes_sent_ = 0; } | |
241 | |
242 void ClearBytesReceived() { bytes_received_ = 0; } | |
243 | |
244 void SetWriteError(int error) { fake_channel_.SetError(error); } | |
245 | |
246 size_t bytes_received() const { return bytes_received_; } | |
247 | |
248 size_t bytes_sent() const { return bytes_sent_; } | |
249 | |
250 FakeTransportChannel* fake_channel() { return &fake_channel_; } | |
251 | |
252 QuicTransportChannel* quic_channel() { return &quic_channel_; } | |
253 | |
254 private: | |
255 // QUIC channel callback. | |
256 void OnTransportChannelReadPacket(TransportChannel* channel, | |
257 const char* data, | |
258 size_t size, | |
259 const rtc::PacketTime& packet_time, | |
260 int flags) { | |
261 bytes_received_ += size; | |
262 // Only SRTP packets should have the bypass flag set. | |
263 int expected_flags = IsRtpLeadByte(data[0]) ? cricket::PF_SRTP_BYPASS : 0; | |
264 ASSERT_EQ(expected_flags, flags); | |
265 } | |
266 | |
267 std::string name_; // Channel name. | |
268 size_t bytes_sent_; // Bytes sent by QUIC channel. | |
269 size_t bytes_received_; // Bytes received by fake channel. | |
270 FakeTransportChannel fake_channel_; | |
271 QuicTransportChannel quic_channel_; | |
272 }; | |
273 | |
274 class QuicTransportChannelTest : public testing::Test { | |
275 public: | |
276 QuicTransportChannelTest() : peer1_("P1"), peer2_("P2") {} | |
277 | |
278 // Performs negotiation before QUIC handshake, then connects the fake | |
279 // transport channels of each peer. As a side effect, the QUIC channels | |
280 // start sending handshake messages. | |
281 void Connect(rtc::SSLRole peer1_ssl_role, rtc::SSLRole peer2_ssl_role) { | |
282 ASSERT_NE(peer1_ssl_role, peer2_ssl_role); | |
283 NegotiateBeforeQuic(peer1_ssl_role, peer2_ssl_role); | |
284 peer1_.Connect(&peer2_); | |
285 } | |
286 | |
287 // By default, |peer1_| has client role and |peer2_| has server role in the | |
288 // QUIC handshake. | |
289 void Connect() { Connect(rtc::SSL_CLIENT, rtc::SSL_SERVER); } | |
290 | |
291 // Disconnects the fake transport channels. | |
292 void Disconnect() { | |
293 peer1_.Disconnect(); | |
294 peer2_.Disconnect(); | |
295 } | |
296 | |
297 // Sets up ICE parameters and exchanges fingerprints before QUIC handshake. | |
298 void NegotiateBeforeQuic(rtc::SSLRole peer1_ssl_role, | |
299 rtc::SSLRole peer2_ssl_role) { | |
300 peer1_.NegotiateBeforeQuic(&peer2_, cricket::ICEROLE_CONTROLLED, | |
301 peer1_ssl_role, peer2_ssl_role); | |
302 peer2_.NegotiateBeforeQuic(&peer1_, cricket::ICEROLE_CONTROLLING, | |
303 peer2_ssl_role, peer1_ssl_role); | |
304 } | |
305 | |
306 // Check whether |peer2_| receives packets sent by |peer1_|. | |
307 void TestTransfer(size_t count, bool srtp, bool expect_success) { | |
308 LOG(INFO) << "Expect packets, srtp=" << srtp | |
309 << ", success=" << expect_success; | |
310 peer1_.ClearBytesSent(); | |
311 peer2_.ClearBytesReceived(); | |
312 peer1_.SendPackets(count, srtp, expect_success); | |
313 | |
314 if (expect_success) { | |
315 size_t total_bytes = kPacketSize * count; | |
316 EXPECT_EQ_WAIT(total_bytes, peer2_.bytes_received(), kTimeoutMs); | |
317 EXPECT_EQ(total_bytes, peer1_.bytes_sent()); | |
318 } else { | |
319 EXPECT_EQ(0u, peer1_.bytes_sent()); | |
320 } | |
321 } | |
322 | |
323 // Check that non-SRTP is not sent with the SRTP_BYPASS flag. | |
324 void TestTransferInvalidSrtp() { | |
325 peer1_.ClearBytesSent(); | |
326 peer2_.ClearBytesReceived(); | |
327 EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket()); | |
328 EXPECT_EQ(0u, peer2_.bytes_received()); | |
329 } | |
330 | |
331 // Check that peers export identical keying material after the QUIC handshake. | |
332 void TestExportKeyingMaterial() { | |
333 uint8_t key1[kOutputKeyLength]; | |
334 uint8_t key2[kOutputKeyLength]; | |
335 | |
336 bool from_success = peer1_.quic_channel()->ExportKeyingMaterial( | |
337 kExporterLabel, kExporterContext, kExporterContextLength, true, key1, | |
338 kOutputKeyLength); | |
339 ASSERT_TRUE(from_success); | |
340 bool to_success = peer2_.quic_channel()->ExportKeyingMaterial( | |
341 kExporterLabel, kExporterContext, kExporterContextLength, true, key2, | |
342 kOutputKeyLength); | |
343 ASSERT_TRUE(to_success); | |
344 | |
345 EXPECT_EQ(0, memcmp(key1, key2, sizeof(key1))); | |
346 } | |
347 | |
348 // Checks if QUIC handshake is done. | |
349 bool handshake_confirmed() const { | |
350 return peer1_.handshake_confirmed() && peer2_.handshake_confirmed(); | |
351 } | |
352 | |
353 // Checks if QUIC channels are writable. | |
354 bool quic_writable() { | |
355 return peer1_.quic_channel()->writable() && | |
356 peer2_.quic_channel()->writable(); | |
357 } | |
358 | |
359 protected: | |
360 // QUIC peer with a client role, who initiates the QUIC handshake. | |
361 QuicTestPeer peer1_; | |
362 // QUIC peer with a server role, who responds to the client peer. | |
363 QuicTestPeer peer2_; | |
364 }; | |
365 | |
366 // Test that the QUIC channel passes down ICE parameters to the underlying ICE | |
367 // channel. | |
368 TEST_F(QuicTransportChannelTest, ChannelSetupIce) { | |
369 NegotiateBeforeQuic(rtc::SSL_CLIENT, rtc::SSL_SERVER); | |
370 FakeTransportChannel* channel1 = peer1_.fake_channel(); | |
371 FakeTransportChannel* channel2 = peer2_.fake_channel(); | |
372 EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole()); | |
373 EXPECT_EQ(2u, channel1->IceTiebreaker()); | |
374 EXPECT_EQ(kIceUfrag, channel1->ice_ufrag()); | |
375 EXPECT_EQ(kIcePwd, channel1->ice_pwd()); | |
376 EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole()); | |
377 EXPECT_EQ(1u, channel2->IceTiebreaker()); | |
378 } | |
379 | |
380 // Test export keying material after QUIC handshake. | |
381 TEST_F(QuicTransportChannelTest, ExportKeyingMaterial) { | |
382 Connect(); | |
383 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
384 TestExportKeyingMaterial(); | |
385 } | |
386 | |
387 // Test that QUIC channel is not writable before the QUIC handshake. | |
388 TEST_F(QuicTransportChannelTest, NotWritableBeforeHandshake) { | |
389 Connect(); | |
390 EXPECT_FALSE(quic_writable()); | |
391 Disconnect(); | |
392 EXPECT_FALSE(quic_writable()); | |
393 Connect(); | |
394 EXPECT_FALSE(quic_writable()); | |
395 } | |
396 | |
397 // Test that once handshake begins, QUIC is not writable until its completion. | |
398 TEST_F(QuicTransportChannelTest, QuicHandshake) { | |
399 Connect(); | |
400 EXPECT_FALSE(quic_writable()); | |
401 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
402 EXPECT_TRUE(quic_writable()); | |
403 } | |
404 | |
405 // Non-SRTP data should not be sent using SendPacket(), regardless of QUIC | |
406 // channel state. | |
407 TEST_F(QuicTransportChannelTest, TransferNonSrtp) { | |
408 TestTransfer(1, false, false); | |
409 TestTransfer(1, true, false); | |
410 Connect(); | |
411 TestTransfer(1, false, false); | |
412 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
413 TestTransfer(1, false, false); | |
414 } | |
415 | |
416 // SRTP data should always be sent, regardless of QUIC channel state. | |
417 TEST_F(QuicTransportChannelTest, TransferSrtp) { | |
418 Connect(); | |
419 TestTransfer(10, true, true); | |
420 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
421 TestTransfer(10, true, true); | |
422 } | |
423 | |
424 // Test that invalid SRTP (non-SRTP data with | |
425 // PF_SRTP_BYPASS flag) fails to send with return value -1. | |
426 TEST_F(QuicTransportChannelTest, TransferInvalidSrtp) { | |
427 TestTransferInvalidSrtp(); | |
428 Connect(); | |
429 TestTransferInvalidSrtp(); | |
430 } | |
431 | |
432 // Test QuicTransportChannel::WritePacket return values under various states | |
433 // of the wrapped channel. | |
434 TEST_F(QuicTransportChannelTest, QuicWritePacket) { | |
435 peer1_.fake_channel()->Connect(); | |
436 peer2_.fake_channel()->Connect(); | |
437 peer1_.fake_channel()->SetDestination(peer2_.fake_channel()); | |
438 | |
439 // Write blocked error. | |
440 peer1_.SetWriteError(EWOULDBLOCK); | |
441 std::string packet = "FAKEQUICPACKET"; | |
442 net::WriteResult write_blocked_result = peer1_.WriteQuicPacket(packet); | |
443 EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_blocked_result.status); | |
444 EXPECT_EQ(EWOULDBLOCK, write_blocked_result.error_code); | |
445 | |
446 // Errors other than write blocked. | |
447 peer1_.SetWriteError(ETIMEDOUT); | |
448 net::WriteResult write_error_result = peer1_.WriteQuicPacket(packet); | |
449 EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_error_result.status); | |
450 EXPECT_EQ(ETIMEDOUT, write_error_result.error_code); | |
451 | |
452 // No error. | |
453 peer1_.SetWriteError(kNoWriteError); | |
454 net::WriteResult no_error_result = peer1_.WriteQuicPacket(packet); | |
455 EXPECT_EQ(net::WRITE_STATUS_OK, no_error_result.status); | |
456 EXPECT_EQ(static_cast<int>(packet.size()), no_error_result.bytes_written); | |
457 } | |
458 | |
459 // Test that SSL roles can be reversed before QUIC handshake. | |
460 TEST_F(QuicTransportChannelTest, QuicRoleReversalBeforeQuic) { | |
461 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER)); | |
462 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT)); | |
463 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER)); | |
464 } | |
465 | |
466 // Test that SSL roles cannot be reversed after QUIC handshake. SetSslRole | |
467 // returns true if the current SSL role equals the proposed SSL role. | |
468 TEST_F(QuicTransportChannelTest, QuicRoleReversalAfterQuic) { | |
469 Connect(); | |
470 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
471 EXPECT_FALSE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER)); | |
472 EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT)); | |
473 EXPECT_FALSE(peer2_.quic_channel()->SetSslRole(rtc::SSL_CLIENT)); | |
474 EXPECT_TRUE(peer2_.quic_channel()->SetSslRole(rtc::SSL_SERVER)); | |
475 } | |
476 | |
477 // Set SSL role, then check that GetSslRole returns the same value. | |
478 TEST_F(QuicTransportChannelTest, SetGetSslRole) { | |
479 ASSERT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER)); | |
480 rtc::scoped_ptr<rtc::SSLRole> role(new rtc::SSLRole()); | |
481 ASSERT_TRUE(peer1_.quic_channel()->GetSslRole(role.get())); | |
482 EXPECT_EQ(rtc::SSL_SERVER, *role); | |
483 } | |
484 | |
485 // Test that after QUIC handshake is complete, QUIC handshake remains confirmed | |
486 // even if underlying channel reconnects. | |
487 TEST_F(QuicTransportChannelTest, HandshakeConfirmedAfterReconnect) { | |
488 Connect(); | |
489 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
490 Disconnect(); | |
491 EXPECT_TRUE(handshake_confirmed()); | |
492 Connect(); | |
493 EXPECT_TRUE(handshake_confirmed()); | |
494 } | |
495 | |
496 // Test that QUIC is able to resume a handshake if the channel becomes write | |
497 // blocked then writable again. | |
498 TEST_F(QuicTransportChannelTest, TestQuicCryptoStreamWriteBlocked) { | |
499 peer1_.SetWriteError(EWOULDBLOCK); | |
500 ASSERT_FALSE(peer1_.quic_channel()->HasDataToWrite()); | |
501 Connect(); | |
502 ASSERT_TRUE(peer1_.quic_channel()->HasDataToWrite()); | |
503 ASSERT_FALSE(handshake_confirmed()); | |
504 peer1_.SetWriteError(kNoWriteError); | |
505 peer1_.quic_channel()->OnCanWrite(); | |
506 ASSERT_FALSE(peer1_.quic_channel()->HasDataToWrite()); | |
507 ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs); | |
508 } | |
OLD | NEW |