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 <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/format_macros.h" | 11 #include "base/format_macros.h" |
12 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
13 #include "base/sys_byteorder.h" | 13 #include "base/sys_byteorder.h" |
14 #include "base/trace_event/trace_event.h" | 14 #include "base/trace_event/trace_event.h" |
15 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
16 #include "net/log/net_log.h" | 16 #include "net/log/net_log.h" |
| 17 #include "net/log/net_log_event_type.h" |
17 #include "net/socket/client_socket_handle.h" | 18 #include "net/socket/client_socket_handle.h" |
18 | 19 |
19 namespace net { | 20 namespace net { |
20 | 21 |
21 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; | 22 const unsigned int SOCKS5ClientSocket::kGreetReadHeaderSize = 2; |
22 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; | 23 const unsigned int SOCKS5ClientSocket::kWriteHeaderSize = 10; |
23 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; | 24 const unsigned int SOCKS5ClientSocket::kReadHeaderSize = 5; |
24 const uint8_t SOCKS5ClientSocket::kSOCKS5Version = 0x05; | 25 const uint8_t SOCKS5ClientSocket::kSOCKS5Version = 0x05; |
25 const uint8_t SOCKS5ClientSocket::kTunnelCommand = 0x01; | 26 const uint8_t SOCKS5ClientSocket::kTunnelCommand = 0x01; |
26 const uint8_t SOCKS5ClientSocket::kNullByte = 0x00; | 27 const uint8_t SOCKS5ClientSocket::kNullByte = 0x00; |
(...skipping 23 matching lines...) Expand all Loading... |
50 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { | 51 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { |
51 DCHECK(transport_.get()); | 52 DCHECK(transport_.get()); |
52 DCHECK(transport_->socket()); | 53 DCHECK(transport_->socket()); |
53 DCHECK_EQ(STATE_NONE, next_state_); | 54 DCHECK_EQ(STATE_NONE, next_state_); |
54 DCHECK(user_callback_.is_null()); | 55 DCHECK(user_callback_.is_null()); |
55 | 56 |
56 // If already connected, then just return OK. | 57 // If already connected, then just return OK. |
57 if (completed_handshake_) | 58 if (completed_handshake_) |
58 return OK; | 59 return OK; |
59 | 60 |
60 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT); | 61 net_log_.BeginEvent(NetLogEventType::SOCKS5_CONNECT); |
61 | 62 |
62 next_state_ = STATE_GREET_WRITE; | 63 next_state_ = STATE_GREET_WRITE; |
63 buffer_.clear(); | 64 buffer_.clear(); |
64 | 65 |
65 int rv = DoLoop(OK); | 66 int rv = DoLoop(OK); |
66 if (rv == ERR_IO_PENDING) { | 67 if (rv == ERR_IO_PENDING) { |
67 user_callback_ = callback; | 68 user_callback_ = callback; |
68 } else { | 69 } else { |
69 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); | 70 net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_CONNECT, rv); |
70 } | 71 } |
71 return rv; | 72 return rv; |
72 } | 73 } |
73 | 74 |
74 void SOCKS5ClientSocket::Disconnect() { | 75 void SOCKS5ClientSocket::Disconnect() { |
75 completed_handshake_ = false; | 76 completed_handshake_ = false; |
76 transport_->socket()->Disconnect(); | 77 transport_->socket()->Disconnect(); |
77 | 78 |
78 // Reset other states to make sure they aren't mistakenly used later. | 79 // Reset other states to make sure they aren't mistakenly used later. |
79 // These are the states initialized by Connect(). | 80 // These are the states initialized by Connect(). |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 | 196 |
196 // Since Run() may result in Read being called, | 197 // Since Run() may result in Read being called, |
197 // clear user_callback_ up front. | 198 // clear user_callback_ up front. |
198 base::ResetAndReturn(&user_callback_).Run(result); | 199 base::ResetAndReturn(&user_callback_).Run(result); |
199 } | 200 } |
200 | 201 |
201 void SOCKS5ClientSocket::OnIOComplete(int result) { | 202 void SOCKS5ClientSocket::OnIOComplete(int result) { |
202 DCHECK_NE(STATE_NONE, next_state_); | 203 DCHECK_NE(STATE_NONE, next_state_); |
203 int rv = DoLoop(result); | 204 int rv = DoLoop(result); |
204 if (rv != ERR_IO_PENDING) { | 205 if (rv != ERR_IO_PENDING) { |
205 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); | 206 net_log_.EndEvent(NetLogEventType::SOCKS5_CONNECT); |
206 DoCallback(rv); | 207 DoCallback(rv); |
207 } | 208 } |
208 } | 209 } |
209 | 210 |
210 void SOCKS5ClientSocket::OnReadWriteComplete(const CompletionCallback& callback, | 211 void SOCKS5ClientSocket::OnReadWriteComplete(const CompletionCallback& callback, |
211 int result) { | 212 int result) { |
212 DCHECK_NE(ERR_IO_PENDING, result); | 213 DCHECK_NE(ERR_IO_PENDING, result); |
213 DCHECK(!callback.is_null()); | 214 DCHECK(!callback.is_null()); |
214 | 215 |
215 if (result > 0) | 216 if (result > 0) |
216 was_ever_used_ = true; | 217 was_ever_used_ = true; |
217 callback.Run(result); | 218 callback.Run(result); |
218 } | 219 } |
219 | 220 |
220 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 221 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
221 DCHECK_NE(next_state_, STATE_NONE); | 222 DCHECK_NE(next_state_, STATE_NONE); |
222 int rv = last_io_result; | 223 int rv = last_io_result; |
223 do { | 224 do { |
224 State state = next_state_; | 225 State state = next_state_; |
225 next_state_ = STATE_NONE; | 226 next_state_ = STATE_NONE; |
226 switch (state) { | 227 switch (state) { |
227 case STATE_GREET_WRITE: | 228 case STATE_GREET_WRITE: |
228 DCHECK_EQ(OK, rv); | 229 DCHECK_EQ(OK, rv); |
229 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); | 230 net_log_.BeginEvent(NetLogEventType::SOCKS5_GREET_WRITE); |
230 rv = DoGreetWrite(); | 231 rv = DoGreetWrite(); |
231 break; | 232 break; |
232 case STATE_GREET_WRITE_COMPLETE: | 233 case STATE_GREET_WRITE_COMPLETE: |
233 rv = DoGreetWriteComplete(rv); | 234 rv = DoGreetWriteComplete(rv); |
234 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); | 235 net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_GREET_WRITE, |
| 236 rv); |
235 break; | 237 break; |
236 case STATE_GREET_READ: | 238 case STATE_GREET_READ: |
237 DCHECK_EQ(OK, rv); | 239 DCHECK_EQ(OK, rv); |
238 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ); | 240 net_log_.BeginEvent(NetLogEventType::SOCKS5_GREET_READ); |
239 rv = DoGreetRead(); | 241 rv = DoGreetRead(); |
240 break; | 242 break; |
241 case STATE_GREET_READ_COMPLETE: | 243 case STATE_GREET_READ_COMPLETE: |
242 rv = DoGreetReadComplete(rv); | 244 rv = DoGreetReadComplete(rv); |
243 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); | 245 net_log_.EndEventWithNetErrorCode(NetLogEventType::SOCKS5_GREET_READ, |
| 246 rv); |
244 break; | 247 break; |
245 case STATE_HANDSHAKE_WRITE: | 248 case STATE_HANDSHAKE_WRITE: |
246 DCHECK_EQ(OK, rv); | 249 DCHECK_EQ(OK, rv); |
247 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); | 250 net_log_.BeginEvent(NetLogEventType::SOCKS5_HANDSHAKE_WRITE); |
248 rv = DoHandshakeWrite(); | 251 rv = DoHandshakeWrite(); |
249 break; | 252 break; |
250 case STATE_HANDSHAKE_WRITE_COMPLETE: | 253 case STATE_HANDSHAKE_WRITE_COMPLETE: |
251 rv = DoHandshakeWriteComplete(rv); | 254 rv = DoHandshakeWriteComplete(rv); |
252 net_log_.EndEventWithNetErrorCode( | 255 net_log_.EndEventWithNetErrorCode( |
253 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); | 256 NetLogEventType::SOCKS5_HANDSHAKE_WRITE, rv); |
254 break; | 257 break; |
255 case STATE_HANDSHAKE_READ: | 258 case STATE_HANDSHAKE_READ: |
256 DCHECK_EQ(OK, rv); | 259 DCHECK_EQ(OK, rv); |
257 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); | 260 net_log_.BeginEvent(NetLogEventType::SOCKS5_HANDSHAKE_READ); |
258 rv = DoHandshakeRead(); | 261 rv = DoHandshakeRead(); |
259 break; | 262 break; |
260 case STATE_HANDSHAKE_READ_COMPLETE: | 263 case STATE_HANDSHAKE_READ_COMPLETE: |
261 rv = DoHandshakeReadComplete(rv); | 264 rv = DoHandshakeReadComplete(rv); |
262 net_log_.EndEventWithNetErrorCode( | 265 net_log_.EndEventWithNetErrorCode( |
263 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); | 266 NetLogEventType::SOCKS5_HANDSHAKE_READ, rv); |
264 break; | 267 break; |
265 default: | 268 default: |
266 NOTREACHED() << "bad state"; | 269 NOTREACHED() << "bad state"; |
267 rv = ERR_UNEXPECTED; | 270 rv = ERR_UNEXPECTED; |
268 break; | 271 break; |
269 } | 272 } |
270 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 273 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
271 return rv; | 274 return rv; |
272 } | 275 } |
273 | 276 |
274 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 277 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
275 | 278 |
276 int SOCKS5ClientSocket::DoGreetWrite() { | 279 int SOCKS5ClientSocket::DoGreetWrite() { |
277 // Since we only have 1 byte to send the hostname length in, if the | 280 // Since we only have 1 byte to send the hostname length in, if the |
278 // URL has a hostname longer than 255 characters we can't send it. | 281 // URL has a hostname longer than 255 characters we can't send it. |
279 if (0xFF < host_request_info_.hostname().size()) { | 282 if (0xFF < host_request_info_.hostname().size()) { |
280 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); | 283 net_log_.AddEvent(NetLogEventType::SOCKS_HOSTNAME_TOO_BIG); |
281 return ERR_SOCKS_CONNECTION_FAILED; | 284 return ERR_SOCKS_CONNECTION_FAILED; |
282 } | 285 } |
283 | 286 |
284 if (buffer_.empty()) { | 287 if (buffer_.empty()) { |
285 buffer_ = std::string(kSOCKS5GreetWriteData, | 288 buffer_ = std::string(kSOCKS5GreetWriteData, |
286 arraysize(kSOCKS5GreetWriteData)); | 289 arraysize(kSOCKS5GreetWriteData)); |
287 bytes_sent_ = 0; | 290 bytes_sent_ = 0; |
288 } | 291 } |
289 | 292 |
290 next_state_ = STATE_GREET_WRITE_COMPLETE; | 293 next_state_ = STATE_GREET_WRITE_COMPLETE; |
(...skipping 26 matching lines...) Expand all Loading... |
317 handshake_buf_ = new IOBuffer(handshake_buf_len); | 320 handshake_buf_ = new IOBuffer(handshake_buf_len); |
318 return transport_->socket() | 321 return transport_->socket() |
319 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); | 322 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); |
320 } | 323 } |
321 | 324 |
322 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 325 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
323 if (result < 0) | 326 if (result < 0) |
324 return result; | 327 return result; |
325 | 328 |
326 if (result == 0) { | 329 if (result == 0) { |
327 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); | 330 net_log_.AddEvent( |
| 331 NetLogEventType::SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); |
328 return ERR_SOCKS_CONNECTION_FAILED; | 332 return ERR_SOCKS_CONNECTION_FAILED; |
329 } | 333 } |
330 | 334 |
331 bytes_received_ += result; | 335 bytes_received_ += result; |
332 buffer_.append(handshake_buf_->data(), result); | 336 buffer_.append(handshake_buf_->data(), result); |
333 if (bytes_received_ < kGreetReadHeaderSize) { | 337 if (bytes_received_ < kGreetReadHeaderSize) { |
334 next_state_ = STATE_GREET_READ; | 338 next_state_ = STATE_GREET_READ; |
335 return OK; | 339 return OK; |
336 } | 340 } |
337 | 341 |
338 // Got the greet data. | 342 // Got the greet data. |
339 if (buffer_[0] != kSOCKS5Version) { | 343 if (buffer_[0] != kSOCKS5Version) { |
340 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 344 net_log_.AddEvent(NetLogEventType::SOCKS_UNEXPECTED_VERSION, |
341 NetLog::IntCallback("version", buffer_[0])); | 345 NetLog::IntCallback("version", buffer_[0])); |
342 return ERR_SOCKS_CONNECTION_FAILED; | 346 return ERR_SOCKS_CONNECTION_FAILED; |
343 } | 347 } |
344 if (buffer_[1] != 0x00) { | 348 if (buffer_[1] != 0x00) { |
345 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, | 349 net_log_.AddEvent(NetLogEventType::SOCKS_UNEXPECTED_AUTH, |
346 NetLog::IntCallback("method", buffer_[1])); | 350 NetLog::IntCallback("method", buffer_[1])); |
347 return ERR_SOCKS_CONNECTION_FAILED; | 351 return ERR_SOCKS_CONNECTION_FAILED; |
348 } | 352 } |
349 | 353 |
350 buffer_.clear(); | 354 buffer_.clear(); |
351 next_state_ = STATE_HANDSHAKE_WRITE; | 355 next_state_ = STATE_HANDSHAKE_WRITE; |
352 return OK; | 356 return OK; |
353 } | 357 } |
354 | 358 |
355 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 359 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 return transport_->socket() | 431 return transport_->socket() |
428 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); | 432 ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_); |
429 } | 433 } |
430 | 434 |
431 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 435 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
432 if (result < 0) | 436 if (result < 0) |
433 return result; | 437 return result; |
434 | 438 |
435 // The underlying socket closed unexpectedly. | 439 // The underlying socket closed unexpectedly. |
436 if (result == 0) { | 440 if (result == 0) { |
437 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); | 441 net_log_.AddEvent( |
| 442 NetLogEventType::SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); |
438 return ERR_SOCKS_CONNECTION_FAILED; | 443 return ERR_SOCKS_CONNECTION_FAILED; |
439 } | 444 } |
440 | 445 |
441 buffer_.append(handshake_buf_->data(), result); | 446 buffer_.append(handshake_buf_->data(), result); |
442 bytes_received_ += result; | 447 bytes_received_ += result; |
443 | 448 |
444 // When the first few bytes are read, check how many more are required | 449 // When the first few bytes are read, check how many more are required |
445 // and accordingly increase them | 450 // and accordingly increase them |
446 if (bytes_received_ == kReadHeaderSize) { | 451 if (bytes_received_ == kReadHeaderSize) { |
447 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { | 452 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { |
448 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 453 net_log_.AddEvent(NetLogEventType::SOCKS_UNEXPECTED_VERSION, |
449 NetLog::IntCallback("version", buffer_[0])); | 454 NetLog::IntCallback("version", buffer_[0])); |
450 return ERR_SOCKS_CONNECTION_FAILED; | 455 return ERR_SOCKS_CONNECTION_FAILED; |
451 } | 456 } |
452 if (buffer_[1] != 0x00) { | 457 if (buffer_[1] != 0x00) { |
453 net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR, | 458 net_log_.AddEvent(NetLogEventType::SOCKS_SERVER_ERROR, |
454 NetLog::IntCallback("error_code", buffer_[1])); | 459 NetLog::IntCallback("error_code", buffer_[1])); |
455 return ERR_SOCKS_CONNECTION_FAILED; | 460 return ERR_SOCKS_CONNECTION_FAILED; |
456 } | 461 } |
457 | 462 |
458 // We check the type of IP/Domain the server returns and accordingly | 463 // We check the type of IP/Domain the server returns and accordingly |
459 // increase the size of the response. For domains, we need to read the | 464 // increase the size of the response. For domains, we need to read the |
460 // size of the domain, so the initial request size is upto the domain | 465 // size of the domain, so the initial request size is upto the domain |
461 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 466 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
462 // read, we substract 1 byte from the additional request size. | 467 // read, we substract 1 byte from the additional request size. |
463 SocksEndPointAddressType address_type = | 468 SocksEndPointAddressType address_type = |
464 static_cast<SocksEndPointAddressType>(buffer_[3]); | 469 static_cast<SocksEndPointAddressType>(buffer_[3]); |
465 if (address_type == kEndPointDomain) | 470 if (address_type == kEndPointDomain) |
466 read_header_size += static_cast<uint8_t>(buffer_[4]); | 471 read_header_size += static_cast<uint8_t>(buffer_[4]); |
467 else if (address_type == kEndPointResolvedIPv4) | 472 else if (address_type == kEndPointResolvedIPv4) |
468 read_header_size += sizeof(struct in_addr) - 1; | 473 read_header_size += sizeof(struct in_addr) - 1; |
469 else if (address_type == kEndPointResolvedIPv6) | 474 else if (address_type == kEndPointResolvedIPv6) |
470 read_header_size += sizeof(struct in6_addr) - 1; | 475 read_header_size += sizeof(struct in6_addr) - 1; |
471 else { | 476 else { |
472 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, | 477 net_log_.AddEvent(NetLogEventType::SOCKS_UNKNOWN_ADDRESS_TYPE, |
473 NetLog::IntCallback("address_type", buffer_[3])); | 478 NetLog::IntCallback("address_type", buffer_[3])); |
474 return ERR_SOCKS_CONNECTION_FAILED; | 479 return ERR_SOCKS_CONNECTION_FAILED; |
475 } | 480 } |
476 | 481 |
477 read_header_size += 2; // for the port. | 482 read_header_size += 2; // for the port. |
478 next_state_ = STATE_HANDSHAKE_READ; | 483 next_state_ = STATE_HANDSHAKE_READ; |
479 return OK; | 484 return OK; |
480 } | 485 } |
481 | 486 |
482 // When the final bytes are read, setup handshake. We ignore the rest | 487 // When the final bytes are read, setup handshake. We ignore the rest |
(...skipping 12 matching lines...) Expand all Loading... |
495 | 500 |
496 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { | 501 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { |
497 return transport_->socket()->GetPeerAddress(address); | 502 return transport_->socket()->GetPeerAddress(address); |
498 } | 503 } |
499 | 504 |
500 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { | 505 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { |
501 return transport_->socket()->GetLocalAddress(address); | 506 return transport_->socket()->GetLocalAddress(address); |
502 } | 507 } |
503 | 508 |
504 } // namespace net | 509 } // namespace net |
OLD | NEW |