diff options
Diffstat (limited to 'web/server/static')
-rw-r--r-- | web/server/static/README.md | 4 | ||||
-rw-r--r-- | web/server/static/static-threaded.c | 132 |
2 files changed, 82 insertions, 54 deletions
diff --git a/web/server/static/README.md b/web/server/static/README.md index 6a83b70d..c4e5c4c1 100644 --- a/web/server/static/README.md +++ b/web/server/static/README.md @@ -2,6 +2,10 @@ title: "`static-threaded` web server" description: "The Netdata Agent's static-threaded web server spawns a fixed number of threads that listen to web requests and uses non-blocking I/O." custom_edit_url: https://github.com/netdata/netdata/edit/master/web/server/static/README.md +sidebar_label: "`static-threaded` web server" +learn_status: "Published" +learn_topic_type: "Tasks" +learn_rel_path: "Developers/Web" --> # `static-threaded` web server diff --git a/web/server/static/static-threaded.c b/web/server/static/static-threaded.c index aca7d7ec..52bb56cd 100644 --- a/web/server/static/static-threaded.c +++ b/web/server/static/static-threaded.c @@ -28,7 +28,7 @@ long web_client_streaming_rate_t = 0L; static struct web_client *web_client_create_on_fd(POLLINFO *pi) { struct web_client *w; - w = web_client_get_from_cache_or_allocate(); + w = web_client_get_from_cache(); w->ifd = w->ofd = pi->fd; strncpyz(w->client_ip, pi->client_ip, sizeof(w->client_ip) - 1); @@ -39,7 +39,19 @@ static struct web_client *web_client_create_on_fd(POLLINFO *pi) { if(unlikely(!*w->client_port)) strcpy(w->client_port, "-"); w->port_acl = pi->port_acl; - web_client_initialize_connection(w); + int flag = 1; + if(unlikely(web_client_check_tcp(w) && setsockopt(w->ifd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0)) + debug(D_WEB_CLIENT, "%llu: failed to enable TCP_NODELAY on socket fd %d.", w->id, w->ifd); + + flag = 1; + if(unlikely(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0)) + debug(D_WEB_CLIENT, "%llu: failed to enable SO_KEEPALIVE on socket fd %d.", w->id, w->ifd); + + web_client_update_acl_matches(w); + web_client_enable_wait_receive(w); + + web_server_log_connection(w, "CONNECTED"); + w->pollinfo_slot = pi->slot; return(w); } @@ -107,7 +119,10 @@ static void web_server_file_del_callback(POLLINFO *pi) { if(unlikely(!w->pollinfo_slot)) { debug(D_WEB_CLIENT, "%llu: CROSS WEB CLIENT CLEANUP (iFD %d, oFD %d)", w->id, pi->fd, w->ofd); - web_client_release(w); + web_server_log_connection(w, "DISCONNECTED"); + web_client_request_done(w); + web_client_release_to_cache(w); + global_statistics_web_client_disconnected(); } worker_is_idle(); @@ -278,7 +293,10 @@ static void web_server_del_callback(POLLINFO *pi) { pi->flags |= POLLINFO_FLAG_DONT_CLOSE; debug(D_WEB_CLIENT, "%llu: CLOSING CLIENT FD %d", w->id, pi->fd); - web_client_release(w); + web_server_log_connection(w, "DISCONNECTED"); + web_client_request_done(w); + web_client_release_to_cache(w); + global_statistics_web_client_disconnected(); } worker_is_idle(); @@ -293,61 +311,70 @@ static int web_server_rcv_callback(POLLINFO *pi, short int *events) { struct web_client *w = (struct web_client *)pi->data; int fd = pi->fd; - if(unlikely(web_client_receive(w) < 0)) { - ret = -1; - goto cleanup; - } + ssize_t bytes; + bytes = web_client_receive(w); - debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd); - worker_is_idle(); - worker_is_busy(WORKER_JOB_PROCESS); - web_client_process_request(w); + if (likely(bytes > 0)) { + debug(D_WEB_CLIENT, "%llu: processing received data on fd %d.", w->id, fd); + worker_is_idle(); + worker_is_busy(WORKER_JOB_PROCESS); + web_client_process_request(w); - if (unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) { - web_client_send(w); - } + if (unlikely(w->mode == WEB_CLIENT_MODE_STREAM)) { + web_client_send(w); + } - else if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { - if(w->pollinfo_filecopy_slot == 0) { - debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd); - - if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) { - // add a new socket to poll_events, with the same - debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd); - - POLLINFO *fpi = poll_add_fd( - pi->p - , w->ifd - , pi->port_acl - , 0 - , POLLINFO_FLAG_CLIENT_SOCKET - , "FILENAME" - , "" - , "" - , web_server_file_add_callback - , web_server_file_del_callback - , web_server_file_read_callback - , web_server_file_write_callback - , (void *) w - ); - - if(fpi) - w->pollinfo_filecopy_slot = fpi->slot; - else { - error("Failed to add filecopy fd. Closing client."); - ret = -1; - goto cleanup; + else if(unlikely(w->mode == WEB_CLIENT_MODE_FILECOPY)) { + if(w->pollinfo_filecopy_slot == 0) { + debug(D_WEB_CLIENT, "%llu: FILECOPY DETECTED ON FD %d", w->id, pi->fd); + + if (unlikely(w->ifd != -1 && w->ifd != w->ofd && w->ifd != fd)) { + // add a new socket to poll_events, with the same + debug(D_WEB_CLIENT, "%llu: CREATING FILECOPY SLOT ON FD %d", w->id, pi->fd); + + POLLINFO *fpi = poll_add_fd( + pi->p + , w->ifd + , pi->port_acl + , 0 + , POLLINFO_FLAG_CLIENT_SOCKET + , "FILENAME" + , "" + , "" + , web_server_file_add_callback + , web_server_file_del_callback + , web_server_file_read_callback + , web_server_file_write_callback + , (void *) w + ); + + if(fpi) + w->pollinfo_filecopy_slot = fpi->slot; + else { + error("Failed to add filecopy fd. Closing client."); + ret = -1; + goto cleanup; + } } } } - } - else { - if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + else { + if(unlikely(w->ifd == fd && web_client_has_wait_receive(w))) + *events |= POLLIN; + } + + if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) + *events |= POLLOUT; + } else if(unlikely(bytes < 0)) { + ret = -1; + goto cleanup; + } else if (unlikely(bytes == 0)) { + if(unlikely(w->ifd == fd && web_client_has_ssl_wait_receive(w))) *events |= POLLIN; - } - if(unlikely(w->ofd == fd && web_client_has_wait_send(w))) - *events |= POLLOUT; + if(unlikely(w->ofd == fd && web_client_has_ssl_wait_send(w))) + *events |= POLLOUT; + } ret = web_server_check_client_status(w); @@ -393,9 +420,6 @@ cleanup: static void socket_listen_main_static_threaded_worker_cleanup(void *ptr) { worker_private = (struct web_server_static_threaded_worker *)ptr; - info("freeing local web clients cache..."); - web_client_cache_destroy(); - info("stopped after %zu connects, %zu disconnects (max concurrent %zu), %zu receptions and %zu sends", worker_private->connected, worker_private->disconnected, |