From fca446d8e9d9df9e481535090661ca91fa194f53 Mon Sep 17 00:00:00 2001 From: Theis Pieter Hollebeek Date: Mon, 23 Mar 2026 13:17:41 +0100 Subject: [PATCH] impl tcp.cpp --- backend/Makefile | 34 ++++++++--------- backend/compile_flags.txt | 4 +- backend/src/main.c | 60 ------------------------------ backend/src/main.cpp | 12 ++++++ backend/src/tcp.cpp | 78 +++++++++++++++++++++++++++++++++++++++ backend/src/tcp.hpp | 38 +++++++++++++++++++ 6 files changed, 147 insertions(+), 79 deletions(-) delete mode 100644 backend/src/main.c create mode 100644 backend/src/main.cpp create mode 100644 backend/src/tcp.cpp create mode 100644 backend/src/tcp.hpp diff --git a/backend/Makefile b/backend/Makefile index 2c7a175..91efa4d 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -1,54 +1,54 @@ MAKEFLAGS += -j16 -CC=gcc -LD=gcc +CXX=g++ +LD=g++ CLANG_FORMAT=clang-format -CFLAGS = -std=c23 -pedantic-errors -Wall -Wextra -Wconversion +CXXFLAGS = -std=c++23 -pedantic-errors -Wall -Wextra -Wconversion LDFLAGS = -libraries = libmicrohttpd +# libraries = "" -CFLAGS += $(shell pkg-config $(libraries) --cflags) -LDFLAGS += $(shell pkg-config $(libraries) --libs) +# CXXFLAGS += $(shell pkg-config $(libraries) --cflags) +# LDFLAGS += $(shell pkg-config $(libraries) --libs) RELEASE = 0 GDB = 0 ifeq ($(RELEASE),1) - CFLAGS += -O3 + CXXFLAGS += -O3 else - CFLAGS += -g -Wno-unused + CXXFLAGS += -g -Wno-unused ifeq ($(GDB),1) - CFLAGS += -ggdb + CXXFLAGS += -ggdb else - CFLAGS += -fsanitize=address + CXXFLAGS += -fsanitize=address endif endif NO_MAIN = 0 ifeq ($(NO_MAIN),1) - CFLAGS += -Dmain="not_main" + CXXFLAGS += -Dmain="not_main" endif build_dir = build obj_dir = $(build_dir)/obj sources = \ - src/main.c + src/main.cpp target=$(build_dir)/backend all: $(target) -$(target): $(sources:%.c=$(obj_dir)/%.o) - $(LD) -o $@ $(CFLAGS) $(LDFLAGS) $^ +$(target): $(sources:%.cpp=$(obj_dir)/%.o) + $(LD) -o $@ $(CXXFLAGS) $(LDFLAGS) $^ -$(obj_dir)/%.o: %.c +$(obj_dir)/%.o: %.cpp @mkdir -p $(dir $@) - $(CC) $< -c -o $@ -MMD -MP $(CFLAGS) + $(CXX) $< -c -o $@ -MMD -MP $(CXXFLAGS) format: $(CLANG_FORMAT) -style=file -i src/* @@ -59,5 +59,5 @@ check: clean: rm -rf $(build_dir) --include $(sources:%.c=$(obj_dir)/%.d) +-include $(sources:%.cpp=$(obj_dir)/%.d) diff --git a/backend/compile_flags.txt b/backend/compile_flags.txt index ca856b8..aedb8ea 100644 --- a/backend/compile_flags.txt +++ b/backend/compile_flags.txt @@ -1,5 +1,5 @@ --xc --std=c23 +-xc++ +-std=c++23 -pedantic-errors -Wall -Wextra diff --git a/backend/src/main.c b/backend/src/main.c deleted file mode 100644 index 7ec81ef..0000000 --- a/backend/src/main.c +++ /dev/null @@ -1,60 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#define PORT 8888 - -int print_out_key( - void* cls, enum MHD_ValueKind kind, const char* key, const char* value) -{ - printf("%s: %s\n", key, value); - return MHD_YES; -} - -int answer_to_connection(void* cls, struct MHD_Connection* connection, - const char* url, const char* method, const char* version, - const char* upload_data, size_t* upload_data_size, void** req_cls) -{ - const char* page = "Hello, browser!"; - struct MHD_Response* response; - int ret; - - MHD_get_connection_values(connection, - MHD_HEADER_KIND, - (MHD_KeyValueIterator)&print_out_key, - NULL); - - printf("New %s request for %s using version %s\n", method, url, version); - - response = MHD_create_response_from_buffer( - strlen(page), (void*)page, MHD_RESPMEM_PERSISTENT); - - ret = (int)MHD_queue_response(connection, MHD_HTTP_OK, response); - MHD_destroy_response(response); - - return ret; -} - -int main(void) -{ - printf("hello\n"); - struct MHD_Daemon* daemon; - - daemon = MHD_start_daemon(MHD_USE_INTERNAL_POLLING_THREAD, - PORT, - NULL, - NULL, - (MHD_AccessHandlerCallback)&answer_to_connection, - NULL, - MHD_OPTION_END); - - if (NULL == daemon) - return 1; - getchar(); - - MHD_stop_daemon(daemon); - return 0; -} diff --git a/backend/src/main.cpp b/backend/src/main.cpp new file mode 100644 index 0000000..4fe2dbd --- /dev/null +++ b/backend/src/main.cpp @@ -0,0 +1,12 @@ +#include +#include +#include +#include + +#define PORT 8888 + +int main(void) +{ + printf("hello\n"); + return 0; +} diff --git a/backend/src/tcp.cpp b/backend/src/tcp.cpp new file mode 100644 index 0000000..beb01f3 --- /dev/null +++ b/backend/src/tcp.cpp @@ -0,0 +1,78 @@ +#include "tcp.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mst { +auto errno_shim(std::string_view message) -> std::string +{ + auto x = strerror(errno); + return std::format("{} ({})", message, x); +} + +auto TcpConnection::write(uint8_t* buffer, size_t len) -> Result +{ + ssize_t bytes_written = ::write(this->fd, buffer, len); + if (bytes_written < 0) { + return std::unexpected(errno_shim("could not write bytes")); + } + return bytes_written; +} + +auto TcpConnection::read(uint8_t* buffer, size_t len) -> Result +{ + ssize_t bytes_read = ::recv(this->fd, buffer, len, 0); + if (bytes_read < 0) { + return std::unexpected(errno_shim("could not read bytes")); + } + return bytes_read; +} + +auto TcpListener::bind(const std::string& host, uint16_t port) + -> Result +{ + int socket_fd = 0; + if ((socket_fd = ::socket(AF_INET, SOCK_STREAM, 0)) < 0) { + return std::unexpected(errno_shim("could not get socket")); + } + + struct sockaddr_in address = { + .sin_family = AF_INET, + .sin_port = htons(port), + .sin_addr = in_addr { .s_addr = inet_addr(host.c_str()) }, + .sin_zero = { }, + }; + + if (::bind(socket_fd, (struct sockaddr*)&address, sizeof(address)) < 0) { + return std::unexpected(errno_shim("could not bind")); + } + + if (::listen(socket_fd, 0) < 0) { + return std::unexpected(errno_shim("could not listen")); + } + + return TcpListener(socket_fd, address); +} + +auto TcpListener::accept() -> Result +{ + socklen_t size = sizeof(address); + + int socket = ::accept(this->fd, (struct sockaddr*)&address, &size); + if (socket < 0) { + return std::unexpected(errno_shim("could not accept")); + } + return TcpConnection(*this, socket); +} + +} diff --git a/backend/src/tcp.hpp b/backend/src/tcp.hpp new file mode 100644 index 0000000..b6e2b78 --- /dev/null +++ b/backend/src/tcp.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include + +namespace mst { +template using Result = std::expected; + +class TcpListener; + +class TcpConnection { +public: + auto write(uint8_t* buffer, size_t len) -> Result; + auto read(uint8_t* buffer, size_t len) -> Result; + TcpConnection(TcpListener&, int fd) + : fd(fd) { }; + +private: + int fd; +}; + +class TcpListener { + +public: + static auto bind(const std::string& host, uint16_t port) + -> Result; + auto accept() -> Result; + +private: + TcpListener(int fd, sockaddr_in address) + : fd(fd) + , address(address) { }; + int fd; + sockaddr_in address; +}; +}