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

Unified Diff: webrtc/p2p/quic/quictransportchannel_unittest.cc

Issue 1721673004: Create QuicTransportChannel (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Modify WritePacket() and respond to comments Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/p2p/quic/quictransportchannel.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/p2p/quic/quictransportchannel_unittest.cc
diff --git a/webrtc/p2p/quic/quictransportchannel_unittest.cc b/webrtc/p2p/quic/quictransportchannel_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..0165ebbc6a35b2c4c1ec38edc6b26faca6aed14a
--- /dev/null
+++ b/webrtc/p2p/quic/quictransportchannel_unittest.cc
@@ -0,0 +1,494 @@
+/*
+ * Copyright 2016 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/p2p/quic/quictransportchannel.h"
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "webrtc/base/common.h"
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/scoped_ptr.h"
+#include "webrtc/base/sslidentity.h"
+#include "webrtc/p2p/base/faketransportcontroller.h"
+
+using cricket::ConnectionRole;
+using cricket::IceRole;
+using cricket::QuicTransportChannel;
+using cricket::TransportChannel;
+using cricket::TransportDescription;
+
+// Timeout in milliseconds for asynchronous operations in unit tests.
+const int kTimeoutMs = 1000;
+
+// Export keying material parameters.
+const char kExporterLabel[] = "label";
+const uint8_t kExporterContext[] = "context";
+const size_t kExporterContextLength = sizeof(kExporterContext);
+const size_t kOutputKeyLength = 20;
+
+// Packet size for SRTP.
+const size_t kPacketSize = 100;
+
+// Indicates channel has no write error.
+const int kNoWriteError = 0;
+
+// ICE parameters.
+const char kIceUfrag[] = "TESTICEUFRAG0001";
+const char kIcePwd[] = "TESTICEPWD00000000000001";
+
+// QUIC packet parameters.
+const net::IPAddressNumber kIpAddress(net::kIPv4AddressSize, 0);
+const net::IPEndPoint kIpEndpoint(kIpAddress, 0);
+
+// Detects incoming RTP packets.
+bool IsRtpLeadByte(uint8_t b) {
+ return (b & 0xC0) == 0x80;
+}
+// Detects incoming QUIC packets.
+bool IsQuicLeadByte(uint8_t b) {
+ return (b & 0x80) == 0;
+}
+
+// Maps SSL role to ICE connection role. The peer with a client role is assumed
+// to be the one who initiates the connection.
+ConnectionRole SslRoleToConnectionRole(rtc::SSLRole ssl_role) {
+ return (ssl_role == rtc::SSL_CLIENT) ? cricket::CONNECTIONROLE_ACTIVE
+ : cricket::CONNECTIONROLE_PASSIVE;
+}
+
+// Allows cricket::FakeTransportChannel to simulate write blocked
+// and write error states.
+// TODO(mikescarlett): Add this functionality to cricket::FakeTransportChannel.
+class FakeTransportChannel : public cricket::FakeTransportChannel {
+ public:
+ FakeTransportChannel(const std::string& name, int component)
+ : cricket::FakeTransportChannel(name, component), error_(kNoWriteError) {}
+ int GetError() override { return error_; }
+ void SetError(int error) { error_ = error; }
+ int SendPacket(const char* data,
+ size_t len,
+ const rtc::PacketOptions& options,
+ int flags) override {
+ if (error_ == kNoWriteError) {
+ return cricket::FakeTransportChannel::SendPacket(data, len, options,
+ flags);
+ }
+ return -1;
+ }
+
+ private:
+ int error_;
+};
+
+// Peer who establishes a handshake using a QuicTransportChannel, which wraps
+// a FakeTransportChannel to simulate network connectivity and ICE negotiation.
+class QuicTestPeer : public sigslot::has_slots<> {
+ public:
+ explicit QuicTestPeer(const std::string& name)
+ : name_(name),
+ bytes_sent_(0),
+ fake_channel_(name_, 0),
+ quic_channel_(&fake_channel_) {
+ quic_channel_.SignalReadPacket.connect(
+ this, &QuicTestPeer::OnTransportChannelReadPacket);
+ fake_channel_.SetAsync(true);
+ SetLocalCertificate();
+ }
+
+ // Connects |fake_channel_| to that of the other peer.
+ void Connect(QuicTestPeer* peer) {
+ fake_channel_.Connect();
+ peer->fake_channel_.Connect();
+ fake_channel_.SetDestination(&peer->fake_channel_);
+ }
+
+ // Disconnects |fake_channel_|.
+ void Disconnect() { fake_channel_.SetDestination(nullptr); }
+
+ // Simulates the fingerprint exchange and ICE parameter negotiation
+ // which is done before QUIC handshake is started. Peer certificates must be
+ // set first.
+ void NegotiateBeforeQuic(QuicTestPeer* peer,
+ IceRole ice_role,
+ rtc::SSLRole local_ssl_role,
+ rtc::SSLRole remote_ssl_role) {
pthatcher1 2016/03/01 22:46:52 Should this be called SetIceAndCryptoParameters?
mikescarlett 2016/03/02 02:34:19 I moved the crypto-related stuff outside and put I
+ rtc::scoped_refptr<rtc::RTCCertificate> local_cert =
+ quic_channel()->GetLocalCertificate();
+ ASSERT_TRUE(local_cert);
+ rtc::scoped_refptr<rtc::RTCCertificate> remote_cert =
+ peer->quic_channel()->GetLocalCertificate();
+ ASSERT_TRUE(remote_cert);
+ // Create fingerprints from certificates.
+ rtc::scoped_ptr<rtc::SSLFingerprint> local_fingerprint;
+ rtc::scoped_ptr<rtc::SSLFingerprint> remote_fingerprint;
+ local_fingerprint.reset(CreateFingerprint(local_cert.get()));
+ ASSERT_NE(local_fingerprint, nullptr);
+ remote_fingerprint.reset(CreateFingerprint(remote_cert.get()));
+ ASSERT_NE(remote_fingerprint, nullptr);
+ // Pass the ICE credentials to the underlying channel.
+ SetIceCredentials(ice_role, local_fingerprint.get(),
+ remote_fingerprint.get(), local_ssl_role,
+ remote_ssl_role);
+ // Set SSL and fingerprint parameters for QUIC channel.
+ quic_channel_.SetSslRole(local_ssl_role);
+ quic_channel_.SetRemoteFingerprint(
+ remote_fingerprint->algorithm,
+ reinterpret_cast<const uint8_t*>(remote_fingerprint->digest.data()),
+ remote_fingerprint->digest.size());
+ }
+
+ // Generates ICE credentials and passes them to |quic_channel_|.
+ void SetIceCredentials(IceRole ice_role,
pthatcher1 2016/03/01 22:46:52 Since this is only called once, I'd suggest just i
mikescarlett 2016/03/02 02:34:19 I merged them into SetIceParameters.
+ rtc::SSLFingerprint* local_fingerprint,
+ rtc::SSLFingerprint* remote_fingerprint,
+ rtc::SSLRole local_ssl_role,
+ rtc::SSLRole remote_ssl_role) {
+ quic_channel_.SetIceRole(ice_role);
+ quic_channel_.SetIceTiebreaker(
+ (ice_role == cricket::ICEROLE_CONTROLLING) ? 1 : 2);
+
+ ConnectionRole local_connection_role =
+ SslRoleToConnectionRole(local_ssl_role);
+ ConnectionRole remote_connection_role =
+ SslRoleToConnectionRole(remote_ssl_role);
+
+ TransportDescription local_desc(std::vector<std::string>(), kIceUfrag,
+ kIcePwd, cricket::ICEMODE_FULL,
+ local_connection_role, local_fingerprint);
+ TransportDescription remote_desc(
+ std::vector<std::string>(), kIceUfrag, kIcePwd, cricket::ICEMODE_FULL,
+ remote_connection_role, remote_fingerprint);
+
+ quic_channel_.SetIceCredentials(local_desc.ice_ufrag, local_desc.ice_pwd);
+ quic_channel_.SetRemoteIceCredentials(remote_desc.ice_ufrag,
+ remote_desc.ice_pwd);
+ }
+
+ // Sets certificate for |quic_channel_|.
+ void SetLocalCertificate() {
+ quic_channel_.SetLocalCertificate(
+ rtc::RTCCertificate::Create(rtc::scoped_ptr<rtc::SSLIdentity>(
+ rtc::SSLIdentity::Generate(name_, rtc::KT_DEFAULT))));
+ }
+
+ // Creates fingerprint from certificate.
+ rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) {
+ std::string digest_algorithm;
+ bool get_digest_algorithm =
+ cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm);
+ if (!get_digest_algorithm || digest_algorithm.empty()) {
+ return nullptr;
+ }
+ scoped_ptr<rtc::SSLFingerprint> fingerprint(
+ rtc::SSLFingerprint::Create(digest_algorithm, cert->identity()));
+ if (digest_algorithm != rtc::DIGEST_SHA_256) {
+ return nullptr;
+ }
+ return fingerprint.release();
+ }
+
+ // Send packets to the other peer via |quic_channel_|.
+ void SendPackets(size_t count, bool srtp, bool expect_success) {
pthatcher1 2016/03/01 22:46:52 This method is only called once, so it seems like
mikescarlett 2016/03/02 02:34:19 Done. Split this and moved asserts like you sugges
+ char packet[kPacketSize];
+ for (size_t sent = 0; sent < count; ++sent) {
+ // If |srtp| is true, make this packet look like SRTP.
+ packet[0] = (srtp) ? 0x80 : 0x00;
+ // Set the bypass flag if we're sending SRTP.
+ int flags = srtp ? cricket::PF_SRTP_BYPASS : 0;
+ rtc::PacketOptions packet_options;
+ int rv = quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options,
+ flags);
+ if (rv > 0) {
+ ASSERT_TRUE(expect_success);
+ ASSERT_EQ(kPacketSize, static_cast<size_t>(rv));
+ bytes_sent_ += rv;
+ } else {
+ ASSERT_FALSE(expect_success);
+ ASSERT_EQ(-1, rv);
+ }
+ }
+ }
+
+ // Sends a non-SRTP packet with the PF_SRTP_BYPASS flag.
+ int SendInvalidSrtpPacket() {
pthatcher1 2016/03/01 22:46:52 Ah, well now it looks like you should have three m
mikescarlett 2016/03/02 02:34:19 Done.
+ char packet[kPacketSize];
+ // Fill the packet with 0 to form an invalid SRTP packet.
+ memset(packet, 0, kPacketSize);
+ rtc::PacketOptions packet_options;
+ return quic_channel_.SendPacket(&packet[0], kPacketSize, packet_options,
+ cricket::PF_SRTP_BYPASS);
+ }
+
+ net::WriteResult WriteQuicPacket(std::string packet) {
+ return quic_channel_.WritePacket(packet.data(), packet.size(), kIpAddress,
+ kIpEndpoint);
+ }
+
+ bool handshake_confirmed() const {
pthatcher1 2016/03/01 22:46:52 Would a more correct name be quic_connected()?
mikescarlett 2016/03/02 02:34:19 That's fine. Done.
+ return quic_channel_.quic_state() == cricket::QUIC_TRANSPORT_CONNECTED;
+ }
+
+ void ClearBytesSent() { bytes_sent_ = 0; }
+
+ void ClearBytesReceived() { bytes_received_ = 0; }
+
+ void SetWriteError(int error) { fake_channel_.SetError(error); }
+
+ size_t bytes_received() const { return bytes_received_; }
+
+ size_t bytes_sent() const { return bytes_sent_; }
+
+ FakeTransportChannel* fake_channel() { return &fake_channel_; }
pthatcher1 2016/03/01 22:46:52 I would call this ice_channel(), even though it's
mikescarlett 2016/03/02 02:34:19 Done.
+
+ QuicTransportChannel* quic_channel() { return &quic_channel_; }
+
+ private:
+ // QUIC channel callback.
+ void OnTransportChannelReadPacket(TransportChannel* channel,
+ const char* data,
+ size_t size,
+ const rtc::PacketTime& packet_time,
+ int flags) {
+ bytes_received_ += size;
+ // Only SRTP packets should have the bypass flag set.
+ int expected_flags = IsRtpLeadByte(data[0]) ? cricket::PF_SRTP_BYPASS : 0;
+ ASSERT_EQ(expected_flags, flags);
+ }
+
+ std::string name_; // Channel name.
+ size_t bytes_sent_; // Bytes sent by QUIC channel.
+ size_t bytes_received_; // Bytes received by fake channel.
+ FakeTransportChannel fake_channel_;
+ QuicTransportChannel quic_channel_;
+};
+
+class QuicTransportChannelTest : public testing::Test {
+ public:
+ QuicTransportChannelTest() : peer1_("P1"), peer2_("P2") {}
+
+ // Performs negotiation before QUIC handshake, then connects the fake
+ // transport channels of each peer. As a side effect, the QUIC channels
+ // start sending handshake messages.
+ void Connect(rtc::SSLRole peer1_ssl_role, rtc::SSLRole peer2_ssl_role) {
+ ASSERT_NE(peer1_ssl_role, peer2_ssl_role);
+ NegotiateBeforeQuic(peer1_ssl_role, peer2_ssl_role);
+ peer1_.Connect(&peer2_);
+ }
+
+ // By default, |peer1_| has client role and |peer2_| has server role in the
+ // QUIC handshake.
+ void Connect() { Connect(rtc::SSL_CLIENT, rtc::SSL_SERVER); }
+
+ // Disconnects the fake transport channels.
+ void Disconnect() {
+ peer1_.Disconnect();
+ peer2_.Disconnect();
+ }
+
+ // Sets up ICE parameters and exchanges fingerprints before QUIC handshake.
+ void NegotiateBeforeQuic(rtc::SSLRole peer1_ssl_role,
+ rtc::SSLRole peer2_ssl_role) {
+ peer1_.NegotiateBeforeQuic(&peer2_, cricket::ICEROLE_CONTROLLED,
+ peer1_ssl_role, peer2_ssl_role);
+ peer2_.NegotiateBeforeQuic(&peer1_, cricket::ICEROLE_CONTROLLING,
+ peer2_ssl_role, peer1_ssl_role);
+ }
pthatcher1 2016/03/01 22:46:52 You have 4 methods that basically do a given opera
mikescarlett 2016/03/02 02:34:19 I merged this into one method and will revisit whe
+
+ // Check whether |peer2_| receives packets sent by |peer1_|.
+ void TestTransfer(size_t count, bool srtp, bool expect_success) {
pthatcher1 2016/03/01 22:46:52 I'd suggest to just inline this code into the test
mikescarlett 2016/03/02 02:34:19 Inlined.
+ peer1_.ClearBytesSent();
+ peer2_.ClearBytesReceived();
+ peer1_.SendPackets(count, srtp, expect_success);
+
+ if (expect_success) {
+ size_t total_bytes = kPacketSize * count;
+ EXPECT_EQ_WAIT(total_bytes, peer2_.bytes_received(), kTimeoutMs);
+ EXPECT_EQ(total_bytes, peer1_.bytes_sent());
+ } else {
+ EXPECT_EQ(0u, peer1_.bytes_sent());
+ }
+ }
+
+ // Check that non-SRTP is not sent with the SRTP_BYPASS flag.
+ void TestTransferInvalidSrtp() {
+ peer1_.ClearBytesSent();
+ peer2_.ClearBytesReceived();
+ EXPECT_EQ(-1, peer1_.SendInvalidSrtpPacket());
+ EXPECT_EQ(0u, peer2_.bytes_received());
+ }
+
+ // Check that peers export identical keying material after the QUIC handshake.
+ void TestExportKeyingMaterial() {
pthatcher1 2016/03/01 22:46:52 Same here: Just put this in the test case.
mikescarlett 2016/03/02 02:34:19 Inlined.
+ uint8_t key1[kOutputKeyLength];
+ uint8_t key2[kOutputKeyLength];
+
+ bool from_success = peer1_.quic_channel()->ExportKeyingMaterial(
+ kExporterLabel, kExporterContext, kExporterContextLength, true, key1,
+ kOutputKeyLength);
+ ASSERT_TRUE(from_success);
+ bool to_success = peer2_.quic_channel()->ExportKeyingMaterial(
+ kExporterLabel, kExporterContext, kExporterContextLength, true, key2,
+ kOutputKeyLength);
+ ASSERT_TRUE(to_success);
+
+ EXPECT_EQ(0, memcmp(key1, key2, sizeof(key1)));
+ }
+
+ // Checks if QUIC handshake is done.
+ bool handshake_confirmed() const {
+ return peer1_.handshake_confirmed() && peer2_.handshake_confirmed();
+ }
+
+ // Checks if QUIC channels are writable.
+ bool quic_writable() {
+ return peer1_.quic_channel()->writable() &&
+ peer2_.quic_channel()->writable();
+ }
+
+ protected:
+ // QUIC peer with a client role, who initiates the QUIC handshake.
+ QuicTestPeer peer1_;
+ // QUIC peer with a server role, who responds to the client peer.
+ QuicTestPeer peer2_;
+};
+
+// Test that the QUIC channel passes down ICE parameters to the underlying ICE
+// channel.
+TEST_F(QuicTransportChannelTest, ChannelSetupIce) {
+ NegotiateBeforeQuic(rtc::SSL_CLIENT, rtc::SSL_SERVER);
+ FakeTransportChannel* channel1 = peer1_.fake_channel();
+ FakeTransportChannel* channel2 = peer2_.fake_channel();
+ EXPECT_EQ(cricket::ICEROLE_CONTROLLED, channel1->GetIceRole());
+ EXPECT_EQ(2u, channel1->IceTiebreaker());
+ EXPECT_EQ(kIceUfrag, channel1->ice_ufrag());
+ EXPECT_EQ(kIcePwd, channel1->ice_pwd());
+ EXPECT_EQ(cricket::ICEROLE_CONTROLLING, channel2->GetIceRole());
+ EXPECT_EQ(1u, channel2->IceTiebreaker());
+}
+
+// Test export keying material after QUIC handshake.
+TEST_F(QuicTransportChannelTest, ExportKeyingMaterial) {
+ Connect();
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ TestExportKeyingMaterial();
+}
+
+// Test that QUIC channel is not writable before the QUIC handshake.
+TEST_F(QuicTransportChannelTest, NotWritableBeforeHandshake) {
+ Connect();
+ EXPECT_FALSE(quic_writable());
+ Disconnect();
+ EXPECT_FALSE(quic_writable());
+ Connect();
+ EXPECT_FALSE(quic_writable());
+}
+
+// Test that once handshake begins, QUIC is not writable until its completion.
+TEST_F(QuicTransportChannelTest, QuicHandshake) {
+ Connect();
+ EXPECT_FALSE(quic_writable());
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ EXPECT_TRUE(quic_writable());
+}
+
+// Non-SRTP data should not be sent using SendPacket(), regardless of QUIC
+// channel state.
+TEST_F(QuicTransportChannelTest, TransferNonSrtp) {
+ TestTransfer(1, false, false);
+ TestTransfer(1, true, false);
+ Connect();
+ TestTransfer(1, false, false);
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ TestTransfer(1, false, false);
+}
+
+// SRTP data should always be sent, regardless of QUIC channel state.
+TEST_F(QuicTransportChannelTest, TransferSrtp) {
+ Connect();
+ TestTransfer(10, true, true);
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ TestTransfer(10, true, true);
+}
+
+// Test that invalid SRTP (non-SRTP data with
+// PF_SRTP_BYPASS flag) fails to send with return value -1.
+TEST_F(QuicTransportChannelTest, TransferInvalidSrtp) {
+ TestTransferInvalidSrtp();
+ Connect();
+ TestTransferInvalidSrtp();
+}
+
+// Test that QuicTransportChannel::WritePacket blocks when underlying channel
pthatcher1 2016/03/01 22:46:52 when underlying => when the underlying
mikescarlett 2016/03/02 02:34:19 Done.
+// is not writable, and otherwise succeeds.
+TEST_F(QuicTransportChannelTest, QuicWritePacket) {
+ peer1_.fake_channel()->Connect();
+ peer2_.fake_channel()->Connect();
+ peer1_.fake_channel()->SetDestination(peer2_.fake_channel());
+ std::string packet = "FAKEQUICPACKET";
+
+ // QUIC should be write blocked when the underlying channel is not writable.
+ peer1_.fake_channel()->SetWritable(false);
+ EXPECT_TRUE(peer1_.quic_channel()->IsWriteBlocked());
+ net::WriteResult write_blocked_result = peer1_.WriteQuicPacket(packet);
+ EXPECT_EQ(net::WRITE_STATUS_BLOCKED, write_blocked_result.status);
+ EXPECT_EQ(EWOULDBLOCK, write_blocked_result.error_code);
+
+ // QUIC should ignore errors when the underlying channel is writable.
+ peer1_.fake_channel()->SetWritable(true);
+ EXPECT_FALSE(peer1_.quic_channel()->IsWriteBlocked());
+ peer1_.SetWriteError(EWOULDBLOCK);
+ net::WriteResult ignore_error_result = peer1_.WriteQuicPacket(packet);
+ EXPECT_EQ(net::WRITE_STATUS_OK, ignore_error_result.status);
+ EXPECT_EQ(0, ignore_error_result.bytes_written);
+
+ peer1_.SetWriteError(kNoWriteError);
+ net::WriteResult no_error_result = peer1_.WriteQuicPacket(packet);
+ EXPECT_EQ(net::WRITE_STATUS_OK, no_error_result.status);
+ EXPECT_EQ(static_cast<int>(packet.size()), no_error_result.bytes_written);
+}
+
+// Test that SSL roles can be reversed before QUIC handshake.
+TEST_F(QuicTransportChannelTest, QuicRoleReversalBeforeQuic) {
+ EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
+ EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
+ EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
+}
+
+// Test that SSL roles cannot be reversed after QUIC handshake. SetSslRole
+// returns true if the current SSL role equals the proposed SSL role.
+TEST_F(QuicTransportChannelTest, QuicRoleReversalAfterQuic) {
+ Connect();
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ EXPECT_FALSE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
+ EXPECT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
+ EXPECT_FALSE(peer2_.quic_channel()->SetSslRole(rtc::SSL_CLIENT));
+ EXPECT_TRUE(peer2_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
+}
+
+// Set SSL role, then check that GetSslRole returns the same value.
+TEST_F(QuicTransportChannelTest, SetGetSslRole) {
+ ASSERT_TRUE(peer1_.quic_channel()->SetSslRole(rtc::SSL_SERVER));
+ rtc::scoped_ptr<rtc::SSLRole> role(new rtc::SSLRole());
+ ASSERT_TRUE(peer1_.quic_channel()->GetSslRole(role.get()));
+ EXPECT_EQ(rtc::SSL_SERVER, *role);
+}
+
+// Test that after QUIC handshake is complete, QUIC handshake remains confirmed
+// even if underlying channel reconnects.
+TEST_F(QuicTransportChannelTest, HandshakeConfirmedAfterReconnect) {
+ Connect();
+ ASSERT_TRUE_WAIT(handshake_confirmed(), kTimeoutMs);
+ Disconnect();
+ EXPECT_TRUE(handshake_confirmed());
+ Connect();
+ EXPECT_TRUE(handshake_confirmed());
+}
« 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