From 5dbcc3e3d0be0812dae06fcb5e30d91bb877d245 Mon Sep 17 00:00:00 2001 From: "Gu://em_" Date: Wed, 26 Nov 2025 21:57:45 +0100 Subject: [PATCH] feat: (Almost) functionnal package --- httpd/src/http/headers.c | 13 +++++ httpd/src/http/http.c | 94 +++++++++++++++++++++++++++++++++ httpd/src/http/http.h | 8 ++- httpd/src/logger/errors.c | 3 ++ httpd/src/logger/logs.c | 3 ++ httpd/src/server/server.c | 39 +++++++------- httpd/src/server/server.h | 2 + httpd/src/utils/string/string.c | 31 +++++++---- 8 files changed, 164 insertions(+), 29 deletions(-) diff --git a/httpd/src/http/headers.c b/httpd/src/http/headers.c index 8fefc1b..5463d92 100644 --- a/httpd/src/http/headers.c +++ b/httpd/src/http/headers.c @@ -87,6 +87,19 @@ ssize_t parse_headers(struct http_request *res, struct string *req, return i + 1; } +struct http_header *get_header(struct http_header *headers, const char *field) +{ + while (headers != NULL) + { + if (string_compare_n_str(headers->field, field, strlen(field)) == 0) + return headers; + + headers = headers->next; + } + + return NULL; +} + struct http_header *create_header(const char *field, const char *value) { struct http_header *res = calloc(1, sizeof(struct http_header)); diff --git a/httpd/src/http/http.c b/httpd/src/http/http.c index c105986..5c9aa07 100644 --- a/httpd/src/http/http.c +++ b/httpd/src/http/http.c @@ -1,11 +1,15 @@ #include "http.h" +#include #include #include #include #include #include +#include +#include +#include "../logger/logs.h" #include "../utils/files/files.h" #include "../utils/parsing/words.h" #include "../utils/time/fmt_time.h" @@ -108,6 +112,24 @@ static bool find_target(struct http_request *req) return true; } +// WARNING allocates result on the heap +static char *get_http_method(enum http_method method) +{ + char *res = malloc(8 * sizeof(char)); + switch (method) + { + case GET: + strcpy(res, "HEAD"); + return res; + case HEAD: + strcpy(res, "HEAD"); + return res; + default: + free(res); + return NULL; + } +} + static struct string *generate_status_message(int status_code) { char *message; @@ -145,6 +167,63 @@ void http_init(struct config *cfg) config = cfg; } +// TODO handle logs +void handle_request(int client_fd) +{ + ssize_t nread = 0; + char buffer[BUFFER_SIZE]; // Declared in server.h + struct string *str = string_create(NULL, 0); + if (str == NULL) + return; + + // Store request + while ((nread = recv(client_fd, buffer, BUFFER_SIZE, 0)) > 0) + { + string_concat_str(str, buffer, nread); + } + + // Parse request + struct http_request *req = parse_request(str); + if (req == NULL) + return; + char *method = get_http_method(req->method); + char *target = string_to_charptr(req->target); + log_request(method, target, "127.0.0.1"); + free(method); + free(target); + + // Generate response + struct http_response *resp = generate_response(req); + if (resp == NULL) + return; + + // Format response to string + struct string *res = format_response(resp); + if (res == NULL) + return; + + // Send response + ssize_t nsent; + while ((nsent = send(client_fd, res, res->size, 0)) > 0) + ; + // Send file + struct http_header *cl_header = get_header(resp->headers, "Content-Length"); + if (cl_header != NULL) + { + char *target = string_to_charptr(req->target); + char *cl_str = string_to_charptr(cl_header->value); + int fd = open(target, O_RDONLY); + if (fd > 0) + sendfile(client_fd, fd, 0, atoi(cl_str)); + } + + // Free + string_destroy(str); + string_destroy(res); + destroy_request(req); + destroy_response(resp); +} + // TODO handle logs and free adequately struct http_request *parse_request(struct string *req) { @@ -260,3 +339,18 @@ void destroy_request(struct http_request *req) free(req); } } + +void destroy_response(struct http_response *resp) +{ + if (resp != NULL) + { + if (resp->status_msg != NULL) + string_destroy(resp->status_msg); + if (resp->protocol != NULL) + string_destroy(resp->protocol); + + destroy_headers(resp->headers); + + free(resp); + } +} diff --git a/httpd/src/http/http.h b/httpd/src/http/http.h index 0d8da69..0a895da 100644 --- a/httpd/src/http/http.h +++ b/httpd/src/http/http.h @@ -3,7 +3,7 @@ // === Definitions -#define _POSIX_C_SOURCE 200809L +// #define _POSIX_C_SOURCE 200809L // Error codes #define ERR_HTTP_INVALID_INPUT -1 @@ -68,6 +68,12 @@ struct http_response */ void http_init(struct config* cfg); +/* @brief Reads, parses the request and responds adequately all-in-one + * + * @param client_fd + */ + void handle_request(int client_fd); + /* @brief Parses the HTTP request and splits it into a request structure * * @param req diff --git a/httpd/src/logger/errors.c b/httpd/src/logger/errors.c index bca0182..fb23f4d 100644 --- a/httpd/src/logger/errors.c +++ b/httpd/src/logger/errors.c @@ -26,6 +26,9 @@ void print_err() void print_log_err(char *format, ...) { + if (!config.enabled) + return; + // Log prefix (time and server name) fprintf(config.logfile_stream, "%s [%s] ", get_time(), config.server_cfg->server_name); diff --git a/httpd/src/logger/logs.c b/httpd/src/logger/logs.c index b3bc6f2..fabd878 100644 --- a/httpd/src/logger/logs.c +++ b/httpd/src/logger/logs.c @@ -24,6 +24,9 @@ int log_init(struct config *global_config) void print_log(char *format, ...) { + if (!config.enabled) + return; + // Log prefix (time and server name) fprintf(config.logfile_stream, "%s [%s] ", get_time(), config.server_cfg->server_name); diff --git a/httpd/src/server/server.c b/httpd/src/server/server.c index ea193a4..9b39a6f 100644 --- a/httpd/src/server/server.c +++ b/httpd/src/server/server.c @@ -1,13 +1,12 @@ #include "server.h" -#define _POSIX_C_SOURCE 200112L - #include #include #include #include #include +#include "../http/http.h" #include "../logger/errors.h" // #include "../logger/logs.h" @@ -70,24 +69,25 @@ static int get_socket(const char *hostname, const char *port) } // Reads and sends back received data to client -static void send_back(int client_fd) -{ - ssize_t nread = 0; - char buffer[BUFFER_SIZE]; +// For testing purposes +// static void send_back(int client_fd) +// { +// ssize_t nread = 0; +// char buffer[BUFFER_SIZE]; - while ((nread = recv(client_fd, buffer, BUFFER_SIZE, 0)) > 0) - { - ssize_t sent; - while (nread > 0) - { - sent = send(client_fd, buffer, nread, 0); - if (sent == -1) // Send failed - break; +// while ((nread = recv(client_fd, buffer, BUFFER_SIZE, 0)) > 0) +// { +// ssize_t sent; +// while (nread > 0) +// { +// sent = send(client_fd, buffer, nread, 0); +// if (sent == -1) // Send failed +// break; - nread -= sent; - } - } -} +// nread -= sent; +// } +// } +// } // === Functions @@ -111,7 +111,8 @@ void start_server(const char *host, const char *port) // TODO handle signals to stop - send_back(client_fd); + handle_request(client_fd); + // send_back(client_fd); close(client_fd); } diff --git a/httpd/src/server/server.h b/httpd/src/server/server.h index dac01d8..b25ee40 100644 --- a/httpd/src/server/server.h +++ b/httpd/src/server/server.h @@ -1,6 +1,8 @@ #ifndef SERVER_H #define SERVER_H +#define _POSIX_C_SOURCE 200112L + /* @brief * * @param hpstname diff --git a/httpd/src/utils/string/string.c b/httpd/src/utils/string/string.c index b5fe69e..29df1ef 100644 --- a/httpd/src/utils/string/string.c +++ b/httpd/src/utils/string/string.c @@ -6,18 +6,22 @@ struct string *string_create(const char *str, size_t size) { - struct string *res = malloc(sizeof(struct string)); + struct string *res = calloc(1, sizeof(struct string)); if (res == NULL) return NULL; - res->data = malloc(size * sizeof(char)); - if (res->data == NULL) + if (size > 0) { - free(res); - return NULL; + res->data = malloc(size * sizeof(char)); + if (res->data == NULL) + { + free(res); + return NULL; + } + + memcpy(res->data, str, size); } - memcpy(res->data, str, size); res->size = size; return res; } @@ -55,9 +59,18 @@ void string_concat_str(struct string *str, const char *to_concat, size_t size) return; str->size = new_size; - str->data = realloc(str->data, new_size); - if (str->data == NULL) - return; // Handle ? + if (str_size == 0) + { + str->data = malloc(new_size); + if (str->data == NULL) + return; // Handle ? + } + else + { + str->data = realloc(str->data, new_size); + if (str->data == NULL) + return; // Handle ? + } for (size_t i = 0; i < size; i++) {