If file non existant crashing resolved

This commit is contained in:
cdricms
2024-11-15 10:56:07 +01:00
parent 9ccde76edc
commit ce2edb6293
8 changed files with 209 additions and 74 deletions

View File

@@ -40,7 +40,7 @@ void http_request_set(HttpRequest *__req, char *key, char *value) {
else if (!strcmp(key, "Upgrade-Insecure-Requests"))
__req->upgrade_insecure_requests = value;
else if (!strcmp(key, "Accept"))
;
free(value);
// __req->accept = value;
else if (!strcmp(key, "Sec-Fetch-Site"))
__req->sec_fetch_site = value;
@@ -52,9 +52,12 @@ void http_request_set(HttpRequest *__req, char *key, char *value) {
__req->accept_encoding = value;
else if (!strcmp(key, "Connection"))
__req->connection = value;
else
free(value);
}
HttpRequest *handle_request(char *__req) {
printf("%s\n", __req);
HttpRequest *request = malloc(sizeof(HttpRequest));
unsigned int line_count = 0;
char *line_start = __req;
@@ -62,9 +65,7 @@ HttpRequest *handle_request(char *__req) {
while ((line_end = strchr(line_start, '\n')) != NULL) {
line_count++;
size_t l_length = line_end - line_start;
char *line = malloc(sizeof(char) * l_length);
if (line == NULL)
return NULL;
char line[l_length];
strncpy(line, line_start, l_length);
line[l_length - 1] = 0;
@@ -79,20 +80,49 @@ HttpRequest *handle_request(char *__req) {
request->path = path;
} else {
char key[100] = {0};
char *value = malloc(sizeof(char) * 256);
char *colon_pos = strchr(line, ':');
if (colon_pos != NULL) {
size_t k_length = colon_pos - line;
strncpy(key, line, k_length);
size_t v_length = l_length - k_length - 3;
char *value = malloc(sizeof(char) * v_length);
strcpy(value, colon_pos + 2);
http_request_set(request, key, value);
}
}
// TODO: Analyze line
free(line);
line_start = line_end + 1;
}
return request;
}
void free_request(HttpRequest *__req) {
if (__req == NULL)
return;
if (__req->path != NULL)
free(__req->path);
if (__req->host != NULL)
free(__req->host);
if (__req->sec_fetch_dest != NULL)
free(__req->sec_fetch_dest);
if (__req->user_agent != NULL)
free(__req->user_agent);
if (__req->upgrade_insecure_requests != NULL)
free(__req->upgrade_insecure_requests);
if (__req->accept != NULL)
free(__req->accept);
if (__req->sec_fetch_site != NULL)
free(__req->sec_fetch_site);
if (__req->sec_fetch_mode != NULL)
free(__req->sec_fetch_mode);
if (__req->accept_language != NULL)
free(__req->accept_language);
if (__req->accept_encoding != NULL)
free(__req->accept_encoding);
if (__req->connection != NULL)
free(__req->connection);
free(__req);
}

View File

@@ -20,5 +20,6 @@ typedef struct {
HttpRequest *handle_request(char *__req);
void print_request(const HttpRequest *__req);
void free_request(HttpRequest *__req);
#endif

View File

@@ -1,5 +1,5 @@
#include "http_content_type.h"
#include "http_response.h"
#include "http_content_type.h"
#include "http_status.h"
#include <stddef.h>
#include <stdio.h>
@@ -31,15 +31,18 @@ bool construct_response(HttpResponse __res, char *out) {
return true;
}
void http_respond(HttpResponse __res, int clientfd) {
void http_respond(HttpResponse *__res, int clientfd) {
if (__res == NULL)
return;
char response[BUFSIZ];
// TODO: Handle return
construct_response(__res, response);
construct_response(*__res, response);
send(clientfd, response, strlen(response), 0);
}
char *read_file(const char *__path) {
// If the file does not exist
if (access(__path, F_OK) != 0) {
return NULL;
}
@@ -48,10 +51,12 @@ char *read_file(const char *__path) {
if (f == NULL) {
return NULL;
}
// Get the length of the file
fseek(f, 0, SEEK_END);
size_t length = ftell(f);
rewind(f);
// Initialize a value to get the content
char *content = malloc(length * sizeof(char));
if (content == NULL) {
@@ -59,6 +64,7 @@ char *read_file(const char *__path) {
return NULL;
}
// Read the file into content and set the last char to \0
size_t bytesRead = fread(content, sizeof(char), length, f);
content[bytesRead] = 0;
@@ -72,10 +78,13 @@ HttpResponse *from_file(const char *__path) {
if (content == NULL)
return NULL;
HttpResponse response = {.status_code = HTTP_OK,
HttpResponse response = {
.status_code = HTTP_OK,
.content_length = strlen(content),
.content_type = HTTP_CT_HTML,
.body = content};
.body = content,
.body_in_heap = true,
};
HttpResponse *res = malloc(sizeof(response));
*res = response;
@@ -84,7 +93,7 @@ HttpResponse *from_file(const char *__path) {
}
void free_response(HttpResponse *__res) {
if (__res->body != NULL)
if (__res->body != NULL && __res->body_in_heap)
free(__res->body);
free(__res);

View File

@@ -11,12 +11,19 @@ typedef struct {
HttpContentType content_type;
size_t content_length;
char *body;
bool body_in_heap;
} HttpResponse;
// It will create a string respecting the Hypertext Transfer Protocol.
//
// To then be sent to the client.
bool construct_response(HttpResponse __res, char *out);
void http_respond(HttpResponse __res, int clientfd);
// Respond a http response to the client (clientfd);
void http_respond(HttpResponse *__res, int clientfd);
// Read a file from a specified path
char *read_file(const char *__path);
// Given a path will return a HttpResponse
HttpResponse *from_file(const char *__path);
void free_response(HttpResponse *__res);

98
http/http_server.c Normal file
View File

@@ -0,0 +1,98 @@
#include "http_server.h"
#include "http_content_type.h"
#include "http_request.h"
#include "http_response.h"
#include "http_status.h"
#include <asm-generic/socket.h>
#include <malloc.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
HttpServerRunStatus http_server_setup(HttpServer *s) {
int opt = 1;
if ((s->server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return HTTP_SRS_SOCKET_FAILED;
if (setsockopt(s->server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)))
return HTTP_SRS_SETSOCKOPT_FAILED;
if (s->address == NULL) {
printf("Setting server address\n");
s->address = malloc(sizeof(*s->address));
s->address->sin_family = AF_INET;
s->address->sin_addr.s_addr = INADDR_ANY;
s->address->sin_port = htons(s->port);
}
if (bind(s->server_fd, (struct sockaddr *)s->address, sizeof(*s->address)) <
0)
return HTTP_SRS_BIND_FAILED;
if (listen(s->server_fd, s->workers) < 0)
return HTTP_SRS_LISTEN_FAILED;
return HTTP_SRS_SETUP;
}
HttpServerRunStatus http_server_run(HttpServer *s) {
int client_fd;
ssize_t valread;
socklen_t addrlen = sizeof(*s->address);
if ((client_fd =
accept(s->server_fd, (struct sockaddr *)s->address, &addrlen)) < 0)
return HTTP_SRS_ACCEPT_FAILED;
char request[BUFSIZ] = {0};
if ((valread = read(client_fd, request, 1024 - 1)) < 0)
return HTTP_SRS_READ_FAILED;
HttpRequest *req = handle_request(request);
if (req == NULL)
return HTTP_SRS_HANDLE_REQUEST_FAILED;
HttpResponse *res;
if (!strcmp(req->path, "/")) {
res = from_file("./" DEFAULT_HTML);
} else {
char path[] = ".";
strcat(path, req->path);
res = from_file(path);
}
// print_request(req);
// free_request(req);
if (res == NULL) {
HttpResponse __res = {
.status_code = HTTP_NOT_FOUND,
.body = "",
.content_type = HTTP_CT_PLAIN_TEXT,
.content_length = 1,
.body_in_heap = false,
};
res = malloc(sizeof(__res));
*res = __res;
}
http_respond(res, client_fd);
free_response(res);
close(client_fd);
return HTTP_SRS_RUNNING;
}
HttpServerRunStatus http_server_stop(HttpServer *s) {
close(s->server_fd);
if (s->address != NULL)
free(s->address);
return HTTP_SRS_STOPPED;
}

35
http/http_server.h Normal file
View File

@@ -0,0 +1,35 @@
#ifndef HTTP_SERVER_H
#define HTTP_SERVER_H
#include <netinet/in.h>
#include <sys/socket.h>
#ifndef DEFAULT_HTML
#define DEFAULT_HTML "index.html"
#endif
typedef enum {
HTTP_SRS_RUNNING = 0,
HTTP_SRS_SETUP,
HTTP_SRS_STOPPED,
HTTP_SRS_SOCKET_FAILED,
HTTP_SRS_SETSOCKOPT_FAILED,
HTTP_SRS_BIND_FAILED,
HTTP_SRS_LISTEN_FAILED,
HTTP_SRS_ACCEPT_FAILED,
HTTP_SRS_READ_FAILED,
HTTP_SRS_HANDLE_REQUEST_FAILED,
} HttpServerRunStatus;
typedef struct {
int port;
int server_fd;
unsigned int workers;
struct sockaddr_in *address;
} HttpServer;
HttpServerRunStatus http_server_setup(HttpServer *s);
HttpServerRunStatus http_server_run(HttpServer *s);
HttpServerRunStatus http_server_stop(HttpServer *s);
#endif

68
main.c
View File

@@ -1,73 +1,23 @@
#include "http/http_request.h"
#include "http/http_response.h"
#include "http/http_server.h"
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#define DEFAULT_HTML "index.html"
int main() {
HttpServer server = {.port = 8080, .workers = 3};
if (http_server_setup(&server) != HTTP_SRS_SETUP)
exit(1);
const int PORT = 8080;
HttpServerRunStatus status;
int serverfd, clientfd;
ssize_t valread;
while ((status = http_server_run(&server)) == HTTP_SRS_RUNNING)
;
struct sockaddr_in address;
int opt = 1;
socklen_t addrlen = sizeof(address);
char request[BUFSIZ] = {0};
printf("Status: %d\n", status);
if ((serverfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(serverfd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(serverfd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
if ((clientfd = accept(serverfd, (struct sockaddr *)&address, &addrlen)) <
0) {
perror("accept");
exit(EXIT_FAILURE);
}
valread = read(clientfd, request,
1024 - 1); // subtract 1 for the null
// terminator at the end
HttpRequest *req = handle_request(request);
HttpResponse *res;
if (!strcmp(req->path, "/")) {
res = from_file("./" DEFAULT_HTML);
} else {
char path[] = ".";
strcat(path, req->path);
res = from_file(path);
}
free(req);
http_respond(*res, clientfd);
free_response(res);
// closing the connected socket
close(clientfd);
// closing the listening socket
close(clientfd);
http_server_stop(&server);
return 0;
}

View File

@@ -6,6 +6,11 @@ kind "StaticLib"
language "C"
targetdir "bin/%{cfg.buildcfg}"
filter "configurations:Debug"
symbols "On"
buildoptions { "-g3", "-O0", "-fno-inline" } -- Ensure debug symbols are generated for static library
optimize "Off"
files {
"http/*.c",
"http/*.h"