/* * 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/api/quicdatachannel.h" #include #include #include #include #include #include "webrtc/base/bind.h" #include "webrtc/base/gunit.h" #include "webrtc/base/scoped_ref_ptr.h" #include "webrtc/p2p/base/faketransportcontroller.h" #include "webrtc/p2p/quic/quictransportchannel.h" #include "webrtc/p2p/quic/reliablequicstream.h" using cricket::FakeTransportChannel; using cricket::QuicTransportChannel; using cricket::ReliableQuicStream; using webrtc::DataBuffer; using webrtc::DataChannelObserver; using webrtc::DataChannelInit; using webrtc::QuicDataChannel; namespace { // Timeout for asynchronous operations. static const int kTimeoutMs = 1000; // milliseconds // Small messages that can be sent within a single QUIC packet. static const std::string kSmallMessage1 = "Hello, world!"; static const std::string kSmallMessage2 = "WebRTC"; static const std::string kSmallMessage3 = "1"; static const std::string kSmallMessage4 = "abcdefghijklmnopqrstuvwxyz"; static const DataBuffer kSmallBuffer1(kSmallMessage1); static const DataBuffer kSmallBuffer2(kSmallMessage2); static const DataBuffer kSmallBuffer3(kSmallMessage3); static const DataBuffer kSmallBuffer4(kSmallMessage4); // Large messages (> 1350 bytes) that exceed the max size of a QUIC packet. // These are < 16 KB so they don't exceed the QUIC stream flow control limit. static const std::string kLargeMessage1 = std::string("a", 2000); static const std::string kLargeMessage2 = std::string("a", 4000); static const std::string kLargeMessage3 = std::string("a", 8000); static const std::string kLargeMessage4 = std::string("a", 12000); static const DataBuffer kLargeBuffer1(kLargeMessage1); static const DataBuffer kLargeBuffer2(kLargeMessage2); static const DataBuffer kLargeBuffer3(kLargeMessage3); static const DataBuffer kLargeBuffer4(kLargeMessage4); // Oversized message (> 16 KB) that violates the QUIC stream flow control limit. static const std::string kOversizedMessage = std::string("a", 20000); static const DataBuffer kOversizedBuffer(kOversizedMessage); // Creates a fingerprint from a certificate. static rtc::SSLFingerprint* CreateFingerprint(rtc::RTCCertificate* cert) { std::string digest_algorithm; cert->ssl_certificate().GetSignatureDigestAlgorithm(&digest_algorithm); std::unique_ptr fingerprint( rtc::SSLFingerprint::Create(digest_algorithm, cert->identity())); return fingerprint.release(); } // FakeObserver receives messages from the QuicDataChannel. class FakeObserver : public DataChannelObserver { public: FakeObserver() : on_state_change_count_(0), on_buffered_amount_change_count_(0) {} // DataChannelObserver overrides. void OnStateChange() override { ++on_state_change_count_; } void OnBufferedAmountChange(uint64_t previous_amount) override { ++on_buffered_amount_change_count_; } void OnMessage(const webrtc::DataBuffer& buffer) override { messages_.push_back(std::string(buffer.data.data(), buffer.size())); } const std::vector& messages() const { return messages_; } size_t messages_received() const { return messages_.size(); } size_t on_state_change_count() const { return on_state_change_count_; } size_t on_buffered_amount_change_count() const { return on_buffered_amount_change_count_; } private: std::vector messages_; size_t on_state_change_count_; size_t on_buffered_amount_change_count_; }; // FakeQuicDataTransport simulates QuicDataTransport by dispatching QUIC // stream messages to data channels and encoding/decoding messages. class FakeQuicDataTransport : public sigslot::has_slots<> { public: FakeQuicDataTransport() {} void ConnectToTransportChannel(QuicTransportChannel* quic_transport_channel) { quic_transport_channel->SignalIncomingStream.connect( this, &FakeQuicDataTransport::OnIncomingStream); } rtc::scoped_refptr CreateDataChannel( int id, const std::string& label, const std::string& protocol) { DataChannelInit config; config.id = id; config.protocol = protocol; rtc::scoped_refptr data_channel(new QuicDataChannel( rtc::Thread::Current(), rtc::Thread::Current(), label, config)); data_channel_by_id_[id] = data_channel; return data_channel; } private: void OnIncomingStream(cricket::ReliableQuicStream* stream) { incoming_stream_ = stream; incoming_stream_->SignalDataReceived.connect( this, &FakeQuicDataTransport::OnDataReceived); } void OnDataReceived(net::QuicStreamId id, const char* data, size_t len) { ASSERT_EQ(incoming_stream_->id(), id); incoming_stream_->SignalDataReceived.disconnect(this); // Retrieve the data channel ID and message ID. int data_channel_id; uint64_t message_id; size_t bytes_read; ASSERT_TRUE(webrtc::ParseQuicDataMessageHeader(data, len, &data_channel_id, &message_id, &bytes_read)); data += bytes_read; len -= bytes_read; // Dispatch the message to the matching QuicDataChannel. const auto& kv = data_channel_by_id_.find(data_channel_id); ASSERT_NE(kv, data_channel_by_id_.end()); QuicDataChannel* data_channel = kv->second; QuicDataChannel::Message message; message.id = message_id; message.buffer = rtc::CopyOnWriteBuffer(data, len); message.stream = incoming_stream_; data_channel->OnIncomingMessage(std::move(message)); incoming_stream_ = nullptr; } // Map of data channel ID => QuicDataChannel. std::map> data_channel_by_id_; // Last incoming QUIC stream which has arrived. cricket::ReliableQuicStream* incoming_stream_ = nullptr; }; // A peer who creates a QuicDataChannel to transfer data, and simulates network // connectivity with a fake ICE channel wrapped by the QUIC transport channel. class QuicDataChannelPeer { public: QuicDataChannelPeer() : ice_transport_channel_(new FakeTransportChannel("data", 0)), quic_transport_channel_(ice_transport_channel_) { ice_transport_channel_->SetAsync(true); fake_quic_data_transport_.ConnectToTransportChannel( &quic_transport_channel_); } void GenerateCertificateAndFingerprint() { rtc::scoped_refptr local_cert = rtc::RTCCertificate::Create(std::unique_ptr( rtc::SSLIdentity::Generate("cert_name", rtc::KT_DEFAULT))); quic_transport_channel_.SetLocalCertificate(local_cert); local_fingerprint_.reset(CreateFingerprint(local_cert.get())); } rtc::scoped_refptr CreateDataChannelWithTransportChannel( int id, const std::string& label, const std::string& protocol) { rtc::scoped_refptr data_channel = fake_quic_data_transport_.CreateDataChannel(id, label, protocol); data_channel->SetTransportChannel(&quic_transport_channel_); return data_channel; } rtc::scoped_refptr CreateDataChannelWithoutTransportChannel( int id, const std::string& label, const std::string& protocol) { return fake_quic_data_transport_.CreateDataChannel(id, label, protocol); } // Connects |ice_transport_channel_| to that of the other peer. void Connect(QuicDataChannelPeer* other_peer) { ice_transport_channel_->Connect(); other_peer->ice_transport_channel_->Connect(); ice_transport_channel_->SetDestination(other_peer->ice_transport_channel_); } std::unique_ptr& local_fingerprint() { return local_fingerprint_; } QuicTransportChannel* quic_transport_channel() { return &quic_transport_channel_; } FakeTransportChannel* ice_transport_channel() { return ice_transport_channel_; } private: FakeTransportChannel* ice_transport_channel_; QuicTransportChannel quic_transport_channel_; std::unique_ptr local_fingerprint_; FakeQuicDataTransport fake_quic_data_transport_; }; class QuicDataChannelTest : public testing::Test { public: QuicDataChannelTest() {} // Connect the QuicTransportChannels and complete the crypto handshake. void ConnectTransportChannels() { SetCryptoParameters(); peer1_.Connect(&peer2_); ASSERT_TRUE_WAIT(peer1_.quic_transport_channel()->writable() && peer2_.quic_transport_channel()->writable(), kTimeoutMs); } // Sets crypto parameters required for the QUIC handshake. void SetCryptoParameters() { peer1_.GenerateCertificateAndFingerprint(); peer2_.GenerateCertificateAndFingerprint(); peer1_.quic_transport_channel()->SetSslRole(rtc::SSL_CLIENT); peer2_.quic_transport_channel()->SetSslRole(rtc::SSL_SERVER); std::unique_ptr& peer1_fingerprint = peer1_.local_fingerprint(); std::unique_ptr& peer2_fingerprint = peer2_.local_fingerprint(); peer1_.quic_transport_channel()->SetRemoteFingerprint( peer2_fingerprint->algorithm, reinterpret_cast(peer2_fingerprint->digest.data()), peer2_fingerprint->digest.size()); peer2_.quic_transport_channel()->SetRemoteFingerprint( peer1_fingerprint->algorithm, reinterpret_cast(peer1_fingerprint->digest.data()), peer1_fingerprint->digest.size()); } protected: QuicDataChannelPeer peer1_; QuicDataChannelPeer peer2_; }; // Tests that a QuicDataChannel transitions from connecting to open when // the QuicTransportChannel becomes writable for the first time. TEST_F(QuicDataChannelTest, DataChannelOpensWhenTransportChannelConnects) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(4, "label", "protocol"); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel->state()); ConnectTransportChannels(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel->state(), kTimeoutMs); } // Tests that a QuicDataChannel transitions from connecting to open when // SetTransportChannel is called with a QuicTransportChannel that is already // writable. TEST_F(QuicDataChannelTest, DataChannelOpensWhenTransportChannelWritable) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithoutTransportChannel(4, "label", "protocol"); ConnectTransportChannels(); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel->state()); data_channel->SetTransportChannel(peer1_.quic_transport_channel()); EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel->state()); } // Tests that the QuicDataChannel transfers messages small enough to fit into a // single QUIC stream frame. TEST_F(QuicDataChannelTest, TransferSmallMessage) { ConnectTransportChannels(); int data_channel_id = 2; std::string label = "label"; std::string protocol = "protocol"; rtc::scoped_refptr peer1_data_channel = peer1_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer1_data_channel->state() == webrtc::DataChannelInterface::kOpen); rtc::scoped_refptr peer2_data_channel = peer2_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer2_data_channel->state() == webrtc::DataChannelInterface::kOpen); FakeObserver peer1_observer; peer1_data_channel->RegisterObserver(&peer1_observer); FakeObserver peer2_observer; peer2_data_channel->RegisterObserver(&peer2_observer); // peer1 -> peer2 EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer1)); ASSERT_EQ_WAIT(1, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kSmallMessage1, peer2_observer.messages()[0]); // peer2 -> peer1 EXPECT_TRUE(peer2_data_channel->Send(kSmallBuffer2)); ASSERT_EQ_WAIT(1, peer1_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kSmallMessage2, peer1_observer.messages()[0]); // peer2 -> peer1 EXPECT_TRUE(peer2_data_channel->Send(kSmallBuffer3)); ASSERT_EQ_WAIT(2, peer1_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kSmallMessage3, peer1_observer.messages()[1]); // peer1 -> peer2 EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer4)); ASSERT_EQ_WAIT(2, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kSmallMessage4, peer2_observer.messages()[1]); } // Tests that QuicDataChannel transfers messages large enough to fit into // multiple QUIC stream frames, which don't violate the QUIC flow control limit. // These require buffering by the QuicDataChannel. TEST_F(QuicDataChannelTest, TransferLargeMessage) { ConnectTransportChannels(); int data_channel_id = 347; std::string label = "label"; std::string protocol = "protocol"; rtc::scoped_refptr peer1_data_channel = peer1_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer1_data_channel->state() == webrtc::DataChannelInterface::kOpen); rtc::scoped_refptr peer2_data_channel = peer2_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer2_data_channel->state() == webrtc::DataChannelInterface::kOpen); FakeObserver peer1_observer; peer1_data_channel->RegisterObserver(&peer1_observer); FakeObserver peer2_observer; peer2_data_channel->RegisterObserver(&peer2_observer); // peer1 -> peer2 EXPECT_TRUE(peer1_data_channel->Send(kLargeBuffer1)); ASSERT_TRUE_WAIT(peer2_observer.messages_received() == 1, kTimeoutMs); EXPECT_EQ(kLargeMessage1, peer2_observer.messages()[0]); // peer2 -> peer1 EXPECT_TRUE(peer2_data_channel->Send(kLargeBuffer2)); ASSERT_EQ_WAIT(1, peer1_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kLargeMessage2, peer1_observer.messages()[0]); // peer2 -> peer1 EXPECT_TRUE(peer2_data_channel->Send(kLargeBuffer3)); ASSERT_EQ_WAIT(2, peer1_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kLargeMessage3, peer1_observer.messages()[1]); // peer1 -> peer2 EXPECT_TRUE(peer1_data_channel->Send(kLargeBuffer4)); ASSERT_EQ_WAIT(2, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kLargeMessage4, peer2_observer.messages()[1]); } // Tests that when a message size exceeds the flow control limit (> 16KB), the // QuicDataChannel can queue the data and send it after receiving window update // frames from the remote peer. TEST_F(QuicDataChannelTest, TransferOversizedMessage) { ConnectTransportChannels(); int data_channel_id = 189; std::string label = "label"; std::string protocol = "protocol"; rtc::scoped_refptr peer1_data_channel = peer1_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); rtc::scoped_refptr peer2_data_channel = peer2_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer2_data_channel->state() == webrtc::DataChannelInterface::kOpen); FakeObserver peer1_observer; peer1_data_channel->RegisterObserver(&peer1_observer); FakeObserver peer2_observer; peer2_data_channel->RegisterObserver(&peer2_observer); EXPECT_TRUE(peer1_data_channel->Send(kOversizedBuffer)); EXPECT_EQ(1, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_EQ_WAIT(1, peer2_data_channel->GetNumIncomingStreams(), kTimeoutMs); ASSERT_EQ_WAIT(1, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ(kOversizedMessage, peer2_observer.messages()[0]); EXPECT_EQ(0, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_EQ(0, peer2_data_channel->GetNumIncomingStreams()); } // Tests that empty messages can be sent. TEST_F(QuicDataChannelTest, TransferEmptyMessage) { ConnectTransportChannels(); int data_channel_id = 69; std::string label = "label"; std::string protocol = "protocol"; rtc::scoped_refptr peer1_data_channel = peer1_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); rtc::scoped_refptr peer2_data_channel = peer2_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer2_data_channel->state() == webrtc::DataChannelInterface::kOpen); FakeObserver peer1_observer; peer1_data_channel->RegisterObserver(&peer1_observer); FakeObserver peer2_observer; peer2_data_channel->RegisterObserver(&peer2_observer); EXPECT_TRUE(peer1_data_channel->Send(DataBuffer(""))); ASSERT_EQ_WAIT(1, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ("", peer2_observer.messages()[0]); } // Tests that when the QuicDataChannel is open and sends a message while the // QuicTransportChannel is unwritable, it gets buffered then received once the // QuicTransportChannel becomes writable again. TEST_F(QuicDataChannelTest, MessagesReceivedWhenTransportChannelReconnects) { ConnectTransportChannels(); int data_channel_id = 401; std::string label = "label"; std::string protocol = "protocol"; rtc::scoped_refptr peer1_data_channel = peer1_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer1_data_channel->state() == webrtc::DataChannelInterface::kOpen); rtc::scoped_refptr peer2_data_channel = peer2_.CreateDataChannelWithTransportChannel(data_channel_id, label, protocol); ASSERT_TRUE(peer2_data_channel->state() == webrtc::DataChannelInterface::kOpen); FakeObserver peer1_observer; peer1_data_channel->RegisterObserver(&peer1_observer); FakeObserver peer2_observer; peer2_data_channel->RegisterObserver(&peer2_observer); // writable => unwritable peer1_.ice_transport_channel()->SetWritable(false); ASSERT_FALSE(peer1_.quic_transport_channel()->writable()); // Verify that sent data is buffered. EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer1)); EXPECT_EQ(1, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer2)); EXPECT_EQ(2, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer3)); EXPECT_EQ(3, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_TRUE(peer1_data_channel->Send(kSmallBuffer4)); EXPECT_EQ(4, peer1_data_channel->GetNumWriteBlockedStreams()); // unwritable => writable peer1_.ice_transport_channel()->SetWritable(true); ASSERT_TRUE(peer1_.quic_transport_channel()->writable()); ASSERT_EQ_WAIT(4, peer2_observer.messages_received(), kTimeoutMs); EXPECT_EQ(0, peer1_data_channel->GetNumWriteBlockedStreams()); EXPECT_EQ(0, peer2_data_channel->GetNumIncomingStreams()); } // Tests that the QuicDataChannel does not send before it is open. TEST_F(QuicDataChannelTest, TransferMessageBeforeChannelOpens) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(6, "label", "protocol"); ASSERT_TRUE(data_channel->state() == webrtc::DataChannelInterface::kConnecting); EXPECT_FALSE(data_channel->Send(kSmallBuffer1)); } // Tests that the QuicDataChannel does not send after it is closed. TEST_F(QuicDataChannelTest, TransferDataAfterChannelClosed) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(42, "label", "protocol"); data_channel->Close(); ASSERT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); EXPECT_FALSE(data_channel->Send(kSmallBuffer1)); } // Tests that QuicDataChannel state changes fire OnStateChanged() for the // observer, with the correct data channel states, when the data channel // transitions from kConnecting => kOpen => kClosing => kClosed. TEST_F(QuicDataChannelTest, OnStateChangedFired) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(7, "label", "protocol"); FakeObserver observer; data_channel->RegisterObserver(&observer); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel->state()); EXPECT_EQ(0, observer.on_state_change_count()); ConnectTransportChannels(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kOpen, data_channel->state(), kTimeoutMs); EXPECT_EQ(1, observer.on_state_change_count()); data_channel->Close(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); // 2 state changes due to kClosing and kClosed. EXPECT_EQ(3, observer.on_state_change_count()); } // Tests that a QuicTransportChannel can be closed without being opened when it // is connected to a transprot chanenl. TEST_F(QuicDataChannelTest, NeverOpenedWithTransportChannel) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(7, "label", "protocol"); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel->state()); data_channel->Close(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); } // Tests that a QuicTransportChannel can be closed without being opened or // connected to a transport channel. TEST_F(QuicDataChannelTest, NeverOpenedWithoutTransportChannel) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithoutTransportChannel(7, "label", "protocol"); EXPECT_EQ(webrtc::DataChannelInterface::kConnecting, data_channel->state()); data_channel->Close(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); } // Tests that the QuicDataChannel is closed when the QUIC connection closes. TEST_F(QuicDataChannelTest, ClosedOnTransportError) { ConnectTransportChannels(); rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(1, "label", "protocol"); EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel->state()); ReliableQuicStream* stream = peer1_.quic_transport_channel()->CreateQuicStream(); ASSERT_NE(nullptr, stream); stream->CloseConnectionWithDetails(net::QuicErrorCode::QUIC_NO_ERROR, "Closing QUIC for testing"); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); } // Tests that an already closed QuicDataChannel does not fire onStateChange and // remains closed. TEST_F(QuicDataChannelTest, DoesNotChangeStateWhenClosed) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(4, "label", "protocol"); FakeObserver observer; data_channel->RegisterObserver(&observer); data_channel->Close(); EXPECT_EQ_WAIT(webrtc::DataChannelInterface::kClosed, data_channel->state(), kTimeoutMs); // OnStateChange called for kClosing and kClosed. EXPECT_EQ(2, observer.on_state_change_count()); // Call Close() again to verify that the state cannot be kClosing. data_channel->Close(); EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state()); EXPECT_EQ(2, observer.on_state_change_count()); ConnectTransportChannels(); EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state()); EXPECT_EQ(2, observer.on_state_change_count()); // writable => unwritable peer1_.ice_transport_channel()->SetWritable(false); ASSERT_FALSE(peer1_.quic_transport_channel()->writable()); EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state()); EXPECT_EQ(2, observer.on_state_change_count()); // unwritable => writable peer1_.ice_transport_channel()->SetWritable(true); ASSERT_TRUE(peer1_.quic_transport_channel()->writable()); EXPECT_EQ(webrtc::DataChannelInterface::kClosed, data_channel->state()); EXPECT_EQ(2, observer.on_state_change_count()); } // Tests that when the QuicDataChannel is open and the QuicTransportChannel // transitions between writable and unwritable, it does not fire onStateChange // and remains open. TEST_F(QuicDataChannelTest, DoesNotChangeStateWhenTransportChannelReconnects) { ConnectTransportChannels(); rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(4, "label", "protocol"); FakeObserver observer; data_channel->RegisterObserver(&observer); EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel->state()); EXPECT_EQ(0, observer.on_state_change_count()); // writable => unwritable peer1_.ice_transport_channel()->SetWritable(false); ASSERT_FALSE(peer1_.quic_transport_channel()->writable()); EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel->state()); EXPECT_EQ(0, observer.on_state_change_count()); // unwritable => writable peer1_.ice_transport_channel()->SetWritable(true); ASSERT_TRUE(peer1_.quic_transport_channel()->writable()); EXPECT_EQ(webrtc::DataChannelInterface::kOpen, data_channel->state()); EXPECT_EQ(0, observer.on_state_change_count()); } // Tests that SetTransportChannel returns false when setting a NULL transport // channel or a transport channel that is not equivalent to the one already set. TEST_F(QuicDataChannelTest, SetTransportChannelReturnValue) { rtc::scoped_refptr data_channel = peer1_.CreateDataChannelWithTransportChannel(4, "label", "protocol"); EXPECT_FALSE(data_channel->SetTransportChannel(nullptr)); QuicTransportChannel* transport_channel = peer1_.quic_transport_channel(); EXPECT_TRUE(data_channel->SetTransportChannel(transport_channel)); EXPECT_TRUE(data_channel->SetTransportChannel(transport_channel)); QuicTransportChannel* other_transport_channel = peer2_.quic_transport_channel(); EXPECT_FALSE(data_channel->SetTransportChannel(other_transport_channel)); } // Tests that the QUIC message header is encoded with the correct number of // bytes and is properly decoded. TEST_F(QuicDataChannelTest, EncodeParseQuicDataMessageHeader) { int data_channel_id1 = 127; // 1 byte uint64_t message_id1 = 0; // 1 byte rtc::CopyOnWriteBuffer header1; webrtc::WriteQuicDataChannelMessageHeader(data_channel_id1, message_id1, &header1); EXPECT_EQ(2u, header1.size()); int decoded_data_channel_id1; uint64_t decoded_message_id1; size_t bytes_read1; ASSERT_TRUE(webrtc::ParseQuicDataMessageHeader( header1.data(), header1.size(), &decoded_data_channel_id1, &decoded_message_id1, &bytes_read1)); EXPECT_EQ(data_channel_id1, decoded_data_channel_id1); EXPECT_EQ(message_id1, decoded_message_id1); EXPECT_EQ(2u, bytes_read1); int data_channel_id2 = 4178; // 2 bytes uint64_t message_id2 = 1324921792003; // 6 bytes rtc::CopyOnWriteBuffer header2; webrtc::WriteQuicDataChannelMessageHeader(data_channel_id2, message_id2, &header2); EXPECT_EQ(8u, header2.size()); int decoded_data_channel_id2; uint64_t decoded_message_id2; size_t bytes_read2; ASSERT_TRUE(webrtc::ParseQuicDataMessageHeader( header2.data(), header2.size(), &decoded_data_channel_id2, &decoded_message_id2, &bytes_read2)); EXPECT_EQ(data_channel_id2, decoded_data_channel_id2); EXPECT_EQ(message_id2, decoded_message_id2); EXPECT_EQ(8u, bytes_read2); } } // namespace