Enable retries for SSL_ERROR_WANT_READ (#14120)
* enable retries for SSL_ERROR_WANT_READ * only when bytes is <= 0 * treat ERROR_WANT_READ/WRITE as 0 bytes * dont close connection on zero bytes * reuse ssl connection * treat zero bytes * ifdef for old openssl * revert check
Emmanuel Vasilakis committed
Jan 13, 2023 at 17:51 UTC
c5374729144d6c48c0792d5f6f796b1a6908b7ce
5 files changed
+45
-29
libnetdata/socket/security.c
+1
-1
@@ -310,7 +310,7 @@ int security_process_accept(SSL *ssl,int msg) {
310
int counter = 0;
311
while ((err = ERR_get_error()) != 0) {
312
ERR_error_string_n(err, buf, sizeof(buf));
313
- info("%d SSL Handshake error (%s) on socket %d ", counter++, ERR_error_string((long)SSL_get_error(ssl, test), NULL), sock);
313
+ error("%d SSL Handshake error (%s) on socket %d", counter++, ERR_error_string((long)SSL_get_error(ssl, test), NULL), sock);
314
}
315
return NETDATA_SSL_NO_HANDSHAKE;
316
}
libnetdata/socket/socket.c
+21
-13
@@ -926,13 +926,17 @@ ssize_t netdata_ssl_read(SSL *ssl, void *buf, size_t num) {
926
int bytes, err, retries = 0;
927
928
//do {
929
- bytes = SSL_read(ssl, buf, (int)num);
930
- err = SSL_get_error(ssl, bytes);
931
- retries++;
932
- //} while (bytes <= 0 && (err == SSL_ERROR_WANT_READ));
929
+ bytes = SSL_read(ssl, buf, (int)num);
930
+ err = SSL_get_error(ssl, bytes);
931
+ retries++;
932
+ //} while (bytes <= 0 && err == SSL_ERROR_WANT_READ);
933
934
- if(unlikely(bytes <= 0))
935
- error("SSL_read() returned %d bytes, SSL error %d", bytes, err);
934
+ if(unlikely(bytes <= 0)) {
935
+ if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
936
+ bytes = 0;
937
+ } else
938
+ error("SSL_write() returned %d bytes, SSL error %d", bytes, err);
939
+ }
940
941
if(retries > 1)
942
error_limit(&erl, "SSL_read() retried %d times", retries);
@@ -947,17 +951,21 @@ ssize_t netdata_ssl_write(SSL *ssl, const void *buf, size_t num) {
951
size_t total = 0;
952
953
//do {
950
- bytes = SSL_write(ssl, (uint8_t *)buf + total, (int)(num - total));
951
- err = SSL_get_error(ssl, bytes);
952
- retries++;
954
+ bytes = SSL_write(ssl, (uint8_t *)buf + total, (int)(num - total));
955
+ err = SSL_get_error(ssl, bytes);
956
+ retries++;
957
954
- if(bytes > 0)
955
- total += bytes;
958
+ if(bytes > 0)
959
+ total += bytes;
960
961
//} while ((bytes <= 0 && (err == SSL_ERROR_WANT_WRITE)) || (bytes > 0 && total < num));
962
959
- if(unlikely(bytes <= 0))
960
- error("SSL_write() returned %d bytes, SSL error %d", bytes, err);
963
+ if(unlikely(bytes <= 0)) {
964
+ if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
965
+ bytes = 0;
966
+ } else
967
+ error("SSL_write() returned %d bytes, SSL error %d", bytes, err);
968
+ }
969
970
if(retries > 1)
971
error_limit(&erl, "SSL_write() retried %d times", retries);
streaming/sender.c
+4
-2
@@ -818,8 +818,10 @@ static ssize_t attempt_read(struct sender_state *s) {
818
return ret;
819
}
820
821
- worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
822
- rrdpush_sender_thread_close_socket(s->host);
821
+ if (ret == -1) {
822
+ worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
823
+ rrdpush_sender_thread_close_socket(s->host);
824
+ }
825
return ret;
826
}
827
#endif
web/server/web_client.c
+11
-12
@@ -1250,12 +1250,15 @@ static inline void web_client_send_http_header(struct web_client *w) {
1250
if(bytes > 0)
1251
w->stats_sent_bytes += bytes;
1252
1253
- error("HTTP headers failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client."
1254
- , buffer_strlen(w->response.header_output)
1255
- , bytes);
1253
+ if (bytes < 0) {
1254
1257
- WEB_CLIENT_IS_DEAD(w);
1258
- return;
1255
+ error("HTTP headers failed to be sent (I sent %zu bytes but the system sent %zd bytes). Closing web client."
1256
+ , buffer_strlen(w->response.header_output)
1257
+ , bytes);
1258
+
1259
+ WEB_CLIENT_IS_DEAD(w);
1260
+ return;
1261
+ }
1262
}
1263
else
1264
w->stats_sent_bytes += bytes;
@@ -1615,7 +1618,6 @@ ssize_t web_client_send_chunk_header(struct web_client *w, size_t len)
1618
1619
else if(bytes == 0) {
1620
debug(D_WEB_CLIENT, "%llu: Did not send chunk header to the client.", w->id);
1618
- WEB_CLIENT_IS_DEAD(w);
1621
}
1622
else {
1623
debug(D_WEB_CLIENT, "%llu: Failed to send chunk header to client.", w->id);
@@ -1638,7 +1640,6 @@ ssize_t web_client_send_chunk_close(struct web_client *w)
1640
1641
else if(bytes == 0) {
1642
debug(D_WEB_CLIENT, "%llu: Did not send chunk suffix to the client.", w->id);
1641
- WEB_CLIENT_IS_DEAD(w);
1643
}
1644
else {
1645
debug(D_WEB_CLIENT, "%llu: Failed to send chunk suffix to client.", w->id);
@@ -1661,7 +1662,6 @@ ssize_t web_client_send_chunk_finalize(struct web_client *w)
1662
1663
else if(bytes == 0) {
1664
debug(D_WEB_CLIENT, "%llu: Did not send chunk finalize suffix to the client.", w->id);
1664
- WEB_CLIENT_IS_DEAD(w);
1665
}
1666
else {
1667
debug(D_WEB_CLIENT, "%llu: Failed to send chunk finalize suffix to client.", w->id);
@@ -1778,7 +1778,6 @@ ssize_t web_client_send_deflate(struct web_client *w)
1778
debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client (zhave = %zu, zsent = %zu, need to send = %zu).",
1779
w->id, w->response.zhave, w->response.zsent, w->response.zhave - w->response.zsent);
1780
1781
- WEB_CLIENT_IS_DEAD(w);
1781
}
1782
else {
1783
debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
@@ -1831,7 +1830,6 @@ ssize_t web_client_send(struct web_client *w) {
1830
}
1831
else if(likely(bytes == 0)) {
1832
debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
1834
- WEB_CLIENT_IS_DEAD(w);
1833
}
1834
else {
1835
debug(D_WEB_CLIENT, "%llu: Failed to send data to client.", w->id);
@@ -1931,10 +1929,11 @@ ssize_t web_client_receive(struct web_client *w)
1929
debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes);
1930
debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->response.data->buffer[old]);
1931
}
1934
- else {
1932
+ else if (bytes < 0) {
1933
debug(D_WEB_CLIENT, "%llu: receive data failed.", w->id);
1934
WEB_CLIENT_IS_DEAD(w);
1937
- }
1935
+ } else
1936
+ debug(D_WEB_CLIENT, "%llu: Received %zd bytes.", w->id, bytes);
1937
1938
return(bytes);
1939
}
web/server/web_client_cache.c
+8
-1
@@ -11,7 +11,14 @@
11
static void web_client_reuse_ssl(struct web_client *w) {
12
if (netdata_ssl_srv_ctx) {
13
if (w->ssl.conn) {
14
- SSL_clear(w->ssl.conn);
14
+ SSL_SESSION *session = SSL_get_session(w->ssl.conn);
15
+ SSL *old = w->ssl.conn;
16
+ w->ssl.conn = SSL_new(netdata_ssl_srv_ctx);
17
+#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_111
18
+ if (SSL_SESSION_is_resumable(session))
19
+#endif
20
+ SSL_set_session(w->ssl.conn, session);
21
+ SSL_free(old);
22
}
23
}
24
}