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) { | |
Ryan Hamilton
2012/12/22 22:31:32
Instead of parsing all the fields of the the CHLO
wtc
2013/01/15 03:57:59
Thank you for the suggestion. I did the latter, bu
| |
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(4u, tag_value_map[kCGST].size()); | |
164 CryptoTag congestion[1]; | |
165 memcpy(&congestion[0], &tag_value_map[kCGST][0], 4); | |
166 EXPECT_EQ(kQBIC, congestion[0]); | |
167 } | |
168 | |
36 TEST_F(QuicClientSessionTest, CryptoConnectSendsCorrectData) { | 169 TEST_F(QuicClientSessionTest, CryptoConnectSendsCorrectData) { |
37 EXPECT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 170 EXPECT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
38 ASSERT_EQ(1u, connection_->packets_.size()); | 171 ASSERT_EQ(1u, connection_->packets_.size()); |
39 scoped_ptr<QuicPacket> chlo(ConstructHandshakePacket(guid_, kCHLO)); | 172 CheckClientHelloPacket(connection_->packets_[0]); |
40 CompareQuicDataWithHexError("CHLO", connection_->packets_[0], chlo.get()); | |
41 } | 173 } |
42 | 174 |
43 TEST_F(QuicClientSessionTest, CryptoConnectSendsCompletesAfterSHLO) { | 175 TEST_F(QuicClientSessionTest, CryptoConnectSendsCompletesAfterSHLO) { |
44 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 176 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
45 // Send the SHLO message. | 177 // Send the SHLO message. |
46 CryptoHandshakeMessage server_message; | 178 CryptoHandshakeMessage server_message; |
47 server_message.tag = kSHLO; | 179 server_message.tag = kSHLO; |
48 session_.GetCryptoStream()->OnHandshakeMessage(server_message); | 180 session_.GetCryptoStream()->OnHandshakeMessage(server_message); |
49 EXPECT_EQ(OK, callback_.WaitForResult()); | 181 EXPECT_EQ(OK, callback_.WaitForResult()); |
50 } | 182 } |
51 | 183 |
52 TEST_F(QuicClientSessionTest, MaxNumConnections) { | 184 TEST_F(QuicClientSessionTest, MaxNumConnections) { |
53 // Initialize crypto before the client session will create a stream. | 185 // Initialize crypto before the client session will create a stream. |
54 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); | 186 ASSERT_EQ(ERR_IO_PENDING, session_.CryptoConnect(callback_.callback())); |
187 // Simulate the server crypto handshake. | |
55 CryptoHandshakeMessage server_message; | 188 CryptoHandshakeMessage server_message; |
56 server_message.tag = kSHLO; | 189 server_message.tag = kSHLO; |
57 session_.GetCryptoStream()->OnHandshakeMessage(server_message); | 190 session_.GetCryptoStream()->OnHandshakeMessage(server_message); |
58 callback_.WaitForResult(); | 191 callback_.WaitForResult(); |
59 | 192 |
60 std::vector<QuicReliableClientStream*> streams; | 193 std::vector<QuicReliableClientStream*> streams; |
61 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { | 194 for (size_t i = 0; i < kDefaultMaxStreamsPerConnection; i++) { |
62 QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream(); | 195 QuicReliableClientStream* stream = session_.CreateOutgoingReliableStream(); |
63 EXPECT_TRUE(stream); | 196 EXPECT_TRUE(stream); |
64 streams.push_back(stream); | 197 streams.push_back(stream); |
65 } | 198 } |
66 EXPECT_FALSE(session_.CreateOutgoingReliableStream()); | 199 EXPECT_FALSE(session_.CreateOutgoingReliableStream()); |
67 | 200 |
68 // Close a stream and ensure I can now open a new one. | 201 // Close a stream and ensure I can now open a new one. |
69 session_.CloseStream(streams[0]->id()); | 202 session_.CloseStream(streams[0]->id()); |
70 EXPECT_TRUE(session_.CreateOutgoingReliableStream()); | 203 EXPECT_TRUE(session_.CreateOutgoingReliableStream()); |
71 } | 204 } |
72 | 205 |
73 } // namespace | 206 } // namespace |
74 } // namespace test | 207 } // namespace test |
75 } // namespace net | 208 } // namespace net |
OLD | NEW |