Skip to content

Commit

Permalink
Add experimental option for TCP FastOpen.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
mbelshe@chromium.org committed Oct 26, 2010
1 parent 35011c7 commit 7f7e923
Show file tree
Hide file tree
Showing 36 changed files with 257 additions and 32 deletions.
4 changes: 4 additions & 0 deletions chrome/browser/browser_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@
#include "net/http/http_stream_factory.h"
#include "net/socket/client_socket_pool_base.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/tcp_client_socket.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"

Expand Down Expand Up @@ -196,6 +197,9 @@ void BrowserMainParts::EarlyInitialization() {
if (parsed_command_line().HasSwitch(switches::kEnableSnapStart))
net::SSLConfigService::EnableSnapStart();

if (parsed_command_line().HasSwitch(switches::kEnableTcpFastOpen))
net::set_tcp_fastopen_enabled(true);

PostEarlyInitialization();
}

Expand Down
4 changes: 4 additions & 0 deletions chrome/common/chrome_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,10 @@ const char kEnableSyncTypedUrls[] = "enable-sync-typed-urls";
// Enable tabbed options, ie: dom-ui version of options window.
const char kEnableTabbedOptions[] = "enable-tabbed-options";

// Enable use of experimental TCP sockets API for sending data in the
// SYN packet.
const char kEnableTcpFastOpen[] = "enable-tcp-fastopen";

// Enables TopSites.
const char kEnableTopSites[] = "enable-top-sites";

Expand Down
2 changes: 2 additions & 0 deletions chrome/common/chrome_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ extern const char kEnableSyncPreferences[];
extern const char kEnableSyncSessions[];
extern const char kEnableSyncTypedUrls[];
extern const char kEnableTabbedOptions[];
extern const char kEnableTcpFastOpen[];

extern const char kEnableTopSites[];
extern const char kEnableTouch[];
extern const char kEnableVerticalTabs[];
Expand Down
4 changes: 4 additions & 0 deletions jingle/notifier/base/fake_ssl_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -328,4 +328,8 @@ bool FakeSSLClientSocket::WasEverUsed() const {
return transport_socket_->WasEverUsed();
}

bool FakeSSLClientSocket::UsingTCPFastOpen() const {
return transport_socket_->UsingTCPFastOpen();
}

} // namespace notifier
1 change: 1 addition & 0 deletions jingle/notifier/base/fake_ssl_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class FakeSSLClientSocket : public net::ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

private:
enum HandshakeState {
Expand Down
1 change: 1 addition & 0 deletions jingle/notifier/base/fake_ssl_client_socket_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ class MockClientSocket : public net::ClientSocket {
MOCK_METHOD0(SetSubresourceSpeculation, void());
MOCK_METHOD0(SetOmniboxSpeculation, void());
MOCK_CONST_METHOD0(WasEverUsed, bool());
MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
};

// Break up |data| into a bunch of chunked MockReads/Writes and push
Expand Down
8 changes: 8 additions & 0 deletions net/http/http_proxy_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,14 @@ bool HttpProxyClientSocket::WasEverUsed() const {
return false;
}

bool HttpProxyClientSocket::UsingTCPFastOpen() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->UsingTCPFastOpen();
}
NOTREACHED();
return false;
}

int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(!user_callback_);
Expand Down
1 change: 1 addition & 0 deletions net/http/http_proxy_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class HttpProxyClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand Down
1 change: 1 addition & 0 deletions net/net.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@
'socket/ssl_client_socket_pool.h',
'socket/ssl_client_socket_win.cc',
'socket/ssl_client_socket_win.h',
'socket/tcp_client_socket.cc',
'socket/tcp_client_socket.h',
'socket/tcp_client_socket_libevent.cc',
'socket/tcp_client_socket_libevent.h',
Expand Down
4 changes: 4 additions & 0 deletions net/socket/client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ class ClientSocket : public Socket {
// this call to the transport socket.
virtual bool WasEverUsed() const = 0;

// Returns true if the underlying transport socket is using TCP FastOpen.
// TCP FastOpen is an experiment with sending data in the TCP SYN packet.
virtual bool UsingTCPFastOpen() const = 0;

protected:
// The following class is only used to gather statistics about the history of
// a socket. It is only instantiated and used in basic sockets, such as
Expand Down
1 change: 1 addition & 0 deletions net/socket/client_socket_pool_base_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ class MockClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation() {}
virtual void SetOmniboxSpeculation() {}
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
virtual bool UsingTCPFastOpen() const { return false; }

private:
bool connected_;
Expand Down
4 changes: 4 additions & 0 deletions net/socket/socket_test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,10 @@ bool MockSSLClientSocket::WasEverUsed() const {
return transport_->socket()->WasEverUsed();
}

bool MockSSLClientSocket::UsingTCPFastOpen() const {
return transport_->socket()->UsingTCPFastOpen();
}

int MockSSLClientSocket::Read(net::IOBuffer* buf, int buf_len,
net::CompletionCallback* callback) {
return transport_->socket()->Read(buf, buf_len, callback);
Expand Down
3 changes: 3 additions & 0 deletions net/socket/socket_test_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,7 @@ class MockTCPClientSocket : public MockClientSocket {
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const { return IsConnected(); }
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
virtual bool UsingTCPFastOpen() const { return false; }

// Socket methods:
virtual int Read(net::IOBuffer* buf, int buf_len,
Expand Down Expand Up @@ -654,6 +655,7 @@ class DeterministicMockTCPClientSocket : public MockClientSocket,
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const { return IsConnected(); }
virtual bool WasEverUsed() const { return was_used_to_convey_data_; }
virtual bool UsingTCPFastOpen() const { return false; }

// Socket methods:
virtual int Write(net::IOBuffer* buf, int buf_len,
Expand Down Expand Up @@ -698,6 +700,7 @@ class MockSSLClientSocket : public MockClientSocket {
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(net::IOBuffer* buf, int buf_len,
Expand Down
8 changes: 8 additions & 0 deletions net/socket/socks5_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ bool SOCKS5ClientSocket::WasEverUsed() const {
return false;
}

bool SOCKS5ClientSocket::UsingTCPFastOpen() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->UsingTCPFastOpen();
}
NOTREACHED();
return false;
}

// Read is called by the transport layer above to read. This can only be done
// if the SOCKS handshake is complete.
int SOCKS5ClientSocket::Read(IOBuffer* buf, int buf_len,
Expand Down
1 change: 1 addition & 0 deletions net/socket/socks5_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class SOCKS5ClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand Down
9 changes: 9 additions & 0 deletions net/socket/socks_client_socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,15 @@ bool SOCKSClientSocket::WasEverUsed() const {
return false;
}

bool SOCKSClientSocket::UsingTCPFastOpen() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->UsingTCPFastOpen();
}
NOTREACHED();
return false;
}


// Read is called by the transport layer above to read. This can only be done
// if the SOCKS handshake is complete.
int SOCKSClientSocket::Read(IOBuffer* buf, int buf_len,
Expand Down
1 change: 1 addition & 0 deletions net/socket/socks_client_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class SOCKSClientSocket : public ClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand Down
8 changes: 8 additions & 0 deletions net/socket/ssl_client_socket_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,14 @@ bool SSLClientSocketMac::WasEverUsed() const {
return false;
}

bool SSLClientSocketMac::UsingTCPFastOpen() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->UsingTCPFastOpen();
}
NOTREACHED();
return false;
}

int SSLClientSocketMac::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
DCHECK(completed_handshake());
Expand Down
1 change: 1 addition & 0 deletions net/socket/ssl_client_socket_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class SSLClientSocketMac : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand Down
83 changes: 57 additions & 26 deletions net/socket/ssl_client_socket_nss.cc
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
pseudo_connected_(false),
eset_mitm_detected_(false),
netnanny_mitm_detected_(false),
peername_initialized_(false),
dnssec_provider_(NULL),
next_handshake_state_(STATE_NONE),
nss_fd_(NULL),
Expand Down Expand Up @@ -589,6 +590,16 @@ int SSLClientSocketNSS::Connect(CompletionCallback* callback) {
return rv;
}

// Attempt to initialize the peer name. In the case of TCP FastOpen,
// we don't have the peer yet.
if (!UsingTCPFastOpen()) {
rv = InitializeSSLPeerName();
if (rv != OK) {
net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
return rv;
}
}

if (ssl_config_.snap_start_enabled && ssl_host_info_.get()) {
GotoState(STATE_SNAP_START_LOAD_INFO);
} else {
Expand Down Expand Up @@ -619,28 +630,6 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_OUT_OF_MEMORY; // TODO(port): map NSPR error code.
}

// Tell NSS who we're connected to
AddressList peer_address;
int err = transport_->socket()->GetPeerAddress(&peer_address);
if (err != OK)
return err;

const struct addrinfo* ai = peer_address.head();

PRNetAddr peername;
memset(&peername, 0, sizeof(peername));
DCHECK_LE(ai->ai_addrlen, sizeof(peername));
size_t len = std::min(static_cast<size_t>(ai->ai_addrlen), sizeof(peername));
memcpy(&peername, ai->ai_addr, len);

// Adjust the address family field for BSD, whose sockaddr
// structure has a one-byte length and one-byte address family
// field at the beginning. PRNetAddr has a two-byte address
// family field at the beginning.
peername.raw.family = ai->ai_addr->sa_family;

memio_SetPeerName(nss_fd_, &peername);

// Grab pointer to buffers
nss_bufs_ = memio_GetSecret(nss_fd_);

Expand Down Expand Up @@ -795,20 +784,48 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
// Tell SSL the hostname we're trying to connect to.
SSL_SetURL(nss_fd_, hostname_.c_str());

// Tell SSL we're a client; needed if not letting NSPR do socket I/O
SSL_ResetHandshake(nss_fd_, 0);

return OK;
}

int SSLClientSocketNSS::InitializeSSLPeerName() {
// Tell NSS who we're connected to
AddressList peer_address;
int err = transport_->socket()->GetPeerAddress(&peer_address);
if (err != OK)
return err;

const struct addrinfo* ai = peer_address.head();

PRNetAddr peername;
memset(&peername, 0, sizeof(peername));
DCHECK_LE(ai->ai_addrlen, sizeof(peername));
size_t len = std::min(static_cast<size_t>(ai->ai_addrlen),
sizeof(peername));
memcpy(&peername, ai->ai_addr, len);

// Adjust the address family field for BSD, whose sockaddr
// structure has a one-byte length and one-byte address family
// field at the beginning. PRNetAddr has a two-byte address
// family field at the beginning.
peername.raw.family = ai->ai_addr->sa_family;

memio_SetPeerName(nss_fd_, &peername);

// Set the peer ID for session reuse. This is necessary when we create an
// SSL tunnel through a proxy -- GetPeerName returns the proxy's address
// rather than the destination server's address in that case.
// TODO(wtc): port in |peer_address| is not the server's port when a proxy is
// used.
std::string peer_id = base::StringPrintf("%s:%d", hostname_.c_str(),
peer_address.GetPort());
rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
SECStatus rv = SSL_SetSockPeerID(nss_fd_, const_cast<char*>(peer_id.c_str()));
if (rv != SECSuccess)
LogFailedNSSFunction(net_log_, "SSL_SetSockPeerID", peer_id.c_str());

// Tell SSL we're a client; needed if not letting NSPR do socket I/O
SSL_ResetHandshake(nss_fd_, 0);

peername_initialized_ = true;
return OK;
}

Expand Down Expand Up @@ -854,6 +871,7 @@ void SSLClientSocketNSS::Disconnect() {
pseudo_connected_ = false;
eset_mitm_detected_ = false;
netnanny_mitm_detected_= false;
peername_initialized_ = false;
nss_bufs_ = NULL;
client_certs_.clear();
client_auth_cert_needed_ = false;
Expand Down Expand Up @@ -919,6 +937,14 @@ bool SSLClientSocketNSS::WasEverUsed() const {
return false;
}

bool SSLClientSocketNSS::UsingTCPFastOpen() const {
if (transport_.get() && transport_->socket()) {
return transport_->socket()->UsingTCPFastOpen();
}
NOTREACHED();
return false;
}

int SSLClientSocketNSS::Read(IOBuffer* buf, int buf_len,
CompletionCallback* callback) {
EnterFunction(buf_len);
Expand Down Expand Up @@ -1373,6 +1399,11 @@ int SSLClientSocketNSS::BufferSend(void) {

void SSLClientSocketNSS::BufferSendComplete(int result) {
EnterFunction(result);

// In the case of TCP FastOpen, connect is now finished.
if (!peername_initialized_ && UsingTCPFastOpen())
InitializeSSLPeerName();

memio_PutWriteResult(nss_bufs_, MapErrorToNSS(result));
transport_send_busy_ = false;
OnSendComplete(result);
Expand Down
7 changes: 7 additions & 0 deletions net/socket/ssl_client_socket_nss.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
virtual void SetSubresourceSpeculation();
virtual void SetOmniboxSpeculation();
virtual bool WasEverUsed() const;
virtual bool UsingTCPFastOpen() const;

// Socket methods:
virtual int Read(IOBuffer* buf, int buf_len, CompletionCallback* callback);
Expand All @@ -73,6 +74,9 @@ class SSLClientSocketNSS : public SSLClientSocket {
// Initializes NSS SSL options. Returns a net error code.
int InitializeSSLOptions();

// Initializes the socket peer name in SSL. Returns a net error code.
int InitializeSSLPeerName();

void InvalidateSessionIfBadCertificate();
#if defined(OS_MACOSX) || defined(OS_WIN)
// Creates an OS certificate from a DER-encoded certificate.
Expand Down Expand Up @@ -188,6 +192,9 @@ class SSLClientSocketNSS : public SSLClientSocket {
// connections.
bool netnanny_mitm_detected_;

// True if the peer name has been initialized.
bool peername_initialized_;

// This pointer is owned by the caller of UseDNSSEC.
DNSSECProvider* dnssec_provider_;
// The time when we started waiting for DNSSEC records.
Expand Down
Loading

0 comments on commit 7f7e923

Please sign in to comment.