| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 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 | 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/socket/socks5_client_socket.h" | 5 #include "net/socket/socks5_client_socket.h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 7 #include <map> | 8 #include <map> |
| 8 #include "build/build_config.h" | 9 #include "build/build_config.h" |
| 9 #if defined(OS_WIN) | 10 #if defined(OS_WIN) |
| 10 #include <ws2tcpip.h> | 11 #include <ws2tcpip.h> |
| 11 #elif defined(OS_POSIX) | 12 #elif defined(OS_POSIX) |
| 12 #include <netdb.h> | 13 #include <netdb.h> |
| 13 #endif | 14 #endif |
| 14 #include "net/base/address_list.h" | 15 #include "net/base/address_list.h" |
| 15 #include "net/base/load_log.h" | 16 #include "net/base/load_log.h" |
| 16 #include "net/base/load_log_unittest.h" | 17 #include "net/base/load_log_unittest.h" |
| 17 #include "net/base/mock_host_resolver.h" | 18 #include "net/base/mock_host_resolver.h" |
| 18 #include "net/base/test_completion_callback.h" | 19 #include "net/base/test_completion_callback.h" |
| 19 #include "net/base/winsock_init.h" | 20 #include "net/base/winsock_init.h" |
| 20 #include "net/socket/client_socket_factory.h" | 21 #include "net/socket/client_socket_factory.h" |
| 21 #include "net/socket/socket_test_util.h" | 22 #include "net/socket/socket_test_util.h" |
| 22 #include "net/socket/tcp_client_socket.h" | 23 #include "net/socket/tcp_client_socket.h" |
| 23 #include "testing/gtest/include/gtest/gtest.h" | 24 #include "testing/gtest/include/gtest/gtest.h" |
| 24 #include "testing/platform_test.h" | 25 #include "testing/platform_test.h" |
| 25 | 26 |
| 26 //----------------------------------------------------------------------------- | 27 //----------------------------------------------------------------------------- |
| 27 | 28 |
| 28 namespace net { | 29 namespace net { |
| 29 | 30 |
| 31 namespace { |
| 32 |
| 30 // Base class to test SOCKS5ClientSocket | 33 // Base class to test SOCKS5ClientSocket |
| 31 class SOCKS5ClientSocketTest : public PlatformTest { | 34 class SOCKS5ClientSocketTest : public PlatformTest { |
| 32 public: | 35 public: |
| 33 SOCKS5ClientSocketTest(); | 36 SOCKS5ClientSocketTest(); |
| 34 // Create a SOCKSClientSocket on top of a MockSocket. | 37 // Create a SOCKSClientSocket on top of a MockSocket. |
| 35 SOCKS5ClientSocket* BuildMockSocket(MockRead reads[], | 38 SOCKS5ClientSocket* BuildMockSocket(MockRead reads[], |
| 36 MockWrite writes[], | 39 MockWrite writes[], |
| 37 const std::string& hostname, | 40 const std::string& hostname, |
| 38 int port); | 41 int port); |
| 42 |
| 39 virtual void SetUp(); | 43 virtual void SetUp(); |
| 40 | 44 |
| 41 protected: | 45 protected: |
| 42 const uint16 kNwPort; | 46 const uint16 kNwPort; |
| 43 scoped_ptr<SOCKS5ClientSocket> user_sock_; | 47 scoped_ptr<SOCKS5ClientSocket> user_sock_; |
| 44 AddressList address_list_; | 48 AddressList address_list_; |
| 45 ClientSocket* tcp_sock_; | 49 ClientSocket* tcp_sock_; |
| 46 TestCompletionCallback callback_; | 50 TestCompletionCallback callback_; |
| 47 scoped_refptr<MockHostResolver> host_resolver_; | 51 scoped_refptr<MockHostResolver> host_resolver_; |
| 48 scoped_ptr<SocketDataProvider> data_; | 52 scoped_ptr<SocketDataProvider> data_; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 63 HostResolver::RequestInfo info("www.socks-proxy.com", 1080); | 67 HostResolver::RequestInfo info("www.socks-proxy.com", 1080); |
| 64 int rv = host_resolver_->Resolve(info, &address_list_, NULL, NULL, NULL); | 68 int rv = host_resolver_->Resolve(info, &address_list_, NULL, NULL, NULL); |
| 65 ASSERT_EQ(OK, rv); | 69 ASSERT_EQ(OK, rv); |
| 66 } | 70 } |
| 67 | 71 |
| 68 SOCKS5ClientSocket* SOCKS5ClientSocketTest::BuildMockSocket( | 72 SOCKS5ClientSocket* SOCKS5ClientSocketTest::BuildMockSocket( |
| 69 MockRead reads[], | 73 MockRead reads[], |
| 70 MockWrite writes[], | 74 MockWrite writes[], |
| 71 const std::string& hostname, | 75 const std::string& hostname, |
| 72 int port) { | 76 int port) { |
| 73 | |
| 74 TestCompletionCallback callback; | 77 TestCompletionCallback callback; |
| 75 data_.reset(new StaticSocketDataProvider(reads, writes)); | 78 data_.reset(new StaticSocketDataProvider(reads, writes)); |
| 76 tcp_sock_ = new MockTCPClientSocket(address_list_, data_.get()); | 79 tcp_sock_ = new MockTCPClientSocket(address_list_, data_.get()); |
| 77 | 80 |
| 78 int rv = tcp_sock_->Connect(&callback, NULL); | 81 int rv = tcp_sock_->Connect(&callback, NULL); |
| 79 EXPECT_EQ(ERR_IO_PENDING, rv); | 82 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 80 rv = callback.WaitForResult(); | 83 rv = callback.WaitForResult(); |
| 81 EXPECT_EQ(OK, rv); | 84 EXPECT_EQ(OK, rv); |
| 82 EXPECT_TRUE(tcp_sock_->IsConnected()); | 85 EXPECT_TRUE(tcp_sock_->IsConnected()); |
| 83 | 86 |
| 84 return new SOCKS5ClientSocket(tcp_sock_, | 87 return new SOCKS5ClientSocket(tcp_sock_, |
| 85 HostResolver::RequestInfo(hostname, port), | 88 HostResolver::RequestInfo(hostname, port)); |
| 86 host_resolver_); | |
| 87 } | 89 } |
| 88 | 90 |
| 89 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; | 91 const char kSOCKS5GreetRequest[] = { 0x05, 0x01, 0x00 }; |
| 90 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; | 92 const char kSOCKS5GreetResponse[] = { 0x05, 0x00 }; |
| 91 | |
| 92 const char kSOCKS5OkRequest[] = | |
| 93 { 0x05, 0x01, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; | |
| 94 const char kSOCKS5OkResponse[] = | 93 const char kSOCKS5OkResponse[] = |
| 95 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; | 94 { 0x05, 0x00, 0x00, 0x01, 127, 0, 0, 1, 0x00, 0x50 }; |
| 96 | 95 |
| 96 |
| 97 // Tests a complete SOCKS5 handshake and the disconnection. | 97 // Tests a complete SOCKS5 handshake and the disconnection. |
| 98 TEST_F(SOCKS5ClientSocketTest, CompleteHandshake) { | 98 TEST_F(SOCKS5ClientSocketTest, CompleteHandshake) { |
| 99 const std::string payload_write = "random data"; | 99 const std::string payload_write = "random data"; |
| 100 const std::string payload_read = "moar random data"; | 100 const std::string payload_read = "moar random data"; |
| 101 | 101 |
| 102 const char kSOCKS5OkRequest[] = { |
| 103 0x05, // Version |
| 104 0x01, // Command (CONNECT) |
| 105 0x00, // Reserved. |
| 106 0x03, // Address type (DOMAINNAME). |
| 107 0x09, // Length of domain (9) |
| 108 // Domain string: |
| 109 'l', 'o', 'c', 'a', 'l', 'h', 'o', 's', 't', |
| 110 0x00, 0x50, // 16-bit port (80) |
| 111 }; |
| 112 |
| 102 MockWrite data_writes[] = { | 113 MockWrite data_writes[] = { |
| 103 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), | 114 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), |
| 104 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)), | 115 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)), |
| 105 MockWrite(true, payload_write.data(), payload_write.size()) }; | 116 MockWrite(true, payload_write.data(), payload_write.size()) }; |
| 106 MockRead data_reads[] = { | 117 MockRead data_reads[] = { |
| 107 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | 118 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), |
| 108 MockRead(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), | 119 MockRead(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)), |
| 109 MockRead(true, payload_read.data(), payload_read.size()) }; | 120 MockRead(true, payload_read.data(), payload_read.size()) }; |
| 110 | 121 |
| 111 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); | 122 user_sock_.reset(BuildMockSocket(data_reads, data_writes, "localhost", 80)); |
| 112 | 123 |
| 113 // At this state the TCP connection is completed but not the SOCKS handshake. | 124 // At this state the TCP connection is completed but not the SOCKS handshake. |
| 114 EXPECT_TRUE(tcp_sock_->IsConnected()); | 125 EXPECT_TRUE(tcp_sock_->IsConnected()); |
| 115 EXPECT_FALSE(user_sock_->IsConnected()); | 126 EXPECT_FALSE(user_sock_->IsConnected()); |
| 116 | 127 |
| 117 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); | 128 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
| 118 int rv = user_sock_->Connect(&callback_, log); | 129 int rv = user_sock_->Connect(&callback_, log); |
| 119 EXPECT_EQ(ERR_IO_PENDING, rv); | 130 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 120 EXPECT_FALSE(user_sock_->IsConnected()); | 131 EXPECT_FALSE(user_sock_->IsConnected()); |
| 121 EXPECT_TRUE( | 132 EXPECT_TRUE( |
| 122 LogContains(*log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | 133 LogContains(*log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); |
| 123 | 134 |
| 124 rv = callback_.WaitForResult(); | 135 rv = callback_.WaitForResult(); |
| 125 | 136 |
| 126 EXPECT_EQ(OK, rv); | 137 EXPECT_EQ(OK, rv); |
| 127 EXPECT_TRUE(user_sock_->IsConnected()); | 138 EXPECT_TRUE(user_sock_->IsConnected()); |
| 128 EXPECT_EQ(SOCKS5ClientSocket::kEndPointResolvedIPv4, | |
| 129 user_sock_->address_type_); | |
| 130 EXPECT_TRUE(LogContains( | 139 EXPECT_TRUE(LogContains( |
| 131 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | 140 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); |
| 132 | 141 |
| 133 scoped_refptr<IOBuffer> buffer = new IOBuffer(payload_write.size()); | 142 scoped_refptr<IOBuffer> buffer = new IOBuffer(payload_write.size()); |
| 134 memcpy(buffer->data(), payload_write.data(), payload_write.size()); | 143 memcpy(buffer->data(), payload_write.data(), payload_write.size()); |
| 135 rv = user_sock_->Write(buffer, payload_write.size(), &callback_); | 144 rv = user_sock_->Write(buffer, payload_write.size(), &callback_); |
| 136 EXPECT_EQ(ERR_IO_PENDING, rv); | 145 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 137 rv = callback_.WaitForResult(); | 146 rv = callback_.WaitForResult(); |
| 138 EXPECT_EQ(static_cast<int>(payload_write.size()), rv); | 147 EXPECT_EQ(static_cast<int>(payload_write.size()), rv); |
| 139 | 148 |
| 140 buffer = new IOBuffer(payload_read.size()); | 149 buffer = new IOBuffer(payload_read.size()); |
| 141 rv = user_sock_->Read(buffer, payload_read.size(), &callback_); | 150 rv = user_sock_->Read(buffer, payload_read.size(), &callback_); |
| 142 EXPECT_EQ(ERR_IO_PENDING, rv); | 151 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 143 rv = callback_.WaitForResult(); | 152 rv = callback_.WaitForResult(); |
| 144 EXPECT_EQ(static_cast<int>(payload_read.size()), rv); | 153 EXPECT_EQ(static_cast<int>(payload_read.size()), rv); |
| 145 EXPECT_EQ(payload_read, std::string(buffer->data(), payload_read.size())); | 154 EXPECT_EQ(payload_read, std::string(buffer->data(), payload_read.size())); |
| 146 | 155 |
| 147 user_sock_->Disconnect(); | 156 user_sock_->Disconnect(); |
| 148 EXPECT_FALSE(tcp_sock_->IsConnected()); | 157 EXPECT_FALSE(tcp_sock_->IsConnected()); |
| 149 EXPECT_FALSE(user_sock_->IsConnected()); | 158 EXPECT_FALSE(user_sock_->IsConnected()); |
| 150 } | 159 } |
| 151 | 160 |
| 152 // Tries to connect to a DNS which fails domain lookup. | 161 // Test that you can call Connect() again after having called Disconnect(). |
| 153 TEST_F(SOCKS5ClientSocketTest, FailedDNS) { | 162 TEST_F(SOCKS5ClientSocketTest, ConnectAndDisconnectTwice) { |
| 154 const std::string hostname = "unresolved.ipv4.address"; | 163 const std::string hostname = "my-host-name"; |
| 155 const char kSOCKS5DomainRequest[] = { 0x05, 0x01, 0x00, 0x03 }; | 164 const char kSOCKS5DomainRequest[] = { |
| 165 0x05, // VER |
| 166 0x01, // CMD |
| 167 0x00, // RSV |
| 168 0x03, // ATYPE |
| 169 }; |
| 156 | 170 |
| 157 host_resolver_->rules()->AddSimulatedFailure(hostname.c_str()); | 171 std::string request(kSOCKS5DomainRequest, arraysize(kSOCKS5DomainRequest)); |
| 158 | |
| 159 std::string request(kSOCKS5DomainRequest, | |
| 160 arraysize(kSOCKS5DomainRequest)); | |
| 161 request.push_back(hostname.size()); | 172 request.push_back(hostname.size()); |
| 162 request.append(hostname); | 173 request.append(hostname); |
| 163 request.append(reinterpret_cast<const char*>(&kNwPort), sizeof(kNwPort)); | 174 request.append(reinterpret_cast<const char*>(&kNwPort), sizeof(kNwPort)); |
| 164 | 175 |
| 165 MockWrite data_writes[] = { | 176 for (int i = 0; i < 2; ++i) { |
| 166 MockWrite(false, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), | 177 MockWrite data_writes[] = { |
| 167 MockWrite(false, request.data(), request.size()) }; | 178 MockWrite(false, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), |
| 168 MockRead data_reads[] = { | 179 MockWrite(false, request.data(), request.size()) |
| 169 MockRead(false, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | 180 }; |
| 170 MockRead(false, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)) }; | 181 MockRead data_reads[] = { |
| 182 MockRead(false, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), |
| 183 MockRead(false, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)) |
| 184 }; |
| 171 | 185 |
| 172 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); | 186 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); |
| 173 | 187 |
| 174 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); | 188 int rv = user_sock_->Connect(&callback_, NULL); |
| 175 int rv = user_sock_->Connect(&callback_, log); | 189 EXPECT_EQ(OK, rv); |
| 176 EXPECT_EQ(ERR_IO_PENDING, rv); | 190 EXPECT_TRUE(user_sock_->IsConnected()); |
| 177 EXPECT_TRUE(LogContains( | 191 |
| 178 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | 192 user_sock_->Disconnect(); |
| 179 rv = callback_.WaitForResult(); | 193 EXPECT_FALSE(user_sock_->IsConnected()); |
| 180 EXPECT_EQ(OK, rv); | 194 } |
| 181 EXPECT_TRUE(user_sock_->IsConnected()); | |
| 182 EXPECT_EQ(SOCKS5ClientSocket::kEndPointFailedDomain, | |
| 183 user_sock_->address_type_); | |
| 184 EXPECT_TRUE(LogContains( | |
| 185 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | |
| 186 } | 195 } |
| 187 | 196 |
| 188 // Tries to connect to a domain that resolves to IPv6. | 197 // Test that we fail trying to connect to a hosname longer than 255 bytes. |
| 189 TEST_F(SOCKS5ClientSocketTest, IPv6Domain) { | 198 TEST_F(SOCKS5ClientSocketTest, LargeHostNameFails) { |
| 190 const std::string hostname = "an.ipv6.address"; | 199 // Create a string of length 256, where each character is 'x'. |
| 191 const char kSOCKS5IPv6Request[] = { 0x05, 0x01, 0x00, 0x04 }; | 200 std::string large_host_name; |
| 192 const uint8 ipv6_addr[] = { 0x20, 0x01, 0x0d, 0xb8, 0x87, 0x14, 0x3a, 0x90, | 201 std::fill_n(std::back_inserter(large_host_name), 256, 'x'); |
| 193 0x00, 0x00, 0x00, 0x00, 0x00, 0x000, 0x00, 0x12 }; | |
| 194 | 202 |
| 195 host_resolver_->rules()->AddIPv6Rule(hostname, "2001:db8:8714:3a90::12"); | 203 // Create a SOCKS socket, with mock transport socket. |
| 204 // (Data from these mocks will not be used). |
| 205 MockWrite data_writes[] = {MockWrite(false, ERR_UNEXPECTED)}; |
| 206 MockRead data_reads[] = {MockRead(false, ERR_UNEXPECTED)}; |
| 207 user_sock_.reset(BuildMockSocket(data_reads, data_writes, |
| 208 large_host_name, 80)); |
| 196 | 209 |
| 197 std::string request(kSOCKS5IPv6Request, | 210 // Try to connect -- should fail (without having read/written anything to |
| 198 arraysize(kSOCKS5IPv6Request)); | 211 // the transport socket first) because the hostname is too long. |
| 199 request.append(reinterpret_cast<const char*>(&ipv6_addr), sizeof(ipv6_addr)); | 212 TestCompletionCallback callback; |
| 200 request.append(reinterpret_cast<const char*>(&kNwPort), sizeof(kNwPort)); | 213 int rv = user_sock_->Connect(&callback, NULL); |
| 201 | 214 EXPECT_EQ(ERR_INVALID_URL, rv); |
| 202 MockWrite data_writes[] = { | |
| 203 MockWrite(false, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), | |
| 204 MockWrite(false, request.data(), request.size()) }; | |
| 205 MockRead data_reads[] = { | |
| 206 MockRead(false, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | |
| 207 MockRead(false, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)) }; | |
| 208 | |
| 209 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); | |
| 210 | |
| 211 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); | |
| 212 int rv = user_sock_->Connect(&callback_, log); | |
| 213 EXPECT_EQ(ERR_IO_PENDING, rv); | |
| 214 EXPECT_TRUE(LogContains( | |
| 215 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | |
| 216 rv = callback_.WaitForResult(); | |
| 217 EXPECT_EQ(OK, rv); | |
| 218 EXPECT_TRUE(user_sock_->IsConnected()); | |
| 219 EXPECT_EQ(SOCKS5ClientSocket::kEndPointResolvedIPv6, | |
| 220 user_sock_->address_type_); | |
| 221 EXPECT_TRUE(LogContains( | |
| 222 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | |
| 223 } | 215 } |
| 224 | 216 |
| 225 TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) { | 217 TEST_F(SOCKS5ClientSocketTest, PartialReadWrites) { |
| 226 const std::string hostname = "www.google.com"; | 218 const std::string hostname = "www.google.com"; |
| 227 | 219 |
| 220 const char kSOCKS5OkRequest[] = { |
| 221 0x05, // Version |
| 222 0x01, // Command (CONNECT) |
| 223 0x00, // Reserved. |
| 224 0x03, // Address type (DOMAINNAME). |
| 225 0x0E, // Length of domain (14) |
| 226 // Domain string: |
| 227 'w', 'w', 'w', '.', 'g', 'o', 'o', 'g', 'l', 'e', '.', 'c', 'o', 'm', |
| 228 0x00, 0x50, // 16-bit port (80) |
| 229 }; |
| 230 |
| 228 // Test for partial greet request write | 231 // Test for partial greet request write |
| 229 { | 232 { |
| 230 const char partial1[] = { 0x05, 0x01 }; | 233 const char partial1[] = { 0x05, 0x01 }; |
| 231 const char partial2[] = { 0x00 }; | 234 const char partial2[] = { 0x00 }; |
| 232 MockWrite data_writes[] = { | 235 MockWrite data_writes[] = { |
| 233 MockWrite(true, arraysize(partial1)), | 236 MockWrite(true, arraysize(partial1)), |
| 234 MockWrite(true, partial2, arraysize(partial2)), | 237 MockWrite(true, partial2, arraysize(partial2)), |
| 235 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)) }; | 238 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)) }; |
| 236 MockRead data_reads[] = { | 239 MockRead data_reads[] = { |
| 237 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | 240 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), |
| (...skipping 28 matching lines...) Expand all Loading... |
| 266 EXPECT_EQ(ERR_IO_PENDING, rv); | 269 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 267 EXPECT_TRUE(LogContains( | 270 EXPECT_TRUE(LogContains( |
| 268 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | 271 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); |
| 269 rv = callback_.WaitForResult(); | 272 rv = callback_.WaitForResult(); |
| 270 EXPECT_EQ(OK, rv); | 273 EXPECT_EQ(OK, rv); |
| 271 EXPECT_TRUE(user_sock_->IsConnected()); | 274 EXPECT_TRUE(user_sock_->IsConnected()); |
| 272 EXPECT_TRUE(LogContains( | 275 EXPECT_TRUE(LogContains( |
| 273 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | 276 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); |
| 274 } | 277 } |
| 275 | 278 |
| 276 // Test for partial handshake request write | 279 // Test for partial handshake request write. |
| 277 { | 280 { |
| 278 const char partial1[] = { 0x05, 0x01, 0x00 }; | 281 // NOTE: in this branch MockWrite doesn't support partial successes, so |
| 279 const char partial2[] = { 0x01, 127, 0, 0, 1, 0x00, 0x50 }; | 282 // the MockWrite must correspond exactly with the request. |
| 283 const int kSplitPoint = arraysize(kSOCKS5OkRequest); |
| 280 MockWrite data_writes[] = { | 284 MockWrite data_writes[] = { |
| 281 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), | 285 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), |
| 282 MockWrite(true, arraysize(partial1)), | 286 MockWrite(true, kSOCKS5OkRequest, kSplitPoint), |
| 283 MockWrite(true, partial2, arraysize(partial2)) }; | 287 MockWrite(true, kSOCKS5OkRequest + kSplitPoint, |
| 288 arraysize(kSOCKS5OkRequest) - kSplitPoint) |
| 289 }; |
| 284 MockRead data_reads[] = { | 290 MockRead data_reads[] = { |
| 285 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | 291 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), |
| 286 MockRead(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)) }; | 292 MockRead(true, kSOCKS5OkResponse, arraysize(kSOCKS5OkResponse)) }; |
| 287 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); | 293 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); |
| 288 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); | 294 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
| 289 int rv = user_sock_->Connect(&callback_, log); | 295 int rv = user_sock_->Connect(&callback_, log); |
| 290 EXPECT_EQ(ERR_IO_PENDING, rv); | 296 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 291 EXPECT_TRUE(LogContains( | 297 EXPECT_TRUE(LogContains( |
| 292 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | 298 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); |
| 293 rv = callback_.WaitForResult(); | 299 rv = callback_.WaitForResult(); |
| 294 EXPECT_EQ(OK, rv); | 300 EXPECT_EQ(OK, rv); |
| 295 EXPECT_TRUE(user_sock_->IsConnected()); | 301 EXPECT_TRUE(user_sock_->IsConnected()); |
| 296 EXPECT_TRUE(LogContains( | 302 EXPECT_TRUE(LogContains( |
| 297 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | 303 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); |
| 298 } | 304 } |
| 299 | 305 |
| 300 // Test for partial handshake response read | 306 // Test for partial handshake response read |
| 301 { | 307 { |
| 302 const char partial1[] = { 0x05, 0x00, 0x00, 0x01, 127, 0 }; | 308 const int kSplitPoint = 6; // Break the handshake read into two parts. |
| 303 const char partial2[] = { 0, 1, 0x00, 0x50 }; | |
| 304 MockWrite data_writes[] = { | 309 MockWrite data_writes[] = { |
| 305 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), | 310 MockWrite(true, kSOCKS5GreetRequest, arraysize(kSOCKS5GreetRequest)), |
| 306 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)) }; | 311 MockWrite(true, kSOCKS5OkRequest, arraysize(kSOCKS5OkRequest)) |
| 312 }; |
| 307 MockRead data_reads[] = { | 313 MockRead data_reads[] = { |
| 308 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), | 314 MockRead(true, kSOCKS5GreetResponse, arraysize(kSOCKS5GreetResponse)), |
| 309 MockRead(true, partial1, arraysize(partial1)), | 315 MockRead(true, kSOCKS5OkResponse, kSplitPoint), |
| 310 MockRead(true, partial2, arraysize(partial2)) }; | 316 MockRead(true, kSOCKS5OkResponse + kSplitPoint, arraysize(kSOCKS5OkRespo
nse) - kSplitPoint) |
| 317 }; |
| 318 |
| 311 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); | 319 user_sock_.reset(BuildMockSocket(data_reads, data_writes, hostname, 80)); |
| 312 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); | 320 scoped_refptr<LoadLog> log(new LoadLog(LoadLog::kUnbounded)); |
| 313 int rv = user_sock_->Connect(&callback_, log); | 321 int rv = user_sock_->Connect(&callback_, log); |
| 314 EXPECT_EQ(ERR_IO_PENDING, rv); | 322 EXPECT_EQ(ERR_IO_PENDING, rv); |
| 315 EXPECT_TRUE(LogContains( | 323 EXPECT_TRUE(LogContains( |
| 316 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); | 324 *log, 0, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_BEGIN)); |
| 317 rv = callback_.WaitForResult(); | 325 rv = callback_.WaitForResult(); |
| 318 EXPECT_EQ(OK, rv); | 326 EXPECT_EQ(OK, rv); |
| 319 EXPECT_TRUE(user_sock_->IsConnected()); | 327 EXPECT_TRUE(user_sock_->IsConnected()); |
| 320 EXPECT_TRUE(LogContains( | 328 EXPECT_TRUE(LogContains( |
| 321 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); | 329 *log, -1, LoadLog::TYPE_SOCKS5_CONNECT, LoadLog::PHASE_END)); |
| 322 } | 330 } |
| 323 } | 331 } |
| 324 | 332 |
| 333 } // namespace |
| 334 |
| 325 } // namespace net | 335 } // namespace net |
| OLD | NEW |