Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: net/socket/socks_client_socket_unittest.cc

Issue 139009: Tests for socks4/4a implementation. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: scoped_refptr Created 11 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/socks_client_socket.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2009 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/socket/socks_client_socket.h"
6
7 #include "net/base/address_list.h"
8 #include "net/base/host_resolver_unittest.h"
9 #include "net/base/listen_socket.h"
10 #include "net/base/test_completion_callback.h"
11 #include "net/base/winsock_init.h"
12 #include "net/socket/client_socket_factory.h"
13 #include "net/socket/tcp_client_socket.h"
14 #include "net/socket/socket_test_util.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "testing/platform_test.h"
17
18 //-----------------------------------------------------------------------------
19
20 namespace net {
21
22 const char kSOCKSOkRequest[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
23 const char kSOCKS4aInitialRequest[] =
24 { 0x04, 0x01, 0x00, 0x50, 0, 0, 0, 127, 0 };
25 const char kSOCKSOkReply[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
26
27 class SOCKSClientSocketTest : public PlatformTest {
28 public:
29 SOCKSClientSocketTest();
30 // Create a SOCKSClientSocket on top of a MockSocket.
31 SOCKSClientSocket* BuildMockSocket(MockRead reads[], MockWrite writes[],
32 const std::string& hostname, int port);
33 virtual void SetUp();
34
35 protected:
36 scoped_ptr<SOCKSClientSocket> user_sock_;
37 AddressList address_list_;
38 ClientSocket* tcp_sock_;
39 ScopedHostMapper host_mapper_;
40 TestCompletionCallback callback_;
41 scoped_refptr<RuleBasedHostMapper> mapper_;
42 scoped_refptr<HostResolver> host_resolver_;
43 scoped_ptr<MockSocket> mock_socket_;
44
45 private:
46 DISALLOW_COPY_AND_ASSIGN(SOCKSClientSocketTest);
47 };
48
49 SOCKSClientSocketTest::SOCKSClientSocketTest()
50 : host_resolver_(new HostResolver(0, 0)) {
51 }
52
53 // Set up platform before every test case
54 void SOCKSClientSocketTest::SetUp() {
55 PlatformTest::SetUp();
56
57 // Resolve the "localhost" AddressList used by the tcp_connection to connect.
58 scoped_refptr<HostResolver> resolver = new HostResolver();
59 HostResolver::RequestInfo info("localhost", 1080);
60 int rv = resolver->Resolve(info, &address_list_, NULL, NULL);
61 ASSERT_EQ(OK, rv);
62
63 // Create a new host mapping for the duration of this test case only.
64 mapper_ = new RuleBasedHostMapper();
65 host_mapper_.Init(mapper_);
66 mapper_->AddRule("www.google.com", "127.0.0.1");
67 }
68
69 SOCKSClientSocket* SOCKSClientSocketTest::BuildMockSocket(
70 MockRead reads[],
71 MockWrite writes[],
72 const std::string& hostname,
73 int port) {
74
75 TestCompletionCallback callback;
76 mock_socket_.reset(new StaticMockSocket(reads, writes));
77 tcp_sock_ = new MockTCPClientSocket(address_list_, mock_socket_.get());
78
79 int rv = tcp_sock_->Connect(&callback);
80 EXPECT_EQ(ERR_IO_PENDING, rv);
81 rv = callback.WaitForResult();
82 EXPECT_EQ(OK, rv);
83 EXPECT_TRUE(tcp_sock_->IsConnected());
84
85 return new SOCKSClientSocket(tcp_sock_,
86 HostResolver::RequestInfo(hostname, port),
87 host_resolver_);
88 }
89
90 // Tests a complete handshake and the disconnection.
91 TEST_F(SOCKSClientSocketTest, CompleteHandshake) {
92 const std::string payload_write = "random data";
93 const std::string payload_read = "moar random data";
94
95 MockWrite data_writes[] = {
96 MockWrite(true, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)),
97 MockWrite(true, payload_write.data(), payload_write.size()) };
98 MockRead data_reads[] = {
99 MockRead(true, kSOCKSOkReply, arraysize(kSOCKSOkReply)),
100 MockRead(true, payload_read.data(), payload_read.size()) };
101
102 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80));
103
104 // At this state the TCP connection is completed but not the SOCKS handshake.
105 EXPECT_TRUE(tcp_sock_->IsConnected());
106 EXPECT_FALSE(user_sock_->IsConnected());
107
108 int rv = user_sock_->Connect(&callback_);
109 EXPECT_EQ(ERR_IO_PENDING, rv);
110 EXPECT_FALSE(user_sock_->IsConnected());
111 rv = callback_.WaitForResult();
112
113 EXPECT_EQ(OK, rv);
114 EXPECT_TRUE(user_sock_->IsConnected());
115 EXPECT_EQ(SOCKSClientSocket::kSOCKS4, user_sock_->socks_version_);
116
117 scoped_refptr<IOBuffer> buffer = new IOBuffer(payload_write.size());
118 memcpy(buffer->data(), payload_write.data(), payload_write.size());
119 rv = user_sock_->Write(buffer, payload_write.size(), &callback_);
120 EXPECT_EQ(ERR_IO_PENDING, rv);
121 rv = callback_.WaitForResult();
122 EXPECT_EQ(static_cast<int>(payload_write.size()), rv);
123
124 buffer = new IOBuffer(payload_read.size());
125 rv = user_sock_->Read(buffer, payload_read.size(), &callback_);
126 EXPECT_EQ(ERR_IO_PENDING, rv);
127 rv = callback_.WaitForResult();
128 EXPECT_EQ(static_cast<int>(payload_read.size()), rv);
129 EXPECT_EQ(payload_read, std::string(buffer->data(), payload_read.size()));
130
131 user_sock_->Disconnect();
132 EXPECT_FALSE(tcp_sock_->IsConnected());
133 EXPECT_FALSE(user_sock_->IsConnected());
134 }
135
136 // List of responses from the socks server and the errors they should
137 // throw up are tested here.
138 TEST_F(SOCKSClientSocketTest, HandshakeFailures) {
139 const struct {
140 const char fail_reply[8];
141 Error fail_code;
142 } tests[] = {
143 // Failure of the server response code
144 {
145 { 0x01, 0x5A, 0x00, 0x00, 0, 0, 0, 0 },
146 ERR_INVALID_RESPONSE,
147 },
148 // Failure of the null byte
149 {
150 { 0x00, 0x5B, 0x00, 0x00, 0, 0, 0, 0 },
151 ERR_FAILED,
152 },
153 };
154
155 //---------------------------------------
156
157 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
158 MockWrite data_writes[] = {
159 MockWrite(false, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
160 MockRead data_reads[] = {
161 MockRead(false, tests[i].fail_reply, arraysize(tests[i].fail_reply)) };
162
163 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80));
164
165 int rv = user_sock_->Connect(&callback_);
166 EXPECT_EQ(ERR_IO_PENDING, rv);
167 rv = callback_.WaitForResult();
168 EXPECT_EQ(tests[i].fail_code, rv);
169 EXPECT_FALSE(user_sock_->IsConnected());
170 EXPECT_TRUE(tcp_sock_->IsConnected());
171 }
172 }
173
174 // Tests scenario when the server sends the handshake response in
175 // more than one packet.
176 TEST_F(SOCKSClientSocketTest, PartialServerReads) {
177 const char kSOCKSPartialReply1[] = { 0x00 };
178 const char kSOCKSPartialReply2[] = { 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
179
180 MockWrite data_writes[] = {
181 MockWrite(true, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
182 MockRead data_reads[] = {
183 MockRead(true, kSOCKSPartialReply1, arraysize(kSOCKSPartialReply1)),
184 MockRead(true, kSOCKSPartialReply2, arraysize(kSOCKSPartialReply2)) };
185
186 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80));
187
188 int rv = user_sock_->Connect(&callback_);
189 EXPECT_EQ(ERR_IO_PENDING, rv);
190 rv = callback_.WaitForResult();
191 EXPECT_EQ(OK, rv);
192 EXPECT_TRUE(user_sock_->IsConnected());
193 }
194
195 // Tests scenario when the client sends the handshake request in
196 // more than one packet.
197 TEST_F(SOCKSClientSocketTest, PartialClientWrites) {
198 const char kSOCKSPartialRequest1[] = { 0x04, 0x01 };
199 const char kSOCKSPartialRequest2[] = { 0x00, 0x50, 127, 0, 0, 1, 0 };
200
201 MockWrite data_writes[] = {
202 MockWrite(true, arraysize(kSOCKSPartialRequest1)),
203 // simulate some empty writes
204 MockWrite(true, 0),
205 MockWrite(true, 0),
206 MockWrite(true, kSOCKSPartialRequest2,
207 arraysize(kSOCKSPartialRequest2)) };
208 MockRead data_reads[] = {
209 MockRead(true, kSOCKSOkReply, arraysize(kSOCKSOkReply)) };
210
211 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80));
212
213 int rv = user_sock_->Connect(&callback_);
214 EXPECT_EQ(ERR_IO_PENDING, rv);
215 rv = callback_.WaitForResult();
216 EXPECT_EQ(OK, rv);
217 EXPECT_TRUE(user_sock_->IsConnected());
218 }
219
220 // Tests the case when the server sends a smaller sized handshake data
221 // and closes the connection.
222 TEST_F(SOCKSClientSocketTest, FailedSocketRead) {
223 MockWrite data_writes[] = {
224 MockWrite(true, kSOCKSOkRequest, arraysize(kSOCKSOkRequest)) };
225 MockRead data_reads[] = {
226 MockRead(true, kSOCKSOkReply, arraysize(kSOCKSOkReply) - 2),
227 // close connection unexpectedly
228 MockRead(false, 0) };
229
230 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80));
231
232 int rv = user_sock_->Connect(&callback_);
233 EXPECT_EQ(ERR_IO_PENDING, rv);
234 rv = callback_.WaitForResult();
235 EXPECT_EQ(ERR_CONNECTION_CLOSED, rv);
236 EXPECT_FALSE(user_sock_->IsConnected());
237 }
238
239 // Tries to connect to an unknown DNS and on failure should revert to SOCKS4A.
240 TEST_F(SOCKSClientSocketTest, SOCKS4AFailedDNS) {
241 const char hostname[] = "unresolved.ipv4.address";
242
243 mapper_->AddSimulatedFailure(hostname);
244
245 std::string request(kSOCKS4aInitialRequest,
246 arraysize(kSOCKS4aInitialRequest));
247 request.append(hostname, arraysize(hostname));
248
249 MockWrite data_writes[] = {
250 MockWrite(false, request.data(), request.size()) };
251 MockRead data_reads[] = {
252 MockRead(false, kSOCKSOkReply, arraysize(kSOCKSOkReply)) };
253
254 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80));
255
256 int rv = user_sock_->Connect(&callback_);
257 EXPECT_EQ(ERR_IO_PENDING, rv);
258 rv = callback_.WaitForResult();
259 EXPECT_EQ(OK, rv);
260 EXPECT_TRUE(user_sock_->IsConnected());
261 EXPECT_EQ(SOCKSClientSocket::kSOCKS4a, user_sock_->socks_version_);
262 }
263
264 // Tries to connect to a domain that resolves to IPv6.
265 // Should revert to SOCKS4a.
266 TEST_F(SOCKSClientSocketTest, SOCKS4AIfDomainInIPv6) {
267 const char hostname[] = "an.ipv6.address";
268
269 mapper_->AddRule(hostname, "2001:db8:8714:3a90::12");
270
271 std::string request(kSOCKS4aInitialRequest,
272 arraysize(kSOCKS4aInitialRequest));
273 request.append(hostname, arraysize(hostname));
274
275 MockWrite data_writes[] = {
276 MockWrite(false, request.data(), request.size()) };
277 MockRead data_reads[] = {
278 MockRead(false, kSOCKSOkReply, arraysize(kSOCKSOkReply)) };
279
280 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80));
281
282 int rv = user_sock_->Connect(&callback_);
283 EXPECT_EQ(ERR_IO_PENDING, rv);
284 rv = callback_.WaitForResult();
285 EXPECT_EQ(OK, rv);
286 EXPECT_TRUE(user_sock_->IsConnected());
287 EXPECT_EQ(SOCKSClientSocket::kSOCKS4a, user_sock_->socks_version_);
288 }
289
290 } // namespace net
291
OLDNEW
« no previous file with comments | « net/socket/socks_client_socket.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698