fix http parser and config

This commit is contained in:
2025-05-08 16:58:42 +02:00
parent 8e880f59be
commit 8ff2bb608c
11 changed files with 50 additions and 35 deletions

1
.gitignore vendored
View File

@@ -56,4 +56,3 @@ modules.order
Module.symvers Module.symvers
Mkfile.old Mkfile.old
dkms.conf dkms.conf
doxygen-awesome-css

View File

@@ -8,7 +8,7 @@ A minimal web server. This is a personal project; it is not intended to be a pro
- libcyaml - libcyaml
- libyaml - libyaml
- [doxygen](https://www.doxygen.nl/) - [doxygen](https://www.doxygen.nl/)
- Optional, just to build the docs. - Optional, just to build the docs. It requires `dot`.
## How to build ## How to build

View File

@@ -1,6 +1,6 @@
# Default config file of CWS # Default config file of CWS
host: localhost hostname: localhost
port: 3030 port: 3030
www: "www" # Directory used to retrieve html files
cert: "cert.pem" cert: "cert.pem"
key: "key.pem" key: "key.pem"

View File

@@ -1,10 +1,9 @@
#ifndef CWS_HTTP_H #ifndef CWS_HTTP_H
#define CWS_HTTP_H #define CWS_HTTP_H
#include "utils/config.h"
#include "utils/hashmap.h" #include "utils/hashmap.h"
#define CWS_WWW "../www" /**< Directory used to get html files */
/** In the future I'll move conf stuff under a server struct, I can skip just because I want something that works */
#define CWS_HTTP_LOCATION_LEN 512 #define CWS_HTTP_LOCATION_LEN 512
#define CWS_HTTP_LOCATION_PATH_LEN 1024 #define CWS_HTTP_LOCATION_PATH_LEN 1024
#define CWS_HTTP_VERSION_LEN 8 #define CWS_HTTP_VERSION_LEN 8
@@ -14,8 +13,8 @@ typedef enum cws_http_method_t {
CWS_HTTP_POST, /**< POST method */ CWS_HTTP_POST, /**< POST method */
CWS_HTTP_PUT, CWS_HTTP_PUT,
CWS_HTTP_DELETE, CWS_HTTP_DELETE,
CWS_HTTP_HEAD,
} cws_http_method; } cws_http_method;
/* In the future I'll add HEAD, PUT, DELETE */
/** /**
* @brief HTTP request struct * @brief HTTP request struct
@@ -39,7 +38,7 @@ typedef struct cws_http_t {
* @param[in] request_str The http request sent to the server * @param[in] request_str The http request sent to the server
* @return Returns a http_t pointer to the request * @return Returns a http_t pointer to the request
*/ */
cws_http *cws_http_parse(char *request_str, int sockfd); cws_http *cws_http_parse(char *request_str, int sockfd, cws_config *config);
void cws_http_parse_method(cws_http *request, const char *method); void cws_http_parse_method(cws_http *request, const char *method);
void cws_http_get_content_type(cws_http *request, char *content_type); void cws_http_get_content_type(cws_http *request, char *content_type);

View File

@@ -4,6 +4,7 @@
#include <netdb.h> #include <netdb.h>
#include <sys/socket.h> #include <sys/socket.h>
#include "utils/config.h"
#include "utils/hashmap.h" #include "utils/hashmap.h"
/* Clients max queue */ /* Clients max queue */
@@ -21,11 +22,10 @@ extern volatile bool cws_server_run;
/** /**
* @brief Runs the server * @brief Runs the server
* *
* @param[in] hostname The hostname of the server (default localhost, it could be NULL) * @param[in] config The server's config
* @param[in] service The service (found in /etc/services) or the port where to run
* @return 0 on success, -1 on error * @return 0 on success, -1 on error
*/ */
int cws_server_start(const char *hostname, const char *service); int cws_server_start(cws_config *config);
/** /**
* @brief Setups hints object * @brief Setups hints object
@@ -41,7 +41,7 @@ void cws_server_setup_hints(struct addrinfo *hints, size_t len, const char *host
* *
* @param[in,out] sockfd Socket of the commincation endpoint * @param[in,out] sockfd Socket of the commincation endpoint
*/ */
void cws_server_loop(int sockfd); void cws_server_loop(int sockfd, cws_config *config);
/** /**
* @brief Adds a file descriptor to the interest list * @brief Adds a file descriptor to the interest list

View File

@@ -2,9 +2,9 @@
#define CWS_CONFIG_H #define CWS_CONFIG_H
typedef struct cws_config_t { typedef struct cws_config_t {
char *host; char *hostname;
char *port; char *port;
char *www;
char *cert; char *cert;
char *key; char *key;
} cws_config; } cws_config;

View File

@@ -8,7 +8,7 @@
#include "utils/colors.h" #include "utils/colors.h"
#include "utils/utils.h" #include "utils/utils.h"
cws_http *cws_http_parse(char *request_str, int sockfd) { cws_http *cws_http_parse(char *request_str, int sockfd, cws_config *config) {
cws_http *request = malloc(sizeof(cws_http)); cws_http *request = malloc(sizeof(cws_http));
if (request == NULL) { if (request == NULL) {
return NULL; return NULL;
@@ -21,6 +21,8 @@ cws_http *cws_http_parse(char *request_str, int sockfd) {
/* Parse HTTP method */ /* Parse HTTP method */
char *pch = strtok(request_str, " "); char *pch = strtok(request_str, " ");
if (pch == NULL) { if (pch == NULL) {
cws_http_free(request);
return NULL; return NULL;
} }
CWS_LOG_DEBUG("[http] method: %s", pch); CWS_LOG_DEBUG("[http] method: %s", pch);
@@ -29,6 +31,8 @@ cws_http *cws_http_parse(char *request_str, int sockfd) {
/* Parse location */ /* Parse location */
pch = strtok(NULL, " "); pch = strtok(NULL, " ");
if (pch == NULL) { if (pch == NULL) {
cws_http_free(request);
return NULL; return NULL;
} }
CWS_LOG_DEBUG("[http] location: %s", pch); CWS_LOG_DEBUG("[http] location: %s", pch);
@@ -36,15 +40,17 @@ cws_http *cws_http_parse(char *request_str, int sockfd) {
/* Adjust location path */ /* Adjust location path */
if (strcmp(request->location, "/") == 0) { if (strcmp(request->location, "/") == 0) {
snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s/index.html", CWS_WWW); snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s/index.html", config->www);
} else { } else {
snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s%s", CWS_WWW, request->location); snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s%s", config->www, request->location);
} }
CWS_LOG_DEBUG("[http] location path: %s", request->location_path); CWS_LOG_DEBUG("[http] location path: %s", request->location_path);
/* Parse HTTP version */ /* Parse HTTP version */
pch = strtok(NULL, " \r\n"); pch = strtok(NULL, " \r\n");
if (pch == NULL) { if (pch == NULL) {
cws_http_free(request);
return NULL; return NULL;
} }
CWS_LOG_DEBUG("[http] version: %s", pch); CWS_LOG_DEBUG("[http] version: %s", pch);

View File

@@ -12,18 +12,21 @@ void cws_signal_handler(int signo) { cws_server_run = false; }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret; int ret;
struct sigaction act = {.sa_handler = cws_signal_handler};
ret = sigaction(SIGINT, &act, NULL);
if (!ret) {
CWS_LOG_ERROR("sigaction()");
return 1;
}
cws_config *config = cws_config_init(); cws_config *config = cws_config_init();
if (config == NULL) { if (config == NULL) {
CWS_LOG_ERROR("Unable to read config file"); CWS_LOG_ERROR("Unable to read config file");
return 1; return 1;
} }
struct sigaction act = {.sa_handler = cws_signal_handler}; CWS_LOG_INFO("Running cws on http://%s:%s...", config->hostname, config->port);
ret = sigaction(SIGINT, &act, NULL); ret = cws_server_start(config);
CWS_LOG_INFO("Running cws on http://%s:%s...", config->host, config->port);
ret = cws_server_start(config->host, config->port);
if (ret < 0) { if (ret < 0) {
CWS_LOG_ERROR("Unable to start web server"); CWS_LOG_ERROR("Unable to start web server");
} }

View File

@@ -13,18 +13,17 @@
#include "http/http.h" #include "http/http.h"
#include "utils/colors.h" #include "utils/colors.h"
#include "utils/hashmap.h"
#include "utils/utils.h" #include "utils/utils.h"
volatile bool cws_server_run = 1; volatile bool cws_server_run = 1;
int cws_server_start(const char *hostname, const char *service) { int cws_server_start(cws_config *config) {
struct addrinfo hints; struct addrinfo hints;
struct addrinfo *res; struct addrinfo *res;
cws_server_setup_hints(&hints, sizeof hints, hostname); cws_server_setup_hints(&hints, sizeof hints, config->hostname);
int status = getaddrinfo(hostname, service, &hints, &res); int status = getaddrinfo(config->hostname, config->port, &hints, &res);
if (status != 0) { if (status != 0) {
CWS_LOG_ERROR("getaddrinfo() error: %s", gai_strerror(status)); CWS_LOG_ERROR("getaddrinfo() error: %s", gai_strerror(status));
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
@@ -51,7 +50,7 @@ int cws_server_start(const char *hostname, const char *service) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
cws_server_loop(sockfd); cws_server_loop(sockfd, config);
freeaddrinfo(res); freeaddrinfo(res);
close(sockfd); close(sockfd);
@@ -74,7 +73,7 @@ void cws_server_setup_hints(struct addrinfo *hints, size_t len, const char *host
} }
} }
void cws_server_loop(int sockfd) { void cws_server_loop(int sockfd, cws_config *config) {
struct sockaddr_storage their_sa; struct sockaddr_storage their_sa;
socklen_t theirsa_size = sizeof their_sa; socklen_t theirsa_size = sizeof their_sa;
@@ -132,7 +131,7 @@ void cws_server_loop(int sockfd) {
data[bytes_read] = '\0'; data[bytes_read] = '\0';
/* Parse HTTP request */ /* Parse HTTP request */
cws_http *request = cws_http_parse(data, client_fd); cws_http *request = cws_http_parse(data, client_fd, config);
if (request == NULL) { if (request == NULL) {
cws_server_close_client(epfd, client_fd, clients); cws_server_close_client(epfd, client_fd, clients);

View File

@@ -9,10 +9,13 @@ static const cyaml_config_t cyaml_config = {
}; };
static const cyaml_schema_field_t top_mapping_schema[] = { static const cyaml_schema_field_t top_mapping_schema[] = {
CYAML_FIELD_STRING_PTR("host", CYAML_FLAG_POINTER, cws_config, host, 0, CYAML_UNLIMITED), CYAML_FIELD_STRING_PTR("hostname", CYAML_FLAG_POINTER, cws_config, hostname, 0, CYAML_UNLIMITED),
CYAML_FIELD_STRING_PTR("port", CYAML_FLAG_POINTER, cws_config, port, 0, CYAML_UNLIMITED), CYAML_FIELD_STRING_PTR("port", CYAML_FLAG_POINTER, cws_config, port, 0, CYAML_UNLIMITED),
CYAML_FIELD_STRING_PTR("www", CYAML_FLAG_POINTER, cws_config, www, 0, CYAML_UNLIMITED),
CYAML_FIELD_STRING_PTR("cert", CYAML_FLAG_POINTER, cws_config, cert, 0, CYAML_UNLIMITED), CYAML_FIELD_STRING_PTR("cert", CYAML_FLAG_POINTER, cws_config, cert, 0, CYAML_UNLIMITED),
CYAML_FIELD_STRING_PTR("key", CYAML_FLAG_POINTER, cws_config, key, 0, CYAML_UNLIMITED), CYAML_FIELD_END}; CYAML_FIELD_STRING_PTR("key", CYAML_FLAG_POINTER, cws_config, key, 0, CYAML_UNLIMITED),
CYAML_FIELD_END
};
static const cyaml_schema_value_t top_schema = { static const cyaml_schema_value_t top_schema = {
CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, cws_config, top_mapping_schema), CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, cws_config, top_mapping_schema),

View File

@@ -34,10 +34,16 @@ int main(void) {
cws_hashmap *str_hashmap = cws_hm_init(my_hash_fn, my_equal_fn, my_free_fn, my_free_fn); cws_hashmap *str_hashmap = cws_hm_init(my_hash_fn, my_equal_fn, my_free_fn, my_free_fn);
char *key = strdup("test1"); char *key = strdup("test1");
char *value = strdup("value1"); if (key == NULL) {
CWS_LOG_ERROR("strdup() key");
if (key == NULL || value == NULL) { return 1;
CWS_LOG_ERROR("strdup()"); }
char *value = strdup("value1");
if (value == NULL) {
CWS_LOG_ERROR("strdup() value");
free(key);
return 1; return 1;
} }