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 |