• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/quic/quic_client_session.h"
6 
7 #include <vector>
8 
9 #include "base/rand_util.h"
10 #include "net/base/capturing_net_log.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/quic/crypto/aes_128_gcm_12_encrypter.h"
13 #include "net/quic/crypto/crypto_protocol.h"
14 #include "net/quic/crypto/quic_decrypter.h"
15 #include "net/quic/crypto/quic_encrypter.h"
16 #include "net/quic/crypto/quic_server_info.h"
17 #include "net/quic/quic_default_packet_writer.h"
18 #include "net/quic/test_tools/crypto_test_utils.h"
19 #include "net/quic/test_tools/quic_client_session_peer.h"
20 #include "net/quic/test_tools/quic_test_utils.h"
21 #include "net/quic/test_tools/simple_quic_framer.h"
22 #include "net/socket/socket_test_util.h"
23 #include "net/udp/datagram_client_socket.h"
24 
25 using testing::_;
26 
27 namespace net {
28 namespace test {
29 namespace {
30 
31 const char kServerHostname[] = "www.example.com";
32 const uint16 kServerPort = 80;
33 
34 class TestPacketWriter : public QuicDefaultPacketWriter {
35  public:
TestPacketWriter(QuicVersion version)36   TestPacketWriter(QuicVersion version) : version_(version) {}
37 
38   // QuicPacketWriter
WritePacket(const char * buffer,size_t buf_len,const IPAddressNumber & self_address,const IPEndPoint & peer_address)39   virtual WriteResult WritePacket(
40       const char* buffer, size_t buf_len,
41       const IPAddressNumber& self_address,
42       const IPEndPoint& peer_address) OVERRIDE {
43     SimpleQuicFramer framer(SupportedVersions(version_));
44     QuicEncryptedPacket packet(buffer, buf_len);
45     EXPECT_TRUE(framer.ProcessPacket(packet));
46     header_ = framer.header();
47     return WriteResult(WRITE_STATUS_OK, packet.length());
48   }
49 
IsWriteBlockedDataBuffered() const50   virtual bool IsWriteBlockedDataBuffered() const OVERRIDE {
51     // Chrome sockets' Write() methods buffer the data until the Write is
52     // permitted.
53     return true;
54   }
55 
56   // Returns the header from the last packet written.
header()57   const QuicPacketHeader& header() { return header_; }
58 
59  private:
60   QuicVersion version_;
61   QuicPacketHeader header_;
62 };
63 
64 class QuicClientSessionTest : public ::testing::TestWithParam<QuicVersion> {
65  protected:
QuicClientSessionTest()66   QuicClientSessionTest()
67       : writer_(new TestPacketWriter(GetParam())),
68         connection_(
69             new PacketSavingConnection(false, SupportedVersions(GetParam()))),
70         session_(connection_, GetSocket().Pass(), writer_.Pass(), NULL, NULL,
71                  make_scoped_ptr((QuicServerInfo*)NULL),
72                  QuicServerId(kServerHostname, kServerPort, false,
73                               PRIVACY_MODE_DISABLED),
74                  DefaultQuicConfig(), &crypto_config_,
75                  base::MessageLoop::current()->message_loop_proxy().get(),
76                  &net_log_) {
77     session_.config()->SetDefaults();
78     crypto_config_.SetDefaults();
79   }
80 
TearDown()81   virtual void TearDown() OVERRIDE {
82     session_.CloseSessionOnError(ERR_ABORTED);
83   }
84 
GetSocket()85   scoped_ptr<DatagramClientSocket> GetSocket() {
86     socket_factory_.AddSocketDataProvider(&socket_data_);
87     return socket_factory_.CreateDatagramClientSocket(
88         DatagramSocket::DEFAULT_BIND, base::Bind(&base::RandInt),
89         &net_log_, NetLog::Source());
90   }
91 
CompleteCryptoHandshake()92   void CompleteCryptoHandshake() {
93     ASSERT_EQ(ERR_IO_PENDING,
94               session_.CryptoConnect(false, callback_.callback()));
95     CryptoTestUtils::HandshakeWithFakeServer(
96         connection_, session_.GetCryptoStream());
97     ASSERT_EQ(OK, callback_.WaitForResult());
98   }
99 
100   scoped_ptr<QuicDefaultPacketWriter> writer_;
101   PacketSavingConnection* connection_;
102   CapturingNetLog net_log_;
103   MockClientSocketFactory socket_factory_;
104   StaticSocketDataProvider socket_data_;
105   QuicClientSession session_;
106   MockClock clock_;
107   MockRandom random_;
108   QuicConnectionVisitorInterface* visitor_;
109   TestCompletionCallback callback_;
110   QuicCryptoClientConfig crypto_config_;
111 };
112 
113 INSTANTIATE_TEST_CASE_P(Tests, QuicClientSessionTest,
114                         ::testing::ValuesIn(QuicSupportedVersions()));
115 
TEST_P(QuicClientSessionTest,CryptoConnect)116 TEST_P(QuicClientSessionTest, CryptoConnect) {
117   CompleteCryptoHandshake();
118 }
119 
TEST_P(QuicClientSessionTest,MaxNumStreams)120 TEST_P(QuicClientSessionTest, MaxNumStreams) {
121   CompleteCryptoHandshake();
122 
123   std::vector<QuicReliableClientStream*> streams;
124   for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
125     QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
126     EXPECT_TRUE(stream);
127     streams.push_back(stream);
128   }
129   EXPECT_FALSE(session_.CreateOutgoingDataStream());
130 
131   // Close a stream and ensure I can now open a new one.
132   session_.CloseStream(streams[0]->id());
133   EXPECT_TRUE(session_.CreateOutgoingDataStream());
134 }
135 
TEST_P(QuicClientSessionTest,MaxNumStreamsViaRequest)136 TEST_P(QuicClientSessionTest, MaxNumStreamsViaRequest) {
137   CompleteCryptoHandshake();
138 
139   std::vector<QuicReliableClientStream*> streams;
140   for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) {
141     QuicReliableClientStream* stream = session_.CreateOutgoingDataStream();
142     EXPECT_TRUE(stream);
143     streams.push_back(stream);
144   }
145 
146   QuicReliableClientStream* stream;
147   QuicClientSession::StreamRequest stream_request;
148   TestCompletionCallback callback;
149   ASSERT_EQ(ERR_IO_PENDING,
150             stream_request.StartRequest(session_.GetWeakPtr(), &stream,
151                                         callback.callback()));
152 
153   // Close a stream and ensure I can now open a new one.
154   session_.CloseStream(streams[0]->id());
155   ASSERT_TRUE(callback.have_result());
156   EXPECT_EQ(OK, callback.WaitForResult());
157   EXPECT_TRUE(stream != NULL);
158 }
159 
TEST_P(QuicClientSessionTest,GoAwayReceived)160 TEST_P(QuicClientSessionTest, GoAwayReceived) {
161   CompleteCryptoHandshake();
162 
163   // After receiving a GoAway, I should no longer be able to create outgoing
164   // streams.
165   session_.OnGoAway(QuicGoAwayFrame(QUIC_PEER_GOING_AWAY, 1u, "Going away."));
166   EXPECT_EQ(NULL, session_.CreateOutgoingDataStream());
167 }
168 
169 }  // namespace
170 }  // namespace test
171 }  // namespace net
172