fix: Goodbye memory leaks, welcome to awesome error codes that work just well
This commit is contained in:
parent
f16bdbdf73
commit
eee5f940e3
13 changed files with 96 additions and 40 deletions
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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"));
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue