Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: net/socket/tcp_client_socket_win.cc

Issue 10309002: Reimplements net::AddressList without struct addrinfo. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: get_canonical_name -> canonical_name. iterator to indexing Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/tcp_client_socket_win.h ('k') | net/socket/tcp_server_socket_libevent.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/tcp_client_socket_win.h" 5 #include "net/socket/tcp_client_socket_win.h"
6 6
7 #include <mstcpip.h> 7 #include <mstcpip.h>
8 8
9 #include "base/basictypes.h" 9 #include "base/basictypes.h"
10 #include "base/compiler_specific.h" 10 #include "base/compiler_specific.h"
11 #include "base/metrics/stats_counters.h" 11 #include "base/metrics/stats_counters.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/win/object_watcher.h" 13 #include "base/win/object_watcher.h"
14 #include "base/win/windows_version.h" 14 #include "base/win/windows_version.h"
15 #include "net/base/address_list_net_log_param.h" 15 #include "net/base/address_list_net_log_param.h"
16 #include "net/base/connection_type_histograms.h" 16 #include "net/base/connection_type_histograms.h"
17 #include "net/base/io_buffer.h" 17 #include "net/base/io_buffer.h"
18 #include "net/base/ip_endpoint.h" 18 #include "net/base/ip_endpoint.h"
19 #include "net/base/net_errors.h" 19 #include "net/base/net_errors.h"
20 #include "net/base/net_log.h" 20 #include "net/base/net_log.h"
21 #include "net/base/net_util.h" 21 #include "net/base/net_util.h"
22 #include "net/base/network_change_notifier.h" 22 #include "net/base/network_change_notifier.h"
23 #include "net/base/sys_addrinfo.h"
24 #include "net/base/winsock_init.h" 23 #include "net/base/winsock_init.h"
25 #include "net/base/winsock_util.h" 24 #include "net/base/winsock_util.h"
26 25
27 namespace net { 26 namespace net {
28 27
29 namespace { 28 namespace {
30 29
31 bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) { 30 bool SetSocketReceiveBufferSize(SOCKET socket, int32 size) {
32 int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, 31 int rv = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
33 reinterpret_cast<const char*>(&size), sizeof(size)); 32 reinterpret_cast<const char*>(&size), sizeof(size));
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 } 309 }
311 310
312 //----------------------------------------------------------------------------- 311 //-----------------------------------------------------------------------------
313 312
314 TCPClientSocketWin::TCPClientSocketWin(const AddressList& addresses, 313 TCPClientSocketWin::TCPClientSocketWin(const AddressList& addresses,
315 net::NetLog* net_log, 314 net::NetLog* net_log,
316 const net::NetLog::Source& source) 315 const net::NetLog::Source& source)
317 : socket_(INVALID_SOCKET), 316 : socket_(INVALID_SOCKET),
318 bound_socket_(INVALID_SOCKET), 317 bound_socket_(INVALID_SOCKET),
319 addresses_(addresses), 318 addresses_(addresses),
320 current_ai_(NULL), 319 current_address_index_(-1),
321 waiting_read_(false), 320 waiting_read_(false),
322 waiting_write_(false), 321 waiting_write_(false),
323 next_connect_state_(CONNECT_STATE_NONE), 322 next_connect_state_(CONNECT_STATE_NONE),
324 connect_os_error_(0), 323 connect_os_error_(0),
325 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)), 324 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
326 previously_disconnected_(false), 325 previously_disconnected_(false),
327 num_bytes_read_(0) { 326 num_bytes_read_(0) {
328 scoped_refptr<NetLog::EventParameters> params; 327 scoped_refptr<NetLog::EventParameters> params;
329 if (source.is_valid()) 328 if (source.is_valid())
330 params = new NetLogSourceParameter("source_dependency", source); 329 params = new NetLogSourceParameter("source_dependency", source);
(...skipping 11 matching lines...) Expand all
342 341
343 int error = SetupSocket(socket); 342 int error = SetupSocket(socket);
344 if (error) 343 if (error)
345 return MapSystemError(error); 344 return MapSystemError(error);
346 345
347 socket_ = socket; 346 socket_ = socket;
348 SetNonBlocking(socket_); 347 SetNonBlocking(socket_);
349 348
350 core_ = new Core(this); 349 core_ = new Core(this);
351 350
352 current_ai_ = addresses_.head(); 351 current_address_index_ = 0;
353 use_history_.set_was_ever_connected(); 352 use_history_.set_was_ever_connected();
354 353
355 return OK; 354 return OK;
356 } 355 }
357 356
358 int TCPClientSocketWin::Bind(const IPEndPoint& address) { 357 int TCPClientSocketWin::Bind(const IPEndPoint& address) {
359 if (current_ai_ != NULL || bind_address_.get()) { 358 if (current_address_index_ >= 0 || bind_address_.get()) {
360 // Cannot bind the socket if we are already connected or connecting. 359 // Cannot bind the socket if we are already connected or connecting.
361 return ERR_UNEXPECTED; 360 return ERR_UNEXPECTED;
362 } 361 }
363 362
364 sockaddr_storage addr_storage; 363 SockaddrStorage storage;
365 sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 364 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
366 size_t addr_len = sizeof(addr_storage);
367 if (!address.ToSockAddr(addr, &addr_len))
368 return ERR_INVALID_ARGUMENT; 365 return ERR_INVALID_ARGUMENT;
369 366
370 // Create |bound_socket_| and try to bound it to |address|. 367 // Create |bound_socket_| and try to bound it to |address|.
371 int error = CreateSocket(address.GetFamily(), &bound_socket_); 368 int error = CreateSocket(address.GetFamily(), &bound_socket_);
372 if (error) 369 if (error)
373 return MapSystemError(error); 370 return MapSystemError(error);
374 371
375 if (bind(bound_socket_, addr, addr_len)) { 372 if (bind(bound_socket_, storage.addr, storage.addr_len)) {
376 error = errno; 373 error = errno;
377 if (closesocket(bound_socket_) < 0) 374 if (closesocket(bound_socket_) < 0)
378 PLOG(ERROR) << "closesocket"; 375 PLOG(ERROR) << "closesocket";
379 bound_socket_ = INVALID_SOCKET; 376 bound_socket_ = INVALID_SOCKET;
380 return MapSystemError(error); 377 return MapSystemError(error);
381 } 378 }
382 379
383 bind_address_.reset(new IPEndPoint(address)); 380 bind_address_.reset(new IPEndPoint(address));
384 381
385 return 0; 382 return 0;
386 } 383 }
387 384
388 385
389 int TCPClientSocketWin::Connect(const CompletionCallback& callback) { 386 int TCPClientSocketWin::Connect(const CompletionCallback& callback) {
390 DCHECK(CalledOnValidThread()); 387 DCHECK(CalledOnValidThread());
391 388
392 // If already connected, then just return OK. 389 // If already connected, then just return OK.
393 if (socket_ != INVALID_SOCKET) 390 if (socket_ != INVALID_SOCKET)
394 return OK; 391 return OK;
395 392
396 base::StatsCounter connects("tcp.connect"); 393 base::StatsCounter connects("tcp.connect");
397 connects.Increment(); 394 connects.Increment();
398 395
399 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT, 396 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT,
400 new AddressListNetLogParam(addresses_)); 397 new AddressListNetLogParam(addresses_));
401 398
402 // We will try to connect to each address in addresses_. Start with the 399 // We will try to connect to each address in addresses_. Start with the
403 // first one in the list. 400 // first one in the list.
404 next_connect_state_ = CONNECT_STATE_CONNECT; 401 next_connect_state_ = CONNECT_STATE_CONNECT;
405 current_ai_ = addresses_.head(); 402 current_address_index_ = 0;
406 403
407 int rv = DoConnectLoop(OK); 404 int rv = DoConnectLoop(OK);
408 if (rv == ERR_IO_PENDING) { 405 if (rv == ERR_IO_PENDING) {
409 // Synchronous operation not supported. 406 // Synchronous operation not supported.
410 DCHECK(!callback.is_null()); 407 DCHECK(!callback.is_null());
411 // TODO(ajwong): Is setting read_callback_ the right thing to do here?? 408 // TODO(ajwong): Is setting read_callback_ the right thing to do here??
412 read_callback_ = callback; 409 read_callback_ = callback;
413 } else { 410 } else {
414 LogConnectCompletion(rv); 411 LogConnectCompletion(rv);
415 } 412 }
(...skipping 20 matching lines...) Expand all
436 LOG(DFATAL) << "bad state " << state; 433 LOG(DFATAL) << "bad state " << state;
437 rv = ERR_UNEXPECTED; 434 rv = ERR_UNEXPECTED;
438 break; 435 break;
439 } 436 }
440 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE); 437 } while (rv != ERR_IO_PENDING && next_connect_state_ != CONNECT_STATE_NONE);
441 438
442 return rv; 439 return rv;
443 } 440 }
444 441
445 int TCPClientSocketWin::DoConnect() { 442 int TCPClientSocketWin::DoConnect() {
446 const struct addrinfo* ai = current_ai_; 443 DCHECK_GE(current_address_index_, 0);
447 DCHECK(ai); 444 DCHECK_LT(current_address_index_, static_cast<int>(addresses_.size()));
448 DCHECK_EQ(0, connect_os_error_); 445 DCHECK_EQ(0, connect_os_error_);
449 446
447 const IPEndPoint& endpoint = addresses_[current_address_index_];
448
450 if (previously_disconnected_) { 449 if (previously_disconnected_) {
451 use_history_.Reset(); 450 use_history_.Reset();
452 previously_disconnected_ = false; 451 previously_disconnected_ = false;
453 } 452 }
454 453
455 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT, 454 net_log_.BeginEvent(NetLog::TYPE_TCP_CONNECT_ATTEMPT,
456 new NetLogStringParameter( 455 new NetLogStringParameter("address",
457 "address", NetAddressToStringWithPort(current_ai_))); 456 endpoint.ToString()));
458 457
459 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 458 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
460 459
461 if (bound_socket_ != INVALID_SOCKET) { 460 if (bound_socket_ != INVALID_SOCKET) {
462 DCHECK(bind_address_.get()); 461 DCHECK(bind_address_.get());
463 socket_ = bound_socket_; 462 socket_ = bound_socket_;
464 bound_socket_ = INVALID_SOCKET; 463 bound_socket_ = INVALID_SOCKET;
465 } else { 464 } else {
466 connect_os_error_ = CreateSocket(ai->ai_family, &socket_); 465 connect_os_error_ = CreateSocket(endpoint.GetFamily(), &socket_);
467 if (connect_os_error_ != 0) 466 if (connect_os_error_ != 0)
468 return MapSystemError(connect_os_error_); 467 return MapSystemError(connect_os_error_);
469 468
470 if (bind_address_.get()) { 469 if (bind_address_.get()) {
471 sockaddr_storage addr_storage; 470 SockaddrStorage storage;
472 sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); 471 if (!bind_address_->ToSockAddr(storage.addr, &storage.addr_len))
473 size_t addr_len = sizeof(addr_storage);
474 if (!bind_address_->ToSockAddr(addr, &addr_len))
475 return ERR_INVALID_ARGUMENT; 472 return ERR_INVALID_ARGUMENT;
476 if (bind(socket_, addr, addr_len)) 473 if (bind(socket_, storage.addr, storage.addr_len))
477 return MapSystemError(errno); 474 return MapSystemError(errno);
478 } 475 }
479 } 476 }
480 477
481 DCHECK(!core_); 478 DCHECK(!core_);
482 core_ = new Core(this); 479 core_ = new Core(this);
483 // WSAEventSelect sets the socket to non-blocking mode as a side effect. 480 // WSAEventSelect sets the socket to non-blocking mode as a side effect.
484 // Our connect() and recv() calls require that the socket be non-blocking. 481 // Our connect() and recv() calls require that the socket be non-blocking.
485 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT); 482 WSAEventSelect(socket_, core_->read_overlapped_.hEvent, FD_CONNECT);
486 483
484 SockaddrStorage storage;
485 if (!endpoint.ToSockAddr(storage.addr, &storage.addr_len))
486 return ERR_INVALID_ARGUMENT;
487 connect_start_time_ = base::TimeTicks::Now(); 487 connect_start_time_ = base::TimeTicks::Now();
488 if (!connect(socket_, ai->ai_addr, static_cast<int>(ai->ai_addrlen))) { 488 if (!connect(socket_, storage.addr, storage.addr_len)) {
489 // Connected without waiting! 489 // Connected without waiting!
490 // 490 //
491 // The MSDN page for connect says: 491 // The MSDN page for connect says:
492 // With a nonblocking socket, the connection attempt cannot be completed 492 // With a nonblocking socket, the connection attempt cannot be completed
493 // immediately. In this case, connect will return SOCKET_ERROR, and 493 // immediately. In this case, connect will return SOCKET_ERROR, and
494 // WSAGetLastError will return WSAEWOULDBLOCK. 494 // WSAGetLastError will return WSAEWOULDBLOCK.
495 // which implies that for a nonblocking socket, connect never returns 0. 495 // which implies that for a nonblocking socket, connect never returns 0.
496 // It's not documented whether the event object will be signaled or not 496 // It's not documented whether the event object will be signaled or not
497 // if connect does return 0. So the code below is essentially dead code 497 // if connect does return 0. So the code below is essentially dead code
498 // and we don't know if it's correct. 498 // and we don't know if it's correct.
(...skipping 26 matching lines...) Expand all
525 if (result == OK) { 525 if (result == OK) {
526 connect_time_micros_ = base::TimeTicks::Now() - connect_start_time_; 526 connect_time_micros_ = base::TimeTicks::Now() - connect_start_time_;
527 use_history_.set_was_ever_connected(); 527 use_history_.set_was_ever_connected();
528 return OK; // Done! 528 return OK; // Done!
529 } 529 }
530 530
531 // Close whatever partially connected socket we currently have. 531 // Close whatever partially connected socket we currently have.
532 DoDisconnect(); 532 DoDisconnect();
533 533
534 // Try to fall back to the next address in the list. 534 // Try to fall back to the next address in the list.
535 if (current_ai_->ai_next) { 535 if (current_address_index_ + 1 < static_cast<int>(addresses_.size())) {
536 next_connect_state_ = CONNECT_STATE_CONNECT; 536 next_connect_state_ = CONNECT_STATE_CONNECT;
537 current_ai_ = current_ai_->ai_next; 537 ++current_address_index_;
538 return OK; 538 return OK;
539 } 539 }
540 540
541 // Otherwise there is nothing to fall back to, so give up. 541 // Otherwise there is nothing to fall back to, so give up.
542 return result; 542 return result;
543 } 543 }
544 544
545 void TCPClientSocketWin::Disconnect() { 545 void TCPClientSocketWin::Disconnect() {
546 DoDisconnect(); 546 DoDisconnect();
547 current_ai_ = NULL; 547 current_address_index_ = -1;
548 } 548 }
549 549
550 void TCPClientSocketWin::DoDisconnect() { 550 void TCPClientSocketWin::DoDisconnect() {
551 DCHECK(CalledOnValidThread()); 551 DCHECK(CalledOnValidThread());
552 552
553 if (socket_ == INVALID_SOCKET) 553 if (socket_ == INVALID_SOCKET)
554 return; 554 return;
555 555
556 // Note: don't use CancelIo to cancel pending IO because it doesn't work 556 // Note: don't use CancelIo to cancel pending IO because it doesn't work
557 // when there is a Winsock layered service provider. 557 // when there is a Winsock layered service provider.
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
622 return false; 622 return false;
623 623
624 return true; 624 return true;
625 } 625 }
626 626
627 int TCPClientSocketWin::GetPeerAddress(AddressList* address) const { 627 int TCPClientSocketWin::GetPeerAddress(AddressList* address) const {
628 DCHECK(CalledOnValidThread()); 628 DCHECK(CalledOnValidThread());
629 DCHECK(address); 629 DCHECK(address);
630 if (!IsConnected()) 630 if (!IsConnected())
631 return ERR_SOCKET_NOT_CONNECTED; 631 return ERR_SOCKET_NOT_CONNECTED;
632 *address = AddressList::CreateByCopyingFirstAddress(current_ai_); 632 *address = AddressList(addresses_[current_address_index_]);
633 return OK; 633 return OK;
634 } 634 }
635 635
636 int TCPClientSocketWin::GetLocalAddress(IPEndPoint* address) const { 636 int TCPClientSocketWin::GetLocalAddress(IPEndPoint* address) const {
637 DCHECK(CalledOnValidThread()); 637 DCHECK(CalledOnValidThread());
638 DCHECK(address); 638 DCHECK(address);
639 if (!IsConnected()) 639 if (!IsConnected())
640 return ERR_SOCKET_NOT_CONNECTED; 640 return ERR_SOCKET_NOT_CONNECTED;
641 641
642 struct sockaddr_storage addr_storage; 642 struct sockaddr_storage addr_storage;
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 use_history_.set_was_used_to_convey_data(); 908 use_history_.set_was_used_to_convey_data();
909 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes, 909 net_log_.AddByteTransferEvent(NetLog::TYPE_SOCKET_BYTES_SENT, num_bytes,
910 core_->write_buffer_.buf); 910 core_->write_buffer_.buf);
911 } 911 }
912 } 912 }
913 core_->write_iobuffer_ = NULL; 913 core_->write_iobuffer_ = NULL;
914 DoWriteCallback(rv); 914 DoWriteCallback(rv);
915 } 915 }
916 916
917 } // namespace net 917 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/tcp_client_socket_win.h ('k') | net/socket/tcp_server_socket_libevent.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698