fix: Goodbye memory leaks, welcome to awesome error codes that work just well

This commit is contained in:
Gu://em_ 2025-11-28 15:44:33 +01:00
parent f16bdbdf73
commit eee5f940e3
13 changed files with 96 additions and 40 deletions

View file

@ -48,7 +48,7 @@ int start_daemon(void)
pid_t pid = fork(); pid_t pid = fork();
if (!pid) // Daemon if (!pid) // Daemon
{ {
start_server(config->servers->ip, config->servers->port); start_server(config);
} }
else // Parent else // Parent
{ {

View file

@ -5,12 +5,15 @@
#include <string.h> #include <string.h>
#include "../utils/parsing/words.h" #include "../utils/parsing/words.h"
#include "../utils/string/string.h"
void destroy_headers(struct http_header *headers) void destroy_headers(struct http_header *headers)
{ {
while (headers != NULL) while (headers != NULL)
{ {
struct http_header *next = headers->next; struct http_header *next = headers->next;
string_destroy(headers->field);
string_destroy(headers->value);
free(headers); free(headers);
headers = next; headers = next;
} }

View file

@ -91,21 +91,19 @@ static void split_target(struct http_request *req)
} }
} }
// Finds a valid path based on the client input // Finds a valid path based on the client input and returns the corresponding
static bool find_target(struct http_request *req) // FILES return value (see files.h)
static int find_target(struct http_request *req)
{ {
// Check filename // Check filename
if (!check_filename(req->target)) if (!check_filename(req->target))
return false; return ERR_FILES_FORBIDDEN;
char *target = string_to_charptr(req->target); char *target = string_to_charptr(req->target);
int err = is_directory(target); int err = is_directory(target);
free(target); free(target);
err = 0; // TODO fix that bug
if (err == -1) // Doesn't exists if (err == FILES_DIR) // Is a directory
return false;
else if (err == 1)
{ {
// Append default file if directory // Append default file if directory
if (req->target->data[req->target->size - 1] != '/') if (req->target->data[req->target->size - 1] != '/')
@ -117,11 +115,10 @@ static bool find_target(struct http_request *req)
target = string_to_charptr(req->target); target = string_to_charptr(req->target);
err = is_directory(target); err = is_directory(target);
free(target); free(target);
return err == 0; return err;
} }
// Exists return err;
return true;
} }
// WARNING allocates result on the heap // WARNING allocates result on the heap
@ -218,7 +215,7 @@ void handle_request(int client_fd, char *client_ip)
return; return;
char *method = get_http_method(req->method); char *method = get_http_method(req->method);
char *target = string_to_charptr(req->target); char *target = string_to_charptr(req->target);
log_request(method, target, client_ip); print_log_request(method, target, client_ip);
free(method); free(method);
free(target); free(target);
@ -253,12 +250,15 @@ void handle_request(int client_fd, char *client_ip)
int fd = open(target, O_RDONLY); int fd = open(target, O_RDONLY);
if (fd > 0) if (fd > 0)
sendfile(client_fd, fd, 0, atoi(cl_str)); sendfile(client_fd, fd, 0, atoi(cl_str));
free(target);
free(cl_str);
} }
// Log response // Log response
method = get_http_method(req->method); method = get_http_method(req->method);
target = string_to_charptr(req->target); target = string_to_charptr(req->target);
log_response(resp->status_code, method, target, client_ip); print_log_response(resp->status_code, method, target, client_ip);
free(method); free(method);
free(target); free(target);
@ -314,12 +314,23 @@ struct http_response *generate_response(struct http_request *req)
// Status code // Status code
if (req->status_code == 0) if (req->status_code == 0)
{ {
if (!find_target(req)) switch (find_target(req))
res->status_code = 404; {
else case FILES_REG:
res->status_code = 200; res->status_code = 200;
break;
case ERR_FILES_NOT_FOUND:
res->status_code = 404;
break;
default:
res->status_code = 403;
break;
}
} }
else
res->status_code = req->status_code;
// Check protocol and method
check_req(req, res); check_req(req, res);
// Headers // Headers
@ -339,8 +350,7 @@ struct http_response *generate_response(struct http_request *req)
} }
else else
{ {
res->status_code = res->status_code = 403;
404; // TODO replace by 403 once find_target is fixed
} }
} }
append_header(&res->headers, create_header("Connection", "close")); append_header(&res->headers, create_header("Connection", "close"));

View file

@ -73,7 +73,7 @@ void http_init(struct config *cfg);
* *
* @param client_fd * @param client_fd
*/ */
void handle_request(int client_fd, char* client_ip); void handle_request(int client_fd, char *client_ip);
/* @brief Parses the HTTP request and splits it into a request structure /* @brief Parses the HTTP request and splits it into a request structure
* *

View file

@ -16,11 +16,11 @@ void errlog_init(bool enabled, int logfile_fd, struct server_config *serv_cfg);
*/ */
void print_err(); void print_err();
/* @brief Prints error logs, just like print_log(), and also to stderr /* @brief Prints error logs, just like print_log() but for errors
*/ */
void print_log_err(char *format, ...); void print_log_err(char *format, ...);
/* @brief Prints error logs, just like print_log() /* @brief Returns the string corresponding to the last error that happened
*/ */
char *get_err(); char *get_err();

View file

@ -60,14 +60,20 @@ void print_log(char *format, ...)
dprintf(config.logfile_fd, "\n"); dprintf(config.logfile_fd, "\n");
} }
void log_request(char *request_type, char *target, char *client_ip) void print_log_request(char *request_type, char *target, char *client_ip)
{ {
print_log("received %s, on '%s' from %s", request_type, target, client_ip); print_log("received %s, on '%s' from %s", request_type, target, client_ip);
} }
void log_response(int status_code, char *request_type, char *target, void print_log_response(int status_code, char *request_type, char *target,
char *client_ip) char *client_ip)
{ {
print_log("responding with %d to %s for %s on '%s'", status_code, client_ip, print_log("responding with %d to %s for %s on '%s'", status_code, client_ip,
request_type, target); request_type, target);
} }
void log_terminate(void)
{
if (config.logfile_fd != 0 && config.logfile_fd != STDOUT_FILENO)
close(config.logfile_fd);
}

View file

@ -35,7 +35,7 @@ void print_log(char *format, ...);
* @param target * @param target
* @param client_ip * @param client_ip
*/ */
void log_request(char *request_type, char *target, char *client_ip); void print_log_request(char *request_type, char *target, char *client_ip);
/* @brief Prints response logs with the adequate format in the logfile /* @brief Prints response logs with the adequate format in the logfile
* *
@ -44,7 +44,11 @@ void log_request(char *request_type, char *target, char *client_ip);
* @param target * @param target
* @param client_ip * @param client_ip
*/ */
void log_response(int status_code, char *request_type, char *target, void print_log_response(int status_code, char *request_type, char *target,
char *client_ip); char *client_ip);
/* @brief Gracefully exits the logs module
*/
void log_terminate(void);
#endif // ! LOGS_H #endif // ! LOGS_H

View file

@ -24,7 +24,7 @@ int main(int argc, char **argv)
switch (config->daemon) switch (config->daemon)
{ {
case NO_OPTION: case NO_OPTION:
start_server(config->servers->ip, config->servers->port); start_server(config);
break; break;
case START: case START:
@ -43,5 +43,6 @@ int main(int argc, char **argv)
return 2; return 2;
} }
config_destroy(config);
return 0; return 0;
} }

View file

@ -23,7 +23,8 @@
// === Static variables // === Static variables
int server_socket = 0; static int server_socket = 0;
static struct config *config;
// === Static functions // === Static functions
@ -111,12 +112,13 @@ static void get_ip(struct sockaddr *client_addr, char *res)
static void signal_handler(int signal) static void signal_handler(int signal)
{ {
print_log("signal received: %d", signal); print_log("EVENT Signal received: %d", signal);
switch (signal) switch (signal)
{ {
case SIGINT: { case SIGINT: {
print_log("Stopping server..."); print_log("STOPPING Stopping server...");
stop_server(); stop_server();
config_destroy(config);
exit(0); exit(0);
} }
default: default:
@ -126,8 +128,12 @@ static void signal_handler(int signal)
// === Functions // === Functions
void start_server(const char *host, const char *port) void start_server(struct config *cfg)
{ {
config = cfg;
const char *host = config->servers->ip;
const char *port = config->servers->port;
server_socket = get_socket(host, port); server_socket = get_socket(host, port);
if (server_socket == -1) if (server_socket == -1)
// TODO log that // TODO log that
@ -145,14 +151,16 @@ void start_server(const char *host, const char *port)
if (sigemptyset(&siga.sa_mask) < 0) if (sigemptyset(&siga.sa_mask) < 0)
// TODO log that // TODO log that
return; return;
if (sigaction(SIGINT, &siga, NULL) == -1) if (sigaction(SIGINT, &siga, NULL) == -1
|| sigaction(SIGPIPE, &siga, NULL) == -1)
return; return;
// Main loop // Main loop
while (1) while (1)
{ {
struct sockaddr client_addr; struct sockaddr client_addr;
int client_fd = accept(server_socket, &client_addr, NULL); socklen_t client_addr_len = sizeof(struct sockaddr);
int client_fd = accept(server_socket, &client_addr, &client_addr_len);
if (client_fd == -1) if (client_fd == -1)
continue; continue;

View file

@ -1,7 +1,7 @@
#ifndef SERVER_H #ifndef SERVER_H
#define SERVER_H #define SERVER_H
// #define _POSIX_C_SOURCE 200112L #include "../config/config.h"
/* @brief Starts the HTTP server /* @brief Starts the HTTP server
* *
@ -10,7 +10,7 @@
* @param hostname * @param hostname
* @param port * @param port
*/ */
void start_server(const char *host, const char *port); void start_server(struct config *cfg);
/* @brief Stops the currently running HTTP server /* @brief Stops the currently running HTTP server
*/ */

View file

@ -2,6 +2,7 @@
#include "files.h" #include "files.h"
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -13,10 +14,22 @@
int is_directory(const char *path) int is_directory(const char *path)
{ {
struct stat path_stat; struct stat path_stat;
if (lstat(path, &path_stat) != 0) if (lstat(path, &path_stat) == 0)
return S_ISDIR(path_stat.st_mode); {
if (S_ISDIR(path_stat.st_mode)) // Directory
return FILES_DIR;
else if (S_ISREG(path_stat.st_mode)) // Regular file
return FILES_REG;
else
return FILES_OTHER;
}
else else
return -1; {
if (errno == ENOENT) // File not found
return ERR_FILES_NOT_FOUND;
else // Other errors
return ERR_FILES_FORBIDDEN;
}
} }
// TODO handle logging // TODO handle logging

View file

@ -5,6 +5,15 @@
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
// Return codes
#define FILES_REG 0
#define FILES_DIR 1
#define FILES_OTHER 8
// Errors
#define ERR_FILES_NOT_FOUND -1
#define ERR_FILES_FORBIDDEN -2
// === Includes // === Includes
#include <stdbool.h> #include <stdbool.h>
@ -29,7 +38,8 @@
* *
* @param path * @param path
* *
* @return 1 if path is a directory, 0 if it is not and -1 if path is not valid * @return Returns the corresponding return value / error code (see header
* definitions)
*/ */
int is_directory(const char *path); int is_directory(const char *path);

View file

@ -114,6 +114,7 @@ void str_concat_string(const char *str, size_t size, struct string *to_concat)
memcpy(to_concat->data, str, size); memcpy(to_concat->data, str, size);
memcpy(to_concat->data + size, tmp, tmp_size); memcpy(to_concat->data + size, tmp, tmp_size);
free(tmp);
} }
} }