Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/quic/quic_client_session.h" | 5 #include "net/quic/quic_client_session.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "net/base/test_completion_callback.h" | 10 #include "net/base/test_completion_callback.h" |
| 11 #include "net/quic/crypto/crypto_protocol.h" | 11 #include "net/quic/crypto/crypto_protocol.h" |
| 12 #include "net/quic/test_tools/quic_test_utils.h" | 12 #include "net/quic/test_tools/quic_test_utils.h" |
| 13 | 13 |
| 14 using base::StringPiece; | |
| 15 using std::vector; | |
| 14 using testing::_; | 16 using testing::_; |
| 15 | 17 |
| 16 namespace net { | 18 namespace net { |
| 17 namespace test { | 19 namespace test { |
| 18 namespace { | 20 namespace { |
| 19 | 21 |
| 22 class TestEncrypter : public QuicEncrypter { | |
| 23 public: | |
| 24 virtual QuicData* Encrypt(StringPiece associated_data, | |
| 25 StringPiece plaintext) { | |
| 26 return new QuicData(plaintext.data(), plaintext.length()); | |
| 27 } | |
| 28 virtual size_t GetMaxPlaintextSize(size_t ciphertext_size) { | |
| 29 return ciphertext_size; | |
| 30 } | |
| 31 virtual size_t GetCiphertextSize(size_t plaintext_size) { | |
| 32 return plaintext_size; | |
| 33 } | |
| 34 }; | |
| 35 | |
| 36 class TestDecrypter : public QuicDecrypter { | |
| 37 public: | |
| 38 virtual QuicData* Decrypt(StringPiece associated_data, | |
| 39 StringPiece ciphertext) { | |
| 40 return new QuicData(ciphertext.data(), ciphertext.length()); | |
| 41 } | |
| 42 }; | |
| 43 | |
| 44 class TestQuicVisitor : public NoOpFramerVisitor { | |
| 45 public: | |
| 46 TestQuicVisitor() {} | |
| 47 | |
| 48 // NoOpFramerVisitor | |
| 49 virtual void OnStreamFrame(const QuicStreamFrame& frame) { | |
| 50 frame_ = frame; | |
| 51 } | |
| 52 | |
| 53 QuicStreamFrame* frame() { return &frame_; } | |
| 54 | |
| 55 private: | |
| 56 QuicStreamFrame frame_; | |
| 57 | |
| 58 DISALLOW_COPY_AND_ASSIGN(TestQuicVisitor); | |
| 59 }; | |
| 60 | |
| 61 class TestCryptoVisitor : public CryptoFramerVisitorInterface { | |
| 62 public: | |
| 63 TestCryptoVisitor() | |
| 64 : error_count_(0) { | |
| 65 } | |
| 66 | |
| 67 virtual void OnError(CryptoFramer* framer) { | |
| 68 DLOG(ERROR) << "CryptoFramer Error: " << framer->error(); | |
| 69 ++error_count_; | |
| 70 } | |
| 71 | |
| 72 virtual void OnHandshakeMessage(const CryptoHandshakeMessage& message) { | |
| 73 messages_.push_back(message); | |
| 74 } | |
| 75 | |
| 76 // Counters from the visitor callbacks. | |
| 77 int error_count_; | |
| 78 | |
| 79 vector<CryptoHandshakeMessage> messages_; | |
| 80 }; | |
| 81 | |
| 20 class QuicClientSessionTest : public ::testing::Test { | 82 class QuicClientSessionTest : public ::testing::Test { |
| 21 protected: | 83 protected: |
| 22 QuicClientSessionTest() | 84 QuicClientSessionTest() |
| 23 : guid_(1), | 85 : guid_(1), |
| 24 connection_(new PacketSavingConnection(guid_, IPEndPoint())), | 86 connection_(new PacketSavingConnection(guid_, IPEndPoint())), |
| 25 session_(connection_, NULL, NULL) { | 87 session_(connection_, NULL, NULL) { |
| 26 } | 88 } |
| 27 | 89 |
| 28 protected: | 90 // Checks whether |packet| is the default ClientHello packet. |
| 91 void CheckClientHelloPacket(QuicPacket* packet); | |
| 92 | |
| 29 QuicGuid guid_; | 93 QuicGuid guid_; |
| 30 PacketSavingConnection* connection_; | 94 PacketSavingConnection* connection_; |
| 31 QuicClientSession session_; | 95 QuicClientSession session_; |
| 32 QuicConnectionVisitorInterface* visitor_; | 96 QuicConnectionVisitorInterface* visitor_; |
| 33 TestCompletionCallback callback_; | 97 TestCompletionCallback callback_; |
| 34 }; | 98 }; |
| 35 | 99 |
| 100 void QuicClientSessionTest::CheckClientHelloPacket(QuicPacket* packet) { | |
| 101 QuicFramer quic_framer(new TestDecrypter, new TestEncrypter); | |
| 102 TestQuicVisitor quic_visitor; | |
| 103 quic_framer.set_visitor(&quic_visitor); | |
| 104 QuicEncryptedPacket encrypted(packet->data(), packet->length()); | |
| 105 ASSERT_TRUE(quic_framer.ProcessPacket(IPEndPoint(), IPEndPoint(), | |
| 106 encrypted)); | |
| 107 EXPECT_EQ(kCryptoStreamId, quic_visitor.frame()->stream_id); | |
| 108 EXPECT_FALSE(quic_visitor.frame()->fin); | |
| 109 EXPECT_EQ(0u, quic_visitor.frame()->offset); | |
| 110 | |
| 111 // Check quic_visitor.frame()->data. | |
| 112 test::TestCryptoVisitor crypto_visitor; | |
| 113 CryptoFramer crypto_framer; | |
| 114 crypto_framer.set_visitor(&crypto_visitor); | |
| 115 ASSERT_TRUE(crypto_framer.ProcessInput(quic_visitor.frame()->data)); | |
| 116 ASSERT_EQ(0u, crypto_framer.InputBytesRemaining()); | |
| 117 ASSERT_EQ(1u, crypto_visitor.messages_.size()); | |
| 118 EXPECT_EQ(kCHLO, crypto_visitor.messages_[0].tag); | |
| 119 | |
| 120 CryptoTagValueMap& tag_value_map = | |
| 121 crypto_visitor.messages_[0].tag_value_map; | |
| 122 ASSERT_EQ(7u, tag_value_map.size()); | |
| 123 | |
| 124 // kNONC | |
| 125 // TODO(wtc): check the nonce. | |
| 126 ASSERT_EQ(32u, tag_value_map[kNONC].size()); | |
| 127 | |
| 128 // kAEAD | |
| 129 ASSERT_EQ(8u, tag_value_map[kAEAD].size()); | |
| 130 CryptoTag cipher[2]; | |
| 131 memcpy(&cipher[0], &tag_value_map[kAEAD][0], 4); | |
| 132 memcpy(&cipher[1], &tag_value_map[kAEAD][4], 4); | |
| 133 EXPECT_EQ(kAESG, cipher[0]); | |
| 134 EXPECT_EQ(kAESH, cipher[1]); | |
| 135 | |
| 136 // kICSL | |
| 137 ASSERT_EQ(4u, tag_value_map[kICSL].size()); | |
| 138 uint32 idle_lifetime; | |
| 139 memcpy(&idle_lifetime, tag_value_map[kICSL].data(), 4); | |
| 140 EXPECT_EQ(300u, idle_lifetime); | |
| 141 | |
| 142 // kKATO | |
| 143 ASSERT_EQ(4u, tag_value_map[kKATO].size()); | |
| 144 uint32 keepalive_timeout; | |
| 145 memcpy(&keepalive_timeout, tag_value_map[kKATO].data(), 4); | |
| 146 EXPECT_EQ(0u, keepalive_timeout); | |
| 147 | |
| 148 // kVERS | |
| 149 ASSERT_EQ(2u, tag_value_map[kVERS].size()); | |
| 150 uint16 version; | |
| 151 memcpy(&version, tag_value_map[kVERS].data(), 2); | |
| 152 EXPECT_EQ(0u, version); | |
| 153 | |
| 154 // kKEXS | |
| 155 ASSERT_EQ(8u, tag_value_map[kKEXS].size()); | |
| 156 CryptoTag key_exchange[2]; | |
| 157 memcpy(&key_exchange[0], &tag_value_map[kKEXS][0], 4); | |
| 158 memcpy(&key_exchange[1], &tag_value_map[kKEXS][4], 4); | |
| 159 EXPECT_EQ(kC255, key_exchange[0]); | |
| 160 EXPECT_EQ(kP256, key_exchange[1]); | |
| 161 | |
| 162 // kCGST | |
| 163 ASSERT_EQ(8u, tag_value_map[kCGST].size()); | |
| 164 CryptoTag congestion[2]; | |
| 165 memcpy(&congestion[0], &tag_value_map[kCGST][0], 4); | |
| 166 memcpy(&congestion[1], &tag_value_map[kCGST][4], 4); | |
| 167 EXPECT_EQ(kQBIC, congestion[0]); | |
| 168 EXPECT_EQ(kINAR, congestion[1]); | |
| 169 } | |
| 170 | |
| 36 TEST_F(QuicClientSessionTest, CryptoConnectSendsCorrectData) { | 171 TEST_F(QuicClientSessionTest, CryptoConnectSendsCorrectData) { |
| 37 EXPECT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 172 EXPECT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
| 38 ASSERT_EQ(1u, connection_->packets_.size()); | 173 ASSERT_EQ(1u, connection_->packets_.size()); |
| 39 scoped_ptr<QuicPacket> chlo(ConstructHandshakePacket(guid_, kCHLO)); | 174 CheckClientHelloPacket(connection_->packets_[0]); |
| 40 CompareQuicDataWithHexError("CHLO", connection_->packets_[0], chlo.get()); | |
| 41 } | 175 } |
| 42 | 176 |
| 43 TEST_F(QuicClientSessionTest, CryptoConnectSendsCompletesAfterSHLO) { | 177 TEST_F(QuicClientSessionTest, CryptoConnectSendsCompletesAfterSHLO) { |
| 44 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 178 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
|
wtc
2012/12/20 00:33:08
Do you want me to copy
ASSERT_EQ(1u, connection_
Ryan Hamilton
2012/12/20 18:51:06
I think it's fine to rely on the earlier test.
| |
| 45 // Send the SHLO message. | 179 // Send the SHLO message. |
| 46 CryptoHandshakeMessage server_message; | 180 CryptoHandshakeMessage server_message; |
| 47 server_message.tag = kSHLO; | 181 server_message.tag = kSHLO; |
| 48 session_.GetCryptoStream()->OnHandshakeMessage(server_message); | 182 session_.GetCryptoStream()->OnHandshakeMessage(server_message); |
| 49 EXPECT_EQ(OK, callback_.WaitForResult()); | 183 EXPECT_EQ(OK, callback_.WaitForResult()); |
| 50 } | 184 } |
| 51 | 185 |
| 52 TEST_F(QuicClientSessionTest, MaxNumConnections) { | 186 TEST_F(QuicClientSessionTest, MaxNumConnections) { |
| 53 // Initialize crypto before the client session will create a stream. | 187 // Initialize crypto before the client session will create a stream. |
| 54 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 188 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
| 189 ASSERT_EQ(1u, connection_->packets_.size()); | |
| 190 CheckClientHelloPacket(connection_->packets_[0]); | |
|
wtc
2012/12/20 00:33:08
Note that I copied these two lines to this test. N
Ryan Hamilton
2012/12/20 18:51:06
My vote goes for not duplicating the earlier test,
| |
| 191 // Simulate the server crypto handshake. | |
| 55 CryptoHandshakeMessage server_message; | 192 CryptoHandshakeMessage server_message; |
| 56 server_message.tag = kSHLO; | 193 server_message.tag = kSHLO; |
| 57 session_.GetCryptoStream()->OnHandshakeMessage(server_message); | 194 session_.GetCryptoStream()->OnHandshakeMessage(server_message); |
| 58 callback_.WaitForResult(); | 195 callback_.WaitForResult(); |
| 59 | 196 |
| 60 std::vector<QuicReliableClientStream*> streams; | 197 std::vector<QuicReliableClientStream*> streams; |
| 61 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { | 198 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { |
| 62 QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream(); | 199 QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream(); |
| 63 EXPECT_TRUE(stream); | 200 EXPECT_TRUE(stream); |
| 64 streams.push_back(stream); | 201 streams.push_back(stream); |
| 65 } | 202 } |
| 66 EXPECT_FALSE(session_.CreateOutgoingReliableStream()); | 203 EXPECT_FALSE(session_.CreateOutgoingReliableStream()); |
| 67 | 204 |
| 68 // Close a stream and ensure I can now open a new one. | 205 // Close a stream and ensure I can now open a new one. |
| 69 session_.CloseStream(streams[0]->id()); | 206 session_.CloseStream(streams[0]->id()); |
| 70 EXPECT_TRUE(session_.CreateOutgoingReliableStream()); | 207 EXPECT_TRUE(session_.CreateOutgoingReliableStream()); |
| 71 } | 208 } |
| 72 | 209 |
| 73 } // namespace | 210 } // namespace |
| 74 } // namespace test | 211 } // namespace test |
| 75 } // namespace net | 212 } // namespace net |
| OLD | NEW |