| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/field_trial.h" // for SlowStart trial | 9 #include "base/field_trial.h" // for SlowStart trial |
| 10 #include "base/memory_debug.h" | 10 #include "base/memory_debug.h" |
| 11 #include "base/stats_counters.h" | 11 #include "base/stats_counters.h" |
| 12 #include "base/string_util.h" | 12 #include "base/string_util.h" |
| 13 #include "base/sys_info.h" | 13 #include "base/sys_info.h" |
| 14 #include "base/trace_event.h" | 14 #include "base/trace_event.h" |
| 15 #include "net/base/io_buffer.h" | 15 #include "net/base/io_buffer.h" |
| 16 #include "net/base/load_log.h" |
| 16 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
| 17 #include "net/base/winsock_init.h" | 18 #include "net/base/winsock_init.h" |
| 18 | 19 |
| 19 namespace net { | 20 namespace net { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 // If the (manual-reset) event object is signaled, resets it and returns true. | 24 // If the (manual-reset) event object is signaled, resets it and returns true. |
| 24 // Otherwise, does nothing and returns false. Called after a Winsock function | 25 // Otherwise, does nothing and returns false. Called after a Winsock function |
| 25 // succeeds synchronously | 26 // succeeds synchronously |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 waiting_write_(false), | 265 waiting_write_(false), |
| 265 read_callback_(NULL), | 266 read_callback_(NULL), |
| 266 write_callback_(NULL) { | 267 write_callback_(NULL) { |
| 267 EnsureWinsockInit(); | 268 EnsureWinsockInit(); |
| 268 } | 269 } |
| 269 | 270 |
| 270 TCPClientSocketWin::~TCPClientSocketWin() { | 271 TCPClientSocketWin::~TCPClientSocketWin() { |
| 271 Disconnect(); | 272 Disconnect(); |
| 272 } | 273 } |
| 273 | 274 |
| 274 int TCPClientSocketWin::Connect(CompletionCallback* callback) { | 275 int TCPClientSocketWin::Connect(CompletionCallback* callback, |
| 276 LoadLog* load_log) { |
| 275 // If already connected, then just return OK. | 277 // If already connected, then just return OK. |
| 276 if (socket_ != INVALID_SOCKET) | 278 if (socket_ != INVALID_SOCKET) |
| 277 return OK; | 279 return OK; |
| 278 | 280 |
| 281 DCHECK(!load_log_); |
| 282 |
| 279 static StatsCounter connects("tcp.connect"); | 283 static StatsCounter connects("tcp.connect"); |
| 280 connects.Increment(); | 284 connects.Increment(); |
| 281 | 285 |
| 282 TRACE_EVENT_BEGIN("socket.connect", this, ""); | 286 TRACE_EVENT_BEGIN("socket.connect", this, ""); |
| 287 |
| 288 LoadLog::BeginEvent(load_log, LoadLog::TYPE_TCP_CONNECT); |
| 289 |
| 290 int rv = DoConnect(); |
| 291 |
| 292 if (rv == ERR_IO_PENDING) { |
| 293 // Synchronous operation not supported. |
| 294 DCHECK(callback); |
| 295 |
| 296 load_log_ = load_log; |
| 297 waiting_connect_ = true; |
| 298 read_callback_ = callback; |
| 299 } else { |
| 300 TRACE_EVENT_END("socket.connect", this, ""); |
| 301 LoadLog::EndEvent(load_log, LoadLog::TYPE_TCP_CONNECT); |
| 302 } |
| 303 |
| 304 return rv; |
| 305 } |
| 306 |
| 307 int TCPClientSocketWin::DoConnect() { |
| 283 const struct addrinfo* ai = current_ai_; | 308 const struct addrinfo* ai = current_ai_; |
| 284 DCHECK(ai); | 309 DCHECK(ai); |
| 285 | 310 |
| 286 int rv = CreateSocket(ai); | 311 int rv = CreateSocket(ai); |
| 287 if (rv != OK) | 312 if (rv != OK) |
| 288 return rv; | 313 return rv; |
| 289 | 314 |
| 290 DCHECK(!core_); | 315 DCHECK(!core_); |
| 291 core_ = new Core(this); | 316 core_ = new Core(this); |
| 292 | 317 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 304 // The MSDN page for connect says: | 329 // The MSDN page for connect says: |
| 305 // With a nonblocking socket, the connection attempt cannot be completed | 330 // With a nonblocking socket, the connection attempt cannot be completed |
| 306 // immediately. In this case, connect will return SOCKET_ERROR, and | 331 // immediately. In this case, connect will return SOCKET_ERROR, and |
| 307 // WSAGetLastError will return WSAEWOULDBLOCK. | 332 // WSAGetLastError will return WSAEWOULDBLOCK. |
| 308 // which implies that for a nonblocking socket, connect never returns 0. | 333 // which implies that for a nonblocking socket, connect never returns 0. |
| 309 // It's not documented whether the event object will be signaled or not | 334 // It's not documented whether the event object will be signaled or not |
| 310 // if connect does return 0. So the code below is essentially dead code | 335 // if connect does return 0. So the code below is essentially dead code |
| 311 // and we don't know if it's correct. | 336 // and we don't know if it's correct. |
| 312 NOTREACHED(); | 337 NOTREACHED(); |
| 313 | 338 |
| 314 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { | 339 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) |
| 315 TRACE_EVENT_END("socket.connect", this, ""); | |
| 316 return OK; | 340 return OK; |
| 317 } | |
| 318 } else { | 341 } else { |
| 319 DWORD err = WSAGetLastError(); | 342 DWORD err = WSAGetLastError(); |
| 320 if (err != WSAEWOULDBLOCK) { | 343 if (err != WSAEWOULDBLOCK) { |
| 321 LOG(ERROR) << "connect failed: " << err; | 344 LOG(ERROR) << "connect failed: " << err; |
| 322 return MapConnectError(err); | 345 return MapConnectError(err); |
| 323 } | 346 } |
| 324 } | 347 } |
| 325 | 348 |
| 326 core_->WatchForRead(); | 349 core_->WatchForRead(); |
| 327 waiting_connect_ = true; | |
| 328 read_callback_ = callback; | |
| 329 return ERR_IO_PENDING; | 350 return ERR_IO_PENDING; |
| 330 } | 351 } |
| 331 | 352 |
| 332 void TCPClientSocketWin::Disconnect() { | 353 void TCPClientSocketWin::Disconnect() { |
| 333 if (socket_ == INVALID_SOCKET) | 354 if (socket_ == INVALID_SOCKET) |
| 334 return; | 355 return; |
| 335 | 356 |
| 336 TRACE_EVENT_INSTANT("socket.disconnect", this, ""); | 357 TRACE_EVENT_INSTANT("socket.disconnect", this, ""); |
| 337 | 358 |
| 338 // Note: don't use CancelIo to cancel pending IO because it doesn't work | 359 // Note: don't use CancelIo to cancel pending IO because it doesn't work |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 // since Run may result in Write being called, clear write_callback_ up front. | 601 // since Run may result in Write being called, clear write_callback_ up front. |
| 581 CompletionCallback* c = write_callback_; | 602 CompletionCallback* c = write_callback_; |
| 582 write_callback_ = NULL; | 603 write_callback_ = NULL; |
| 583 c->Run(rv); | 604 c->Run(rv); |
| 584 } | 605 } |
| 585 | 606 |
| 586 void TCPClientSocketWin::DidCompleteConnect() { | 607 void TCPClientSocketWin::DidCompleteConnect() { |
| 587 DCHECK(waiting_connect_); | 608 DCHECK(waiting_connect_); |
| 588 int result; | 609 int result; |
| 589 | 610 |
| 590 TRACE_EVENT_END("socket.connect", this, ""); | |
| 591 waiting_connect_ = false; | 611 waiting_connect_ = false; |
| 592 | 612 |
| 593 WSANETWORKEVENTS events; | 613 WSANETWORKEVENTS events; |
| 594 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, | 614 int rv = WSAEnumNetworkEvents(socket_, core_->read_overlapped_.hEvent, |
| 595 &events); | 615 &events); |
| 596 if (rv == SOCKET_ERROR) { | 616 if (rv == SOCKET_ERROR) { |
| 597 NOTREACHED(); | 617 NOTREACHED(); |
| 598 result = MapWinsockError(WSAGetLastError()); | 618 result = MapWinsockError(WSAGetLastError()); |
| 599 } else if (events.lNetworkEvents & FD_CONNECT) { | 619 } else if (events.lNetworkEvents & FD_CONNECT) { |
| 600 DWORD error_code = static_cast<DWORD>(events.iErrorCode[FD_CONNECT_BIT]); | 620 DWORD error_code = static_cast<DWORD>(events.iErrorCode[FD_CONNECT_BIT]); |
| 601 if (current_ai_->ai_next && ( | 621 if (current_ai_->ai_next && ( |
| 602 error_code == WSAEADDRNOTAVAIL || | 622 error_code == WSAEADDRNOTAVAIL || |
| 603 error_code == WSAEAFNOSUPPORT || | 623 error_code == WSAEAFNOSUPPORT || |
| 604 error_code == WSAECONNREFUSED || | 624 error_code == WSAECONNREFUSED || |
| 605 error_code == WSAENETUNREACH || | 625 error_code == WSAENETUNREACH || |
| 606 error_code == WSAEHOSTUNREACH || | 626 error_code == WSAEHOSTUNREACH || |
| 607 error_code == WSAETIMEDOUT)) { | 627 error_code == WSAETIMEDOUT)) { |
| 608 // Try using the next address. | 628 // Try using the next address. |
| 609 const struct addrinfo* next = current_ai_->ai_next; | 629 const struct addrinfo* next = current_ai_->ai_next; |
| 610 Disconnect(); | 630 Disconnect(); |
| 611 current_ai_ = next; | 631 current_ai_ = next; |
| 612 result = Connect(read_callback_); | 632 scoped_refptr<LoadLog> load_log; |
| 633 load_log.swap(load_log_); |
| 634 TRACE_EVENT_END("socket.connect", this, ""); |
| 635 LoadLog::EndEvent(load_log, LoadLog::TYPE_TCP_CONNECT); |
| 636 result = Connect(read_callback_, load_log); |
| 613 } else { | 637 } else { |
| 614 result = MapConnectError(error_code); | 638 result = MapConnectError(error_code); |
| 639 TRACE_EVENT_END("socket.connect", this, ""); |
| 640 LoadLog::EndEvent(load_log_, LoadLog::TYPE_TCP_CONNECT); |
| 641 load_log_ = NULL; |
| 615 } | 642 } |
| 616 } else { | 643 } else { |
| 617 NOTREACHED(); | 644 NOTREACHED(); |
| 618 result = ERR_UNEXPECTED; | 645 result = ERR_UNEXPECTED; |
| 646 TRACE_EVENT_END("socket.connect", this, ""); |
| 647 LoadLog::EndEvent(load_log_, LoadLog::TYPE_TCP_CONNECT); |
| 648 load_log_ = NULL; |
| 619 } | 649 } |
| 620 | 650 |
| 621 if (result != ERR_IO_PENDING) | 651 if (result != ERR_IO_PENDING) |
| 622 DoReadCallback(result); | 652 DoReadCallback(result); |
| 623 } | 653 } |
| 624 | 654 |
| 625 void TCPClientSocketWin::DidCompleteRead() { | 655 void TCPClientSocketWin::DidCompleteRead() { |
| 626 DCHECK(waiting_read_); | 656 DCHECK(waiting_read_); |
| 627 DWORD num_bytes, flags; | 657 DWORD num_bytes, flags; |
| 628 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, | 658 BOOL ok = WSAGetOverlappedResult(socket_, &core_->read_overlapped_, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 641 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, | 671 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, |
| 642 &num_bytes, FALSE, &flags); | 672 &num_bytes, FALSE, &flags); |
| 643 WSAResetEvent(core_->write_overlapped_.hEvent); | 673 WSAResetEvent(core_->write_overlapped_.hEvent); |
| 644 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes)); | 674 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes)); |
| 645 waiting_write_ = false; | 675 waiting_write_ = false; |
| 646 core_->write_iobuffer_ = NULL; | 676 core_->write_iobuffer_ = NULL; |
| 647 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError())); | 677 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError())); |
| 648 } | 678 } |
| 649 | 679 |
| 650 } // namespace net | 680 } // namespace net |
| OLD | NEW |