If file non existant crashing resolved
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -20,5 +20,6 @@ typedef struct {
|
||||
|
||||
HttpRequest *handle_request(char *__req);
|
||||
void print_request(const HttpRequest *__req);
|
||||
void free_request(HttpRequest *__req);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -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,
|
||||
.content_length = strlen(content),
|
||||
.content_type = HTTP_CT_HTML,
|
||||
.body = content};
|
||||
HttpResponse response = {
|
||||
.status_code = HTTP_OK,
|
||||
.content_length = strlen(content),
|
||||
.content_type = HTTP_CT_HTML,
|
||||
.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);
|
||||
|
||||
@@ -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
98
http/http_server.c
Normal 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
35
http/http_server.h
Normal 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
|
||||
Reference in New Issue
Block a user