15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/socks5_client_socket.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/callback_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h" 125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 SOCKS5ClientSocket::kSOCKS5Version = 0x05; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 SOCKS5ClientSocket::kTunnelCommand = 0x01; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint8 SOCKS5ClientSocket::kNullByte = 0x00; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(struct in_addr) == 4, incorrect_system_size_of_IPv4); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(struct in6_addr) == 16, incorrect_system_size_of_IPv6); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SOCKS5ClientSocket::SOCKS5ClientSocket( 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_ptr<ClientSocketHandle> transport_socket, 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostResolver::RequestInfo& req_info) 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : io_callback_(base::Bind(&SOCKS5ClientSocket::OnIOComplete, 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::Unretained(this))), 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) transport_(transport_socket.Pass()), 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_(STATE_NONE), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_(false), 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_sent_(0), 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_received_(0), 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size(kReadHeaderSize), 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch was_ever_used_(false), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_request_info_(req_info), 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) net_log_(transport_->socket()->NetLog()) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SOCKS5ClientSocket::~SOCKS5ClientSocket() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disconnect(); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_.get()); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_->socket()); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_state_); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If already connected, then just return OK. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (completed_handshake_) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_WRITE; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.clear(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(OK); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_ = callback; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocket::Disconnect() { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_ = false; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->Disconnect(); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reset other states to make sure they aren't mistakenly used later. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // These are the states initialized by Connect(). 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_NONE; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_callback_.Reset(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::IsConnected() const { 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return completed_handshake_ && transport_->socket()->IsConnected(); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::IsConnectedAndIdle() const { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return completed_handshake_ && transport_->socket()->IsConnectedAndIdle(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SOCKS5ClientSocket::NetLog() const { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_log_; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocket::SetSubresourceSpeculation() { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetSubresourceSpeculation(); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocket::SetOmniboxSpeculation() { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetOmniboxSpeculation(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::WasEverUsed() const { 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return was_ever_used_; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::UsingTCPFastOpen() const { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->UsingTCPFastOpen(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::WasNpnNegotiated() const { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->WasNpnNegotiated(); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto SOCKS5ClientSocket::GetNegotiatedProtocol() const { 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetNegotiatedProtocol(); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kProtoUnknown; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetSSLInfo(ssl_info); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Read is called by the transport layer above to read. This can only be done 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the SOCKS handshake is complete. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(completed_handshake_); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_state_); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!callback.is_null()); 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int rv = transport_->socket()->Read( 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch buf, buf_len, 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Unretained(this), callback)); 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (rv > 0) 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch was_ever_used_ = true; 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return rv; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Write is called by the transport layer. This can only be done if the 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SOCKS handshake is complete. 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::Write(IOBuffer* buf, int buf_len, 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const CompletionCallback& callback) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(completed_handshake_); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_state_); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(user_callback_.is_null()); 175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!callback.is_null()); 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int rv = transport_->socket()->Write( 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch buf, buf_len, 179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Unretained(this), callback)); 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (rv > 0) 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch was_ever_used_ = true; 183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return rv; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 186c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetReceiveBufferSize(size); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 190c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint SOCKS5ClientSocket::SetSendBufferSize(int32 size) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetSendBufferSize(size); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocket::DoCallback(int result) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ERR_IO_PENDING, result); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!user_callback_.is_null()); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since Run() may result in Read being called, 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clear user_callback_ up front. 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::ResetAndReturn(&user_callback_).Run(result); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SOCKS5ClientSocket::OnIOComplete(int result) { 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(STATE_NONE, next_state_); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoLoop(result); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoCallback(rv); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid SOCKS5ClientSocket::OnReadWriteComplete(const CompletionCallback& callback, 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int result) { 214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_NE(ERR_IO_PENDING, result); 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(!callback.is_null()); 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (result > 0) 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch was_ever_used_ = true; 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback.Run(result); 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoLoop(int last_io_result) { 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(next_state_, STATE_NONE); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = last_io_result; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state = next_state_; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_NONE; 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GREET_WRITE: 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGreetWrite(); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GREET_WRITE_COMPLETE: 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGreetWriteComplete(rv); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GREET_READ: 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGreetRead(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_GREET_READ_COMPLETE: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoGreetReadComplete(rv); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_HANDSHAKE_WRITE: 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoHandshakeWrite(); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_HANDSHAKE_WRITE_COMPLETE: 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoHandshakeWriteComplete(rv); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_HANDSHAKE_READ: 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(OK, rv); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoHandshakeRead(); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_HANDSHAKE_READ_COMPLETE: 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoHandshakeReadComplete(rv); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode( 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "bad state"; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = ERR_UNEXPECTED; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoGreetWrite() { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we only have 1 byte to send the hostname length in, if the 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // URL has a hostname longer than 255 characters we can't send it. 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0xFF < host_request_info_.hostname().size()) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_.empty()) { 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_ = std::string(kSOCKS5GreetWriteData, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kSOCKS5GreetWriteData)); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_sent_ = 0; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_WRITE_COMPLETE; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t handshake_buf_len = buffer_.size() - bytes_sent_; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_ = new IOBuffer(handshake_buf_len); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_], 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_len); 297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transport_->socket() 298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoGreetWriteComplete(int result) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_sent_ += result; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_sent_ == buffer_.size()) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.clear(); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_received_ = 0; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_READ; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_WRITE; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoGreetRead() { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_READ_COMPLETE; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_ = new IOBuffer(handshake_buf_len); 320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transport_->socket() 321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoGreetReadComplete(int result) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) { 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_received_ += result; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.append(handshake_buf_->data(), result); 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_received_ < kGreetReadHeaderSize) { 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_GREET_READ; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Got the greet data. 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_[0] != kSOCKS5Version) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("version", buffer_[0])); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_[1] != 0x00) { 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("method", buffer_[1])); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.clear(); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_WRITE; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const { 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(handshake->empty()); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->push_back(kSOCKS5Version); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->push_back(kTunnelCommand); // Connect command 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->push_back(kNullByte); // Reserved null 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->push_back(kEndPointDomain); // The type of the address. 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(static_cast<size_t>(0xFF), host_request_info_.hostname().size()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First add the size of the hostname, followed by the hostname. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->push_back(static_cast<unsigned char>( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_request_info_.hostname().size())); 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->append(host_request_info_.hostname()); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint16 nw_port = base::HostToNet16(host_request_info_.port()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Writes the SOCKS handshake data to the underlying socket connection. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoHandshakeWrite() { 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_.empty()) { 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = BuildHandshakeWriteBuffer(&buffer_); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != OK) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_sent_ = 0; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int handshake_buf_len = buffer_.size() - bytes_sent_; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(0, handshake_buf_len); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_ = new IOBuffer(handshake_buf_len); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_len); 395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transport_->socket() 396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We ignore the case when result is 0, since the underlying Write 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // may return spurious writes while waiting on the socket. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_sent_ += result; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_sent_ == buffer_.size()) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_READ; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.clear(); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (bytes_sent_ < buffer_.size()) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_WRITE; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoHandshakeRead() { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_READ_COMPLETE; 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_.empty()) { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_received_ = 0; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size = kReadHeaderSize; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int handshake_buf_len = read_header_size - bytes_received_; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) handshake_buf_ = new IOBuffer(handshake_buf_len); 429868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return transport_->socket() 430868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The underlying socket closed unexpectedly. 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.append(handshake_buf_->data(), result); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bytes_received_ += result; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the first few bytes are read, check how many more are required 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and accordingly increase them 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_received_ == kReadHeaderSize) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("version", buffer_[0])); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (buffer_[1] != 0x00) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR, 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("error_code", buffer_[1])); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We check the type of IP/Domain the server returns and accordingly 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // increase the size of the response. For domains, we need to read the 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size of the domain, so the initial request size is upto the domain 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // read, we substract 1 byte from the additional request size. 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SocksEndPointAddressType address_type = 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<SocksEndPointAddressType>(buffer_[3]); 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (address_type == kEndPointDomain) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size += static_cast<uint8>(buffer_[4]); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (address_type == kEndPointResolvedIPv4) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size += sizeof(struct in_addr) - 1; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (address_type == kEndPointResolvedIPv6) 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size += sizeof(struct in6_addr) - 1; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::IntegerCallback("address_type", buffer_[3])); 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SOCKS_CONNECTION_FAILED; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) read_header_size += 2; // for the port. 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_READ; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the final bytes are read, setup handshake. We ignore the rest 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the response since they represent the SOCKSv5 endpoint and have 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // no use when doing a tunnel connection. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bytes_received_ == read_header_size) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_ = true; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buffer_.clear(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_NONE; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_state_ = STATE_HANDSHAKE_READ; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetPeerAddress(address); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetLocalAddress(address); 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 507