diff options
| -rw-r--r-- | src/routing.c | 14 | ||||
| -rw-r--r-- | src/server.c | 21 | ||||
| -rw-r--r-- | src/template.c | 28 |
3 files changed, 57 insertions, 6 deletions
diff --git a/src/routing.c b/src/routing.c index d5d3969..1ae4ce9 100644 --- a/src/routing.c +++ b/src/routing.c @@ -322,16 +322,26 @@ bool serve_static_file_with_mime(const char *request_path_relative_to_static, co char file_buffer[BUFFER_SIZE]; size_t bytes_read; + bool send_error = false; - while ((bytes_read = fread(file_buffer, 1, sizeof(file_buffer), fp)) > 0) { + clearerr(fp); + while (!send_error && !feof(fp) && !ferror(fp) && (bytes_read = fread(file_buffer, 1, sizeof(file_buffer), fp)) > 0) { if (send(current_client_socket, file_buffer, bytes_read, 0) < 0) { perror("Error sending static file content"); fprintf(stderr, "[ERROR] serve_static_file_with_mime: Failed to send content for '%s'.\n", full_static_path); - break; + send_error = true; } } + if (ferror(fp)) { + perror("Error reading static file"); + fprintf(stderr, "[ERROR] serve_static_file_with_mime: Failed to read '%s'.\n", + full_static_path); + fclose(fp); + return true; + } + fclose(fp); return true; } diff --git a/src/server.c b/src/server.c index 270be70..9c89f11 100644 --- a/src/server.c +++ b/src/server.c @@ -144,8 +144,9 @@ static int initialize_server_socket(const char *ip, int port, int *server_fd_out perror("setsockopt SO_REUSEADDR failed"); } - //Needed for FreeBSD Support - #ifdef SO_REUSEPORT + // Needed for FreeBSD support. On macOS this allows multiple processes to + // bind the same TCP port, which is surprising for a single-instance server. + #if defined(__FreeBSD__) && defined(SO_REUSEPORT) if (setsockopt(*server_fd_out, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt))) { perror("setsockopt SO_REUSEPORT failed"); fprintf(stderr, "[ERROR] initialize_server_socket: Failed to set SO_REUSEPORT.\n"); @@ -184,6 +185,17 @@ static int initialize_server_socket(const char *ip, int port, int *server_fd_out return 0; } +static int set_socket_blocking(int fd) { + int flags = fcntl(fd, F_GETFL, 0); + if (flags < 0) + return -1; + + if ((flags & O_NONBLOCK) == 0) + return 0; + + return fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); +} + void handle_client_connection(int new_socket) { current_client_socket = new_socket; char buffer[BUFFER_SIZE] = {0}; @@ -340,6 +352,11 @@ void beaker_run_with_threads(const char *ip, int port, int num_workers) { int new_socket; while ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) >= 0) { + if (set_socket_blocking(new_socket) < 0) { + perror("fcntl clear O_NONBLOCK failed"); + close(new_socket); + continue; + } if (work_queue_push(&g_work_queue, new_socket) < 0) { fprintf(stderr, "[WARNING] Work queue full, closing connection\n"); const char *busy_response = "HTTP/1.1 503 Service Unavailable\r\nContent-Length: 0\r\n\r\n"; diff --git a/src/template.c b/src/template.c index 6255d1b..0937b66 100644 --- a/src/template.c +++ b/src/template.c @@ -1442,9 +1442,23 @@ char *render_template(const char *template_file, TemplateContext *ctx) { fseek(fp, 0, SEEK_END); long file_size = ftell(fp); + if (file_size < 0) { + perror("Error getting template file size"); + fprintf(stderr, + "[ERROR] render_template: Failed to get size of '%s'.\n", + full_path); + fclose(fp); + return NULL; + } fseek(fp, 0, SEEK_SET); - char *template_content = (char *)malloc(file_size + 1); + if (file_size == 0) { + char *empty_result = render_template_segment("", ctx); + fclose(fp); + return empty_result; + } + + char *template_content = (char *)malloc((size_t)file_size + 1); if (template_content == NULL) { perror("Error allocating memory for template content"); fprintf(stderr, @@ -1454,7 +1468,17 @@ char *render_template(const char *template_file, TemplateContext *ctx) { fclose(fp); return NULL; } - fread(template_content, 1, file_size, fp); + + size_t bytes_read = fread(template_content, 1, (size_t)file_size, fp); + if (bytes_read != (size_t)file_size) { + perror("Error reading template file"); + fprintf(stderr, + "[ERROR] render_template: Failed to read complete template '%s'.\n", + full_path); + free(template_content); + fclose(fp); + return NULL; + } template_content[file_size] = '\0'; fclose(fp); |
