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 |