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.
5 #include "net/socket/socks_client_socket.h"
7 #include "net/base/address_list.h"
8 #include "net/base/net_log.h"
9 #include "net/base/net_log_unittest.h"
10 #include "net/base/mock_host_resolver.h"
11 #include "net/base/test_completion_callback.h"
12 #include "net/base/winsock_init.h"
13 #include "net/socket/client_socket_factory.h"
14 #include "net/socket/tcp_client_socket.h"
15 #include "net/socket/socket_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "testing/platform_test.h"
19 //-----------------------------------------------------------------------------
23 const char kSOCKSOkRequest
[] = { 0x04, 0x01, 0x00, 0x50, 127, 0, 0, 1, 0 };
24 const char kSOCKSOkReply
[] = { 0x00, 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
26 class SOCKSClientSocketTest
: public PlatformTest
{
28 SOCKSClientSocketTest();
29 // Create a SOCKSClientSocket on top of a MockSocket.
30 SOCKSClientSocket
* BuildMockSocket(MockRead reads
[], size_t reads_count
,
31 MockWrite writes
[], size_t writes_count
,
32 HostResolver
* host_resolver
,
33 const std::string
& hostname
, int port
,
38 scoped_ptr
<SOCKSClientSocket
> user_sock_
;
39 AddressList address_list_
;
40 StreamSocket
* tcp_sock_
;
41 TestCompletionCallback callback_
;
42 scoped_ptr
<MockHostResolver
> host_resolver_
;
43 scoped_ptr
<SocketDataProvider
> data_
;
46 SOCKSClientSocketTest::SOCKSClientSocketTest()
47 : host_resolver_(new MockHostResolver
) {
50 // Set up platform before every test case
51 void SOCKSClientSocketTest::SetUp() {
52 PlatformTest::SetUp();
55 SOCKSClientSocket
* SOCKSClientSocketTest::BuildMockSocket(
60 HostResolver
* host_resolver
,
61 const std::string
& hostname
,
65 TestCompletionCallback callback
;
66 data_
.reset(new StaticSocketDataProvider(reads
, reads_count
,
67 writes
, writes_count
));
68 tcp_sock_
= new MockTCPClientSocket(address_list_
, net_log
, data_
.get());
70 int rv
= tcp_sock_
->Connect(callback
.callback());
71 EXPECT_EQ(ERR_IO_PENDING
, rv
);
72 rv
= callback
.WaitForResult();
74 EXPECT_TRUE(tcp_sock_
->IsConnected());
76 return new SOCKSClientSocket(tcp_sock_
,
77 HostResolver::RequestInfo(HostPortPair(hostname
, port
)),
81 // Implementation of HostResolver that never completes its resolve request.
82 // We use this in the test "DisconnectWhileHostResolveInProgress" to make
83 // sure that the outstanding resolve request gets cancelled.
84 class HangingHostResolverWithCancel
: public HostResolver
{
86 HangingHostResolverWithCancel() : outstanding_request_(NULL
) {}
88 virtual int Resolve(const RequestInfo
& info
,
89 AddressList
* addresses
,
90 const CompletionCallback
& callback
,
91 RequestHandle
* out_req
,
92 const BoundNetLog
& net_log
) OVERRIDE
{
94 DCHECK_EQ(false, callback
.is_null());
95 EXPECT_FALSE(HasOutstandingRequest());
96 outstanding_request_
= reinterpret_cast<RequestHandle
>(1);
97 *out_req
= outstanding_request_
;
98 return ERR_IO_PENDING
;
101 virtual int ResolveFromCache(const RequestInfo
& info
,
102 AddressList
* addresses
,
103 const BoundNetLog
& net_log
) OVERRIDE
{
105 return ERR_UNEXPECTED
;
108 virtual void CancelRequest(RequestHandle req
) OVERRIDE
{
109 EXPECT_TRUE(HasOutstandingRequest());
110 EXPECT_EQ(outstanding_request_
, req
);
111 outstanding_request_
= NULL
;
114 bool HasOutstandingRequest() {
115 return outstanding_request_
!= NULL
;
119 RequestHandle outstanding_request_
;
121 DISALLOW_COPY_AND_ASSIGN(HangingHostResolverWithCancel
);
124 // Tests a complete handshake and the disconnection.
125 TEST_F(SOCKSClientSocketTest
, CompleteHandshake
) {
126 const std::string payload_write
= "random data";
127 const std::string payload_read
= "moar random data";
129 MockWrite data_writes
[] = {
130 MockWrite(ASYNC
, kSOCKSOkRequest
, arraysize(kSOCKSOkRequest
)),
131 MockWrite(ASYNC
, payload_write
.data(), payload_write
.size()) };
132 MockRead data_reads
[] = {
133 MockRead(ASYNC
, kSOCKSOkReply
, arraysize(kSOCKSOkReply
)),
134 MockRead(ASYNC
, payload_read
.data(), payload_read
.size()) };
137 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
138 data_writes
, arraysize(data_writes
),
139 host_resolver_
.get(),
143 // At this state the TCP connection is completed but not the SOCKS handshake.
144 EXPECT_TRUE(tcp_sock_
->IsConnected());
145 EXPECT_FALSE(user_sock_
->IsConnected());
147 int rv
= user_sock_
->Connect(callback_
.callback());
148 EXPECT_EQ(ERR_IO_PENDING
, rv
);
150 CapturingNetLog::CapturedEntryList entries
;
151 log
.GetEntries(&entries
);
153 LogContainsBeginEvent(entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
154 EXPECT_FALSE(user_sock_
->IsConnected());
156 rv
= callback_
.WaitForResult();
158 EXPECT_TRUE(user_sock_
->IsConnected());
159 log
.GetEntries(&entries
);
160 EXPECT_TRUE(LogContainsEndEvent(
161 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
163 scoped_refptr
<IOBuffer
> buffer(new IOBuffer(payload_write
.size()));
164 memcpy(buffer
->data(), payload_write
.data(), payload_write
.size());
165 rv
= user_sock_
->Write(buffer
, payload_write
.size(), callback_
.callback());
166 EXPECT_EQ(ERR_IO_PENDING
, rv
);
167 rv
= callback_
.WaitForResult();
168 EXPECT_EQ(static_cast<int>(payload_write
.size()), rv
);
170 buffer
= new IOBuffer(payload_read
.size());
171 rv
= user_sock_
->Read(buffer
, payload_read
.size(), callback_
.callback());
172 EXPECT_EQ(ERR_IO_PENDING
, rv
);
173 rv
= callback_
.WaitForResult();
174 EXPECT_EQ(static_cast<int>(payload_read
.size()), rv
);
175 EXPECT_EQ(payload_read
, std::string(buffer
->data(), payload_read
.size()));
177 user_sock_
->Disconnect();
178 EXPECT_FALSE(tcp_sock_
->IsConnected());
179 EXPECT_FALSE(user_sock_
->IsConnected());
182 // List of responses from the socks server and the errors they should
183 // throw up are tested here.
184 TEST_F(SOCKSClientSocketTest
, HandshakeFailures
) {
186 const char fail_reply
[8];
189 // Failure of the server response code
191 { 0x01, 0x5A, 0x00, 0x00, 0, 0, 0, 0 },
192 ERR_SOCKS_CONNECTION_FAILED
,
194 // Failure of the null byte
196 { 0x00, 0x5B, 0x00, 0x00, 0, 0, 0, 0 },
197 ERR_SOCKS_CONNECTION_FAILED
,
201 //---------------------------------------
203 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(tests
); ++i
) {
204 MockWrite data_writes
[] = {
205 MockWrite(SYNCHRONOUS
, kSOCKSOkRequest
, arraysize(kSOCKSOkRequest
)) };
206 MockRead data_reads
[] = {
207 MockRead(SYNCHRONOUS
, tests
[i
].fail_reply
,
208 arraysize(tests
[i
].fail_reply
)) };
211 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
212 data_writes
, arraysize(data_writes
),
213 host_resolver_
.get(),
217 int rv
= user_sock_
->Connect(callback_
.callback());
218 EXPECT_EQ(ERR_IO_PENDING
, rv
);
220 CapturingNetLog::CapturedEntryList entries
;
221 log
.GetEntries(&entries
);
222 EXPECT_TRUE(LogContainsBeginEvent(
223 entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
225 rv
= callback_
.WaitForResult();
226 EXPECT_EQ(tests
[i
].fail_code
, rv
);
227 EXPECT_FALSE(user_sock_
->IsConnected());
228 EXPECT_TRUE(tcp_sock_
->IsConnected());
229 log
.GetEntries(&entries
);
230 EXPECT_TRUE(LogContainsEndEvent(
231 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
235 // Tests scenario when the server sends the handshake response in
236 // more than one packet.
237 TEST_F(SOCKSClientSocketTest
, PartialServerReads
) {
238 const char kSOCKSPartialReply1
[] = { 0x00 };
239 const char kSOCKSPartialReply2
[] = { 0x5A, 0x00, 0x00, 0, 0, 0, 0 };
241 MockWrite data_writes
[] = {
242 MockWrite(ASYNC
, kSOCKSOkRequest
, arraysize(kSOCKSOkRequest
)) };
243 MockRead data_reads
[] = {
244 MockRead(ASYNC
, kSOCKSPartialReply1
, arraysize(kSOCKSPartialReply1
)),
245 MockRead(ASYNC
, kSOCKSPartialReply2
, arraysize(kSOCKSPartialReply2
)) };
248 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
249 data_writes
, arraysize(data_writes
),
250 host_resolver_
.get(),
254 int rv
= user_sock_
->Connect(callback_
.callback());
255 EXPECT_EQ(ERR_IO_PENDING
, rv
);
256 CapturingNetLog::CapturedEntryList entries
;
257 log
.GetEntries(&entries
);
258 EXPECT_TRUE(LogContainsBeginEvent(
259 entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
261 rv
= callback_
.WaitForResult();
263 EXPECT_TRUE(user_sock_
->IsConnected());
264 log
.GetEntries(&entries
);
265 EXPECT_TRUE(LogContainsEndEvent(
266 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
269 // Tests scenario when the client sends the handshake request in
270 // more than one packet.
271 TEST_F(SOCKSClientSocketTest
, PartialClientWrites
) {
272 const char kSOCKSPartialRequest1
[] = { 0x04, 0x01 };
273 const char kSOCKSPartialRequest2
[] = { 0x00, 0x50, 127, 0, 0, 1, 0 };
275 MockWrite data_writes
[] = {
276 MockWrite(ASYNC
, arraysize(kSOCKSPartialRequest1
)),
277 // simulate some empty writes
280 MockWrite(ASYNC
, kSOCKSPartialRequest2
,
281 arraysize(kSOCKSPartialRequest2
)) };
282 MockRead data_reads
[] = {
283 MockRead(ASYNC
, kSOCKSOkReply
, arraysize(kSOCKSOkReply
)) };
286 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
287 data_writes
, arraysize(data_writes
),
288 host_resolver_
.get(),
292 int rv
= user_sock_
->Connect(callback_
.callback());
293 EXPECT_EQ(ERR_IO_PENDING
, rv
);
294 CapturingNetLog::CapturedEntryList entries
;
295 log
.GetEntries(&entries
);
296 EXPECT_TRUE(LogContainsBeginEvent(
297 entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
299 rv
= callback_
.WaitForResult();
301 EXPECT_TRUE(user_sock_
->IsConnected());
302 log
.GetEntries(&entries
);
303 EXPECT_TRUE(LogContainsEndEvent(
304 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
307 // Tests the case when the server sends a smaller sized handshake data
308 // and closes the connection.
309 TEST_F(SOCKSClientSocketTest
, FailedSocketRead
) {
310 MockWrite data_writes
[] = {
311 MockWrite(ASYNC
, kSOCKSOkRequest
, arraysize(kSOCKSOkRequest
)) };
312 MockRead data_reads
[] = {
313 MockRead(ASYNC
, kSOCKSOkReply
, arraysize(kSOCKSOkReply
) - 2),
314 // close connection unexpectedly
315 MockRead(SYNCHRONOUS
, 0) };
318 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
319 data_writes
, arraysize(data_writes
),
320 host_resolver_
.get(),
324 int rv
= user_sock_
->Connect(callback_
.callback());
325 EXPECT_EQ(ERR_IO_PENDING
, rv
);
326 CapturingNetLog::CapturedEntryList entries
;
327 log
.GetEntries(&entries
);
328 EXPECT_TRUE(LogContainsBeginEvent(
329 entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
331 rv
= callback_
.WaitForResult();
332 EXPECT_EQ(ERR_CONNECTION_CLOSED
, rv
);
333 EXPECT_FALSE(user_sock_
->IsConnected());
334 log
.GetEntries(&entries
);
335 EXPECT_TRUE(LogContainsEndEvent(
336 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
339 // Tries to connect to an unknown hostname. Should fail rather than
340 // falling back to SOCKS4a.
341 TEST_F(SOCKSClientSocketTest
, FailedDNS
) {
342 const char hostname
[] = "unresolved.ipv4.address";
344 host_resolver_
->rules()->AddSimulatedFailure(hostname
);
348 user_sock_
.reset(BuildMockSocket(NULL
, 0,
350 host_resolver_
.get(),
354 int rv
= user_sock_
->Connect(callback_
.callback());
355 EXPECT_EQ(ERR_IO_PENDING
, rv
);
356 CapturingNetLog::CapturedEntryList entries
;
357 log
.GetEntries(&entries
);
358 EXPECT_TRUE(LogContainsBeginEvent(
359 entries
, 0, NetLog::TYPE_SOCKS_CONNECT
));
361 rv
= callback_
.WaitForResult();
362 EXPECT_EQ(ERR_NAME_NOT_RESOLVED
, rv
);
363 EXPECT_FALSE(user_sock_
->IsConnected());
364 log
.GetEntries(&entries
);
365 EXPECT_TRUE(LogContainsEndEvent(
366 entries
, -1, NetLog::TYPE_SOCKS_CONNECT
));
369 // Calls Disconnect() while a host resolve is in progress. The outstanding host
370 // resolve should be cancelled.
371 TEST_F(SOCKSClientSocketTest
, DisconnectWhileHostResolveInProgress
) {
372 scoped_ptr
<HangingHostResolverWithCancel
> hanging_resolver(
373 new HangingHostResolverWithCancel());
375 // Doesn't matter what the socket data is, we will never use it -- garbage.
376 MockWrite data_writes
[] = { MockWrite(SYNCHRONOUS
, "", 0) };
377 MockRead data_reads
[] = { MockRead(SYNCHRONOUS
, "", 0) };
379 user_sock_
.reset(BuildMockSocket(data_reads
, arraysize(data_reads
),
380 data_writes
, arraysize(data_writes
),
381 hanging_resolver
.get(),
385 // Start connecting (will get stuck waiting for the host to resolve).
386 int rv
= user_sock_
->Connect(callback_
.callback());
387 EXPECT_EQ(ERR_IO_PENDING
, rv
);
389 EXPECT_FALSE(user_sock_
->IsConnected());
390 EXPECT_FALSE(user_sock_
->IsConnectedAndIdle());
392 // The host resolver should have received the resolve request.
393 EXPECT_TRUE(hanging_resolver
->HasOutstandingRequest());
395 // Disconnect the SOCKS socket -- this should cancel the outstanding resolve.
396 user_sock_
->Disconnect();
398 EXPECT_FALSE(hanging_resolver
->HasOutstandingRequest());
400 EXPECT_FALSE(user_sock_
->IsConnected());
401 EXPECT_FALSE(user_sock_
->IsConnectedAndIdle());