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
}