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

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

Issue 150003: Reverting 19466. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 11 years, 6 months 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/socks_client_socket.h ('k') | net/socket/socks_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/socks_client_socket.h" 5 #include "net/socket/socks_client_socket.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "build/build_config.h" 8 #include "build/build_config.h"
9 #if defined(OS_WIN) 9 #if defined(OS_WIN)
10 #include <ws2tcpip.h> 10 #include <ws2tcpip.h>
(...skipping 10 matching lines...) Expand all
21 // Every SOCKS server requests a user-id from the client. It is optional 21 // Every SOCKS server requests a user-id from the client. It is optional
22 // and we send an empty string. 22 // and we send an empty string.
23 static const char kEmptyUserId[] = ""; 23 static const char kEmptyUserId[] = "";
24 24
25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS 25 // The SOCKS4a implementation suggests to use an invalid IP in case the DNS
26 // resolution at client fails. 26 // resolution at client fails.
27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 }; 27 static const uint8 kInvalidIp[] = { 0, 0, 0, 127 };
28 28
29 // For SOCKS4, the client sends 8 bytes plus the size of the user-id. 29 // For SOCKS4, the client sends 8 bytes plus the size of the user-id.
30 // For SOCKS4A, this increases to accomodate the unresolved hostname. 30 // For SOCKS4A, this increases to accomodate the unresolved hostname.
31 static const unsigned int kWriteHeaderSize = 8; 31 static const int kWriteHeaderSize = 8;
32 32
33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement. 33 // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement.
34 static const unsigned int kReadHeaderSize = 8; 34 static const int kReadHeaderSize = 8;
35 35
36 // Server Response codes for SOCKS. 36 // Server Response codes for SOCKS.
37 static const uint8 kServerResponseOk = 0x5A; 37 static const uint8 kServerResponseOk = 0x5A;
38 static const uint8 kServerResponseRejected = 0x5B; 38 static const uint8 kServerResponseRejected = 0x5B;
39 static const uint8 kServerResponseNotReachable = 0x5C; 39 static const uint8 kServerResponseNotReachable = 0x5C;
40 static const uint8 kServerResponseMismatchedUserId = 0x5D; 40 static const uint8 kServerResponseMismatchedUserId = 0x5D;
41 41
42 static const uint8 kSOCKSVersion4 = 0x04; 42 static const uint8 kSOCKSVersion4 = 0x04;
43 static const uint8 kSOCKSStreamRequest = 0x01; 43 static const uint8 kSOCKSStreamRequest = 0x01;
44 44
(...skipping 20 matching lines...) Expand all
65 65
66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, 66 SOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket,
67 const HostResolver::RequestInfo& req_info, 67 const HostResolver::RequestInfo& req_info,
68 HostResolver* host_resolver) 68 HostResolver* host_resolver)
69 : ALLOW_THIS_IN_INITIALIZER_LIST( 69 : ALLOW_THIS_IN_INITIALIZER_LIST(
70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 70 io_callback_(this, &SOCKSClientSocket::OnIOComplete)),
71 transport_(transport_socket), 71 transport_(transport_socket),
72 next_state_(STATE_NONE), 72 next_state_(STATE_NONE),
73 socks_version_(kSOCKS4Unresolved), 73 socks_version_(kSOCKS4Unresolved),
74 user_callback_(NULL), 74 user_callback_(NULL),
75 handshake_buf_len_(0),
76 buffer_(NULL),
77 buffer_len_(0),
75 completed_handshake_(false), 78 completed_handshake_(false),
76 bytes_sent_(0), 79 bytes_sent_(0),
77 bytes_received_(0), 80 bytes_received_(0),
78 resolver_(host_resolver), 81 resolver_(host_resolver),
79 host_request_info_(req_info) { 82 host_request_info_(req_info) {
80 } 83 }
81 84
82 SOCKSClientSocket::~SOCKSClientSocket() { 85 SOCKSClientSocket::~SOCKSClientSocket() {
83 Disconnect(); 86 Disconnect();
84 } 87 }
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 } 226 }
224 227
225 // Even if DNS resolution fails, we send OK since the server 228 // Even if DNS resolution fails, we send OK since the server
226 // resolves the domain. 229 // resolves the domain.
227 return OK; 230 return OK;
228 } 231 }
229 232
230 // Builds the buffer that is to be sent to the server. 233 // Builds the buffer that is to be sent to the server.
231 // We check whether the SOCKS proxy is 4 or 4A. 234 // We check whether the SOCKS proxy is 4 or 4A.
232 // In case it is 4A, the record size increases by size of the hostname. 235 // In case it is 4A, the record size increases by size of the hostname.
233 const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { 236 void SOCKSClientSocket::BuildHandshakeWriteBuffer() {
234 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 237 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
235 238
236 SOCKS4ServerRequest request; 239 int record_size = kWriteHeaderSize + arraysize(kEmptyUserId);
237 request.version = kSOCKSVersion4; 240 if (socks_version_ == kSOCKS4a) {
238 request.command = kSOCKSStreamRequest; 241 record_size += host_request_info_.hostname().size() + 1;
239 request.nw_port = htons(host_request_info_.port()); 242 }
243
244 buffer_len_ = record_size;
245 buffer_.reset(new char[buffer_len_]);
246
247 SOCKS4ServerRequest* request =
248 reinterpret_cast<SOCKS4ServerRequest*>(buffer_.get());
249
250 request->version = kSOCKSVersion4;
251 request->command = kSOCKSStreamRequest;
252 request->nw_port = htons(host_request_info_.port());
240 253
241 if (socks_version_ == kSOCKS4) { 254 if (socks_version_ == kSOCKS4) {
242 const struct addrinfo* ai = addresses_.head(); 255 const struct addrinfo* ai = addresses_.head();
243 DCHECK(ai); 256 DCHECK(ai);
244 // If the sockaddr is IPv6, we have already marked the version to socks4a 257 // If the sockaddr is IPv6, we have already marked the version to socks4a
245 // and so this step does not get hit. 258 // and so this step does not get hit.
246 struct sockaddr_in* ipv4_host = 259 struct sockaddr_in *ipv4_host =
247 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); 260 reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
248 memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr)); 261 memcpy(&request->ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
249 262
250 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai); 263 DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai);
251 } else if (socks_version_ == kSOCKS4a) { 264 } else if (socks_version_ == kSOCKS4a) {
252 // invalid IP of the form 0.0.0.127 265 // invalid IP of the form 0.0.0.127
253 memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp)); 266 memcpy(&request->ip, kInvalidIp, arraysize(kInvalidIp));
254 } else { 267 } else {
255 NOTREACHED(); 268 NOTREACHED();
256 } 269 }
257 270
258 std::string handshake_data(reinterpret_cast<char*>(&request), 271 memcpy(&buffer_[kWriteHeaderSize], kEmptyUserId, arraysize(kEmptyUserId));
259 sizeof(request));
260 handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId));
261 272
262 // In case we are passing the domain also, pass the hostname
263 // terminated with a null character.
264 if (socks_version_ == kSOCKS4a) { 273 if (socks_version_ == kSOCKS4a) {
265 handshake_data.append(host_request_info_.hostname()); 274 memcpy(&buffer_[kWriteHeaderSize + arraysize(kEmptyUserId)],
266 handshake_data.push_back('\0'); 275 host_request_info_.hostname().c_str(),
276 host_request_info_.hostname().size() + 1);
267 } 277 }
268
269 return handshake_data;
270 } 278 }
271 279
272 // Writes the SOCKS handshake data to the underlying socket connection. 280 // Writes the SOCKS handshake data to the underlying socket connection.
273 int SOCKSClientSocket::DoHandshakeWrite() { 281 int SOCKSClientSocket::DoHandshakeWrite() {
274 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 282 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
275 283
276 if (buffer_.empty()) { 284 if (!buffer_.get()) {
277 buffer_ = BuildHandshakeWriteBuffer(); 285 BuildHandshakeWriteBuffer();
278 bytes_sent_ = 0; 286 bytes_sent_ = 0;
279 } 287 }
280 288
281 int handshake_buf_len = buffer_.size() - bytes_sent_; 289 handshake_buf_len_ = buffer_len_ - bytes_sent_;
282 DCHECK_GT(handshake_buf_len, 0); 290 DCHECK_GT(handshake_buf_len_, 0);
283 handshake_buf_ = new IOBuffer(handshake_buf_len); 291 handshake_buf_ = new IOBuffer(handshake_buf_len_);
284 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 292 memcpy(handshake_buf_.get()->data(), &buffer_[bytes_sent_],
285 handshake_buf_len); 293 handshake_buf_len_);
286 return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_); 294 return transport_->Write(handshake_buf_, handshake_buf_len_, &io_callback_);
287 } 295 }
288 296
289 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) { 297 int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
290 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 298 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
291 299
292 if (result < 0) 300 if (result < 0)
293 return result; 301 return result;
294 302
295 // We ignore the case when result is 0, since the underlying Write
296 // may return spurious writes while waiting on the socket.
297
298 bytes_sent_ += result; 303 bytes_sent_ += result;
299 if (bytes_sent_ == buffer_.size()) { 304 if (bytes_sent_ == buffer_len_) {
300 next_state_ = STATE_HANDSHAKE_READ; 305 next_state_ = STATE_HANDSHAKE_READ;
301 buffer_.clear(); 306 buffer_.reset(NULL);
302 } else if (bytes_sent_ < buffer_.size()) { 307 } else if (bytes_sent_ < buffer_len_) {
303 next_state_ = STATE_HANDSHAKE_WRITE; 308 next_state_ = STATE_HANDSHAKE_WRITE;
304 } else { 309 } else {
305 return ERR_UNEXPECTED; 310 return ERR_UNEXPECTED;
306 } 311 }
307 312
308 return OK; 313 return OK;
309 } 314 }
310 315
311 int SOCKSClientSocket::DoHandshakeRead() { 316 int SOCKSClientSocket::DoHandshakeRead() {
312 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 317 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
313 318
314 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 319 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
315 320
316 if (buffer_.empty()) { 321 if (!buffer_.get()) {
322 buffer_.reset(new char[kReadHeaderSize]);
323 buffer_len_ = kReadHeaderSize;
317 bytes_received_ = 0; 324 bytes_received_ = 0;
318 } 325 }
319 326
320 int handshake_buf_len = kReadHeaderSize - bytes_received_; 327 handshake_buf_len_ = buffer_len_ - bytes_received_;
321 handshake_buf_ = new IOBuffer(handshake_buf_len); 328 handshake_buf_ = new IOBuffer(handshake_buf_len_);
322 return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_); 329 return transport_->Read(handshake_buf_, handshake_buf_len_, &io_callback_);
323 } 330 }
324 331
325 int SOCKSClientSocket::DoHandshakeReadComplete(int result) { 332 int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
326 DCHECK_NE(kSOCKS4Unresolved, socks_version_); 333 DCHECK_NE(kSOCKS4Unresolved, socks_version_);
327 334
328 if (result < 0) 335 if (result < 0)
329 return result; 336 return result;
330 337 if (bytes_received_ + result > buffer_len_)
331 // The underlying socket closed unexpectedly.
332 if (result == 0)
333 return ERR_CONNECTION_CLOSED;
334
335 if (bytes_received_ + result > kReadHeaderSize)
336 return ERR_INVALID_RESPONSE; 338 return ERR_INVALID_RESPONSE;
337 339
338 buffer_.append(handshake_buf_->data(), result); 340 memcpy(buffer_.get() + bytes_received_, handshake_buf_->data(), result);
339 bytes_received_ += result; 341 bytes_received_ += result;
340 if (bytes_received_ < kReadHeaderSize) { 342 if (bytes_received_ < buffer_len_) {
341 next_state_ = STATE_HANDSHAKE_READ; 343 next_state_ = STATE_HANDSHAKE_READ;
342 return OK; 344 return OK;
343 } 345 }
344 346
345 const SOCKS4ServerResponse* response = 347 SOCKS4ServerResponse* response =
346 reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data()); 348 reinterpret_cast<SOCKS4ServerResponse*>(buffer_.get());
347 349
348 if (response->reserved_null != 0x00) { 350 if (response->reserved_null != 0x00) {
349 LOG(ERROR) << "Unknown response from SOCKS server."; 351 LOG(ERROR) << "Unknown response from SOCKS server.";
350 return ERR_INVALID_RESPONSE; 352 return ERR_INVALID_RESPONSE;
351 } 353 }
352 354
353 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h 355 // TODO(arindam): Add SOCKS specific failure codes in net_error_list.h
354 switch (response->code) { 356 switch (response->code) {
355 case kServerResponseOk: 357 case kServerResponseOk:
356 completed_handshake_ = true; 358 completed_handshake_ = true;
(...skipping 22 matching lines...) Expand all
379 // Needed by ssl_client_socket_nss. 381 // Needed by ssl_client_socket_nss.
380 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) { 382 int SOCKSClientSocket::GetPeerName(struct sockaddr *name, socklen_t *namelen) {
381 // Default implementation just permits some unit tests to link. 383 // Default implementation just permits some unit tests to link.
382 NOTREACHED(); 384 NOTREACHED();
383 return ERR_UNEXPECTED; 385 return ERR_UNEXPECTED;
384 } 386 }
385 #endif 387 #endif
386 388
387 } // namespace net 389 } // namespace net
388 390
OLDNEW
« no previous file with comments | « net/socket/socks_client_socket.h ('k') | net/socket/socks_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698