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

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

Issue 507048: Cleanup: Remove the support for IPv4 and IPv6 addressing types in the SOCKS5 ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Rename error Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/socks5_client_socket.h ('k') | net/socket/socks5_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/compiler_specific.h" 8 #include "base/compiler_specific.h"
9 #include "base/trace_event.h" 9 #include "base/trace_event.h"
10 #include "net/base/io_buffer.h" 10 #include "net/base/io_buffer.h"
11 #include "net/base/load_log.h" 11 #include "net/base/load_log.h"
12 #include "net/base/net_util.h" 12 #include "net/base/net_util.h"
13 #include "net/base/sys_addrinfo.h" 13 #include "net/base/sys_addrinfo.h"
14 14
15 namespace net { 15 namespace net {
16 16
17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; 17 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2;
18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; 18 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10;
19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; 19 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5;
20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; 20 const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05;
21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; 21 const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01;
22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00; 22 const uint8 SOCKS5ClientSocket::kNullByte = 0x00;
23 23
24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); 24 COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4);
25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); 25 COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6);
26 26
27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket, 27 SOCKS5ClientSocket::SOCKS5ClientSocket(ClientSocket* transport_socket,
28 const HostResolver::RequestInfo& req_info, 28 const HostResolver::RequestInfo& req_info)
29 HostResolver* host_resolver)
30 : ALLOW_THIS_IN_INITIALIZER_LIST( 29 : ALLOW_THIS_IN_INITIALIZER_LIST(
31 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)), 30 io_callback_(this, &SOCKS5ClientSocket::OnIOComplete)),
32 transport_(transport_socket), 31 transport_(transport_socket),
33 next_state_(STATE_NONE), 32 next_state_(STATE_NONE),
34 address_type_(kEndPointUnresolved),
35 user_callback_(NULL), 33 user_callback_(NULL),
36 completed_handshake_(false), 34 completed_handshake_(false),
37 bytes_sent_(0), 35 bytes_sent_(0),
38 bytes_received_(0), 36 bytes_received_(0),
39 read_header_size(kReadHeaderSize), 37 read_header_size(kReadHeaderSize),
40 host_request_info_(req_info) { 38 host_request_info_(req_info) {
41 if (host_resolver)
42 host_resolver_.reset(new SingleRequestHostResolver(host_resolver));
43 } 39 }
44 40
45 SOCKS5ClientSocket::~SOCKS5ClientSocket() { 41 SOCKS5ClientSocket::~SOCKS5ClientSocket() {
46 Disconnect(); 42 Disconnect();
47 } 43 }
48 44
49 int SOCKS5ClientSocket::Connect(CompletionCallback* callback, 45 int SOCKS5ClientSocket::Connect(CompletionCallback* callback,
50 LoadLog* load_log) { 46 LoadLog* load_log) {
51 DCHECK(transport_.get()); 47 DCHECK(transport_.get());
52 DCHECK(transport_->IsConnected()); 48 DCHECK(transport_->IsConnected());
53 DCHECK_EQ(STATE_NONE, next_state_); 49 DCHECK_EQ(STATE_NONE, next_state_);
54 DCHECK(!user_callback_); 50 DCHECK(!user_callback_);
55 51
56 // If already connected, then just return OK. 52 // If already connected, then just return OK.
57 if (completed_handshake_) 53 if (completed_handshake_)
58 return OK; 54 return OK;
59 55
60 load_log_ = load_log; 56 load_log_ = load_log;
61 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); 57 LoadLog::BeginEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT);
62 58
63 // If a host resolver was given, try to resolve the address locally. 59 next_state_ = STATE_GREET_WRITE;
64 // Otherwise let the proxy server handle the resolving. 60 buffer_.clear();
65 if (host_resolver_.get()) {
66 next_state_ = STATE_RESOLVE_HOST;
67 } else {
68 next_state_ = STATE_GREET_WRITE;
69 address_type_ = kEndPointFailedDomain;
70 }
71 61
72 int rv = DoLoop(OK); 62 int rv = DoLoop(OK);
73 if (rv == ERR_IO_PENDING) { 63 if (rv == ERR_IO_PENDING) {
74 user_callback_ = callback; 64 user_callback_ = callback;
75 } else { 65 } else {
76 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT); 66 LoadLog::EndEvent(load_log, LoadLog::TYPE_SOCKS5_CONNECT);
77 load_log_ = NULL; 67 load_log_ = NULL;
78 } 68 }
79 return rv; 69 return rv;
80 } 70 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
144 } 134 }
145 } 135 }
146 136
147 int SOCKS5ClientSocket::DoLoop(int last_io_result) { 137 int SOCKS5ClientSocket::DoLoop(int last_io_result) {
148 DCHECK_NE(next_state_, STATE_NONE); 138 DCHECK_NE(next_state_, STATE_NONE);
149 int rv = last_io_result; 139 int rv = last_io_result;
150 do { 140 do {
151 State state = next_state_; 141 State state = next_state_;
152 next_state_ = STATE_NONE; 142 next_state_ = STATE_NONE;
153 switch (state) { 143 switch (state) {
154 case STATE_RESOLVE_HOST:
155 DCHECK_EQ(OK, rv);
156 rv = DoResolveHost();
157 break;
158 case STATE_RESOLVE_HOST_COMPLETE:
159 rv = DoResolveHostComplete(rv);
160 break;
161 case STATE_GREET_WRITE: 144 case STATE_GREET_WRITE:
162 DCHECK_EQ(OK, rv); 145 DCHECK_EQ(OK, rv);
163 rv = DoGreetWrite(); 146 rv = DoGreetWrite();
164 break; 147 break;
165 case STATE_GREET_WRITE_COMPLETE: 148 case STATE_GREET_WRITE_COMPLETE:
166 rv = DoGreetWriteComplete(rv); 149 rv = DoGreetWriteComplete(rv);
167 break; 150 break;
168 case STATE_GREET_READ: 151 case STATE_GREET_READ:
169 DCHECK_EQ(OK, rv); 152 DCHECK_EQ(OK, rv);
170 rv = DoGreetRead(); 153 rv = DoGreetRead();
(...skipping 17 matching lines...) Expand all
188 break; 171 break;
189 default: 172 default:
190 NOTREACHED() << "bad state"; 173 NOTREACHED() << "bad state";
191 rv = ERR_UNEXPECTED; 174 rv = ERR_UNEXPECTED;
192 break; 175 break;
193 } 176 }
194 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 177 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
195 return rv; 178 return rv;
196 } 179 }
197 180
198 int SOCKS5ClientSocket::DoResolveHost() {
199 DCHECK_EQ(kEndPointUnresolved, address_type_);
200
201 next_state_ = STATE_RESOLVE_HOST_COMPLETE;
202 return host_resolver_->Resolve(
203 host_request_info_, &addresses_, &io_callback_, load_log_);
204 }
205
206 int SOCKS5ClientSocket::DoResolveHostComplete(int result) {
207 DCHECK_EQ(kEndPointUnresolved, address_type_);
208
209 bool ok = (result == OK);
210 next_state_ = STATE_GREET_WRITE;
211 if (ok) {
212 DCHECK(addresses_.head());
213 struct sockaddr* host_info = addresses_.head()->ai_addr;
214 if (host_info->sa_family == AF_INET) {
215 address_type_ = kEndPointResolvedIPv4;
216 } else if (host_info->sa_family == AF_INET6) {
217 address_type_ = kEndPointResolvedIPv6;
218 }
219 } else {
220 address_type_ = kEndPointFailedDomain;
221 }
222
223 buffer_.clear();
224
225 // Even if DNS resolution fails, we send OK since the server
226 // resolves the domain.
227 return OK;
228 }
229
230 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication 181 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication
231 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; 182 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 };
232 183
233 int SOCKS5ClientSocket::DoGreetWrite() { 184 int SOCKS5ClientSocket::DoGreetWrite() {
234 if (buffer_.empty()) { 185 if (buffer_.empty()) {
235 buffer_ = std::string(kSOCKS5GreetWriteData, 186 buffer_ = std::string(kSOCKS5GreetWriteData,
236 arraysize(kSOCKS5GreetWriteData)); 187 arraysize(kSOCKS5GreetWriteData));
237 bytes_sent_ = 0; 188 bytes_sent_ = 0;
238 } 189 }
239 190
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00) 236 if (buffer_[0] != kSOCKS5Version || buffer_[1] != 0x00)
286 return ERR_INVALID_RESPONSE; // Unknown error 237 return ERR_INVALID_RESPONSE; // Unknown error
287 238
288 buffer_.clear(); 239 buffer_.clear();
289 next_state_ = STATE_HANDSHAKE_WRITE; 240 next_state_ = STATE_HANDSHAKE_WRITE;
290 return OK; 241 return OK;
291 } 242 }
292 243
293 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) 244 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake)
294 const { 245 const {
295 DCHECK_NE(kEndPointUnresolved, address_type_);
296 DCHECK(handshake->empty()); 246 DCHECK(handshake->empty());
297 247
298 handshake->push_back(kSOCKS5Version); 248 handshake->push_back(kSOCKS5Version);
299 handshake->push_back(kTunnelCommand); // Connect command 249 handshake->push_back(kTunnelCommand); // Connect command
300 handshake->push_back(kNullByte); // Reserved null 250 handshake->push_back(kNullByte); // Reserved null
301 251
302 handshake->push_back(address_type_); // The type of connection 252 handshake->push_back(kEndPointDomain); // The type of the address.
303 if (address_type_ == kEndPointFailedDomain) {
304 if(256 <= host_request_info_.hostname().size())
305 return ERR_ADDRESS_INVALID;
306 253
307 // First add the size of the hostname, followed by the hostname. 254 // We only have 1 byte to send the length in, so if the hostname is
308 handshake->push_back(static_cast<unsigned char>( 255 // longer than this we can't send it!
309 host_request_info_.hostname().size())); 256 if(256 <= host_request_info_.hostname().size())
310 handshake->append(host_request_info_.hostname()); 257 return ERR_INVALID_URL;
311 258
312 } else if (address_type_ == kEndPointResolvedIPv4) { 259 // First add the size of the hostname, followed by the hostname.
313 struct sockaddr_in* ipv4_host = 260 handshake->push_back(static_cast<unsigned char>(
314 reinterpret_cast<struct sockaddr_in*>(addresses_.head()->ai_addr); 261 host_request_info_.hostname().size()));
315 handshake->append(reinterpret_cast<char*>(&ipv4_host->sin_addr), 262 handshake->append(host_request_info_.hostname());
316 sizeof(ipv4_host->sin_addr));
317
318 } else if (address_type_ == kEndPointResolvedIPv6) {
319 struct sockaddr_in6* ipv6_host =
320 reinterpret_cast<struct sockaddr_in6*>(addresses_.head()->ai_addr);
321 handshake->append(reinterpret_cast<char*>(&ipv6_host->sin6_addr),
322 sizeof(ipv6_host->sin6_addr));
323
324 } else {
325 NOTREACHED();
326 }
327 263
328 uint16 nw_port = htons(host_request_info_.port()); 264 uint16 nw_port = htons(host_request_info_.port());
329 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); 265 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port));
330 return OK; 266 return OK;
331 } 267 }
332 268
333 // Writes the SOCKS handshake data to the underlying socket connection. 269 // Writes the SOCKS handshake data to the underlying socket connection.
334 int SOCKS5ClientSocket::DoHandshakeWrite() { 270 int SOCKS5ClientSocket::DoHandshakeWrite() {
335 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 271 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
336 272
337 if (buffer_.empty()) { 273 if (buffer_.empty()) {
338 int rv = BuildHandshakeWriteBuffer(&buffer_); 274 int rv = BuildHandshakeWriteBuffer(&buffer_);
339 if (rv != OK) 275 if (rv != OK)
340 return rv; 276 return rv;
341 bytes_sent_ = 0; 277 bytes_sent_ = 0;
342 } 278 }
343 279
344 int handshake_buf_len = buffer_.size() - bytes_sent_; 280 int handshake_buf_len = buffer_.size() - bytes_sent_;
345 DCHECK_LT(0, handshake_buf_len); 281 DCHECK_LT(0, handshake_buf_len);
346 handshake_buf_ = new IOBuffer(handshake_buf_len); 282 handshake_buf_ = new IOBuffer(handshake_buf_len);
347 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 283 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
348 handshake_buf_len); 284 handshake_buf_len);
349 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); 285 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_);
350 } 286 }
351 287
352 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { 288 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) {
353 DCHECK_NE(kEndPointUnresolved, address_type_);
354
355 if (result < 0) 289 if (result < 0)
356 return result; 290 return result;
357 291
358 // We ignore the case when result is 0, since the underlying Write 292 // We ignore the case when result is 0, since the underlying Write
359 // may return spurious writes while waiting on the socket. 293 // may return spurious writes while waiting on the socket.
360 294
361 bytes_sent_ += result; 295 bytes_sent_ += result;
362 if (bytes_sent_ == buffer_.size()) { 296 if (bytes_sent_ == buffer_.size()) {
363 next_state_ = STATE_HANDSHAKE_READ; 297 next_state_ = STATE_HANDSHAKE_READ;
364 buffer_.clear(); 298 buffer_.clear();
365 } else if (bytes_sent_ < buffer_.size()) { 299 } else if (bytes_sent_ < buffer_.size()) {
366 next_state_ = STATE_HANDSHAKE_WRITE; 300 next_state_ = STATE_HANDSHAKE_WRITE;
367 } else { 301 } else {
368 NOTREACHED(); 302 NOTREACHED();
369 } 303 }
370 304
371 return OK; 305 return OK;
372 } 306 }
373 307
374 int SOCKS5ClientSocket::DoHandshakeRead() { 308 int SOCKS5ClientSocket::DoHandshakeRead() {
375 DCHECK_NE(kEndPointUnresolved, address_type_);
376
377 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 309 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
378 310
379 if (buffer_.empty()) { 311 if (buffer_.empty()) {
380 bytes_received_ = 0; 312 bytes_received_ = 0;
381 read_header_size = kReadHeaderSize; 313 read_header_size = kReadHeaderSize;
382 } 314 }
383 315
384 int handshake_buf_len = read_header_size - bytes_received_; 316 int handshake_buf_len = read_header_size - bytes_received_;
385 handshake_buf_ = new IOBuffer(handshake_buf_len); 317 handshake_buf_ = new IOBuffer(handshake_buf_len);
386 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); 318 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_);
387 } 319 }
388 320
389 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { 321 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
390 DCHECK_NE(kEndPointUnresolved, address_type_);
391
392 if (result < 0) 322 if (result < 0)
393 return result; 323 return result;
394 324
395 // The underlying socket closed unexpectedly. 325 // The underlying socket closed unexpectedly.
396 if (result == 0) 326 if (result == 0)
397 return ERR_CONNECTION_CLOSED; 327 return ERR_CONNECTION_CLOSED;
398 328
399 buffer_.append(handshake_buf_->data(), result); 329 buffer_.append(handshake_buf_->data(), result);
400 bytes_received_ += result; 330 bytes_received_ += result;
401 331
402 // When the first few bytes are read, check how many more are required 332 // When the first few bytes are read, check how many more are required
403 // and accordingly increase them 333 // and accordingly increase them
404 if (bytes_received_ == kReadHeaderSize) { 334 if (bytes_received_ == kReadHeaderSize) {
405 // TODO(arindam): add error codes to net/error_list.h 335 // TODO(arindam): add error codes to net/error_list.h
406 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) 336 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte)
407 return ERR_INVALID_RESPONSE; 337 return ERR_INVALID_RESPONSE;
408 if (buffer_[1] != 0x00) 338 if (buffer_[1] != 0x00)
409 return ERR_FAILED; 339 return ERR_FAILED;
410 340
411 // We check the type of IP/Domain the server returns and accordingly 341 // We check the type of IP/Domain the server returns and accordingly
412 // increase the size of the response. For domains, we need to read the 342 // increase the size of the response. For domains, we need to read the
413 // size of the domain, so the initial request size is upto the domain 343 // size of the domain, so the initial request size is upto the domain
414 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is 344 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is
415 // read, we substract 1 byte from the additional request size. 345 // read, we substract 1 byte from the additional request size.
416 SocksEndPointAddressType address_type = 346 SocksEndPointAddressType address_type =
417 static_cast<SocksEndPointAddressType>(buffer_[3]); 347 static_cast<SocksEndPointAddressType>(buffer_[3]);
418 if (address_type == kEndPointFailedDomain) 348 if (address_type == kEndPointDomain)
419 read_header_size += static_cast<uint8>(buffer_[4]); 349 read_header_size += static_cast<uint8>(buffer_[4]);
420 else if (address_type == kEndPointResolvedIPv4) 350 else if (address_type == kEndPointResolvedIPv4)
421 read_header_size += sizeof(struct in_addr) - 1; 351 read_header_size += sizeof(struct in_addr) - 1;
422 else if (address_type == kEndPointResolvedIPv6) 352 else if (address_type == kEndPointResolvedIPv6)
423 read_header_size += sizeof(struct in6_addr) - 1; 353 read_header_size += sizeof(struct in6_addr) - 1;
424 else 354 else
425 return ERR_INVALID_RESPONSE; 355 return ERR_INVALID_RESPONSE;
426 356
427 read_header_size += 2; // for the port. 357 read_header_size += 2; // for the port.
428 next_state_ = STATE_HANDSHAKE_READ; 358 next_state_ = STATE_HANDSHAKE_READ;
(...skipping 15 matching lines...) Expand all
444 } 374 }
445 375
446 #if defined(OS_LINUX) 376 #if defined(OS_LINUX)
447 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name, 377 int SOCKS5ClientSocket::GetPeerName(struct sockaddr* name,
448 socklen_t* namelen) { 378 socklen_t* namelen) {
449 return transport_->GetPeerName(name, namelen); 379 return transport_->GetPeerName(name, namelen);
450 } 380 }
451 #endif 381 #endif
452 382
453 } // namespace net 383 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/socks5_client_socket.h ('k') | net/socket/socks5_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698