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/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/format_macros.h" | 10 #include "base/format_macros.h" |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { | 67 int SOCKS5ClientSocket::Connect(const CompletionCallback& callback) { |
68 DCHECK(transport_.get()); | 68 DCHECK(transport_.get()); |
69 DCHECK(transport_->socket()); | 69 DCHECK(transport_->socket()); |
70 DCHECK_EQ(STATE_NONE, next_state_); | 70 DCHECK_EQ(STATE_NONE, next_state_); |
71 DCHECK(user_callback_.is_null()); | 71 DCHECK(user_callback_.is_null()); |
72 | 72 |
73 // If already connected, then just return OK. | 73 // If already connected, then just return OK. |
74 if (completed_handshake_) | 74 if (completed_handshake_) |
75 return OK; | 75 return OK; |
76 | 76 |
77 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); | 77 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_CONNECT); |
78 | 78 |
79 next_state_ = STATE_GREET_WRITE; | 79 next_state_ = STATE_GREET_WRITE; |
80 buffer_.clear(); | 80 buffer_.clear(); |
81 | 81 |
82 int rv = DoLoop(OK); | 82 int rv = DoLoop(OK); |
83 if (rv == ERR_IO_PENDING) { | 83 if (rv == ERR_IO_PENDING) { |
84 user_callback_ = callback; | 84 user_callback_ = callback; |
85 } else { | 85 } else { |
86 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); | 86 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_CONNECT, rv); |
87 } | 87 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 // clear user_callback_ up front. | 204 // clear user_callback_ up front. |
205 CompletionCallback c = user_callback_; | 205 CompletionCallback c = user_callback_; |
206 user_callback_.Reset(); | 206 user_callback_.Reset(); |
207 c.Run(result); | 207 c.Run(result); |
208 } | 208 } |
209 | 209 |
210 void SOCKS5ClientSocket::OnIOComplete(int result) { | 210 void SOCKS5ClientSocket::OnIOComplete(int result) { |
211 DCHECK_NE(STATE_NONE, next_state_); | 211 DCHECK_NE(STATE_NONE, next_state_); |
212 int rv = DoLoop(result); | 212 int rv = DoLoop(result); |
213 if (rv != ERR_IO_PENDING) { | 213 if (rv != ERR_IO_PENDING) { |
214 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT, NULL); | 214 net_log_.EndEvent(NetLog::TYPE_SOCKS5_CONNECT); |
215 DoCallback(rv); | 215 DoCallback(rv); |
216 } | 216 } |
217 } | 217 } |
218 | 218 |
219 int SOCKS5ClientSocket::DoLoop(int last_io_result) { | 219 int SOCKS5ClientSocket::DoLoop(int last_io_result) { |
220 DCHECK_NE(next_state_, STATE_NONE); | 220 DCHECK_NE(next_state_, STATE_NONE); |
221 int rv = last_io_result; | 221 int rv = last_io_result; |
222 do { | 222 do { |
223 State state = next_state_; | 223 State state = next_state_; |
224 next_state_ = STATE_NONE; | 224 next_state_ = STATE_NONE; |
225 switch (state) { | 225 switch (state) { |
226 case STATE_GREET_WRITE: | 226 case STATE_GREET_WRITE: |
227 DCHECK_EQ(OK, rv); | 227 DCHECK_EQ(OK, rv); |
228 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE, NULL); | 228 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_WRITE); |
229 rv = DoGreetWrite(); | 229 rv = DoGreetWrite(); |
230 break; | 230 break; |
231 case STATE_GREET_WRITE_COMPLETE: | 231 case STATE_GREET_WRITE_COMPLETE: |
232 rv = DoGreetWriteComplete(rv); | 232 rv = DoGreetWriteComplete(rv); |
233 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); | 233 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_WRITE, rv); |
234 break; | 234 break; |
235 case STATE_GREET_READ: | 235 case STATE_GREET_READ: |
236 DCHECK_EQ(OK, rv); | 236 DCHECK_EQ(OK, rv); |
237 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ, NULL); | 237 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_GREET_READ); |
238 rv = DoGreetRead(); | 238 rv = DoGreetRead(); |
239 break; | 239 break; |
240 case STATE_GREET_READ_COMPLETE: | 240 case STATE_GREET_READ_COMPLETE: |
241 rv = DoGreetReadComplete(rv); | 241 rv = DoGreetReadComplete(rv); |
242 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); | 242 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SOCKS5_GREET_READ, rv); |
243 break; | 243 break; |
244 case STATE_HANDSHAKE_WRITE: | 244 case STATE_HANDSHAKE_WRITE: |
245 DCHECK_EQ(OK, rv); | 245 DCHECK_EQ(OK, rv); |
246 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, NULL); | 246 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE); |
247 rv = DoHandshakeWrite(); | 247 rv = DoHandshakeWrite(); |
248 break; | 248 break; |
249 case STATE_HANDSHAKE_WRITE_COMPLETE: | 249 case STATE_HANDSHAKE_WRITE_COMPLETE: |
250 rv = DoHandshakeWriteComplete(rv); | 250 rv = DoHandshakeWriteComplete(rv); |
251 net_log_.EndEventWithNetErrorCode( | 251 net_log_.EndEventWithNetErrorCode( |
252 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); | 252 NetLog::TYPE_SOCKS5_HANDSHAKE_WRITE, rv); |
253 break; | 253 break; |
254 case STATE_HANDSHAKE_READ: | 254 case STATE_HANDSHAKE_READ: |
255 DCHECK_EQ(OK, rv); | 255 DCHECK_EQ(OK, rv); |
256 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ, NULL); | 256 net_log_.BeginEvent(NetLog::TYPE_SOCKS5_HANDSHAKE_READ); |
257 rv = DoHandshakeRead(); | 257 rv = DoHandshakeRead(); |
258 break; | 258 break; |
259 case STATE_HANDSHAKE_READ_COMPLETE: | 259 case STATE_HANDSHAKE_READ_COMPLETE: |
260 rv = DoHandshakeReadComplete(rv); | 260 rv = DoHandshakeReadComplete(rv); |
261 net_log_.EndEventWithNetErrorCode( | 261 net_log_.EndEventWithNetErrorCode( |
262 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); | 262 NetLog::TYPE_SOCKS5_HANDSHAKE_READ, rv); |
263 break; | 263 break; |
264 default: | 264 default: |
265 NOTREACHED() << "bad state"; | 265 NOTREACHED() << "bad state"; |
266 rv = ERR_UNEXPECTED; | 266 rv = ERR_UNEXPECTED; |
267 break; | 267 break; |
268 } | 268 } |
269 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 269 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
270 return rv; | 270 return rv; |
271 } | 271 } |
272 | 272 |
273 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication | 273 const char kSOCKS5GreetWriteData[] = { 0x05, 0x01, 0x00 }; // no authentication |
274 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; | 274 const char kSOCKS5GreetReadData[] = { 0x05, 0x00 }; |
275 | 275 |
276 int SOCKS5ClientSocket::DoGreetWrite() { | 276 int SOCKS5ClientSocket::DoGreetWrite() { |
277 // Since we only have 1 byte to send the hostname length in, if the | 277 // 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. | 278 // URL has a hostname longer than 255 characters we can't send it. |
279 if (0xFF < host_request_info_.hostname().size()) { | 279 if (0xFF < host_request_info_.hostname().size()) { |
280 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG, NULL); | 280 net_log_.AddEvent(NetLog::TYPE_SOCKS_HOSTNAME_TOO_BIG); |
281 return ERR_SOCKS_CONNECTION_FAILED; | 281 return ERR_SOCKS_CONNECTION_FAILED; |
282 } | 282 } |
283 | 283 |
284 if (buffer_.empty()) { | 284 if (buffer_.empty()) { |
285 buffer_ = std::string(kSOCKS5GreetWriteData, | 285 buffer_ = std::string(kSOCKS5GreetWriteData, |
286 arraysize(kSOCKS5GreetWriteData)); | 286 arraysize(kSOCKS5GreetWriteData)); |
287 bytes_sent_ = 0; | 287 bytes_sent_ = 0; |
288 } | 288 } |
289 | 289 |
290 next_state_ = STATE_GREET_WRITE_COMPLETE; | 290 next_state_ = STATE_GREET_WRITE_COMPLETE; |
(...skipping 26 matching lines...) Expand all Loading... |
317 handshake_buf_ = new IOBuffer(handshake_buf_len); | 317 handshake_buf_ = new IOBuffer(handshake_buf_len); |
318 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 318 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
319 io_callback_); | 319 io_callback_); |
320 } | 320 } |
321 | 321 |
322 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { | 322 int SOCKS5ClientSocket::DoGreetReadComplete(int result) { |
323 if (result < 0) | 323 if (result < 0) |
324 return result; | 324 return result; |
325 | 325 |
326 if (result == 0) { | 326 if (result == 0) { |
327 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING, | 327 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_GREETING); |
328 NULL); | |
329 return ERR_SOCKS_CONNECTION_FAILED; | 328 return ERR_SOCKS_CONNECTION_FAILED; |
330 } | 329 } |
331 | 330 |
332 bytes_received_ += result; | 331 bytes_received_ += result; |
333 buffer_.append(handshake_buf_->data(), result); | 332 buffer_.append(handshake_buf_->data(), result); |
334 if (bytes_received_ < kGreetReadHeaderSize) { | 333 if (bytes_received_ < kGreetReadHeaderSize) { |
335 next_state_ = STATE_GREET_READ; | 334 next_state_ = STATE_GREET_READ; |
336 return OK; | 335 return OK; |
337 } | 336 } |
338 | 337 |
339 // Got the greet data. | 338 // Got the greet data. |
340 if (buffer_[0] != kSOCKS5Version) { | 339 if (buffer_[0] != kSOCKS5Version) { |
341 net_log_.AddEvent( | 340 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
342 NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 341 NetLog::IntegerCallback("version", buffer_[0])); |
343 make_scoped_refptr(new NetLogIntegerParameter("version", buffer_[0]))); | |
344 return ERR_SOCKS_CONNECTION_FAILED; | 342 return ERR_SOCKS_CONNECTION_FAILED; |
345 } | 343 } |
346 if (buffer_[1] != 0x00) { | 344 if (buffer_[1] != 0x00) { |
347 net_log_.AddEvent( | 345 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, |
348 NetLog::TYPE_SOCKS_UNEXPECTED_AUTH, | 346 NetLog::IntegerCallback("method", buffer_[1])); |
349 make_scoped_refptr(new NetLogIntegerParameter("method", buffer_[1]))); | |
350 return ERR_SOCKS_CONNECTION_FAILED; | 347 return ERR_SOCKS_CONNECTION_FAILED; |
351 } | 348 } |
352 | 349 |
353 buffer_.clear(); | 350 buffer_.clear(); |
354 next_state_ = STATE_HANDSHAKE_WRITE; | 351 next_state_ = STATE_HANDSHAKE_WRITE; |
355 return OK; | 352 return OK; |
356 } | 353 } |
357 | 354 |
358 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) | 355 int SOCKS5ClientSocket::BuildHandshakeWriteBuffer(std::string* handshake) |
359 const { | 356 const { |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
430 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, | 427 return transport_->socket()->Read(handshake_buf_, handshake_buf_len, |
431 io_callback_); | 428 io_callback_); |
432 } | 429 } |
433 | 430 |
434 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { | 431 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) { |
435 if (result < 0) | 432 if (result < 0) |
436 return result; | 433 return result; |
437 | 434 |
438 // The underlying socket closed unexpectedly. | 435 // The underlying socket closed unexpectedly. |
439 if (result == 0) { | 436 if (result == 0) { |
440 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE, | 437 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTEDLY_CLOSED_DURING_HANDSHAKE); |
441 NULL); | |
442 return ERR_SOCKS_CONNECTION_FAILED; | 438 return ERR_SOCKS_CONNECTION_FAILED; |
443 } | 439 } |
444 | 440 |
445 buffer_.append(handshake_buf_->data(), result); | 441 buffer_.append(handshake_buf_->data(), result); |
446 bytes_received_ += result; | 442 bytes_received_ += result; |
447 | 443 |
448 // When the first few bytes are read, check how many more are required | 444 // When the first few bytes are read, check how many more are required |
449 // and accordingly increase them | 445 // and accordingly increase them |
450 if (bytes_received_ == kReadHeaderSize) { | 446 if (bytes_received_ == kReadHeaderSize) { |
451 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { | 447 if (buffer_[0] != kSOCKS5Version || buffer_[2] != kNullByte) { |
452 net_log_.AddEvent( | 448 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, |
453 NetLog::TYPE_SOCKS_UNEXPECTED_VERSION, | 449 NetLog::IntegerCallback("version", buffer_[0])); |
454 make_scoped_refptr( | |
455 new NetLogIntegerParameter("version", buffer_[0]))); | |
456 return ERR_SOCKS_CONNECTION_FAILED; | 450 return ERR_SOCKS_CONNECTION_FAILED; |
457 } | 451 } |
458 if (buffer_[1] != 0x00) { | 452 if (buffer_[1] != 0x00) { |
459 net_log_.AddEvent( | 453 net_log_.AddEvent(NetLog::TYPE_SOCKS_SERVER_ERROR, |
460 NetLog::TYPE_SOCKS_SERVER_ERROR, | 454 NetLog::IntegerCallback("error_code", buffer_[1])); |
461 make_scoped_refptr( | |
462 new NetLogIntegerParameter("error_code", buffer_[1]))); | |
463 return ERR_SOCKS_CONNECTION_FAILED; | 455 return ERR_SOCKS_CONNECTION_FAILED; |
464 } | 456 } |
465 | 457 |
466 // We check the type of IP/Domain the server returns and accordingly | 458 // We check the type of IP/Domain the server returns and accordingly |
467 // increase the size of the response. For domains, we need to read the | 459 // increase the size of the response. For domains, we need to read the |
468 // size of the domain, so the initial request size is upto the domain | 460 // size of the domain, so the initial request size is upto the domain |
469 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is | 461 // size. Since for IPv4/IPv6 the size is fixed and hence no 'size' is |
470 // read, we substract 1 byte from the additional request size. | 462 // read, we substract 1 byte from the additional request size. |
471 SocksEndPointAddressType address_type = | 463 SocksEndPointAddressType address_type = |
472 static_cast<SocksEndPointAddressType>(buffer_[3]); | 464 static_cast<SocksEndPointAddressType>(buffer_[3]); |
473 if (address_type == kEndPointDomain) | 465 if (address_type == kEndPointDomain) |
474 read_header_size += static_cast<uint8>(buffer_[4]); | 466 read_header_size += static_cast<uint8>(buffer_[4]); |
475 else if (address_type == kEndPointResolvedIPv4) | 467 else if (address_type == kEndPointResolvedIPv4) |
476 read_header_size += sizeof(struct in_addr) - 1; | 468 read_header_size += sizeof(struct in_addr) - 1; |
477 else if (address_type == kEndPointResolvedIPv6) | 469 else if (address_type == kEndPointResolvedIPv6) |
478 read_header_size += sizeof(struct in6_addr) - 1; | 470 read_header_size += sizeof(struct in6_addr) - 1; |
479 else { | 471 else { |
480 net_log_.AddEvent( | 472 net_log_.AddEvent(NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, |
481 NetLog::TYPE_SOCKS_UNKNOWN_ADDRESS_TYPE, | 473 NetLog::IntegerCallback("address_type", buffer_[3])); |
482 make_scoped_refptr( | |
483 new NetLogIntegerParameter("address_type", buffer_[3]))); | |
484 return ERR_SOCKS_CONNECTION_FAILED; | 474 return ERR_SOCKS_CONNECTION_FAILED; |
485 } | 475 } |
486 | 476 |
487 read_header_size += 2; // for the port. | 477 read_header_size += 2; // for the port. |
488 next_state_ = STATE_HANDSHAKE_READ; | 478 next_state_ = STATE_HANDSHAKE_READ; |
489 return OK; | 479 return OK; |
490 } | 480 } |
491 | 481 |
492 // When the final bytes are read, setup handshake. We ignore the rest | 482 // When the final bytes are read, setup handshake. We ignore the rest |
493 // of the response since they represent the SOCKSv5 endpoint and have | 483 // of the response since they represent the SOCKSv5 endpoint and have |
(...skipping 11 matching lines...) Expand all Loading... |
505 | 495 |
506 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { | 496 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const { |
507 return transport_->socket()->GetPeerAddress(address); | 497 return transport_->socket()->GetPeerAddress(address); |
508 } | 498 } |
509 | 499 |
510 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { | 500 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const { |
511 return transport_->socket()->GetLocalAddress(address); | 501 return transport_->socket()->GetLocalAddress(address); |
512 } | 502 } |
513 | 503 |
514 } // namespace net | 504 } // namespace net |
OLD | NEW |