feat: (Almost) functionnal package

This commit is contained in:
Gu://em_ 2025-11-26 21:57:45 +01:00
parent d2076a5fd5
commit 5dbcc3e3d0
8 changed files with 164 additions and 29 deletions

View file

@ -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));

View file

@ -1,11 +1,15 @@
#include "http.h"
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sendfile.h>
#include <sys/socket.h>
#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);
}
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -1,13 +1,12 @@
#include "server.h"
#define _POSIX_C_SOURCE 200112L
#include <netdb.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/socket.h>
#include <unistd.h>
#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);
}

View file

@ -1,6 +1,8 @@
#ifndef SERVER_H
#define SERVER_H
#define _POSIX_C_SOURCE 200112L
/* @brief
*
* @param hpstname

View file

@ -6,10 +6,12 @@
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;
if (size > 0)
{
res->data = malloc(size * sizeof(char));
if (res->data == NULL)
{
@ -18,6 +20,8 @@ struct string *string_create(const char *str, size_t 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;
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++)
{