1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "net/tools/quic/quic_client_session.h" 6 7#include <vector> 8 9#include "net/base/ip_endpoint.h" 10#include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 11#include "net/quic/quic_flags.h" 12#include "net/quic/test_tools/crypto_test_utils.h" 13#include "net/quic/test_tools/quic_session_peer.h" 14#include "net/quic/test_tools/quic_test_utils.h" 15#include "net/tools/quic/quic_spdy_client_stream.h" 16#include "net/tools/quic/test_tools/quic_test_utils.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19using net::test::CryptoTestUtils; 20using net::test::DefaultQuicConfig; 21using net::test::PacketSavingConnection; 22using net::test::QuicSessionPeer; 23using net::test::SupportedVersions; 24using net::test::TestPeerIPAddress; 25using net::test::ValueRestore; 26using net::test::kTestPort; 27using net::tools::test::MockConnection; 28using testing::Invoke; 29using testing::_; 30 31namespace net { 32namespace tools { 33namespace test { 34namespace { 35 36const char kServerHostname[] = "www.example.com"; 37const uint16 kPort = 80; 38 39class ToolsQuicClientSessionTest 40 : public ::testing::TestWithParam<QuicVersion> { 41 protected: 42 ToolsQuicClientSessionTest() 43 : connection_(new PacketSavingConnection(false, 44 SupportedVersions(GetParam()))) { 45 crypto_config_.SetDefaults(); 46 session_.reset(new QuicClientSession(DefaultQuicConfig(), connection_)); 47 session_->InitializeSession( 48 QuicServerId(kServerHostname, kPort, false, PRIVACY_MODE_DISABLED), 49 &crypto_config_); 50 session_->config()->SetDefaults(); 51 } 52 53 void CompleteCryptoHandshake() { 54 ASSERT_TRUE(session_->CryptoConnect()); 55 CryptoTestUtils::HandshakeWithFakeServer( 56 connection_, session_->GetCryptoStream()); 57 } 58 59 PacketSavingConnection* connection_; 60 scoped_ptr<QuicClientSession> session_; 61 QuicCryptoClientConfig crypto_config_; 62}; 63 64INSTANTIATE_TEST_CASE_P(Tests, ToolsQuicClientSessionTest, 65 ::testing::ValuesIn(QuicSupportedVersions())); 66 67TEST_P(ToolsQuicClientSessionTest, CryptoConnect) { 68 CompleteCryptoHandshake(); 69} 70 71TEST_P(ToolsQuicClientSessionTest, MaxNumStreams) { 72 session_->config()->set_max_streams_per_connection(1, 1); 73 // FLAGS_max_streams_per_connection = 1; 74 // Initialize crypto before the client session will create a stream. 75 CompleteCryptoHandshake(); 76 77 QuicSpdyClientStream* stream = 78 session_->CreateOutgoingDataStream(); 79 ASSERT_TRUE(stream); 80 EXPECT_FALSE(session_->CreateOutgoingDataStream()); 81 82 // Close a stream and ensure I can now open a new one. 83 session_->CloseStream(stream->id()); 84 stream = session_->CreateOutgoingDataStream(); 85 EXPECT_TRUE(stream); 86} 87 88TEST_P(ToolsQuicClientSessionTest, GoAwayReceived) { 89 CompleteCryptoHandshake(); 90 91 // After receiving a GoAway, I should no longer be able to create outgoing 92 // streams. 93 session_->OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away.")); 94 EXPECT_EQ(NULL, session_->CreateOutgoingDataStream()); 95} 96 97TEST_P(ToolsQuicClientSessionTest, SetFecProtectionFromConfig) { 98 ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true); 99 100 // Set FEC config in client's connection options. 101 QuicTagVector copt; 102 copt.push_back(kFHDR); 103 session_->config()->SetConnectionOptionsToSend(copt); 104 105 // Doing the handshake should set up FEC config correctly. 106 CompleteCryptoHandshake(); 107 108 // Verify that headers stream is always protected and data streams are 109 // optionally protected. 110 EXPECT_EQ(FEC_PROTECT_ALWAYS, 111 QuicSessionPeer::GetHeadersStream(session_.get())->fec_policy()); 112 QuicSpdyClientStream* stream = session_->CreateOutgoingDataStream(); 113 ASSERT_TRUE(stream); 114 EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy()); 115} 116 117TEST_P(ToolsQuicClientSessionTest, EmptyPacketReceived) { 118 // This test covers broken behavior that empty packets cause QUIC connection 119 // broken. 120 121 // Create Packet with 0 length. 122 QuicEncryptedPacket invalid_packet(nullptr, 0, false); 123 IPEndPoint server_address(TestPeerIPAddress(), kTestPort); 124 IPEndPoint client_address(TestPeerIPAddress(), kTestPort); 125 126 EXPECT_CALL(*reinterpret_cast<MockConnection*>(session_->connection()), 127 ProcessUdpPacket(server_address, client_address, _)) 128 .WillRepeatedly( 129 Invoke(reinterpret_cast<MockConnection*>(session_->connection()), 130 &MockConnection::ReallyProcessUdpPacket)); 131 132 // Expect call to close connection with error QUIC_INVALID_PACKET_HEADER. 133 // TODO(b/17206611): Correct behavior: packet should get dropped and 134 // connection should remain open. 135 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( 136 QUIC_INVALID_PACKET_HEADER, _)).Times(1); 137 session_->connection()->ProcessUdpPacket(client_address, server_address, 138 invalid_packet); 139 140 // Create a packet that causes DecryptPacket failed. The packet will get 141 // dropped without closing connection. This is a correct behavior. 142 char buf[2] = {0x00, 0x01}; 143 QuicEncryptedPacket valid_packet(buf, 2, false); 144 // Close connection shouldn't be called. 145 EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0); 146 session_->connection()->ProcessUdpPacket(client_address, server_address, 147 valid_packet); 148} 149 150} // namespace 151} // namespace test 152} // namespace tools 153} // namespace net 154