Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
KDesp73 committed Jul 11, 2024
2 parents d824e17 + e328acf commit 689f225
Show file tree
Hide file tree
Showing 7 changed files with 360 additions and 67 deletions.
205 changes: 199 additions & 6 deletions include/extern/httpd.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

/**
* @file httpd.h
* @version v0.0.1
* @version v0.0.3
* @author KDesp73 (Konstantinos Despoinidis)
*/

Expand Down Expand Up @@ -54,7 +54,10 @@
#define FAILURE 1
#define MAX_REQUEST_SIZE 1024
#define MAX_PATH_LENGTH 256
#define PID_PATH clib_format_text("%s/.local/state/webc-daemon.pid", getenv("HOME")) // For daemon
#define CHUNK_SIZE 1024

// For daemon (needs freeing)
#define PID_PATH clib_format_text("%s/.local/state/webc-daemon.pid", getenv("HOME"))

typedef char string[256] ;

Expand All @@ -72,7 +75,9 @@ typedef struct {

typedef struct {
response_header_t header;
char* content;
char** chunks;
size_t* chunk_sizes;
size_t chunks_count;
} response_t;

typedef struct {
Expand Down Expand Up @@ -109,28 +114,216 @@ typedef enum {
DAEMON_RESTART
} DaemonAction;

/**
* Translates url to local path starting from root
*
* /contact -> <root>/contact/index.html
*
* @param url The url taken from the http request
* @param root The path that is considered the root of the website
* @return char* The final path
*/
HTTPDAPI char* url_to_path(const char* url, const char* root);

/**
* Takes a file path and returns its MIME type
*
* @param path The file path
* @return const char* The MIME type
*/
HTTPDAPI const char* content_type(const char* path);
HTTPDAPI const char* current_date();

/**
* Returns the current date in the HTTP format
*
* @return const char* The current date
*/
HTTPDAPI const char* current_date(void);

/**
* Formats the response struct so that it is ready to be sent to the browser
*
* @param response The response struct
* @return const char* The response as a string
*/
HTTPDAPI const char* response_str(response_t response);

/**
* Returns the status message for each HTTP status code
*
* @param status_code The status code [101,511]
* @return const char* The status message
*/
HTTPDAPI const char* status_message(size_t status_code);


/**
* Checks if the server_t struct is ready to use
*
* 1. The root must be set
*
* 2. The request_func function pointer must be set
*
* TODO: more checks
*
* @param server The server struct
* @return int True when everything is OK
*/
HTTPDAPI int check_server(server_t server);

/**
* Checks if the path is a file
*
* @param path The path to check
* @return int True if path is a file
*/
HTTPDAPI int has_file_extension(const char *path);

/**
* Checks if url implies that index.html is being requested
*
* Example: /contact -> True
*
* /contact/index.html -> False
*
* @param url The url taken from the HTTP request
* @return int True if it is needed
*/
HTTPDAPI int is_index_html_needed(const char *url);

/**
* Runs the server as a daemon
*
* @param action The DaemonAction enum (DAEMON_START, DAEMON_STOP, DAEMON_RESTART)
* @param server The server struct
* @return int Status code
*/
HTTPDAPI int run_daemon(DaemonAction action, server_t server);

/**
* Runs the server
*
* @param server The server struct
* @return int Status code
*/
HTTPDAPI int run_server(server_t server);

/**
* Parses the HTTP request received into a request_t struct for easier usage
*
* @param request_str The HTTP request
* @return request_t The parsed request_t struct
*/
HTTPDAPI request_t parse_request(Cstr request_str);

/**
* Makes a response_header_t struct from the content itself
*
* @param content The content to send
* @param type The MIME type of the content
* @param code The HTTP status code
* @return response_header_t The header struct
*/
HTTPDAPI response_header_t header_content(Cstr content, Cstr type, size_t code);

/**
* Makes a response_header_t struct from the file path
*
* @param path The file path
* @param code The HTTP status code
* @return response_header_t The header struct
*/
HTTPDAPI response_header_t header_path(Cstr path, size_t code);

/**
* Determines the appropriate response to the HTTP request
*
* @param request The request_t struct
* @param root The website root path
* @return response_t* The response_t struct pointer containing the HTTP response
*/
HTTPDAPI response_t* response(request_t request, const char* root);

/**
* Initializes a server_t struct (should be used)
*
* @param ip The ip to serve to (127.0.0.1 when NULL)
* @param port The port to serve to
* @param root The site's root
* @return server_t The initialized server struct
*/
HTTPDAPI server_t server_init(const char* ip, int port, const char* root);

/**
* Frees the memory allocated for a response struct
*
* @param response The response_t struct pointer
*/
HTTPDAPI void clean_response(response_t* response);
HTTPDAPI void daemonize(void);

/**
* Forks to a new process and closes all standard descriptors
*/
HTTPDAPI void daemonize(void); // 😈

/**
* Returns a response_t struct pointer containing a templated Error Page
*
* @param code The HTTP status code
* @return response_t* The response struct pointer
*/
HTTPDAPI response_t* error_response(size_t code);

/**
* Sends the response_t struct pointer to the client_socket
*
* @param response The response_t struct pointer
* @param client_socket The client's socket
*/
HTTPDAPI void send_response(response_t* response, int client_socket);

/**
* Formats the response_header_t struct according to the HTTP protocol
*
* @param header The response_header_t struct
* @return char* The header as a string
*/
HTTPDAPI char* header_str(response_header_t header);

/**
* Reads the content of the file into 1KB chunks
*
* @param response The response_t struct pointer to put the chunks
* @param path The file to read
*/
HTTPDAPI void read_content(response_t* response, const char* path);

/**
* Allocates memory for the chunk and chunk_sizes arrays and 0-inits their items
*
* @param response The response_t struct pointer
* @param count The number of chunks to allocate for
*/
HTTPDAPI void make_chunks(response_t* response, size_t count);

/**
* Logs the request_t struct to stderr
*
* @param req The request_t struct to log
*/
HTTPDAPI void log_reguest(request_t req);

/**
* Logs the response_t struct to stderr
*
* @param res The response_t struct to log
*/
HTTPDAPI void log_response(response_t res);


#ifdef HTTPD_IMPLEMENTATION

// TODO: make HTTPDAPI static / Make library header-only
// TODO: make HTTPDAPI static / Make library header-only

#endif // HTTPD_IMPLEMENTATION

Expand Down
10 changes: 3 additions & 7 deletions src/core/utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,10 @@ int is_url(const char *str)
}

int is_markdown_file(const char *path) {
const char *markdownExtension = ".md";
const char *fileExtension = strrchr(path, '.');
const char* markdown_extension = ".md";
const char* file_extension = strrchr(path, '.');

if (fileExtension != NULL && strcmp(fileExtension, markdownExtension) == 0) {
return 1; // It is a Markdown file
}

return 0; // It is not a Markdown file
return (file_extension != NULL && strcmp(file_extension, markdown_extension) == 0);
}

WEBCAPI void WEBC_IntegrateFile(char** buffer, Cstr path)
Expand Down
24 changes: 16 additions & 8 deletions src/server/daemon.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "extern/httpd.h"
#include "webc-actions.h"
#include "webc-server.h"
#include <ctype.h>
#include <signal.h>
Expand All @@ -7,7 +8,7 @@
#include <sys/stat.h>

void start(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree);
void stop(void);
void stop(Tree tree);
void restart(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree);

int valid_pid(char* pid)
Expand Down Expand Up @@ -36,7 +37,8 @@ void strip_whitespace(char *str)
}

void start(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree) {
if (clib_file_exists(PID_PATH)) {
char* path = PID_PATH;
if (clib_file_exists(path)) {
char* old_pid = clib_read_file(PID_PATH, "r");
if (old_pid != NULL) {
strip_whitespace(old_pid);
Expand All @@ -55,7 +57,7 @@ void start(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree) {

// Write the PID file
pid_t pid = getpid();
FILE *pid_file = fopen(PID_PATH, "w");
FILE *pid_file = fopen(path, "w");
if (pid_file == NULL) {
perror("fopen failed");
exit(EXIT_FAILURE);
Expand All @@ -70,12 +72,16 @@ void start(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree) {
serve.serve_root(ip, port, root);
}

free(path);

_exit(EXIT_SUCCESS);
}


void stop(){
char* pid_str = clib_read_file(PID_PATH, "r");
void stop(Tree tree)
{
char* path = PID_PATH;
char* pid_str = clib_read_file(path, "r");
if(pid_str != NULL) strip_whitespace(pid_str);
if(!valid_pid(pid_str)){
ERRO("Httpd server daemon is not active");
Expand All @@ -85,15 +91,17 @@ void stop(){
INFO("Stopping daemon...");
kill(atoi(pid_str), SIGTERM);

char* command = clib_format_text("rm %s", PID_PATH);
char* command = clib_format_text("rm %s", path);
clib_execute_command(command);
WEBC_CleanTree(tree);

free(command);
free(path);
free(pid_str);
}

void restart(WEBCServe serve, Cstr ip, int port, Cstr root, Tree tree){
stop();
stop(tree);
start(serve, ip, port, root, tree);
}

Expand All @@ -104,7 +112,7 @@ WEBCAPI void WEBC_Daemon(DaemonAction action, WEBCServe serve, Cstr ip, int port
start(serve, ip, port, root, tree);
break;
case DAEMON_STOP:
stop();
stop(tree);
break;
case DAEMON_RESTART:
restart(serve, ip, port, root, tree);
Expand Down
Loading

0 comments on commit 689f225

Please sign in to comment.