From d5d4dc64554b0a99d0f5773c454f75c10facdf7c Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 10 Feb 2023 17:39:04 +0100 Subject: [PATCH] backend: refactored tcp --- backend/Makefile | 15 +++++-- backend/linux.c | 90 +++++++++++++++++++++++++++++++++++-- backend/main.c | 111 +++++++++++++--------------------------------- backend/native.h | 16 ------- backend/tcp.h | 32 +++++++++++++ backend/windows.c | 28 +++++++----- 6 files changed, 179 insertions(+), 113 deletions(-) delete mode 100644 backend/native.h create mode 100644 backend/tcp.h diff --git a/backend/Makefile b/backend/Makefile index c257a52..cb672de 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,15 +1,22 @@ -CFLAGS = -std=c17 -Wall -Wextra -Wpedantic -Wconversion +CFLAGS = \ + -std=c17 \ + -Wall \ + -Wextra \ + -Wpedantic \ + -Wconversion \ + +CC = gcc HEADERS = $(wildcard *.h) all: compile_flags.txt server -server: main.o linux.o http.o - gcc $^ -o $@ +server: main.o http.o linux.o + $(CC) $^ -o $@ %.o: %.c $(HEADERS) - gcc $< -c -o $@ $(CFLAGS) + $(CC) $< -c -o $@ $(CFLAGS) clean: rm -rf *.o server client diff --git a/backend/linux.c b/backend/linux.c index 13d5c03..368e82b 100644 --- a/backend/linux.c +++ b/backend/linux.c @@ -1,11 +1,93 @@ -#include "native.h" +#include "tcp.h" +#include +#include +#include +#include +#include +#include +#include +#include -void init_sockets(void) +struct TcpServer { + int server_socket; + struct sockaddr_in server_address; +}; + +struct TcpConnection { + int client_socket; + struct sockaddr_in client_address; +}; + +void tcp_global_initialize_sockets(void) { } + +TcpServer* tcp_server_create(const char* ip, uint16_t port) { + int server_socket = socket(AF_INET, SOCK_STREAM, 0); + if (server_socket < 0) { + printf("error: tcp: could not open socket\n"); + return NULL; + } + if (setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &(int) { 1 }, sizeof(int)) < 0) { + printf("warning: tcp: could not setsockopt SO_REUSEADDR\n"); + } + struct sockaddr_in server_address; + server_address.sin_addr.s_addr = inet_addr(ip); + server_address.sin_family = AF_INET; + server_address.sin_port = htons(port); + if (bind(server_socket, (struct sockaddr*)&server_address, sizeof(server_address)) < 0) { + printf("error: tcp: could not bind socket\n"); + return NULL; + } + if (listen(server_socket, SOMAXCONN) < 0) { + printf("error: tcp: could not listen on server\n"); + return NULL; + } + + TcpServer* self = malloc(sizeof(TcpServer)); + *self = (TcpServer) { + .server_socket = server_socket, + .server_address = server_address, + }; + return self; } -void close_socket(int socket) +void tcp_server_destroy(TcpServer* server) { - close(socket); + close(server->server_socket); + free(server); } +TcpConnection* tcp_server_accept(TcpServer* server) +{ + struct sockaddr_in client_address; + socklen_t client_size; + int client_socket + = accept(server->server_socket, (struct sockaddr*)&client_address, &client_size); + if (client_socket < 0) { + printf("error: tcp: could not accept connection\n"); + return NULL; + } + + TcpConnection* connection = malloc(sizeof(TcpConnection)); + *connection = (TcpConnection) { + .client_socket = client_socket, + .client_address = client_address, + }; + return connection; +} + +void tcp_connection_destroy(TcpConnection* connection) +{ + close(connection->client_socket); + free(connection); +} + +ssize_t tcp_recieve(TcpConnection* connection, uint8_t* data, size_t amount) +{ + return recv(connection->client_socket, data, amount, 0); +} + +ssize_t tcp_send(TcpConnection* connection, uint8_t* data, size_t amount) +{ + return send(connection->client_socket, data, amount, 0); +} diff --git a/backend/main.c b/backend/main.c index c1108af..1512714 100644 --- a/backend/main.c +++ b/backend/main.c @@ -1,5 +1,5 @@ #include "http.h" -#include "native.h" +#include "tcp.h" #include #include #include @@ -7,81 +7,53 @@ #include #include -const uint16_t port = 8201; +const uint16_t port = 8000; -int server_socket = 0; +TcpServer* server = NULL; -void int_handler(int a) +void interrupt_handler(int a) { (void)a; - printf("=== terminated ===\n"); - if (server_socket != 0) - close(server_socket); + printf("\nShutting down gracefully...\n"); + if (server != NULL) + tcp_server_destroy(server); exit(1); } int main(void) { - init_sockets(); + tcp_global_initialize_sockets(); - signal(SIGINT, &int_handler); + signal(SIGINT, &interrupt_handler); printf("starting server...\n"); - server_socket = socket(AF_INET, SOCK_STREAM, 0); - if (server_socket < 0) { - printf("error: could not open socket\n"); + server = tcp_server_create("127.0.0.1", port); + if (server == NULL) return 1; - } - struct sockaddr_in server; - server.sin_addr.s_addr = inet_addr("127.0.0.1"); - server.sin_family = AF_INET; - server.sin_port = htons(port); - if (bind(server_socket, (struct sockaddr*)&server, sizeof(server)) > 0) { - printf("error: could not bind socket\n"); - return 1; - } - if (listen(server_socket, SOMAXCONN) < 0) { - printf("error: could not listen on server"); - return 1; - } printf("listening on port %d\n", port); while (true) { - struct sockaddr_in client; - socklen_t client_size; printf("waiting for client...\n"); - int client_socket = accept(server_socket, (struct sockaddr*)&client, &client_size); - if (client_socket < 0) { - printf("error: could not accept connection\n"); + TcpConnection* client_connection = tcp_server_accept(server); + if (client_connection == NULL) { + printf("error: could not accept client\n"); continue; } printf("client connected\n"); while (true) { uint8_t buffer[8192] = { 0 }; - ssize_t read_size = recv(client_socket, buffer, 8192, 0); - if (read_size < 0) { + ssize_t recieved = tcp_recieve(client_connection, buffer, 8192); + if (recieved < 0) { printf("error: could not recieve\n"); - close_socket(client_socket); break; - } else if (read_size == 0) { + } else if (recieved == 0) { printf("client disconnected\n"); - close_socket(client_socket); break; } - printf("=== recieved start ===\n%s\n=== recieved end ===\n", buffer); - HttpRequestHeader header = parse_http_request_header((char*)buffer, strlen((char*)buffer)); - printf("method: %d\n", header.method); - printf("path_index: %ld\n", header.path_index); - printf("path_length: %ld\n", header.path_length); - printf("content_length: %ld\n", header.content_length); - printf("body_index: %ld\n", header.body_index); - char* path = calloc(header.path_length + 1, sizeof(char)); strncpy(path, (char*)&buffer[header.path_index], header.path_length); - printf("path: %s\n", path); - if (strncmp(path, "/api", 4) == 0) { // something something api } else { @@ -92,37 +64,35 @@ int main(void) "\r\n" "Bad " "request

Fuck you!

\r\n"; - ssize_t written = send(client_socket, send_buffer, sizeof(send_buffer), 0); + ssize_t written = tcp_send(client_connection, send_buffer, sizeof(send_buffer)); if (written < 0) { printf("error: could not write\n"); - close_socket(client_socket); break; } } else if (header.path_length == 0 || strncmp(path, "/", header.path_length) == 0) { FILE* file = fopen("../frontend/index.html", "r"); if (file == NULL) { printf("error: could not open file\n"); - close_socket(client_socket); break; } uint8_t send_buffer[] = "HTTP/1.1 200 OK\r\n" "Content-Type: text/html\r\n" "\r\n"; - ssize_t written = send(client_socket, send_buffer, sizeof(send_buffer), 0); + ssize_t written = tcp_send(client_connection, send_buffer, sizeof(send_buffer)); if (written < 0) { printf("error: could not write\n"); - close_socket(client_socket); break; } char char_read; while ((char_read = (char)fgetc(file)) != EOF) { - write(client_socket, &char_read, sizeof(char)); + tcp_send(client_connection, (uint8_t*)&char_read, sizeof(char)); } } else { char rootpath[] = "../frontend"; size_t filepath_size = sizeof(rootpath) + header.path_length + 1; char* filepath = calloc(filepath_size, sizeof(char)); snprintf(filepath, filepath_size, "%s%s", rootpath, path); + char* dot = strrchr(path, '.'); char mime_type[20] = { 0 }; char file_flag[3] = { 'r', 0 }; @@ -132,6 +102,8 @@ int main(void) snprintf(mime_type, 20, "text/css"); } else if (dot != NULL && strncmp(dot, ".js", 3) == 0) { snprintf(mime_type, 20, "text/javascript"); + } else if (dot != NULL && strncmp(dot, ".map", 4) == 0) { + snprintf(mime_type, 20, "application/json"); } else if (dot != NULL && strncmp(dot, ".ico", 4) == 0) { snprintf(mime_type, 20, "image/x-icon"); } else if (dot != NULL && strncmp(dot, ".jpg", 4) == 0) { @@ -145,15 +117,12 @@ int main(void) file_flag[1] = 'b'; } else { printf("error: unknown file type\n"); - close_socket(client_socket); break; } - printf("\n %s | %s \n", file_flag, filepath); FILE* file = fopen(filepath, file_flag); if (file == NULL) { printf("error: could not open file\n"); - close_socket(client_socket); break; } @@ -161,28 +130,26 @@ int main(void) "Content-Type: "; char send_buffer_2[] = "\r\n" "\r\n"; - ssize_t written - = send(client_socket, send_buffer_1, strlen(send_buffer_1) - 1, 0); + ssize_t written = tcp_send( + client_connection, (uint8_t*)send_buffer_1, strlen(send_buffer_1)); if (written < 0) { printf("error: could not write\n"); - close_socket(client_socket); break; } - written = send(client_socket, mime_type, strlen(mime_type), 0); + written = tcp_send(client_connection, (uint8_t*)mime_type, strlen(mime_type)); if (written < 0) { printf("error: could not write\n"); - close_socket(client_socket); break; } - written = send(client_socket, send_buffer_2, strlen(send_buffer_2), 0); + written = tcp_send( + client_connection, (uint8_t*)send_buffer_2, strlen(send_buffer_2)); if (written < 0) { printf("error: could not write\n"); - close_socket(client_socket); break; } int char_read; while ((char_read = fgetc(file)) != EOF) { - write(client_socket, (char*)&char_read, sizeof(char)); + tcp_send(client_connection, (uint8_t*)&char_read, sizeof(char)); } free(filepath); @@ -190,25 +157,11 @@ int main(void) } } free(path); - - /* uint8_t send_buffer[] - = "HTTP/1.1 200 OK\r\n" - "Content-Type: text/html\r\n" - "\r\n" - "hej med " - "dig

fuck c hashtag

\r\n" - "\r\n"; - ssize_t written = send(client_socket, send_buffer, sizeof(send_buffer), 0); - if (written < 0) { - printf("error: could not write\n"); - close_socket(client_socket); - break; - } */ - printf("disconnecting client\n"); - close_socket(client_socket); break; } + printf("disconnecting client\n"); + tcp_connection_destroy(client_connection); } - + tcp_server_destroy(server); return 0; } diff --git a/backend/native.h b/backend/native.h deleted file mode 100644 index b1d0e2d..0000000 --- a/backend/native.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef _WIN32 - #include - #include - #include - typedef SSIZE_T ssize_t; -#else - #include - #include - #include - #include -#endif - -void init_sockets(void); - -void close_socket(int socket); - diff --git a/backend/tcp.h b/backend/tcp.h new file mode 100644 index 0000000..ed3b2f9 --- /dev/null +++ b/backend/tcp.h @@ -0,0 +1,32 @@ +#ifndef TCP_H +#define TCP_H + +#include +#include + +#ifdef _WIN32 +#include +typedef SSIZE_T ssize_t; +#else +#include +#endif + +void tcp_global_initialize_sockets(void); + +typedef struct TcpServer TcpServer; +typedef struct TcpConnection TcpConnection; + +// returns NULL on errors, and prints the error +TcpServer* tcp_server_create(const char* ip, uint16_t port); +void tcp_server_destroy(TcpServer* server); + +// returns NULL on errors, and prints the error +TcpConnection* tcp_server_accept(TcpServer* server); +void tcp_connection_destroy(TcpConnection* connection); + +// returns amount transmittet >0 on success, ==0 if client was disconnected, and <0 on error +ssize_t tcp_recieve(TcpConnection* connection, uint8_t* data, size_t amount); +// returns amount transmittet >0 on success, ==0 if client was disconnected, and <0 on error +ssize_t tcp_send(TcpConnection* connection, uint8_t* data, size_t amount); + +#endif diff --git a/backend/windows.c b/backend/windows.c index 6643fee..5a0efb8 100644 --- a/backend/windows.c +++ b/backend/windows.c @@ -1,13 +1,21 @@ -#include "native.h" +#include "tcp.h" +#include +#include +#include +#include +#include +#include -void init_sockets(void) -{ - WSADATA data; - WSAStartup(0x0202, &data); -} +struct TcpServer { }; -void close_socket(int socket) -{ - closesocket(socket); -} +struct TcpConnection { }; +void tcp_global_initialize_sockets(void) { } + +TcpServer* tcp_server_create(const char* ip, uint16_t port) { } + +void tcp_connection_destroy(TcpConnection* connection) { } + +ssize_t tcp_recieve(TcpConnection* connection, uint8_t* data, size_t amount) { } + +ssize_t tcp_send(TcpConnection* connection, uint8_t* data, size_t amount) { }