diff --git a/src/security/tls_session.cpp b/src/security/tls_session.cpp index e4ecfe207d979e1f2c89ae0c22df3f2a3e6247b7..724e9b030894a574f3e75904abdcb7bde63bce77 100644 --- a/src/security/tls_session.cpp +++ b/src/security/tls_session.cpp @@ -60,6 +60,7 @@ static constexpr uint16_t INPUT_BUFFER_SIZE {16*1024}; // to be coherent with th static constexpr std::size_t INPUT_MAX_SIZE {1000}; // Maximum number of packets to store before dropping (pkt size = DTLS_MTU) static constexpr ssize_t FLOOD_THRESHOLD {4*1024}; static constexpr auto FLOOD_PAUSE = std::chrono::milliseconds(100); // Time to wait after an invalid cookie packet (anti flood attack) +static constexpr size_t HANDSHAKE_MAX_RETRY {64}; static constexpr auto DTLS_RETRANSMIT_TIMEOUT = std::chrono::milliseconds(1000); // Delay between two handshake request on DTLS static constexpr auto COOKIE_TIMEOUT = std::chrono::seconds(10); // Time to wait for a cookie packet from client static constexpr int MIN_MTU {512 - 20 - 8}; // minimal payload size of a DTLS packet carried by an IPv4 packet @@ -671,11 +672,15 @@ TlsSession::TlsSessionImpl::waitForRawData(unsigned timeout) // non-reliable uses callback installed with setOnRecv() std::unique_lock<std::mutex> lk {rxMutex_}; - rxCv_.wait(lk, [this]{ return !rxQueue_.empty() or state_ == TlsSessionState::SHUTDOWN; }); + rxCv_.wait_for(lk, std::chrono::milliseconds(timeout), [this]{ return !rxQueue_.empty() or state_ == TlsSessionState::SHUTDOWN; }); if (state_ == TlsSessionState::SHUTDOWN) { gnutls_transport_set_errno(session_, EINTR); return -1; } + if (rxQueue_.empty()) { + RING_ERR("[TLS] waitForRawData: timeout after %u ms", timeout); + return 0; + } return 1; } @@ -822,9 +827,14 @@ TlsSession::TlsSessionImpl::handleStateCookie(TlsSessionState state) TlsSessionState TlsSession::TlsSessionImpl::handleStateHandshake(TlsSessionState state) { - RING_DBG("[TLS] handshake"); - - auto ret = gnutls_handshake(session_); + int ret; + size_t retry_count = 0; + do { + RING_DBG("[TLS] handshake"); + ret = gnutls_handshake(session_); + } while ((ret == GNUTLS_E_INTERRUPTED or + ret == GNUTLS_E_AGAIN ) and + ++retry_count < HANDSHAKE_MAX_RETRY); // Stop on fatal error if (gnutls_error_is_fatal(ret)) {