1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/socket/socks_client_socket.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/basictypes.h" 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/io_buffer.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/sys_addrinfo.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_handle.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Every SOCKS server requests a user-id from the client. It is optional 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and we send an empty string. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const char kEmptyUserId[] = ""; 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// For SOCKS4, the client sends 8 bytes plus the size of the user-id. 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const unsigned int kWriteHeaderSize = 8; 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// For SOCKS4 the server sends 8 bytes for acknowledgement. 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const unsigned int kReadHeaderSize = 8; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Server Response codes for SOCKS. 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseOk = 0x5A; 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseRejected = 0x5B; 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseNotReachable = 0x5C; 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kServerResponseMismatchedUserId = 0x5D; 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kSOCKSVersion4 = 0x04; 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const uint8 kSOCKSStreamRequest = 0x01; 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// A struct holding the essential details of the SOCKS4 Server Request. 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The port in the header is stored in network byte order. 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct SOCKS4ServerRequest { 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 version; 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 command; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 nw_port; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 ip[4]; 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(sizeof(SOCKS4ServerRequest) == kWriteHeaderSize, 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks4_server_request_struct_wrong_size); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// A struct holding details of the SOCKS4 Server Response. 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstruct SOCKS4ServerResponse { 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 reserved_null; 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 code; 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 port; 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint8 ip[4]; 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(sizeof(SOCKS4ServerResponse) == kReadHeaderSize, 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott socks4_server_response_struct_wrong_size); 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSOCKSClientSocket::SOCKSClientSocket(ClientSocketHandle* transport_socket, 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const HostResolver::RequestInfo& req_info, 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott HostResolver* host_resolver) 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : ALLOW_THIS_IN_INITIALIZER_LIST( 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott transport_(transport_socket), 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_(STATE_NONE), 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_(NULL), 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_(false), 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_(0), 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_(0), 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_(host_resolver), 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host_request_info_(req_info), 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(transport_socket->socket()->NetLog()) { 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSOCKSClientSocket::SOCKSClientSocket(ClientSocket* transport_socket, 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const HostResolver::RequestInfo& req_info, 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HostResolver* host_resolver) 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ALLOW_THIS_IN_INITIALIZER_LIST( 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch io_callback_(this, &SOCKSClientSocket::OnIOComplete)), 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transport_(new ClientSocketHandle()), 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch next_state_(STATE_NONE), 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_callback_(NULL), 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch completed_handshake_(false), 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_sent_(0), 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bytes_received_(0), 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host_resolver_(host_resolver), 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host_request_info_(req_info), 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_(transport_socket->NetLog()) { 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transport_->set_socket(transport_socket); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSOCKSClientSocket::~SOCKSClientSocket() { 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Disconnect(); 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 947b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 957b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): find out if Connect should block 967b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 977b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint SOCKSClientSocket::Connect(CompletionCallback* callback 987b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID 997b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen , bool wait_for_connect 100e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , bool valid_uid 101e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma , uid_t calling_uid 1027b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif 1037b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen ) { 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(transport_.get()); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transport_->socket()); 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If already connected, then just return OK. 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (completed_handshake_) 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_HOST; 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch net_log_.BeginEvent(NetLog::TYPE_SOCKS_CONNECT, NULL); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoLoop(OK); 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv == ERR_IO_PENDING) { 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = callback; 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS_CONNECT, rv); 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::Disconnect() { 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_ = false; 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott host_resolver_.Cancel(); 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transport_->socket()->Disconnect(); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Reset other states to make sure they aren't mistakenly used later. 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // These are the states initialized by Connect(). 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_NONE; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::IsConnected() const { 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return completed_handshake_ && transport_->socket()->IsConnected(); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::IsConnectedAndIdle() const { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 14521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst BoundNetLog& SOCKSClientSocket::NetLog() const { 14621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return net_log_; 14721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 14821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SOCKSClientSocket::SetSubresourceSpeculation() { 1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetSubresourceSpeculation(); 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SOCKSClientSocket::SetOmniboxSpeculation() { 1583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick transport_->socket()->SetOmniboxSpeculation(); 1603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 1613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SOCKSClientSocket::WasEverUsed() const { 1663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (transport_.get() && transport_->socket()) { 1673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return transport_->socket()->WasEverUsed(); 1683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 1693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 1703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 1723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 173513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool SOCKSClientSocket::UsingTCPFastOpen() const { 174513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch if (transport_.get() && transport_->socket()) { 175513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return transport_->socket()->UsingTCPFastOpen(); 176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch } 177513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch NOTREACHED(); 178513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch return false; 179513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 180513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 181513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Read is called by the transport layer above to read. This can only be done 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// if the SOCKS handshake is complete. 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::Read(IOBuffer* buf, int buf_len, 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Read(buf, buf_len, callback); 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Write is called by the transport layer. This can only be done if the 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// SOCKS handshake is complete. 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::Write(IOBuffer* buf, int buf_len, 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(completed_handshake_); 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(STATE_NONE, next_state_); 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!user_callback_); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Write(buf, buf_len, callback); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::SetReceiveBufferSize(int32 size) { 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetReceiveBufferSize(size); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool SOCKSClientSocket::SetSendBufferSize(int32 size) { 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->SetSendBufferSize(size); 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::DoCallback(int result) { 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(ERR_IO_PENDING, result); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(user_callback_); 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Since Run() may result in Read being called, 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // clear user_callback_ up front. 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* c = user_callback_; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott user_callback_ = NULL; 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DVLOG(1) << "Finished setting up SOCKS handshake"; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott c->Run(result); 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid SOCKSClientSocket::OnIOComplete(int result) { 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(STATE_NONE, next_state_); 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = DoLoop(result); 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != ERR_IO_PENDING) { 22872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS_CONNECT, rv); 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DoCallback(rv); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoLoop(int last_io_result) { 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_NE(next_state_, STATE_NONE); 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = last_io_result; 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott State state = next_state_; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_NONE; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (state) { 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST: 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoResolveHost(); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_RESOLVE_HOST_COMPLETE: 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoResolveHostComplete(rv); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_WRITE: 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeWrite(); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_WRITE_COMPLETE: 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeWriteComplete(rv); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_READ: 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(OK, rv); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeRead(); 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case STATE_HANDSHAKE_READ_COMPLETE: 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = DoHandshakeReadComplete(rv); 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "bad state"; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_UNEXPECTED; 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoResolveHost() { 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_RESOLVE_HOST_COMPLETE; 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SOCKS4 only supports IPv4 addresses, so only try getting the IPv4 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // addresses for the target host. 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen host_request_info_.set_address_family(ADDRESS_FAMILY_IPV4); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return host_resolver_.Resolve( 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch host_request_info_, &addresses_, &io_callback_, net_log_); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoResolveHostComplete(int result) { 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (result != OK) { 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Resolving the hostname failed; fail the request rather than automatically 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // falling back to SOCKS4a (since it can be confusing to see invalid IP 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // addresses being sent to the SOCKS4 server when it doesn't support 4A.) 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen next_state_ = STATE_HANDSHAKE_WRITE; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Builds the buffer that is to be sent to the server. 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottconst std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const { 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SOCKS4ServerRequest request; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.version = kSOCKSVersion4; 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.command = kSOCKSStreamRequest; 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott request.nw_port = htons(host_request_info_.port()); 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const struct addrinfo* ai = addresses_.head(); 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(ai); 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We disabled IPv6 results when resolving the hostname, so none of the 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // results in the list will be IPv6. 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(eroman): we only ever use the first address in the list. It would be 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // more robust to try all the IP addresses we have before 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // failing the connect attempt. 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK_EQ(AF_INET, ai->ai_addr->sa_family); 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct sockaddr_in* ipv4_host = 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen reinterpret_cast<struct sockaddr_in*>(ai->ai_addr); 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen memcpy(&request.ip, &ipv4_host->sin_addr, sizeof(ipv4_host->sin_addr)); 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DVLOG(1) << "Resolved Host is : " << NetAddressToString(ai); 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string handshake_data(reinterpret_cast<char*>(&request), 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott sizeof(request)); 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId)); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return handshake_data; 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Writes the SOCKS handshake data to the underlying socket connection. 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeWrite() { 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer_.empty()) { 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_ = BuildHandshakeWriteBuffer(); 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_ = 0; 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int handshake_buf_len = buffer_.size() - bytes_sent_; 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GT(handshake_buf_len, 0); 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_ = new IOBuffer(handshake_buf_len); 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_len); 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Write(handshake_buf_, handshake_buf_len, 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &io_callback_); 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeWriteComplete(int result) { 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We ignore the case when result is 0, since the underlying Write 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // may return spurious writes while waiting on the socket. 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_sent_ += result; 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_sent_ == buffer_.size()) { 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ; 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.clear(); 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (bytes_sent_ < buffer_.size()) { 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_WRITE; 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeRead() { 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer_.empty()) { 362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_ = 0; 363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int handshake_buf_len = kReadHeaderSize - bytes_received_; 366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott handshake_buf_ = new IOBuffer(handshake_buf_len); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->Read(handshake_buf_, handshake_buf_len, 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &io_callback_); 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint SOCKSClientSocket::DoHandshakeReadComplete(int result) { 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result < 0) 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result; 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // The underlying socket closed unexpectedly. 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (result == 0) 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CONNECTION_CLOSED; 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (bytes_received_ + result > kReadHeaderSize) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(eroman): Describe failure in NetLog. 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_FAILED; 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_.append(handshake_buf_->data(), result); 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_received_ += result; 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_received_ < kReadHeaderSize) { 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott next_state_ = STATE_HANDSHAKE_READ; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const SOCKS4ServerResponse* response = 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data()); 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (response->reserved_null != 0x00) { 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "Unknown response from SOCKS server."; 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_FAILED; 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (response->code) { 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseOk: 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott completed_handshake_ = true; 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseRejected: 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request rejected or failed"; 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_FAILED; 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseNotReachable: 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request failed because client is not running " 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "identd (or not reachable from the server)"; 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_HOST_UNREACHABLE; 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case kServerResponseMismatchedUserId: 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS request failed because client's identd could " 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "not confirm the user ID string in the request"; 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_FAILED; 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "SOCKS server sent unknown response"; 416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_SOCKS_CONNECTION_FAILED; 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Note: we ignore the last 6 bytes as specified by the SOCKS protocol 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint SOCKSClientSocket::GetPeerAddress(AddressList* address) const { 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transport_->socket()->GetPeerAddress(address); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint SOCKSClientSocket::GetLocalAddress(IPEndPoint* address) const { 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return transport_->socket()->GetLocalAddress(address); 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 431