| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/socket/socks5_client_socket.h" | 5 #include "net/socket/socks5_client_socket.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 NOTREACHED(); | 137 NOTREACHED(); |
| 138 return kProtoUnknown; | 138 return kProtoUnknown; |
| 139 } | 139 } |
| 140 | 140 |
| 141 bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) { | 141 bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) { |
| 142 if (transport_.get() && transport_->socket()) { | 142 if (transport_.get() && transport_->socket()) { |
| 143 return transport_->socket()->GetSSLInfo(ssl_info); | 143 return transport_->socket()->GetSSLInfo(ssl_info); |
| 144 } | 144 } |
| 145 NOTREACHED(); | 145 NOTREACHED(); |
| 146 return false; | 146 return false; |
| 147 | |
| 148 } | 147 } |
| 149 | 148 |
| 150 // Read is called by the transport layer above to read. This can only be done | 149 // Read is called by the transport layer above to read. This can only be done |
| 151 // if the SOCKS handshake is complete. | 150 // if the SOCKS handshake is complete. |
| 152 int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len, | 151 int SOCKS5ClientSocket::Read(IOBuffer* buf, |
| 152 int buf_len, |
| 153 const CompletionCallback& callback) { | 153 const CompletionCallback& callback) { |
| 154 DCHECK(completed_handshake_); | 154 DCHECK(completed_handshake_); |
| 155 DCHECK_EQ(STATE_NONE, next_state_); | 155 DCHECK_EQ(STATE_NONE, next_state_); |
| 156 DCHECK(user_callback_.is_null()); | 156 DCHECK(user_callback_.is_null()); |
| 157 DCHECK(!callback.is_null()); | 157 DCHECK(!callback.is_null()); |
| 158 | 158 |
| 159 int rv = transport_->socket()->Read( | 159 int rv = transport_->socket()->Read( |
| 160 buf, buf_len, | 160 buf, |
| 161 buf_len, |
| 161 base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, | 162 base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, |
| 162 base::Unretained(this), callback)); | 163 base::Unretained(this), |
| 164 callback)); |
| 163 if (rv > 0) | 165 if (rv > 0) |
| 164 was_ever_used_ = true; | 166 was_ever_used_ = true; |
| 165 return rv; | 167 return rv; |
| 166 } | 168 } |
| 167 | 169 |
| 168 // Write is called by the transport layer. This can only be done if the | 170 // Write is called by the transport layer. This can only be done if the |
| 169 // SOCKS handshake is complete. | 171 // SOCKS handshake is complete. |
| 170 int SOCKS5ClientSocket::Write(IOBuffer* buf, int buf_len, | 172 int SOCKS5ClientSocket::Write(IOBuffer* buf, |
| 173 int buf_len, |
| 171 const CompletionCallback& callback) { | 174 const CompletionCallback& callback) { |
| 172 DCHECK(completed_handshake_); | 175 DCHECK(completed_handshake_); |
| 173 DCHECK_EQ(STATE_NONE, next_state_); | 176 DCHECK_EQ(STATE_NONE, next_state_); |
| 174 DCHECK(user_callback_.is_null()); | 177 DCHECK(user_callback_.is_null()); |
| 175 DCHECK(!callback.is_null()); | 178 DCHECK(!callback.is_null()); |
| 176 | 179 |
| 177 int rv = transport_->socket()->Write( | 180 int rv = transport_->socket()->Write( |
| 178 buf, buf_len, | 181 buf, |
| 182 buf_len, |
| 179 base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, | 183 base::Bind(&SOCKS5ClientSocket::OnReadWriteComplete, |
| 180 base::Unretained(this), callback)); | 184 base::Unretained(this), |
| 185 callback)); |
| 181 if (rv > 0) | 186 if (rv > 0) |
| 182 was_ever_used_ = true; | 187 was_ever_used_ = true; |
| 183 return rv; | 188 return rv; |
| 184 } | 189 } |
| 185 | 190 |
| 186 int SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) { | 191 int SOCKS5ClientSocket::SetReceiveBufferSize(int32 size) { |
| 187 return transport_->socket()->SetReceiveBufferSize(size); | 192 return transport_->socket()->SetReceiveBufferSize(size); |
| 188 } | 193 } |
| 189 | 194 |
| 190 int SOCKS5ClientSocket::SetSendBufferSize(int32 size) { | 195 int SOCKS5ClientSocket::SetSendBufferSize(int32 size) { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 rv = DoGreetReadComplete(rv); | 249 rv = DoGreetReadComplete(rv); |
| 245 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); | 250 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); |
| 246 break; | 251 break; |
| 247 case STATE_HANDSHAKE_WRITE: | 252 case STATE_HANDSHAKE_WRITE: |
| 248 DCHECK_EQ(OK, rv); | 253 DCHECK_EQ(OK, rv); |
| 249 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); | 254 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); |
| 250 rv = DoHandshakeWrite(); | 255 rv = DoHandshakeWrite(); |
| 251 break; | 256 break; |
| 252 case STATE_HANDSHAKE_WRITE_COMPLETE: | 257 case STATE_HANDSHAKE_WRITE_COMPLETE: |
| 253 rv = DoHandshakeWriteComplete(rv); | 258 rv = DoHandshakeWriteComplete(rv); |
| 254 net_log_.EndEventWithNetErrorCode( | 259 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, |
| 255 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); | 260 rv); |
| 256 break; | 261 break; |
| 257 case STATE_HANDSHAKE_READ: | 262 case STATE_HANDSHAKE_READ: |
| 258 DCHECK_EQ(OK, rv); | 263 DCHECK_EQ(OK, rv); |
| 259 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); | 264 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); |
| 260 rv = DoHandshakeRead(); | 265 rv = DoHandshakeRead(); |
| 261 break; | 266 break; |
| 262 case STATE_HANDSHAKE_READ_COMPLETE: | 267 case STATE_HANDSHAKE_READ_COMPLETE: |
| 263 rv = DoHandshakeReadComplete(rv); | 268 rv = DoHandshakeReadComplete(rv); |
| 264 net_log_.EndEventWithNetErrorCode( | 269 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, |
| 265 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); | 270 rv); |
| 266 break; | 271 break; |
| 267 default: | 272 default: |
| 268 NOTREACHED() << "bad state"; | 273 NOTREACHED() << "bad state"; |
| 269 rv = ERR_UNEXPECTED; | 274 rv = ERR_UNEXPECTED; |
| 270 break; | 275 break; |
| 271 } | 276 } |
| 272 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 277 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 273 return rv; | 278 return rv; |
| 274 } | 279 } |
| 275 | 280 |
| 276 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 281 const char kSOCKS5GreetWriteData[] = {0x05, 0x01, 0x00}; // no authentication |
| 277 | 282 |
| 278 int SOCKS5ClientSocket::DoGreetWrite() { | 283 int SOCKS5ClientSocket::DoGreetWrite() { |
| 279 // Since we only have 1 byte to send the hostname length in, if the | 284 // Since we only have 1 byte to send the hostname length in, if the |
| 280 // URL has a hostname longer than 255 characters we can't send it. | 285 // URL has a hostname longer than 255 characters we can't send it. |
| 281 if (0xFF < host_request_info_.hostname().size()) { | 286 if (0xFF < host_request_info_.hostname().size()) { |
| 282 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); | 287 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); |
| 283 return ERR_SOCKS_CONNECTION_FAILED; | 288 return ERR_SOCKS_CONNECTION_FAILED; |
| 284 } | 289 } |
| 285 | 290 |
| 286 if (buffer_.empty()) { | 291 if (buffer_.empty()) { |
| 287 buffer_ = std::string(kSOCKS5GreetWriteData, | 292 buffer_ = |
| 288 arraysize(kSOCKS5GreetWriteData)); | 293 std::string(kSOCKS5GreetWriteData, arraysize(kSOCKS5GreetWriteData)); |
| 289 bytes_sent_ = 0; | 294 bytes_sent_ = 0; |
| 290 } | 295 } |
| 291 | 296 |
| 292 next_state_ = STATE_GREET_WRITE_COMPLETE; | 297 next_state_ = STATE_GREET_WRITE_COMPLETE; |
| 293 size_t handshake_buf_len = buffer_.size() - bytes_sent_; | 298 size_t handshake_buf_len = buffer_.size() - bytes_sent_; |
| 294 handshake_buf_ = new IOBuffer(handshake_buf_len); | 299 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 295 memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_], | 300 memcpy( |
| 296 handshake_buf_len); | 301 handshake_buf_->data(), &buffer_.data()[bytes_sent_], handshake_buf_len); |
| 297 return transport_->socket() | 302 return transport_->socket()->Write( |
| 298 ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_); | 303 handshake_buf_.get(), handshake_buf_len, io_callback_); |
| 299 } | 304 } |
| 300 | 305 |
| 301 int SOCKS5ClientSocket::DoGreetWriteComplete(int result) { | 306 int SOCKS5ClientSocket::DoGreetWriteComplete(int result) { |
| 302 if (result < 0) | 307 if (result < 0) |
| 303 return result; | 308 return result; |
| 304 | 309 |
| 305 bytes_sent_ += result; | 310 bytes_sent_ += result; |
| 306 if (bytes_sent_ == buffer_.size()) { | 311 if (bytes_sent_ == buffer_.size()) { |
| 307 buffer_.clear(); | 312 buffer_.clear(); |
| 308 bytes_received_ = 0; | 313 bytes_received_ = 0; |
| 309 next_state_ = STATE_GREET_READ; | 314 next_state_ = STATE_GREET_READ; |
| 310 } else { | 315 } else { |
| 311 next_state_ = STATE_GREET_WRITE; | 316 next_state_ = STATE_GREET_WRITE; |
| 312 } | 317 } |
| 313 return OK; | 318 return OK; |
| 314 } | 319 } |
| 315 | 320 |
| 316 int SOCKS5ClientSocket::DoGreetRead() { | 321 int SOCKS5ClientSocket::DoGreetRead() { |
| 317 next_state_ = STATE_GREET_READ_COMPLETE; | 322 next_state_ = STATE_GREET_READ_COMPLETE; |
| 318 size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_; | 323 size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_; |
| 319 handshake_buf_ = new IOBuffer(handshake_buf_len); | 324 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 320 return transport_->socket() | 325 return transport_->socket()->Read( |
| 321 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); | 326 handshake_buf_.get(), handshake_buf_len, io_callback_); |
| 322 } | 327 } |
| 323 | 328 |
| 324 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 329 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
| 325 if (result < 0) | 330 if (result < 0) |
| 326 return result; | 331 return result; |
| 327 | 332 |
| 328 if (result == 0) { | 333 if (result == 0) { |
| 329 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); | 334 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); |
| 330 return ERR_SOCKS_CONNECTION_FAILED; | 335 return ERR_SOCKS_CONNECTION_FAILED; |
| 331 } | 336 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 347 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, | 352 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, |
| 348 NetLog::IntegerCallback("method", buffer_[1])); | 353 NetLog::IntegerCallback("method", buffer_[1])); |
| 349 return ERR_SOCKS_CONNECTION_FAILED; | 354 return ERR_SOCKS_CONNECTION_FAILED; |
| 350 } | 355 } |
| 351 | 356 |
| 352 buffer_.clear(); | 357 buffer_.clear(); |
| 353 next_state_ = STATE_HANDSHAKE_WRITE; | 358 next_state_ = STATE_HANDSHAKE_WRITE; |
| 354 return OK; | 359 return OK; |
| 355 } | 360 } |
| 356 | 361 |
| 357 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 362 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer( |
| 358 const { | 363 std::string* handshake) const { |
| 359 DCHECK(handshake->empty()); | 364 DCHECK(handshake->empty()); |
| 360 | 365 |
| 361 handshake->push_back(kSOCKS5Version); | 366 handshake->push_back(kSOCKS5Version); |
| 362 handshake->push_back(kTunnelCommand); // Connect command | 367 handshake->push_back(kTunnelCommand); // Connect command |
| 363 handshake->push_back(kNullByte); // Reserved null | 368 handshake->push_back(kNullByte); // Reserved null |
| 364 | 369 |
| 365 handshake->push_back(kEndPointDomain); // The type of the address. | 370 handshake->push_back(kEndPointDomain); // The type of the address. |
| 366 | 371 |
| 367 DCHECK_GE(static_cast<size_t>(0xFF), host_request_info_.hostname().size()); | 372 DCHECK_GE(static_cast<size_t>(0xFF), host_request_info_.hostname().size()); |
| 368 | 373 |
| 369 // First add the size of the hostname, followed by the hostname. | 374 // First add the size of the hostname, followed by the hostname. |
| 370 handshake->push_back(static_cast<unsigned char>( | 375 handshake->push_back( |
| 371 host_request_info_.hostname().size())); | 376 static_cast<unsigned char>(host_request_info_.hostname().size())); |
| 372 handshake->append(host_request_info_.hostname()); | 377 handshake->append(host_request_info_.hostname()); |
| 373 | 378 |
| 374 uint16 nw_port = base::HostToNet16(host_request_info_.port()); | 379 uint16 nw_port = base::HostToNet16(host_request_info_.port()); |
| 375 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); | 380 handshake->append(reinterpret_cast<char*>(&nw_port), sizeof(nw_port)); |
| 376 return OK; | 381 return OK; |
| 377 } | 382 } |
| 378 | 383 |
| 379 // Writes the SOCKS handshake data to the underlying socket connection. | 384 // Writes the SOCKS handshake data to the underlying socket connection. |
| 380 int SOCKS5ClientSocket::DoHandshakeWrite() { | 385 int SOCKS5ClientSocket::DoHandshakeWrite() { |
| 381 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; | 386 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |
| 382 | 387 |
| 383 if (buffer_.empty()) { | 388 if (buffer_.empty()) { |
| 384 int rv = BuildHandshakeWriteBuffer(&buffer_); | 389 int rv = BuildHandshakeWriteBuffer(&buffer_); |
| 385 if (rv != OK) | 390 if (rv != OK) |
| 386 return rv; | 391 return rv; |
| 387 bytes_sent_ = 0; | 392 bytes_sent_ = 0; |
| 388 } | 393 } |
| 389 | 394 |
| 390 int handshake_buf_len = buffer_.size() - bytes_sent_; | 395 int handshake_buf_len = buffer_.size() - bytes_sent_; |
| 391 DCHECK_LT(0, handshake_buf_len); | 396 DCHECK_LT(0, handshake_buf_len); |
| 392 handshake_buf_ = new IOBuffer(handshake_buf_len); | 397 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 393 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], | 398 memcpy(handshake_buf_->data(), &buffer_[bytes_sent_], handshake_buf_len); |
| 394 handshake_buf_len); | 399 return transport_->socket()->Write( |
| 395 return transport_->socket() | 400 handshake_buf_.get(), handshake_buf_len, io_callback_); |
| 396 ->Write(handshake_buf_.get(), handshake_buf_len, io_callback_); | |
| 397 } | 401 } |
| 398 | 402 |
| 399 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { | 403 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) { |
| 400 if (result < 0) | 404 if (result < 0) |
| 401 return result; | 405 return result; |
| 402 | 406 |
| 403 // We ignore the case when result is 0, since the underlying Write | 407 // We ignore the case when result is 0, since the underlying Write |
| 404 // may return spurious writes while waiting on the socket. | 408 // may return spurious writes while waiting on the socket. |
| 405 | 409 |
| 406 bytes_sent_ += result; | 410 bytes_sent_ += result; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 419 int SOCKS5ClientSocket::DoHandshakeRead() { | 423 int SOCKS5ClientSocket::DoHandshakeRead() { |
| 420 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 424 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 421 | 425 |
| 422 if (buffer_.empty()) { | 426 if (buffer_.empty()) { |
| 423 bytes_received_ = 0; | 427 bytes_received_ = 0; |
| 424 read_header_size = kReadHeaderSize; | 428 read_header_size = kReadHeaderSize; |
| 425 } | 429 } |
| 426 | 430 |
| 427 int handshake_buf_len = read_header_size - bytes_received_; | 431 int handshake_buf_len = read_header_size - bytes_received_; |
| 428 handshake_buf_ = new IOBuffer(handshake_buf_len); | 432 handshake_buf_ = new IOBuffer(handshake_buf_len); |
| 429 return transport_->socket() | 433 return transport_->socket()->Read( |
| 430 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); | 434 handshake_buf_.get(), handshake_buf_len, io_callback_); |
| 431 } | 435 } |
| 432 | 436 |
| 433 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 437 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
| 434 if (result < 0) | 438 if (result < 0) |
| 435 return result; | 439 return result; |
| 436 | 440 |
| 437 // The underlying socket closed unexpectedly. | 441 // The underlying socket closed unexpectedly. |
| 438 if (result == 0) { | 442 if (result == 0) { |
| 439 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); | 443 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); |
| 440 return ERR_SOCKS_CONNECTION_FAILED; | 444 return ERR_SOCKS_CONNECTION_FAILED; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 | 501 |
| 498 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { | 502 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { |
| 499 return transport_->socket()->GetPeerAddress(address); | 503 return transport_->socket()->GetPeerAddress(address); |
| 500 } | 504 } |
| 501 | 505 |
| 502 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { | 506 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { |
| 503 return transport_->socket()->GetLocalAddress(address); | 507 return transport_->socket()->GetLocalAddress(address); |
| 504 } | 508 } |
| 505 | 509 |
| 506 } // namespace net | 510 } // namespace net |
| OLD | NEW |