@cryptotaxi247 / netdata-1 / commits / c53747291

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 }