uint64_t timeout = KR_CONN_RTT_MAX / 2;
session->has_tls = tls;
if (tls) {
- timeout += KR_CONN_RTT_MAX * 3;
+ timeout += TLS_MAX_HANDSHAKE_TIME;
if (!session->tls_ctx) {
session->tls_ctx = tls_new(master->loop->data);
if (!session->tls_ctx) {
}
int submitted = 0;
+ bool is_retrying = false;
+ uint64_t retrying_start = 0;
while (true) {
ssize_t count = gnutls_record_recv(tls_p->tls_session, tls_p->recv_buf, sizeof(tls_p->recv_buf));
if (count == GNUTLS_E_AGAIN) {
break; /* No data available */
- } else if (count == GNUTLS_E_INTERRUPTED) {
+ } else if (count == GNUTLS_E_INTERRUPTED ||
+ count == GNUTLS_E_REHANDSHAKE) {
+ if (!is_retrying) {
+ is_retrying = true;
+ retrying_start = kr_now();
+ }
+ uint64_t elapsed = kr_now() - retrying_start;
+ if (elapsed > TLS_MAX_HANDSHAKE_TIME) {
+ return kr_error(EIO);
+ }
continue; /* Try reading again */
} else if (count < 0) {
kr_log_verbose("[%s] gnutls_record_recv failed: %s (%zd)\n",
#define MAX_TLS_PADDING KR_EDNS_PAYLOAD
#define TLS_MAX_UNCORK_RETRIES 100
+/* rfc 5476, 7.3 - handshake Protocol overview
+ * https://tools.ietf.org/html/rfc5246#page-33
+ * Message flow for a full handshake (only mandatory messages)
+ * ClientHello -------->
+ ServerHello
+ <-------- ServerHelloDone
+ ClientKeyExchange
+ Finished -------->
+ <-------- Finished
+ *
+ * See also https://blog.cloudflare.com/keyless-ssl-the-nitty-gritty-technical-details/
+ * So it takes 2 RTT.
+ * As we use session tickets, there are additional messages, add one RTT mode.
+ */
+ #define TLS_MAX_HANDSHAKE_TIME (KR_CONN_RTT_MAX * 3)
+
struct tls_ctx_t;
struct tls_client_ctx_t;
struct tls_credentials {