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

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

Issue 4039003: Add experimental option for TCP FastOpen.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 1 month 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_libevent.h ('k') | net/socket/tcp_client_socket_pool_unittest.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) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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_libevent.h" 5 #include "net/socket/tcp_client_socket.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <netdb.h> 9 #include <netdb.h>
10 #include <sys/socket.h> 10 #include <sys/socket.h>
11 #include <netinet/tcp.h> 11 #include <netinet/tcp.h>
12 #if defined(OS_POSIX) 12 #if defined(OS_POSIX)
13 #include <netinet/in.h> 13 #include <netinet/in.h>
14 #endif 14 #endif
15 15
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 const net::NetLog::Source& source) 113 const net::NetLog::Source& source)
114 : socket_(kInvalidSocket), 114 : socket_(kInvalidSocket),
115 addresses_(addresses), 115 addresses_(addresses),
116 current_ai_(NULL), 116 current_ai_(NULL),
117 read_watcher_(this), 117 read_watcher_(this),
118 write_watcher_(this), 118 write_watcher_(this),
119 read_callback_(NULL), 119 read_callback_(NULL),
120 write_callback_(NULL), 120 write_callback_(NULL),
121 next_connect_state_(CONNECT_STATE_NONE), 121 next_connect_state_(CONNECT_STATE_NONE),
122 connect_os_error_(0), 122 connect_os_error_(0),
123 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { 123 net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
124 use_tcp_fastopen_(false),
125 tcp_fastopen_connected_(false) {
124 scoped_refptr<NetLog::EventParameters> params; 126 scoped_refptr<NetLog::EventParameters> params;
125 if (source.is_valid()) 127 if (source.is_valid())
126 params = new NetLogSourceParameter("source_dependency", source); 128 params = new NetLogSourceParameter("source_dependency", source);
127 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); 129 net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
130
131 if (is_tcp_fastopen_enabled())
132 use_tcp_fastopen_ = true;
128 } 133 }
129 134
130 TCPClientSocketLibevent::~TCPClientSocketLibevent() { 135 TCPClientSocketLibevent::~TCPClientSocketLibevent() {
131 Disconnect(); 136 Disconnect();
132 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL); 137 net_log_.EndEvent(NetLog::TYPE_SOCKET_ALIVE, NULL);
133 } 138 }
134 139
135 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) { 140 int TCPClientSocketLibevent::Connect(CompletionCallback* callback) {
136 DCHECK(CalledOnValidThread()); 141 DCHECK(CalledOnValidThread());
137 142
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 "address", NetAddressToStringWithPort(current_ai_))); 204 "address", NetAddressToStringWithPort(current_ai_)));
200 205
201 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE; 206 next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
202 207
203 // Create a non-blocking socket. 208 // Create a non-blocking socket.
204 connect_os_error_ = CreateSocket(current_ai_); 209 connect_os_error_ = CreateSocket(current_ai_);
205 if (connect_os_error_) 210 if (connect_os_error_)
206 return MapPosixError(connect_os_error_); 211 return MapPosixError(connect_os_error_);
207 212
208 // Connect the socket. 213 // Connect the socket.
209 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr, 214 if (!use_tcp_fastopen_) {
210 static_cast<int>(current_ai_->ai_addrlen)))) { 215 if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
211 // Connected without waiting! 216 static_cast<int>(current_ai_->ai_addrlen)))) {
217 // Connected without waiting!
218 return OK;
219 }
220 } else {
221 // With TCP FastOpen, we pretend that the socket is connected.
222 DCHECK(!tcp_fastopen_connected_);
212 return OK; 223 return OK;
213 } 224 }
214 225
215 // Check if the connect() failed synchronously. 226 // Check if the connect() failed synchronously.
216 connect_os_error_ = errno; 227 connect_os_error_ = errno;
217 if (connect_os_error_ != EINPROGRESS) 228 if (connect_os_error_ != EINPROGRESS)
218 return MapConnectError(connect_os_error_); 229 return MapConnectError(connect_os_error_);
219 230
220 // Otherwise the connect() is going to complete asynchronously, so watch 231 // Otherwise the connect() is going to complete asynchronously, so watch
221 // for its completion. 232 // for its completion.
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
358 int buf_len, 369 int buf_len,
359 CompletionCallback* callback) { 370 CompletionCallback* callback) {
360 DCHECK(CalledOnValidThread()); 371 DCHECK(CalledOnValidThread());
361 DCHECK_NE(kInvalidSocket, socket_); 372 DCHECK_NE(kInvalidSocket, socket_);
362 DCHECK(!waiting_connect()); 373 DCHECK(!waiting_connect());
363 DCHECK(!write_callback_); 374 DCHECK(!write_callback_);
364 // Synchronous operation not supported 375 // Synchronous operation not supported
365 DCHECK(callback); 376 DCHECK(callback);
366 DCHECK_GT(buf_len, 0); 377 DCHECK_GT(buf_len, 0);
367 378
368 int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len)); 379 int nwrite = InternalWrite(buf, buf_len);
369 if (nwrite >= 0) { 380 if (nwrite >= 0) {
370 static base::StatsCounter write_bytes("tcp.write_bytes"); 381 static base::StatsCounter write_bytes("tcp.write_bytes");
371 write_bytes.Add(nwrite); 382 write_bytes.Add(nwrite);
372 if (nwrite > 0) 383 if (nwrite > 0)
373 use_history_.set_was_used_to_convey_data(); 384 use_history_.set_was_used_to_convey_data();
374 LogByteTransfer( 385 LogByteTransfer(
375 net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data()); 386 net_log_, NetLog::TYPE_SOCKET_BYTES_SENT, nwrite, buf->data());
376 return nwrite; 387 return nwrite;
377 } 388 }
378 if (errno != EAGAIN && errno != EWOULDBLOCK) 389 if (errno != EAGAIN && errno != EWOULDBLOCK)
379 return MapPosixError(errno); 390 return MapPosixError(errno);
380 391
381 if (!MessageLoopForIO::current()->WatchFileDescriptor( 392 if (!MessageLoopForIO::current()->WatchFileDescriptor(
382 socket_, true, MessageLoopForIO::WATCH_WRITE, 393 socket_, true, MessageLoopForIO::WATCH_WRITE,
383 &write_socket_watcher_, &write_watcher_)) { 394 &write_socket_watcher_, &write_watcher_)) {
384 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno; 395 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
385 return MapPosixError(errno); 396 return MapPosixError(errno);
386 } 397 }
387 398
388 write_buf_ = buf; 399 write_buf_ = buf;
389 write_buf_len_ = buf_len; 400 write_buf_len_ = buf_len;
390 write_callback_ = callback; 401 write_callback_ = callback;
391 return ERR_IO_PENDING; 402 return ERR_IO_PENDING;
392 } 403 }
393 404
405 int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
406 int nwrite;
407 if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
408 // We have a limited amount of data to send in the SYN packet.
409 int kMaxFastOpenSendLength = 1420;
410
411 buf_len = std::min(kMaxFastOpenSendLength, buf_len);
412
413 int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN
414 nwrite = HANDLE_EINTR(sendto(socket_,
415 buf->data(),
416 buf_len,
417 flags,
418 current_ai_->ai_addr,
419 static_cast<int>(current_ai_->ai_addrlen)));
420 tcp_fastopen_connected_ = true;
421
422 if (nwrite < 0) {
423 // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
424 if (errno == EINPROGRESS)
425 errno = EAGAIN;
426
427 // Unlike "normal" nonblocking sockets, the data is already queued,
428 // so tell the app that we've consumed it.
429 return buf_len;
430 }
431 } else {
432 nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
433 }
434 return nwrite;
435 }
436
394 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) { 437 bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
395 DCHECK(CalledOnValidThread()); 438 DCHECK(CalledOnValidThread());
396 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF, 439 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
397 reinterpret_cast<const char*>(&size), 440 reinterpret_cast<const char*>(&size),
398 sizeof(size)); 441 sizeof(size));
399 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno; 442 DCHECK(!rv) << "Could not set socket receive buffer size: " << errno;
400 return rv == 0; 443 return rv == 0;
401 } 444 }
402 445
403 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) { 446 bool TCPClientSocketLibevent::SetSendBufferSize(int32 size) {
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 } 589 }
547 590
548 void TCPClientSocketLibevent::SetOmniboxSpeculation() { 591 void TCPClientSocketLibevent::SetOmniboxSpeculation() {
549 use_history_.set_omnibox_speculation(); 592 use_history_.set_omnibox_speculation();
550 } 593 }
551 594
552 bool TCPClientSocketLibevent::WasEverUsed() const { 595 bool TCPClientSocketLibevent::WasEverUsed() const {
553 return use_history_.was_used_to_convey_data(); 596 return use_history_.was_used_to_convey_data();
554 } 597 }
555 598
599 bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
600 return use_tcp_fastopen_;
601 }
602
556 } // namespace net 603 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/tcp_client_socket_libevent.h ('k') | net/socket/tcp_client_socket_pool_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698