@cryptotaxi247 / netdata-1 / commits / ff4eece8e

Misc SSL improvements 2 (#14334)

* set to wait receive/send when ssl returns wait read/write * compare the bytes * set to normal to prevent going into stream mode with incomplete request * disable wait send

Emmanuel Vasilakis committed Feb 22, 2023 at 19:14 UTC ff4eece8eeebfe9d084b51a3f3337e0cf39c0c3d
3 files changed +83 -69
libnetdata/socket/socket.c
+5 -22
@@ -923,53 +923,36 @@ int connect_to_one_of_urls(const char *destination, int default_port, struct tim
923 ssize_t netdata_ssl_read(SSL *ssl, void *buf, size_t num) {
924 error_limit_static_thread_var(erl, 1, 0);
925
926 - int bytes, err, retries = 0;
926 + int bytes, err;
927
928 - //do {
928 bytes = SSL_read(ssl, buf, (int)num);
929 err = SSL_get_error(ssl, bytes);
931 - retries++;
932 - //} while (bytes <= 0 && err == SSL_ERROR_WANT_READ);
930
931 if(unlikely(bytes <= 0)) {
932 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
933 bytes = 0;
934 } else
938 - error("SSL_write() returned %d bytes, SSL error %d", bytes, err);
935 + error_limit(&erl, "SSL_write() returned %d bytes, SSL error %d", bytes, err);
936 }
937
941 - if(retries > 1)
942 - error_limit(&erl, "SSL_read() retried %d times", retries);
943 -
938 return bytes;
939 }
940
941 ssize_t netdata_ssl_write(SSL *ssl, const void *buf, size_t num) {
942 error_limit_static_thread_var(erl, 1, 0);
943
950 - int bytes, err, retries = 0;
951 - size_t total = 0;
944 + int bytes, err;
945
953 - //do {
954 - bytes = SSL_write(ssl, (uint8_t *)buf + total, (int)(num - total));
946 + bytes = SSL_write(ssl, (uint8_t *)buf, (int)num);
947 err = SSL_get_error(ssl, bytes);
956 - retries++;
957 -
958 - if(bytes > 0)
959 - total += bytes;
960 -
961 - //} while ((bytes <= 0 && (err == SSL_ERROR_WANT_WRITE)) || (bytes > 0 && total < num));
948
949 if(unlikely(bytes <= 0)) {
950 if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
951 bytes = 0;
952 } else
967 - error("SSL_write() returned %d bytes, SSL error %d", bytes, err);
953 + error_limit(&erl, "SSL_write() returned %d bytes, SSL error %d", bytes, err);
954 }
955
970 - if(retries > 1)
971 - error_limit(&erl, "SSL_write() retried %d times", retries);
972 -
956 return bytes;
957 }
958 #endif
web/server/static/static-threaded.c
+58 -46
@@ -293,61 +293,73 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) {
293 struct web_client *w = (struct web_client *)pi->data;
294 int fd = pi->fd;
295
296 - if(unlikely(web_client_receive(w) < 0)) {
297 - ret = -1;
298 - goto cleanup;
299 - }
296 + web_client_disable_wait_receive(w);
297 + web_client_disable_wait_send(w);
298
301 - debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd);
302 - worker_is_idle();
303 - worker_is_busy(WORKER_JOB_PROCESS);
304 - web_client_process_request(w);
299 + ssize_t bytes;
300 + bytes = web_client_receive(w);
301
306 - if (unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) {
307 - web_client_send(w);
308 - }
302 + if (likely(bytes > 0)) {
303 + debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd);
304 + worker_is_idle();
305 + worker_is_busy(WORKER_JOB_PROCESS);
306 + web_client_process_request(w);
307
310 - else if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
311 - if(w->pollinfo_filecopy_slot == 0) {
312 - debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd);
313 -
314 - if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) {
315 - // add a new socket to poll_events, with the same
316 - debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd);
317 -
318 - POLLINFO *fpi = poll_add_fd(
319 - pi->p
320 - , w->ifd
321 - , pi->port_acl
322 - , 0
323 - , POLLINFO_FLAG_CLIENT_SOCKET
324 - , "FILENAME"
325 - , ""
326 - , ""
327 - , web_server_file_add_callback
328 - , web_server_file_del_callback
329 - , web_server_file_read_callback
330 - , web_server_file_write_callback
331 - , (void *) w
332 - );
333 -
334 - if(fpi)
335 - w->pollinfo_filecopy_slot = fpi->slot;
336 - else {
337 - error("Failed to add filecopy fd. Closing client.");
338 - ret = -1;
339 - goto cleanup;
308 + if (unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) {
309 + web_client_send(w);
310 + }
311 +
312 + else if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) {
313 + if(w->pollinfo_filecopy_slot == 0) {
314 + debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd);
315 +
316 + if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) {
317 + // add a new socket to poll_events, with the same
318 + debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd);
319 +
320 + POLLINFO *fpi = poll_add_fd(
321 + pi->p
322 + , w->ifd
323 + , pi->port_acl
324 + , 0
325 + , POLLINFO_FLAG_CLIENT_SOCKET
326 + , "FILENAME"
327 + , ""
328 + , ""
329 + , web_server_file_add_callback
330 + , web_server_file_del_callback
331 + , web_server_file_read_callback
332 + , web_server_file_write_callback
333 + , (void *) w
334 + );
335 +
336 + if(fpi)
337 + w->pollinfo_filecopy_slot = fpi->slot;
338 + else {
339 + error("Failed to add filecopy fd. Closing client.");
340 + ret = -1;
341 + goto cleanup;
342 + }
343 }
344 }
345 }
343 - }
344 - else {
346 + else {
347 + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w)))
348 + *events |= POLLIN;
349 + }
350 +
351 + if(unlikely(w->ofd == fd && web_client_has_wait_send(w)))
352 + *events |= POLLOUT;
353 + } else if(unlikely(bytes < 0)) {
354 + ret = -1;
355 + goto cleanup;
356 + } else if (unlikely(bytes == 0)) {
357 if(unlikely(w->ifd == fd && web_client_has_wait_receive(w)))
358 *events |= POLLIN;
347 - }
359
349 - if(unlikely(w->ofd == fd && web_client_has_wait_send(w)))
350 - *events |= POLLOUT;
360 + if(unlikely(w->ofd == fd && web_client_has_wait_send(w)))
361 + *events |= POLLOUT;
362 + }
363
364 ret = web_server_check_client_status(w);
365
web/server/web_client.c
+20 -1
@@ -38,6 +38,18 @@ static inline int web_client_crock_socket(struct web_client *w) {
38 return 0;
39 }
40
41 +static inline void web_client_enable_wait_from_ssl(struct web_client *w, int bytes) {
42 + int ssl_err = SSL_get_error(w->ssl.conn, bytes);
43 + if (ssl_err == SSL_ERROR_WANT_READ)
44 + web_client_enable_wait_receive(w);
45 + else if (ssl_err == SSL_ERROR_WANT_WRITE)
46 + web_client_enable_wait_send(w);
47 + else if (ssl_err) {
48 + web_client_disable_wait_receive(w);
49 + web_client_disable_wait_send(w);
50 + }
51 +}
52 +
53 static inline int web_client_uncrock_socket(struct web_client *w) {
54 #ifdef TCP_CORK
55 if(likely(w->tcp_cork && w->ofd != -1)) {
@@ -1056,6 +1068,7 @@ static inline ssize_t web_client_send_data(struct web_client *w,const void *buf,
1068 if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1069 if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
1070 bytes = netdata_ssl_write(w->ssl.conn, buf, len) ;
1071 + web_client_enable_wait_from_ssl(w, bytes);
1072 } else {
1073 bytes = send(w->ofd,buf, len , flags);
1074 }
@@ -1211,8 +1224,10 @@ static inline void web_client_send_http_header(struct web_client *w) {
1224 ssize_t bytes;
1225 #ifdef ENABLE_HTTPS
1226 if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1214 - if ( ( w->ssl.conn ) && ( w->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE ) )
1227 + if ( ( w->ssl.conn ) && ( w->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE ) ) {
1228 bytes = netdata_ssl_write(w->ssl.conn, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output));
1229 + web_client_enable_wait_from_ssl(w, bytes);
1230 + }
1231 else {
1232 while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
1233 count++;
@@ -1509,6 +1524,9 @@ void web_client_process_request(struct web_client *w) {
1524 }
1525 else {
1526 // wait for more data
1527 + // set to normal to prevent web_server_rcv_callback
1528 + // from going into stream mode
1529 + w->mode = WEB_CLIENT_MODE_NORMAL;
1530 return;
1531 }
1532 break;
@@ -1905,6 +1923,7 @@ ssize_t web_client_receive(struct web_client *w)
1923 if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1924 if ( ( w->ssl.conn ) && (!w->ssl.flags)) {
1925 bytes = netdata_ssl_read(w->ssl.conn, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
1926 + web_client_enable_wait_from_ssl(w, bytes);
1927 }else {
1928 bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1929 }