Commit 457fa717 authored by Subodh Iyengar's avatar Subodh Iyengar Committed by Facebook Github Bot 2

Fix ssl timeouts during TFO

Summary:
Handle handshake timestamps and timeouts when TFO
is used.

If we fallback from TFO to connects, we should unset
the handshake timeout.

When we restart the handshake, we should reset the handshake
timeout and also reset the timestamps of the connection.

Reviewed By: yfeldblum, djwatson

Differential Revision: D3708660

fbshipit-source-id: 960030ca14d9f1cc8cb83059491ceffe6ba8f2ed
parent ff508994
...@@ -716,10 +716,6 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout, ...@@ -716,10 +716,6 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout,
return invalidState(callback); return invalidState(callback);
} }
handshakeStartTime_ = std::chrono::steady_clock::now();
// Make end time at least >= start time.
handshakeEndTime_ = handshakeStartTime_;
sslState_ = STATE_CONNECTING; sslState_ = STATE_CONNECTING;
handshakeCallback_ = callback; handshakeCallback_ = callback;
...@@ -756,10 +752,19 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout, ...@@ -756,10 +752,19 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout,
SSL_set_ex_data(ssl_, getSSLExDataIndex(), this); SSL_set_ex_data(ssl_, getSSLExDataIndex(), this);
if (timeout > 0) { handshakeConnectTimeout_ = timeout;
handshakeTimeout_.scheduleTimeout(timeout); startSSLConnect();
} }
// This could be called multiple times, during normal ssl connections
// and after TFO fallback.
void AsyncSSLSocket::startSSLConnect() {
handshakeStartTime_ = std::chrono::steady_clock::now();
// Make end time at least >= start time.
handshakeEndTime_ = handshakeStartTime_;
if (handshakeConnectTimeout_ > 0) {
handshakeTimeout_.scheduleTimeout(handshakeConnectTimeout_);
}
handleConnect(); handleConnect();
} }
...@@ -1094,12 +1099,20 @@ AsyncSSLSocket::handleConnect() noexcept { ...@@ -1094,12 +1099,20 @@ AsyncSSLSocket::handleConnect() noexcept {
sslState_ == STATE_CONNECTING); sslState_ == STATE_CONNECTING);
assert(ssl_); assert(ssl_);
auto originalState = state_;
int ret = SSL_connect(ssl_); int ret = SSL_connect(ssl_);
if (ret <= 0) { if (ret <= 0) {
int sslError; int sslError;
unsigned long errError; unsigned long errError;
int errnoCopy = errno; int errnoCopy = errno;
if (willBlock(ret, &sslError, &errError)) { if (willBlock(ret, &sslError, &errError)) {
// We fell back to connecting state due to TFO
if (state_ == StateEnum::CONNECTING) {
DCHECK_EQ(StateEnum::FAST_OPEN, originalState);
if (handshakeTimeout_.isScheduled()) {
handshakeTimeout_.cancelTimeout();
}
}
return; return;
} else { } else {
sslState_ = STATE_ERROR; sslState_ = STATE_ERROR;
...@@ -1147,9 +1160,8 @@ AsyncSSLSocket::handleConnect() noexcept { ...@@ -1147,9 +1160,8 @@ AsyncSSLSocket::handleConnect() noexcept {
void AsyncSSLSocket::invokeConnectSuccess() { void AsyncSSLSocket::invokeConnectSuccess() {
if (sslState_ == SSLStateEnum::STATE_CONNECTING) { if (sslState_ == SSLStateEnum::STATE_CONNECTING) {
// If we failed TFO, we'd fall back to trying to connect the socket, // If we failed TFO, we'd fall back to trying to connect the socket,
// when we succeed we should handle the writes that caused us to start // to setup things like timeouts.
// TFO. startSSLConnect();
handleWrite();
} }
AsyncSocket::invokeConnectSuccess(); AsyncSocket::invokeConnectSuccess();
} }
......
...@@ -815,6 +815,8 @@ class AsyncSSLSocket : public virtual AsyncSocket { ...@@ -815,6 +815,8 @@ class AsyncSSLSocket : public virtual AsyncSocket {
void cacheLocalPeerAddr(); void cacheLocalPeerAddr();
void startSSLConnect();
static void sslInfoCallback(const SSL *ssl, int type, int val); static void sslInfoCallback(const SSL *ssl, int type, int val);
// Whether we've applied the TCP_CORK option to the socket // Whether we've applied the TCP_CORK option to the socket
...@@ -875,6 +877,7 @@ class AsyncSSLSocket : public virtual AsyncSocket { ...@@ -875,6 +877,7 @@ class AsyncSSLSocket : public virtual AsyncSocket {
// Time taken to complete the ssl handshake. // Time taken to complete the ssl handshake.
std::chrono::steady_clock::time_point handshakeStartTime_; std::chrono::steady_clock::time_point handshakeStartTime_;
std::chrono::steady_clock::time_point handshakeEndTime_; std::chrono::steady_clock::time_point handshakeEndTime_;
uint64_t handshakeConnectTimeout_{0};
}; };
} // namespace } // namespace
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment