diff --git a/README.md b/README.md index fea9762..cd5fffd 100644 --- a/README.md +++ b/README.md @@ -32,19 +32,19 @@ And then open the `docs/html/index.html`. ## Roadmap -- Implement Keep-Alive - HTTPS support with TLS +- Support for virtual hosts +- CLI args ## Future -- Support for virtual hosts - Custom web pages (404) -- CLI args - IPv6 compatible - Multithreading to handle concurrent requests - Logging - Compression (Gzip) - Reverse proxy +- PHP-FPM ## Performance diff --git a/config.yaml b/config.yaml index f479853..27ff704 100644 --- a/config.yaml +++ b/config.yaml @@ -1,6 +1,13 @@ -# Default config file of CWS hostname: localhost port: 3030 -www: "www" # Directory used to retrieve html files -cert: "cert.pem" -key: "key.pem" + +virtual_hosts: + - domain: localhost + root: www + ssl: false + + - domain: test.local + root: www + ssl: true + cert: cert.pem + key: key.pem diff --git a/include/utils/config.h b/include/utils/config.h index 28a1fe5..d6d0d7b 100644 --- a/include/utils/config.h +++ b/include/utils/config.h @@ -1,13 +1,24 @@ #ifndef CWS_CONFIG_H #define CWS_CONFIG_H -typedef struct cws_config_t { - char *hostname; - char *port; - char *www; +#include + +struct cws_virtual_host_t { + char *domain; + char *root; + bool ssl; char *cert; char *key; -} cws_config; +}; +typedef struct cws_virtual_host_t cws_virtual_host; + +struct cws_config_t { + char *hostname; + char *port; + cws_virtual_host *virtual_hosts; + unsigned virtual_hosts_count; +}; +typedef struct cws_config_t cws_config; cws_config *cws_config_init(void); void cws_config_free(cws_config *config); diff --git a/src/http/http.c b/src/http/http.c index b6b2d35..2665ab6 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -48,6 +48,9 @@ cws_http *cws_http_parse(mcl_string *request_str, int sockfd, cws_config *config } request->sockfd = sockfd; + /* Prepare the virtual_host struct */ + cws_virtual_host vhost; + char *request_str_cpy = strdup(mcl_string_cstr(request_str)); if (!request_str_cpy) { free(request); @@ -89,7 +92,7 @@ cws_http *cws_http_parse(mcl_string *request_str, int sockfd, cws_config *config } // CWS_LOG_DEBUG("location: %s", pch); mcl_string_append(request->location, pch); - mcl_string_append(request->location_path, config->www); + // TODO: mcl_string_append(request->location_path, config->www); /* Adjust location path */ if (strcmp(mcl_string_cstr(request->location), "/") == 0) { diff --git a/src/main.c b/src/main.c index b1f38cc..08c46fa 100644 --- a/src/main.c +++ b/src/main.c @@ -19,11 +19,16 @@ int main(void) { } cws_config *config = cws_config_init(); - if (!config) { + if (config == NULL) { CWS_LOG_ERROR("Unable to read config file"); return EXIT_FAILURE; } + CWS_LOG_INFO("Virtual hosts count: %d", config->virtual_hosts_count); + for (size_t i = 0; i < config->virtual_hosts_count; ++i) { + CWS_LOG_DEBUG("%s (ssl: %d)", config->virtual_hosts[i].domain, config->virtual_hosts[i].ssl); + } + CWS_LOG_INFO("Running cws on http://%s:%s...", config->hostname, config->port); int ret = cws_server_start(config); if (ret < 0) { diff --git a/src/utils/config.c b/src/utils/config.c index 26d5bfd..0a08c8e 100644 --- a/src/utils/config.c +++ b/src/utils/config.c @@ -1,6 +1,9 @@ #include "utils/config.h" #include +#include + +#include "utils/colors.h" static const cyaml_config_t cyaml_config = { .log_fn = cyaml_log, @@ -8,15 +11,28 @@ static const cyaml_config_t cyaml_config = { .log_level = CYAML_LOG_WARNING, }; -static const cyaml_schema_field_t top_mapping_schema[] = {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("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("key", CYAML_FLAG_POINTER, cws_config, key, 0, CYAML_UNLIMITED), - CYAML_FIELD_END}; +static const cyaml_schema_field_t virtual_hosts_fields[] = { + CYAML_FIELD_STRING_PTR("domain", CYAML_FLAG_POINTER, struct cws_virtual_host_t, domain, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR("root", CYAML_FLAG_POINTER, struct cws_virtual_host_t, root, 0, CYAML_UNLIMITED), + CYAML_FIELD_BOOL("ssl", CYAML_FLAG_DEFAULT, struct cws_virtual_host_t, ssl), + CYAML_FIELD_STRING_PTR("cert", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, struct cws_virtual_host_t, cert, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR("key", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL, struct cws_virtual_host_t, key, 0, CYAML_UNLIMITED), + CYAML_FIELD_END, +}; -static const cyaml_schema_value_t top_schema = { - CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, cws_config, top_mapping_schema), +static cyaml_schema_value_t virtual_hosts_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_DEFAULT, struct cws_virtual_host_t, virtual_hosts_fields), +}; + +static const cyaml_schema_field_t top_schema_fields[] = { + CYAML_FIELD_STRING_PTR("hostname", CYAML_FLAG_POINTER, struct cws_config_t, hostname, 0, CYAML_UNLIMITED), + CYAML_FIELD_STRING_PTR("port", CYAML_FLAG_POINTER, struct cws_config_t, port, 0, CYAML_UNLIMITED), + CYAML_FIELD_SEQUENCE("virtual_hosts", CYAML_FLAG_POINTER, struct cws_config_t, virtual_hosts, &virtual_hosts_schema, 0, CYAML_UNLIMITED), + CYAML_FIELD_END, +}; + +static cyaml_schema_value_t top_schema = { + CYAML_VALUE_MAPPING(CYAML_FLAG_POINTER, struct cws_config_t, top_schema_fields), }; cws_config *cws_config_init(void) { @@ -25,6 +41,8 @@ cws_config *cws_config_init(void) { cyaml_err_t err = cyaml_load_file(path, &cyaml_config, &top_schema, (cyaml_data_t **)&config, NULL); if (err != CYAML_OK) { + CWS_LOG_ERROR("%s", cyaml_strerror(err)); + return NULL; } @@ -34,10 +52,6 @@ cws_config *cws_config_init(void) { void cws_config_free(cws_config *config) { cyaml_err_t err = cyaml_free(&cyaml_config, &top_schema, config, 0); if (err != CYAML_OK) { - /* Handle */ + /* TODO: Handle */ } } - -/* - https://github.com/tlsa/libcyaml/blob/main/docs/guide.md -*/