aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/routing.c14
-rw-r--r--src/server.c21
-rw-r--r--src/template.c28
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);