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