From: Subodh Iyengar Date: Wed, 17 Aug 2016 04:52:12 +0000 (-0700) Subject: Fix ssl timeouts during TFO X-Git-Tag: v2016.08.22.00~22 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=457fa717520ff97cd5dfbbb136cbca6c1d50de12;p=folly.git 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 --- diff --git a/folly/io/async/AsyncSSLSocket.cpp b/folly/io/async/AsyncSSLSocket.cpp index 721fb295..04ca1516 100644 --- a/folly/io/async/AsyncSSLSocket.cpp +++ b/folly/io/async/AsyncSSLSocket.cpp @@ -716,10 +716,6 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout, return invalidState(callback); } - handshakeStartTime_ = std::chrono::steady_clock::now(); - // Make end time at least >= start time. - handshakeEndTime_ = handshakeStartTime_; - sslState_ = STATE_CONNECTING; handshakeCallback_ = callback; @@ -756,10 +752,19 @@ void AsyncSSLSocket::sslConn(HandshakeCB* callback, uint64_t timeout, SSL_set_ex_data(ssl_, getSSLExDataIndex(), this); - if (timeout > 0) { - handshakeTimeout_.scheduleTimeout(timeout); - } + handshakeConnectTimeout_ = 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(); } @@ -1094,12 +1099,20 @@ AsyncSSLSocket::handleConnect() noexcept { sslState_ == STATE_CONNECTING); assert(ssl_); + auto originalState = state_; int ret = SSL_connect(ssl_); if (ret <= 0) { int sslError; unsigned long errError; int errnoCopy = errno; 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; } else { sslState_ = STATE_ERROR; @@ -1147,9 +1160,8 @@ AsyncSSLSocket::handleConnect() noexcept { void AsyncSSLSocket::invokeConnectSuccess() { if (sslState_ == SSLStateEnum::STATE_CONNECTING) { // 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 - // TFO. - handleWrite(); + // to setup things like timeouts. + startSSLConnect(); } AsyncSocket::invokeConnectSuccess(); } diff --git a/folly/io/async/AsyncSSLSocket.h b/folly/io/async/AsyncSSLSocket.h index 0efd73bd..296641db 100644 --- a/folly/io/async/AsyncSSLSocket.h +++ b/folly/io/async/AsyncSSLSocket.h @@ -815,6 +815,8 @@ class AsyncSSLSocket : public virtual AsyncSocket { void cacheLocalPeerAddr(); + void startSSLConnect(); + static void sslInfoCallback(const SSL *ssl, int type, int val); // Whether we've applied the TCP_CORK option to the socket @@ -875,6 +877,7 @@ class AsyncSSLSocket : public virtual AsyncSocket { // Time taken to complete the ssl handshake. std::chrono::steady_clock::time_point handshakeStartTime_; std::chrono::steady_clock::time_point handshakeEndTime_; + uint64_t handshakeConnectTimeout_{0}; }; } // namespace