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

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

Issue 199048: Add methods for setting socket buffers to the Socket (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 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') | no next file » | 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) 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/memory_debug.h" 9 #include "base/memory_debug.h"
10 #include "base/stats_counters.h"
10 #include "base/string_util.h" 11 #include "base/string_util.h"
11 #include "base/sys_info.h" 12 #include "base/sys_info.h"
12 #include "base/trace_event.h" 13 #include "base/trace_event.h"
13 #include "net/base/io_buffer.h" 14 #include "net/base/io_buffer.h"
14 #include "net/base/net_errors.h" 15 #include "net/base/net_errors.h"
15 #include "net/base/winsock_init.h" 16 #include "net/base/winsock_init.h"
16 17
17 namespace net { 18 namespace net {
18 19
19 namespace { 20 namespace {
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 233
233 TCPClientSocketWin::~TCPClientSocketWin() { 234 TCPClientSocketWin::~TCPClientSocketWin() {
234 Disconnect(); 235 Disconnect();
235 } 236 }
236 237
237 int TCPClientSocketWin::Connect(CompletionCallback* callback) { 238 int TCPClientSocketWin::Connect(CompletionCallback* callback) {
238 // If already connected, then just return OK. 239 // If already connected, then just return OK.
239 if (socket_ != INVALID_SOCKET) 240 if (socket_ != INVALID_SOCKET)
240 return OK; 241 return OK;
241 242
243 static StatsCounter connects("tcp.connect");
244 connects.Increment();
245
242 TRACE_EVENT_BEGIN("socket.connect", this, ""); 246 TRACE_EVENT_BEGIN("socket.connect", this, "");
243 const struct addrinfo* ai = current_ai_; 247 const struct addrinfo* ai = current_ai_;
244 DCHECK(ai); 248 DCHECK(ai);
245 249
246 int rv = CreateSocket(ai); 250 int rv = CreateSocket(ai);
247 if (rv != OK) 251 if (rv != OK)
248 return rv; 252 return rv;
249 253
250 DCHECK(!core_); 254 DCHECK(!core_);
251 core_ = new Core(this); 255 core_ = new Core(this);
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) { 383 if (ResetEventIfSignaled(core_->read_overlapped_.hEvent)) {
380 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num)); 384 TRACE_EVENT_END("socket.read", this, StringPrintf("%d bytes", num));
381 385
382 // Because of how WSARecv fills memory when used asynchronously, Purify 386 // Because of how WSARecv fills memory when used asynchronously, Purify
383 // isn't able to detect that it's been initialized, so it scans for 0xcd 387 // isn't able to detect that it's been initialized, so it scans for 0xcd
384 // in the buffer and reports UMRs (uninitialized memory reads) for those 388 // in the buffer and reports UMRs (uninitialized memory reads) for those
385 // individual bytes. We override that in PURIFY builds to avoid the 389 // individual bytes. We override that in PURIFY builds to avoid the
386 // false error reports. 390 // false error reports.
387 // See bug 5297. 391 // See bug 5297.
388 base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num); 392 base::MemoryDebug::MarkAsInitialized(core_->read_buffer_.buf, num);
393 static StatsCounter read_bytes("tcp.read_bytes");
394 read_bytes.Add(num);
389 return static_cast<int>(num); 395 return static_cast<int>(num);
390 } 396 }
391 } else { 397 } else {
392 int err = WSAGetLastError(); 398 int err = WSAGetLastError();
393 if (err != WSA_IO_PENDING) 399 if (err != WSA_IO_PENDING)
394 return MapWinsockError(err); 400 return MapWinsockError(err);
395 } 401 }
396 core_->WatchForRead(); 402 core_->WatchForRead();
397 waiting_read_ = true; 403 waiting_read_ = true;
398 read_callback_ = callback; 404 read_callback_ = callback;
399 core_->read_iobuffer_ = buf; 405 core_->read_iobuffer_ = buf;
400 return ERR_IO_PENDING; 406 return ERR_IO_PENDING;
401 } 407 }
402 408
403 int TCPClientSocketWin::Write(IOBuffer* buf, 409 int TCPClientSocketWin::Write(IOBuffer* buf,
404 int buf_len, 410 int buf_len,
405 CompletionCallback* callback) { 411 CompletionCallback* callback) {
406 DCHECK_NE(socket_, INVALID_SOCKET); 412 DCHECK_NE(socket_, INVALID_SOCKET);
407 DCHECK(!waiting_write_); 413 DCHECK(!waiting_write_);
408 DCHECK(!write_callback_); 414 DCHECK(!write_callback_);
409 DCHECK_GT(buf_len, 0); 415 DCHECK_GT(buf_len, 0);
410 DCHECK(!core_->write_iobuffer_); 416 DCHECK(!core_->write_iobuffer_);
411 417
418 static StatsCounter reads("tcp.writes");
419 reads.Increment();
420
412 core_->write_buffer_.len = buf_len; 421 core_->write_buffer_.len = buf_len;
413 core_->write_buffer_.buf = buf->data(); 422 core_->write_buffer_.buf = buf->data();
414 423
415 TRACE_EVENT_BEGIN("socket.write", this, ""); 424 TRACE_EVENT_BEGIN("socket.write", this, "");
416 // TODO(wtc): Remove the CHECK after enough testing. 425 // TODO(wtc): Remove the CHECK after enough testing.
417 CHECK( 426 CHECK(
418 WaitForSingleObject(core_->write_overlapped_.hEvent, 0) == WAIT_TIMEOUT); 427 WaitForSingleObject(core_->write_overlapped_.hEvent, 0) == WAIT_TIMEOUT);
419 DWORD num; 428 DWORD num;
420 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0, 429 int rv = WSASend(socket_, &core_->write_buffer_, 1, &num, 0,
421 &core_->write_overlapped_, NULL); 430 &core_->write_overlapped_, NULL);
422 if (rv == 0) { 431 if (rv == 0) {
423 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) { 432 if (ResetEventIfSignaled(core_->write_overlapped_.hEvent)) {
424 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num)); 433 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num));
434 static StatsCounter write_bytes("tcp.write_bytes");
435 write_bytes.Add(num);
425 return static_cast<int>(num); 436 return static_cast<int>(num);
426 } 437 }
427 } else { 438 } else {
428 int err = WSAGetLastError(); 439 int err = WSAGetLastError();
429 if (err != WSA_IO_PENDING) 440 if (err != WSA_IO_PENDING)
430 return MapWinsockError(err); 441 return MapWinsockError(err);
431 } 442 }
432 core_->WatchForWrite(); 443 core_->WatchForWrite();
433 waiting_write_ = true; 444 waiting_write_ = true;
434 write_callback_ = callback; 445 write_callback_ = callback;
435 core_->write_iobuffer_ = buf; 446 core_->write_iobuffer_ = buf;
436 return ERR_IO_PENDING; 447 return ERR_IO_PENDING;
437 } 448 }
438 449
450 bool TCPClientSocketWin::SetReceiveBufferSize(int32 size) {
451 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
452 reinterpret_cast<const char*>(&size), sizeof(size));
453 DCHECK(!rv) << "Could not set socket receive buffer size: " << GetLastError();
454 return rv == 0;
455 }
456
457 bool TCPClientSocketWin::SetSendBufferSize(int32 size) {
458 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
459 reinterpret_cast<const char*>(&size), sizeof(size));
460 DCHECK(!rv) << "Could not set socket send buffer size: " << GetLastError();
461 return rv == 0;
462 }
463
439 int TCPClientSocketWin::CreateSocket(const struct addrinfo* ai) { 464 int TCPClientSocketWin::CreateSocket(const struct addrinfo* ai) {
440 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0, 465 socket_ = WSASocket(ai->ai_family, ai->ai_socktype, ai->ai_protocol, NULL, 0,
441 WSA_FLAG_OVERLAPPED); 466 WSA_FLAG_OVERLAPPED);
442 if (socket_ == INVALID_SOCKET) { 467 if (socket_ == INVALID_SOCKET) {
443 DWORD err = WSAGetLastError(); 468 DWORD err = WSAGetLastError();
444 LOG(ERROR) << "WSASocket failed: " << err; 469 LOG(ERROR) << "WSASocket failed: " << err;
445 return MapWinsockError(err); 470 return MapWinsockError(err);
446 } 471 }
447 472
448 // Increase the socket buffer sizes from the default sizes for WinXP. In 473 // Increase the socket buffer sizes from the default sizes for WinXP. In
449 // performance testing, there is substantial benefit by increasing from 8KB 474 // performance testing, there is substantial benefit by increasing from 8KB
450 // to 64KB. 475 // to 64KB.
451 // See also: 476 // See also:
452 // http://support.microsoft.com/kb/823764/EN-US 477 // http://support.microsoft.com/kb/823764/EN-US
453 // On Vista, if we manually set these sizes, Vista turns off its receive 478 // On Vista, if we manually set these sizes, Vista turns off its receive
454 // window auto-tuning feature. 479 // window auto-tuning feature.
455 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx 480 // http://blogs.msdn.com/wndp/archive/2006/05/05/Winhec-blog-tcpip-2.aspx
456 // Since Vista's auto-tune is better than any static value we can could set, 481 // Since Vista's auto-tune is better than any static value we can could set,
457 // only change these on pre-vista machines. 482 // only change these on pre-vista machines.
458 int32 major_version, minor_version, fix_version; 483 int32 major_version, minor_version, fix_version;
459 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version, 484 base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
460 &fix_version); 485 &fix_version);
461 if (major_version < 6) { 486 if (major_version < 6) {
462 const int kSocketBufferSize = 64 * 1024; 487 const int32 kSocketBufferSize = 64 * 1024;
463 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF, 488 SetReceiveBufferSize(kSocketBufferSize);
464 reinterpret_cast<const char*>(&kSocketBufferSize), 489 SetSendBufferSize(kSocketBufferSize);
465 sizeof(kSocketBufferSize));
466 DCHECK(!rv) << "Could not set socket send buffer size";
467 rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
468 reinterpret_cast<const char*>(&kSocketBufferSize),
469 sizeof(kSocketBufferSize));
470 DCHECK(!rv) << "Could not set socket receive buffer size";
471 } 490 }
472 491
473 // Disable Nagle. 492 // Disable Nagle.
474 // The Nagle implementation on windows is governed by RFC 896. The idea 493 // The Nagle implementation on windows is governed by RFC 896. The idea
475 // behind Nagle is to reduce small packets on the network. When Nagle is 494 // behind Nagle is to reduce small packets on the network. When Nagle is
476 // enabled, if a partial packet has been sent, the TCP stack will disallow 495 // enabled, if a partial packet has been sent, the TCP stack will disallow
477 // further *partial* packets until an ACK has been received from the other 496 // further *partial* packets until an ACK has been received from the other
478 // side. Good applications should always strive to send as much data as 497 // side. Good applications should always strive to send as much data as
479 // possible and avoid partial-packet sends. However, in most real world 498 // possible and avoid partial-packet sends. However, in most real world
480 // applications, there are edge cases where this does not happen, and two 499 // applications, there are edge cases where this does not happen, and two
(...skipping 16 matching lines...) Expand all
497 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle)); 516 reinterpret_cast<const char*>(&kDisableNagle), sizeof(kDisableNagle));
498 DCHECK(!rv) << "Could not disable nagle"; 517 DCHECK(!rv) << "Could not disable nagle";
499 518
500 return OK; 519 return OK;
501 } 520 }
502 521
503 void TCPClientSocketWin::DoReadCallback(int rv) { 522 void TCPClientSocketWin::DoReadCallback(int rv) {
504 DCHECK_NE(rv, ERR_IO_PENDING); 523 DCHECK_NE(rv, ERR_IO_PENDING);
505 DCHECK(read_callback_); 524 DCHECK(read_callback_);
506 525
526 static StatsCounter read_bytes("tcp.read_bytes");
527 read_bytes.Add(rv);
528
507 // since Run may result in Read being called, clear read_callback_ up front. 529 // since Run may result in Read being called, clear read_callback_ up front.
508 CompletionCallback* c = read_callback_; 530 CompletionCallback* c = read_callback_;
509 read_callback_ = NULL; 531 read_callback_ = NULL;
510 c->Run(rv); 532 c->Run(rv);
511 } 533 }
512 534
513 void TCPClientSocketWin::DoWriteCallback(int rv) { 535 void TCPClientSocketWin::DoWriteCallback(int rv) {
514 DCHECK_NE(rv, ERR_IO_PENDING); 536 DCHECK_NE(rv, ERR_IO_PENDING);
515 DCHECK(write_callback_); 537 DCHECK(write_callback_);
516 538
539 static StatsCounter write_bytes("tcp.write_bytes");
540 write_bytes.Add(rv);
541
517 // since Run may result in Write being called, clear write_callback_ up front. 542 // since Run may result in Write being called, clear write_callback_ up front.
518 CompletionCallback* c = write_callback_; 543 CompletionCallback* c = write_callback_;
519 write_callback_ = NULL; 544 write_callback_ = NULL;
520 c->Run(rv); 545 c->Run(rv);
521 } 546 }
522 547
523 void TCPClientSocketWin::DidCompleteConnect() { 548 void TCPClientSocketWin::DidCompleteConnect() {
524 DCHECK(waiting_connect_); 549 DCHECK(waiting_connect_);
525 int result; 550 int result;
526 551
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_, 603 BOOL ok = WSAGetOverlappedResult(socket_, &core_->write_overlapped_,
579 &num_bytes, FALSE, &flags); 604 &num_bytes, FALSE, &flags);
580 WSAResetEvent(core_->write_overlapped_.hEvent); 605 WSAResetEvent(core_->write_overlapped_.hEvent);
581 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes)); 606 TRACE_EVENT_END("socket.write", this, StringPrintf("%d bytes", num_bytes));
582 waiting_write_ = false; 607 waiting_write_ = false;
583 core_->write_iobuffer_ = NULL; 608 core_->write_iobuffer_ = NULL;
584 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError())); 609 DoWriteCallback(ok ? num_bytes : MapWinsockError(WSAGetLastError()));
585 } 610 }
586 611
587 } // namespace net 612 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/tcp_client_socket_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698