| Index: net/socket/socks_client_socket.cc
|
| ===================================================================
|
| --- net/socket/socks_client_socket.cc (revision 19473)
|
| +++ net/socket/socks_client_socket.cc (working copy)
|
| @@ -28,10 +28,10 @@
|
|
|
| // For SOCKS4, the client sends 8 bytes plus the size of the user-id.
|
| // For SOCKS4A, this increases to accomodate the unresolved hostname.
|
| -static const int kWriteHeaderSize = 8;
|
| +static const unsigned int kWriteHeaderSize = 8;
|
|
|
| // For SOCKS4 and SOCKS4a, the server sends 8 bytes for acknowledgement.
|
| -static const int kReadHeaderSize = 8;
|
| +static const unsigned int kReadHeaderSize = 8;
|
|
|
| // Server Response codes for SOCKS.
|
| static const uint8 kServerResponseOk = 0x5A;
|
| @@ -72,13 +72,10 @@
|
| next_state_(STATE_NONE),
|
| socks_version_(kSOCKS4Unresolved),
|
| user_callback_(NULL),
|
| - handshake_buf_len_(0),
|
| - buffer_(NULL),
|
| - buffer_len_(0),
|
| completed_handshake_(false),
|
| bytes_sent_(0),
|
| bytes_received_(0),
|
| - resolver_(host_resolver),
|
| + host_resolver_(host_resolver),
|
| host_request_info_(req_info) {
|
| }
|
|
|
| @@ -199,7 +196,7 @@
|
| DCHECK_EQ(kSOCKS4Unresolved, socks_version_);
|
|
|
| next_state_ = STATE_RESOLVE_HOST_COMPLETE;
|
| - return resolver_.Resolve(host_request_info_, &addresses_, &io_callback_);
|
| + return host_resolver_.Resolve(host_request_info_, &addresses_, &io_callback_);
|
| }
|
|
|
| int SOCKSClientSocket::DoResolveHostComplete(int result) {
|
| @@ -233,65 +230,60 @@
|
| // Builds the buffer that is to be sent to the server.
|
| // We check whether the SOCKS proxy is 4 or 4A.
|
| // In case it is 4A, the record size increases by size of the hostname.
|
| -void SOCKSClientSocket::BuildHandshakeWriteBuffer() {
|
| +const std::string SOCKSClientSocket::BuildHandshakeWriteBuffer() const {
|
| DCHECK_NE(kSOCKS4Unresolved, socks_version_);
|
|
|
| - int record_size = kWriteHeaderSize + arraysize(kEmptyUserId);
|
| - if (socks_version_ == kSOCKS4a) {
|
| - record_size += host_request_info_.hostname().size() + 1;
|
| - }
|
| + SOCKS4ServerRequest request;
|
| + request.version = kSOCKSVersion4;
|
| + request.command = kSOCKSStreamRequest;
|
| + request.nw_port = htons(host_request_info_.port());
|
|
|
| - buffer_len_ = record_size;
|
| - buffer_.reset(new char[buffer_len_]);
|
| -
|
| - SOCKS4ServerRequest* request =
|
| - reinterpret_cast<SOCKS4ServerRequest*>(buffer_.get());
|
| -
|
| - request->version = kSOCKSVersion4;
|
| - request->command = kSOCKSStreamRequest;
|
| - request->nw_port = htons(host_request_info_.port());
|
| -
|
| if (socks_version_ == kSOCKS4) {
|
| const struct addrinfo* ai = addresses_.head();
|
| DCHECK(ai);
|
| // If the sockaddr is IPv6, we have already marked the version to socks4a
|
| // and so this step does not get hit.
|
| - struct sockaddr_in *ipv4_host =
|
| + struct sockaddr_in* ipv4_host =
|
| reinterpret_cast<struct sockaddr_in*>(ai->ai_addr);
|
| - memcpy(&request->ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
|
| + memcpy(&request.ip, &(ipv4_host->sin_addr), sizeof(ipv4_host->sin_addr));
|
|
|
| DLOG(INFO) << "Resolved Host is : " << NetAddressToString(ai);
|
| } else if (socks_version_ == kSOCKS4a) {
|
| // invalid IP of the form 0.0.0.127
|
| - memcpy(&request->ip, kInvalidIp, arraysize(kInvalidIp));
|
| + memcpy(&request.ip, kInvalidIp, arraysize(kInvalidIp));
|
| } else {
|
| NOTREACHED();
|
| }
|
|
|
| - memcpy(&buffer_[kWriteHeaderSize], kEmptyUserId, arraysize(kEmptyUserId));
|
| + std::string handshake_data(reinterpret_cast<char*>(&request),
|
| + sizeof(request));
|
| + handshake_data.append(kEmptyUserId, arraysize(kEmptyUserId));
|
|
|
| + // In case we are passing the domain also, pass the hostname
|
| + // terminated with a null character.
|
| if (socks_version_ == kSOCKS4a) {
|
| - memcpy(&buffer_[kWriteHeaderSize + arraysize(kEmptyUserId)],
|
| - host_request_info_.hostname().c_str(),
|
| - host_request_info_.hostname().size() + 1);
|
| + handshake_data.append(host_request_info_.hostname());
|
| + handshake_data.push_back('\0');
|
| }
|
| +
|
| + return handshake_data;
|
| }
|
|
|
| // Writes the SOCKS handshake data to the underlying socket connection.
|
| int SOCKSClientSocket::DoHandshakeWrite() {
|
| next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
|
|
|
| - if (!buffer_.get()) {
|
| - BuildHandshakeWriteBuffer();
|
| + if (buffer_.empty()) {
|
| + buffer_ = BuildHandshakeWriteBuffer();
|
| bytes_sent_ = 0;
|
| }
|
|
|
| - handshake_buf_len_ = buffer_len_ - bytes_sent_;
|
| - DCHECK_GT(handshake_buf_len_, 0);
|
| - handshake_buf_ = new IOBuffer(handshake_buf_len_);
|
| - memcpy(handshake_buf_.get()->data(), &buffer_[bytes_sent_],
|
| - handshake_buf_len_);
|
| - return transport_->Write(handshake_buf_, handshake_buf_len_, &io_callback_);
|
| + int handshake_buf_len = buffer_.size() - bytes_sent_;
|
| + DCHECK_GT(handshake_buf_len, 0);
|
| + handshake_buf_ = new IOBuffer(handshake_buf_len);
|
| + memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
|
| + handshake_buf_len);
|
| + return transport_->Write(handshake_buf_, handshake_buf_len, &io_callback_);
|
| }
|
|
|
| int SOCKSClientSocket::DoHandshakeWriteComplete(int result) {
|
| @@ -300,11 +292,14 @@
|
| if (result < 0)
|
| return result;
|
|
|
| + // We ignore the case when result is 0, since the underlying Write
|
| + // may return spurious writes while waiting on the socket.
|
| +
|
| bytes_sent_ += result;
|
| - if (bytes_sent_ == buffer_len_) {
|
| + if (bytes_sent_ == buffer_.size()) {
|
| next_state_ = STATE_HANDSHAKE_READ;
|
| - buffer_.reset(NULL);
|
| - } else if (bytes_sent_ < buffer_len_) {
|
| + buffer_.clear();
|
| + } else if (bytes_sent_ < buffer_.size()) {
|
| next_state_ = STATE_HANDSHAKE_WRITE;
|
| } else {
|
| return ERR_UNEXPECTED;
|
| @@ -318,15 +313,13 @@
|
|
|
| next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
|
|
|
| - if (!buffer_.get()) {
|
| - buffer_.reset(new char[kReadHeaderSize]);
|
| - buffer_len_ = kReadHeaderSize;
|
| + if (buffer_.empty()) {
|
| bytes_received_ = 0;
|
| }
|
|
|
| - handshake_buf_len_ = buffer_len_ - bytes_received_;
|
| - handshake_buf_ = new IOBuffer(handshake_buf_len_);
|
| - return transport_->Read(handshake_buf_, handshake_buf_len_, &io_callback_);
|
| + int handshake_buf_len = kReadHeaderSize - bytes_received_;
|
| + handshake_buf_ = new IOBuffer(handshake_buf_len);
|
| + return transport_->Read(handshake_buf_, handshake_buf_len, &io_callback_);
|
| }
|
|
|
| int SOCKSClientSocket::DoHandshakeReadComplete(int result) {
|
| @@ -334,18 +327,23 @@
|
|
|
| if (result < 0)
|
| return result;
|
| - if (bytes_received_ + result > buffer_len_)
|
| +
|
| + // The underlying socket closed unexpectedly.
|
| + if (result == 0)
|
| + return ERR_CONNECTION_CLOSED;
|
| +
|
| + if (bytes_received_ + result > kReadHeaderSize)
|
| return ERR_INVALID_RESPONSE;
|
|
|
| - memcpy(buffer_.get() + bytes_received_, handshake_buf_->data(), result);
|
| + buffer_.append(handshake_buf_->data(), result);
|
| bytes_received_ += result;
|
| - if (bytes_received_ < buffer_len_) {
|
| + if (bytes_received_ < kReadHeaderSize) {
|
| next_state_ = STATE_HANDSHAKE_READ;
|
| return OK;
|
| }
|
|
|
| - SOCKS4ServerResponse* response =
|
| - reinterpret_cast<SOCKS4ServerResponse*>(buffer_.get());
|
| + const SOCKS4ServerResponse* response =
|
| + reinterpret_cast<const SOCKS4ServerResponse*>(buffer_.data());
|
|
|
| if (response->reserved_null != 0x00) {
|
| LOG(ERROR) << "Unknown response from SOCKS server.";
|
|
|