feat: (Almost) functionnal package
This commit is contained in:
parent
d2076a5fd5
commit
5dbcc3e3d0
8 changed files with 164 additions and 29 deletions
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#define _POSIX_C_SOURCE 200112L
|
||||
|
||||
/* @brief
|
||||
*
|
||||
* @param hpstname
|
||||
|
|
|
|||
|
|
@ -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++)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue