15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socks5_client_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log_unittest.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/mock_host_resolver.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_factory.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socket_test_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/tcp_client_socket.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Base class to test SOCKS5ClientSocket
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SOCKS5ClientSocketTest : public PlatformTest {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SOCKS5ClientSocketTest();
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a SOCKSClientSocket on top of a MockSocket.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SOCKS5ClientSocket* BuildMockSocket(MockRead reads[],
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      size_t reads_count,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      MockWrite writes[],
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      size_t writes_count,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const std::string& hostname,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int port,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NetLog* net_log);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint16 kNwPort;
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog net_log_;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SOCKS5ClientSocket> user_sock_;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressList address_list_;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamSocket* tcp_sock_;
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockHostResolver> host_resolver_;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SocketDataProvider> data_;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SOCKS5ClientSocketTest);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SOCKS5ClientSocketTest::SOCKS5ClientSocketTest()
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : kNwPort(base::HostToNet16(80)),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    host_resolver_(new MockHostResolver) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set up platform before every test case
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocketTest::SetUp() {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PlatformTest::SetUp();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Resolve the "localhost" AddressList used by the TCP connection to connect.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HostResolver::RequestInfo info(HostPortPair("www.socks-proxy.com", 1080));
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = host_resolver_->Resolve(info, &address_list_, callback.callback(),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   NULL, BoundNetLog());
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(ERR_IO_PENDING, rv);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(OK, rv);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SOCKS5ClientSocket* SOCKS5ClientSocketTest::BuildMockSocket(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead reads[],
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t reads_count,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite writes[],
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t writes_count,
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& hostname,
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog* net_log) {
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data_.reset(new StaticSocketDataProvider(reads, reads_count,
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           writes, writes_count));
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  tcp_sock_ = new MockTCPClientSocket(address_list_, net_log, data_.get());
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = tcp_sock_->Connect(callback.callback());
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback.WaitForResult();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, rv);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(tcp_sock_->IsConnected());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new SOCKS5ClientSocket(tcp_sock_,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HostResolver::RequestInfo(HostPortPair(hostname, port)));
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests a complete SOCKS5 handshake and the disconnection.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SOCKS5ClientSocketTest, CompleteHandshake) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string payload_write = "random data";
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string payload_read = "moar random data";
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kOkRequest[] = {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x05,  // Version
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x01,  // Command (CONNECT)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x00,  // Reserved.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x03,  // Address type (DOMAINNAME).
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x09,  // Length of domain (9)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Domain string:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't',
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x00, 0x50,  // 16-bit port (80)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockWrite(ASYNC, kOkRequest, arraysize(kOkRequest)),
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockWrite(ASYNC, payload_write.data(), payload_write.size()) };
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MockRead(ASYNC, payload_read.data(), payload_read.size()) };
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   data_writes, arraysize(data_writes),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   "localhost", 80, &net_log_));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // At this state the TCP connection is completed but not the SOCKS handshake.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(tcp_sock_->IsConnected());
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(user_sock_->IsConnected());
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = user_sock_->Connect(callback_.callback());
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(user_sock_->IsConnected());
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CapturingNetLog::CapturedEntryList net_log_entries;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.GetEntries(&net_log_entries);
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    NetLog::TYPE_SOCKS5_CONNECT));
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback_.WaitForResult();
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(OK, rv);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(user_sock_->IsConnected());
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.GetEntries(&net_log_entries);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  NetLog::TYPE_SOCKS5_CONNECT));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<IOBuffer> buffer(new IOBuffer(payload_write.size()));
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buffer->data(), payload_write.data(), payload_write.size());
154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv = user_sock_->Write(
155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      buffer.get(), payload_write.size(), callback_.callback());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback_.WaitForResult();
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(payload_write.size()), rv);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  buffer = new IOBuffer(payload_read.size());
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  rv =
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      user_sock_->Read(buffer.get(), payload_read.size(), callback_.callback());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING, rv);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = callback_.WaitForResult();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(static_cast<int>(payload_read.size()), rv);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(payload_read, std::string(buffer->data(), payload_read.size()));
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_sock_->Disconnect();
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(tcp_sock_->IsConnected());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(user_sock_->IsConnected());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that you can call Connect() again after having called Disconnect().
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SOCKS5ClientSocketTest, ConnectAndDisconnectTwice) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string hostname = "my-host-name";
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kSOCKS5DomainRequest[] = {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0x05,  // VER
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0x01,  // CMD
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0x00,  // RSV
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      0x03,  // ATYPE
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string request(kSOCKS5DomainRequest, arraysize(kSOCKS5DomainRequest));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.push_back(hostname.size());
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.append(hostname);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request.append(reinterpret_cast<const char*>(&kNwPort), sizeof(kNwPort));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i) {
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite data_writes[] = {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(SYNCHRONOUS, request.data(), request.size())
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead data_reads[] = {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(SYNCHRONOUS, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(SYNCHRONOUS, kSOCKS5OkResponse, kSOCKS5OkResponseLength)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     data_writes, arraysize(data_writes),
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     hostname, 80, NULL));
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = user_sock_->Connect(callback_.callback());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(user_sock_->IsConnected());
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_->Disconnect();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(user_sock_->IsConnected());
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we fail trying to connect to a hosname longer than 255 bytes.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SOCKS5ClientSocketTest, LargeHostNameFails) {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a string of length 256, where each character is 'x'.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string large_host_name;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::fill_n(std::back_inserter(large_host_name), 256, 'x');
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a SOCKS socket, with mock transport socket.
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockWrite data_writes[] = {MockWrite()};
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRead data_reads[] = {MockRead()};
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   data_writes, arraysize(data_writes),
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   large_host_name, 80, NULL));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to connect -- should fail (without having read/written anything to
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the transport socket first) because the hostname is too long.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = user_sock_->Connect(callback.callback());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_SOCKS_CONNECTION_FAILED, rv);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string hostname = "www.google.com";
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kOkRequest[] = {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x05,  // Version
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x01,  // Command (CONNECT)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x00,  // Reserved.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x03,  // Address type (DOMAINNAME).
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x0E,  // Length of domain (14)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Domain string:
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm',
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    0x00, 0x50,  // 16-bit port (80)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for partial greet request write
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char partial1[] = { 0x05, 0x01 };
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char partial2[] = { 0x00 };
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite data_writes[] = {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, arraysize(partial1)),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, partial2, arraysize(partial2)),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kOkRequest, arraysize(kOkRequest)) };
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead data_reads[] = {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength) };
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     data_writes, arraysize(data_writes),
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     hostname, 80, &net_log_));
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = user_sock_->Connect(callback_.callback());
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CapturingNetLog::CapturedEntryList net_log_entries;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                NetLog::TYPE_SOCKS5_CONNECT));
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback_.WaitForResult();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(user_sock_->IsConnected());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                NetLog::TYPE_SOCKS5_CONNECT));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for partial greet response read
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char partial1[] = { 0x05 };
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char partial2[] = { 0x00 };
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite data_writes[] = {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kOkRequest, arraysize(kOkRequest)) };
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead data_reads[] = {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, partial1, arraysize(partial1)),
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, partial2, arraysize(partial2)),
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength) };
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     data_writes, arraysize(data_writes),
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     hostname, 80, &net_log_));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = user_sock_->Connect(callback_.callback());
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CapturingNetLog::CapturedEntryList net_log_entries;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NetLog::TYPE_SOCKS5_CONNECT));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback_.WaitForResult();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(user_sock_->IsConnected());
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    NetLog::TYPE_SOCKS5_CONNECT));
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for partial handshake request write.
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSplitPoint = 3;  // Break handshake write into two parts.
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite data_writes[] = {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kOkRequest, kSplitPoint),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kOkRequest + kSplitPoint,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  arraysize(kOkRequest) - kSplitPoint)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead data_reads[] = {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5OkResponse, kSOCKS5OkResponseLength) };
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     data_writes, arraysize(data_writes),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     hostname, 80, &net_log_));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = user_sock_->Connect(callback_.callback());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CapturingNetLog::CapturedEntryList net_log_entries;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NetLog::TYPE_SOCKS5_CONNECT));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback_.WaitForResult();
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(user_sock_->IsConnected());
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    NetLog::TYPE_SOCKS5_CONNECT));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test for partial handshake response read
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int kSplitPoint = 6;  // Break the handshake read into two parts.
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockWrite data_writes[] = {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockWrite(ASYNC, kOkRequest, arraysize(kOkRequest))
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockRead data_reads[] = {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength),
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5OkResponse, kSplitPoint),
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        MockRead(ASYNC, kSOCKS5OkResponse + kSplitPoint,
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 kSOCKS5OkResponseLength - kSplitPoint)
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_sock_.reset(BuildMockSocket(data_reads, arraysize(data_reads),
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     data_writes, arraysize(data_writes),
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     hostname, 80, &net_log_));
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = user_sock_->Connect(callback_.callback());
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(ERR_IO_PENDING, rv);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CapturingNetLog::CapturedEntryList net_log_entries;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsBeginEvent(net_log_entries, 0,
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      NetLog::TYPE_SOCKS5_CONNECT));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rv = callback_.WaitForResult();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(OK, rv);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(user_sock_->IsConnected());
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.GetEntries(&net_log_entries);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(LogContainsEndEvent(net_log_entries, -1,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    NetLog::TYPE_SOCKS5_CONNECT));
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
369