Skip to content

Commit

Permalink
Adding multi threaded (fork based) request treatment and more refacto…
Browse files Browse the repository at this point in the history
…ring of the code.
  • Loading branch information
Altaks committed Feb 4, 2024
1 parent 9e0b626 commit 298eee5
Show file tree
Hide file tree
Showing 7 changed files with 91 additions and 84 deletions.
147 changes: 77 additions & 70 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ char * rootDirectory = NULL;
server.sin_addr.s_addr = INADDR_ANY;

// Bind the server address to the socket
int bind_rtrn = bind(sock, (const struct sockaddr *) &server, sizeof(server));
int bind_returned_value = bind(sock, (const struct sockaddr *) &server, sizeof(server));

// Check if the binding was successful
if(bind_rtrn < 0){
if(bind_returned_value < 0){
server_log(FATAL, "Could not bind server address [port:%i] to socket %i due to error : %s", port, sock, strerror(errno));
exit(EXIT_FAILURE);
} else {
Expand All @@ -83,10 +83,10 @@ char * rootDirectory = NULL;
}

// Make the socket listen to incoming connections with a maximum of TCP_STACK connections in the stack
int listen_rtrn = listen(sock, TCP_STACK);
int listen_returned_value = listen(sock, TCP_STACK);

// Check if the socket is now in listen mode
if(listen_rtrn != 0){
if(listen_returned_value != 0){
server_log(FATAL, "Could not make the socket listen due to error : %s", strerror(errno));
exit(EXIT_FAILURE);
} else {
Expand All @@ -103,88 +103,95 @@ char * rootDirectory = NULL;
// Accept the connection from the client socket
dialog_socket = accept(sock, (struct sockaddr *) &client, &len);

// Check if the connection was successful
if(dialog_socket < 0){
server_log(ERROR, "An error occurred while accepting the connection : %s", strerror(errno));
exit(EXIT_FAILURE);
}
// Placing the connection treatment in a child process of the main server process to avoid blocking the server during the treatment
if(fork() == 0){

// Convert the client address to a human-readable string for logging purposes
char* client_addr = addressToString(client);
// Check if the connection was successful
if(dialog_socket < 0){
server_log(ERROR, "An error occurred while accepting the connection : %s", strerror(errno));
exit(EXIT_FAILURE);
}

// Prepare request reading buffer for 1024 bytes chunks reading
ushort buff_len = 1024;
char buff_read[buff_len];
// Convert the client address to a human-readable string for logging purposes
char* client_addr = addressToString(client);

// Allocate memory for the request
char * request = NULL;
// Prepare request reading buffer for 1024 bytes chunks reading
ushort buff_len = 1024;
char buff_read[buff_len];

// Read the request from the client
ssize_t bytes_received = 0;
while(request == NULL || bytes_received > 0) {
// Allocate memory for the request
char * request = NULL;

// Read bytes from the connection
bytes_received = recv(dialog_socket, buff_read, buff_len, 0);
// Read the request from the client
ssize_t bytes_received = 0;
while(request == NULL || bytes_received > 0) {

// Check if an error occurred while reading bytes
if(bytes_received < 0) {
server_log(ERROR, "An error occurred while reading bytes from connection : %s", strerror(errno));
exit(EXIT_FAILURE);
} else if(bytes_received > 0){
// Read bytes from the connection
bytes_received = recv(dialog_socket, buff_read, buff_len, 0);

// Allocate memory for the request if it's the first chunk, else expand the allocated memory chunk
if(request == NULL) {
// Check if an error occurred while reading bytes
if(bytes_received < 0) {
server_log(ERROR, "An error occurred while reading bytes from connection : %s", strerror(errno));
exit(EXIT_FAILURE);
} else if(bytes_received > 0){

// Allocate memory for the request and copy the first chunk of bytes
request = calloc(bytes_received + 1, sizeof(char));
strncpy(request, buff_read, bytes_received);
} else {
// Allocate memory for the request if it's the first chunk, else expand the allocated memory chunk
if(request == NULL) {

// Expand the allocated memory chunk and concatenate the next chunk of bytes
request = reallocarray(request, strlen(request) + strlen(buff_read) + 1, sizeof(char));
if(request == NULL){
printf("Reallocation of buffer at address %p as failed during expanding resources expansion", request);
continue;
// Allocate memory for the request and copy the first chunk of bytes
request = calloc(bytes_received + 1, sizeof(char));
strncpy(request, buff_read, bytes_received);
} else {

// Expand the allocated memory chunk and concatenate the next chunk of bytes
request = reallocarray(request, strlen(request) + strlen(buff_read) + 1, sizeof(char));
if(request == NULL){
printf("Reallocation of buffer at address %p as failed during expanding resources expansion", request);
continue;
}
strcat(request, buff_read);
}
strcat(request, buff_read);
}

// Check if the request has been fully read.
if(strstr(request, "\r\n\r\n") || strstr(request, "\n\n")){
break;
// Check if the request has been fully read.
if(strstr(request, "\r\n\r\n") || strstr(request, "\n\n")){
break;
}
}
}
}

// Build the response for the response algorithm
HTTPResponse httpResponse = buildResponse(rootDirectory, request);

// Convert the response to a HTTP valid string
char * responseStr = responseToStr(httpResponse);

// Send the response to the client if the response is valid
if(responseStr != NULL){
send(dialog_socket, responseStr, strlen(responseStr), 0);
} else {
// TODO : NYI
server_log(ERROR, "Response is NULL ???");
}
// Build the response for the response algorithm
HTTPResponse httpResponse = buildResponse(rootDirectory, request);

// Close the connection with the client
close(dialog_socket);
// Convert the response to an HTTP valid string
char * responseStr = responseToStr(httpResponse);

// Freeing http response manual memory allocations
if(httpResponse.date != NULL) free(httpResponse.date);
if(httpResponse.expires != NULL) free(httpResponse.expires);
if(httpResponse.lastModified != NULL) free(httpResponse.lastModified);
if(httpResponse.body != NULL) free(httpResponse.body);

// Freeing response related strings manual memory allocations
if(client_addr != NULL) free(client_addr);
if(request != NULL) free(request);
if(responseStr != NULL) free(responseStr);
// Send the response to the client if the response is valid
if(responseStr != NULL){
send(dialog_socket, responseStr, strlen(responseStr), 0);
} else {
// TODO : NYI
server_log(ERROR, "Response is NULL ???");
}

// Log the connection closure
server_log(INFO, "Server connection with client on socket %i has been closed and resources have been freed", sock);
// Close the connection with the client
close(dialog_socket);

// Freeing http response manual memory allocations
if(httpResponse.date != NULL) free(httpResponse.date);
if(httpResponse.expires != NULL) free(httpResponse.expires);
if(httpResponse.lastModified != NULL) free(httpResponse.lastModified);
if(httpResponse.body != NULL) free(httpResponse.body);

// Freeing response related strings manual memory allocations
if(client_addr != NULL) free(client_addr);
if(request != NULL) free(request);
if(responseStr != NULL) free(responseStr);

// Log the connection closure
server_log(INFO, "Server connection with client on socket %i has been closed and resources have been freed", sock);
server_log(INFO, "Child process [ppid: %lu, pid: %lu] has finished its treatment and is now exiting", (ulong) getppid(), (ulong) getpid());
// Exit the child process when the connection is closed
exit(EXIT_SUCCESS);
}
}
}
6 changes: 3 additions & 3 deletions network/dialog/requests.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ struct HTTPCommand {
*/
typedef struct HTTPHeader HTTPHeader;
struct HTTPHeader {
char * key;
char * value;
__attribute__((unused)) char * key;
__attribute__((unused)) char * value;
};

/**
Expand All @@ -59,7 +59,7 @@ struct HTTPRequest {
HTTPCommand command;

HTTPHeader * headers;
int headers_count;
__attribute__((unused)) int headers_count;

char * body;
};
Expand Down
10 changes: 5 additions & 5 deletions util/date.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ char* getOffsetDate(int offset){
char * buffer = calloc(30, sizeof(char));

// Get the current date and time
time_t rawtime = time(NULL) + offset;
time_t raw_time = time(NULL) + offset;

// Convert the date and time to a human-readable string
struct tm * timeinfo;
timeinfo = localtime (&rawtime);
struct tm * time_info;
time_info = localtime (&raw_time);

// Format the date and time as GMT
timegm(timeinfo);
timegm(time_info);

// Write the date and time to the buffer
strftime (buffer,30,"%a, %d %b %Y %H:%M:%S %Z",timeinfo);
strftime (buffer, 30, "%a, %d %b %Y %H:%M:%S %Z", time_info);
return buffer;
}
4 changes: 2 additions & 2 deletions util/date/hashmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ int map_get(struct hashmap* map, char* key) {
return map_ind->val;
}

__attribute__((unused)) int map_rem(struct hashmap* map, char* key) {
__attribute__((unused)) void map_rem(struct hashmap* map, char* key) {
struct map_item* map_ind = &map->data[djb2(map, key)];
struct map_item* prev_map_ind;
bool isBase = true;
Expand Down Expand Up @@ -76,7 +76,7 @@ __attribute__((unused)) int map_rem(struct hashmap* map, char* key) {

}

int djb2(struct hashmap* map, char* key) {
int djb2(struct hashmap* map, const char* key) {
int hash = 5381;
int i = 0;
while(key[i] != '\0') {
Expand Down
4 changes: 2 additions & 2 deletions util/date/hashmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ int map_get(struct hashmap* map, char* key);
* @param key the key to remove
* @return the value corresponding to the key
*/
__attribute__((unused)) int map_rem(struct hashmap* map, char* key);
__attribute__((unused)) void map_rem(struct hashmap* map, char* key);

/**
* Hash function for the hashmap
* @param map the hashmap to hash the key for
* @param key the key to hash
* @return the hash of the key
*/
int djb2(struct hashmap* map, char* key);
int djb2(struct hashmap* map, const char* key);

#endif
2 changes: 1 addition & 1 deletion util/math.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "math.h"

int log10(int value){
__attribute__((unused)) int log10(int value){
int result = 0;
while(value > 0){
value /= 10;
Expand Down
2 changes: 1 addition & 1 deletion util/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
* @param value the value to get the log10 of
* @return the log10 of the value
*/
int log10(int value);
__attribute__((unused)) int log10(int value);

#endif

0 comments on commit 298eee5

Please sign in to comment.