summaryrefslogtreecommitdiffstats
path: root/net/socket/tcp_client_socket_libevent.cc
diff options
context:
space:
mode:
authormbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-26 18:29:29 +0000
committermbelshe@chromium.org <mbelshe@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-26 18:29:29 +0000
commit7f7e9239652bbb552bd5ea62d9702edfcf86528c (patch)
tree1b64094581e7cf5f084bc456acf933b871eea4b6 /net/socket/tcp_client_socket_libevent.cc
parent35011c75172bd9085890021da04027925b09addd (diff)
downloadchromium_src-7f7e9239652bbb552bd5ea62d9702edfcf86528c.zip
chromium_src-7f7e9239652bbb552bd5ea62d9702edfcf86528c.tar.gz
chromium_src-7f7e9239652bbb552bd5ea62d9702edfcf86528c.tar.bz2
Add experimental option for TCP FastOpen.
Use chrome.exe --enable-tcp-fastopen BUG=none TEST=none yet Review URL: http://codereview.chromium.org/4039003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63913 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket/tcp_client_socket_libevent.cc')
-rw-r--r--net/socket/tcp_client_socket_libevent.cc59
1 files changed, 53 insertions, 6 deletions
diff --git a/net/socket/tcp_client_socket_libevent.cc b/net/socket/tcp_client_socket_libevent.cc
index cda0955..30f7bc2 100644
--- a/net/socket/tcp_client_socket_libevent.cc
+++ b/net/socket/tcp_client_socket_libevent.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/socket/tcp_client_socket_libevent.h"
+#include "net/socket/tcp_client_socket.h"
#include <errno.h>
#include <fcntl.h>
@@ -121,11 +121,16 @@ TCPClientSocketLibevent::TCPClientSocketLibevent(
next_connect_state_(CONNECT_STATE_NONE),
connect_os_error_(0),
net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)),
- previously_disconnected_(false) {
+ previously_disconnected_(false),
+ use_tcp_fastopen_(false),
+ tcp_fastopen_connected_(false) {
scoped_refptr<NetLog::EventParameters> params;
if (source.is_valid())
params = new NetLogSourceParameter("source_dependency", source);
net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params);
+
+ if (is_tcp_fastopen_enabled())
+ use_tcp_fastopen_ = true;
}
TCPClientSocketLibevent::~TCPClientSocketLibevent() {
@@ -212,9 +217,15 @@ int TCPClientSocketLibevent::DoConnect() {
return MapPosixError(connect_os_error_);
// Connect the socket.
- if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
- static_cast<int>(current_ai_->ai_addrlen)))) {
- // Connected without waiting!
+ if (!use_tcp_fastopen_) {
+ if (!HANDLE_EINTR(connect(socket_, current_ai_->ai_addr,
+ static_cast<int>(current_ai_->ai_addrlen)))) {
+ // Connected without waiting!
+ return OK;
+ }
+ } else {
+ // With TCP FastOpen, we pretend that the socket is connected.
+ DCHECK(!tcp_fastopen_connected_);
return OK;
}
@@ -372,7 +383,7 @@ int TCPClientSocketLibevent::Write(IOBuffer* buf,
DCHECK(callback);
DCHECK_GT(buf_len, 0);
- int nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
+ int nwrite = InternalWrite(buf, buf_len);
if (nwrite >= 0) {
static base::StatsCounter write_bytes("tcp.write_bytes");
write_bytes.Add(nwrite);
@@ -398,6 +409,38 @@ int TCPClientSocketLibevent::Write(IOBuffer* buf,
return ERR_IO_PENDING;
}
+int TCPClientSocketLibevent::InternalWrite(IOBuffer* buf, int buf_len) {
+ int nwrite;
+ if (use_tcp_fastopen_ && !tcp_fastopen_connected_) {
+ // We have a limited amount of data to send in the SYN packet.
+ int kMaxFastOpenSendLength = 1420;
+
+ buf_len = std::min(kMaxFastOpenSendLength, buf_len);
+
+ int flags = 0x20000000; // Magic flag to enable TCP_FASTOPEN
+ nwrite = HANDLE_EINTR(sendto(socket_,
+ buf->data(),
+ buf_len,
+ flags,
+ current_ai_->ai_addr,
+ static_cast<int>(current_ai_->ai_addrlen)));
+ tcp_fastopen_connected_ = true;
+
+ if (nwrite < 0) {
+ // Non-blocking mode is returning EINPROGRESS rather than EAGAIN.
+ if (errno == EINPROGRESS)
+ errno = EAGAIN;
+
+ // Unlike "normal" nonblocking sockets, the data is already queued,
+ // so tell the app that we've consumed it.
+ return buf_len;
+ }
+ } else {
+ nwrite = HANDLE_EINTR(write(socket_, buf->data(), buf_len));
+ }
+ return nwrite;
+}
+
bool TCPClientSocketLibevent::SetReceiveBufferSize(int32 size) {
DCHECK(CalledOnValidThread());
int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
@@ -560,4 +603,8 @@ bool TCPClientSocketLibevent::WasEverUsed() const {
return use_history_.was_used_to_convey_data();
}
+bool TCPClientSocketLibevent::UsingTCPFastOpen() const {
+ return use_tcp_fastopen_;
+}
+
} // namespace net