1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file. 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_client_session.h" 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <vector> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/ip_endpoint.h" 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "net/quic/crypto/aes_128_gcm_12_encrypter.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/quic/quic_flags.h" 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/test_tools/crypto_test_utils.h" 13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "net/quic/test_tools/quic_session_peer.h" 14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/test_tools/quic_test_utils.h" 155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/tools/quic/quic_spdy_client_stream.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/tools/quic/test_tools/quic_test_utils.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::test::CryptoTestUtils; 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using net::test::DefaultQuicConfig; 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using net::test::PacketSavingConnection; 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing net::test::QuicSessionPeer; 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)using net::test::SupportedVersions; 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing net::test::TestPeerIPAddress; 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdochusing net::test::ValueRestore; 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing net::test::kTestPort; 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing net::tools::test::MockConnection; 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing testing::Invoke; 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using testing::_; 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net { 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools { 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace test { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char kServerHostname[] = "www.example.com"; 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const uint16 kPort = 80; 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ToolsQuicClientSessionTest 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public ::testing::TestWithParam<QuicVersion> { 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) protected: 42a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch ToolsQuicClientSessionTest() 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : connection_(new PacketSavingConnection(false, 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SupportedVersions(GetParam()))) { 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) crypto_config_.SetDefaults(); 46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch session_.reset(new QuicClientSession(DefaultQuicConfig(), connection_)); 47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch session_->InitializeSession( 48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch QuicServerId(kServerHostname, kPort, false, PRIVACY_MODE_DISABLED), 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch &crypto_config_); 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_->config()->SetDefaults(); 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void CompleteCryptoHandshake() { 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) ASSERT_TRUE(session_->CryptoConnect()); 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CryptoTestUtils::HandshakeWithFakeServer( 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) connection_, session_->GetCryptoStream()); 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PacketSavingConnection* connection_; 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) scoped_ptr<QuicClientSession> session_; 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) QuicCryptoClientConfig crypto_config_; 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)INSTANTIATE_TEST_CASE_P(Tests, ToolsQuicClientSessionTest, 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ::testing::ValuesIn(QuicSupportedVersions())); 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(ToolsQuicClientSessionTest, CryptoConnect) { 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CompleteCryptoHandshake(); 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(ToolsQuicClientSessionTest, MaxNumStreams) { 722385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch session_->config()->set_max_streams_per_connection(1, 1); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FLAGS_max_streams_per_connection = 1; 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Initialize crypto before the client session will create a stream. 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CompleteCryptoHandshake(); 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicSpdyClientStream* stream = 785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) session_->CreateOutgoingDataStream(); 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ASSERT_TRUE(stream); 805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_FALSE(session_->CreateOutgoingDataStream()); 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Close a stream and ensure I can now open a new one. 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_->CloseStream(stream->id()); 845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream = session_->CreateOutgoingDataStream(); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EXPECT_TRUE(stream); 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_P(ToolsQuicClientSessionTest, GoAwayReceived) { 89868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CompleteCryptoHandshake(); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // After receiving a GoAway, I should no longer be able to create outgoing 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // streams. 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) session_->OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away.")); 945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(NULL, session_->CreateOutgoingDataStream()); 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 97116680a4aac90f2aa7413d9095a592090648e557Ben MurdochTEST_P(ToolsQuicClientSessionTest, SetFecProtectionFromConfig) { 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ValueRestore<bool> old_flag(&FLAGS_enable_quic_fec, true); 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Set FEC config in client's connection options. 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QuicTagVector copt; 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch copt.push_back(kFHDR); 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch session_->config()->SetConnectionOptionsToSend(copt); 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Doing the handshake should set up FEC config correctly. 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CompleteCryptoHandshake(); 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Verify that headers stream is always protected and data streams are 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // optionally protected. 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(FEC_PROTECT_ALWAYS, 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QuicSessionPeer::GetHeadersStream(session_.get())->fec_policy()); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch QuicSpdyClientStream* stream = session_->CreateOutgoingDataStream(); 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ASSERT_TRUE(stream); 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch EXPECT_EQ(FEC_PROTECT_OPTIONAL, stream->fec_policy()); 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_P(ToolsQuicClientSessionTest, EmptyPacketReceived) { 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // This test covers broken behavior that empty packets cause QUIC connection 1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // broken. 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create Packet with 0 length. 1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci QuicEncryptedPacket invalid_packet(nullptr, 0, false); 1231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPEndPoint server_address(TestPeerIPAddress(), kTestPort); 1241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IPEndPoint client_address(TestPeerIPAddress(), kTestPort); 1251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_CALL(*reinterpret_cast<MockConnection*>(session_->connection()), 1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ProcessUdpPacket(server_address, client_address, _)) 1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci .WillRepeatedly( 1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Invoke(reinterpret_cast<MockConnection*>(session_->connection()), 1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci &MockConnection::ReallyProcessUdpPacket)); 1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Expect call to close connection with error QUIC_INVALID_PACKET_HEADER. 1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // TODO(b/17206611): Correct behavior: packet should get dropped and 1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // connection should remain open. 1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_CALL(*connection_, SendConnectionCloseWithDetails( 1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci QUIC_INVALID_PACKET_HEADER, _)).Times(1); 1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci session_->connection()->ProcessUdpPacket(client_address, server_address, 1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci invalid_packet); 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Create a packet that causes DecryptPacket failed. The packet will get 1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // dropped without closing connection. This is a correct behavior. 1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci char buf[2] = {0x00, 0x01}; 1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci QuicEncryptedPacket valid_packet(buf, 2, false); 1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Close connection shouldn't be called. 1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_CALL(*connection_, SendConnectionCloseWithDetails(_, _)).Times(0); 1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci session_->connection()->ProcessUdpPacket(client_address, server_address, 1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci valid_packet); 1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace test 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace tools 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace net 154