From c18d5f993d4a1fd2355facec21df58e8b7fa4dc8 Mon Sep 17 00:00:00 2001 From: Pablu23 Date: Wed, 13 Nov 2024 16:49:49 +0100 Subject: [PATCH] Add correctly shutting down server and stopping threads --- Makefile | 5 ++++- main.cpp | 22 +++++++++++++++++++--- request.cpp | 16 ++++++++-------- response.cpp | 24 ++++++++++++------------ response.hpp | 2 +- router.cpp | 10 ++++++++-- router.hpp | 3 ++- tree.cpp | 14 +++++++------- 8 files changed, 61 insertions(+), 35 deletions(-) diff --git a/Makefile b/Makefile index 895fa40..ac591a3 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,10 @@ fclean: re: fclean $(NAME) -run: all +build: all + g++ -std=c++20 -o server main.cpp -L. -lhttpablu + +run: build g++ -std=c++20 -o server main.cpp -L. -lhttpablu ./server diff --git a/main.cpp b/main.cpp index 35563df..25d43f6 100644 --- a/main.cpp +++ b/main.cpp @@ -1,18 +1,33 @@ #include "http.hpp" #include "router.hpp" +#include +#include +#include using namespace http; -void HelloWorld(Request req, Response *res) { +void hello_world(Request req, Response *res) { res->set_payload("Hello World!"); res->set_content_type("text/plain"); } +static Router router(8181); + +void quit(int s) { + router.stop(); + std::cout << "Stopping Server" << std::endl; +} + int main() { - Router router(8181); + struct sigaction sig_int_handler; + sig_int_handler.sa_handler = quit; + sigemptyset(&sig_int_handler.sa_mask); + sig_int_handler.sa_flags = 0; + + sigaction(SIGINT, &sig_int_handler, nullptr); // Allow all Methods - router.handle("GET /helloWorld", HelloWorld); + router.handle("GET /helloWorld", hello_world); router.handle("GET /healthz", [](Request req, Response *res) { res->set_status_code(StatusCode::OK); res->set_payload(std::vector()); @@ -38,6 +53,7 @@ int main() { res->set_content_type("text/plain"); }); + std::cout << "Starting Server" << std::endl; router.start(); return 0; } diff --git a/request.cpp b/request.cpp index 76ffcfa..63c00e3 100644 --- a/request.cpp +++ b/request.cpp @@ -10,7 +10,7 @@ bool Request::protocol(std::stringstream *ss, int *procPart, char c) { m_method = ss->str(); break; case 1: - m_pathRaw = ss->str(); + m_path_raw = ss->str(); break; case 2: m_protocol = ss->str(); @@ -72,17 +72,17 @@ Request::Request(std::vector buf) : path("") { ss << c; } } - path = Path{m_pathRaw}; + path = Path{m_path_raw}; } -void Request::Print() { +void Request::print() { std::cout << "Protocol: " << m_protocol << "\n" - << "Req: " << m_method << " " << m_pathRaw << std::endl; + << "Req: " << m_method << " " << m_path_raw << std::endl; for (const auto &[key, value] : m_headers) { std::cout << "[" << key << "]: [" << value << "]\n"; } - if (HasData()) { + if (has_data()) { std::cout << "Payload: " << std::endl; for (auto &byte : m_payload) { std::cout << static_cast(byte); @@ -91,6 +91,6 @@ void Request::Print() { } } -std::string Request::Method() { return m_method; } -bool Request::HasData() { return m_payload.size() != 0; } -std::vector Request::Data() { return m_payload; } +std::string Request::method() { return m_method; } +bool Request::has_data() { return m_payload.size() != 0; } +std::vector Request::data() { return m_payload; } diff --git a/response.cpp b/response.cpp index 2afa82d..075890f 100644 --- a/response.cpp +++ b/response.cpp @@ -8,26 +8,26 @@ using namespace http; -Response::Response(statuscode::statusCode statusCode) { +Response::Response(StatusCode::statusCode statusCode) { m_statusCode = statusCode; - SetHeader("Connection", "close"); + set_header("Connection", "close"); } -void Response::SetHeader(const std::string name, const std::string value) { +void Response::set_header(const std::string name, const std::string value) { m_headers.insert_or_assign(name, value); } -void Response::SetPayload(const std::vector data) { +void Response::set_payload(const std::vector data) { m_headers.insert(std::pair( "Content-Length", std::to_string(data.size()))); m_payload = data; } -void Response::SetStatusCode(statuscode::statusCode statuscode) { +void Response::set_status_code(StatusCode::statusCode statuscode) { m_statusCode = statuscode; } -void Response::SetPayload(const std::string data) { +void Response::set_payload(const std::string data) { m_headers.insert(std::pair( "Content-Length", std::to_string(std::strlen(data.data())))); @@ -36,14 +36,14 @@ void Response::SetPayload(const std::string data) { [](char c) { return std::byte(c); }); } -void Response::SetContentType(const std::string type) { +void Response::set_content_type(const std::string type) { m_headers.insert_or_assign("Content-Type", type); } -void Response::Send(int clientSocket) { +std::string Response::compile() { std::stringstream ss; ss << "HTTP/1.1 " << m_statusCode << " " - << statuscode::StatusCodeString(m_statusCode) << "\n"; + << StatusCode::status_code_string(m_statusCode) << "\n"; for (const auto &[key, value] : m_headers) { ss << key << ": " << value << "\n"; } @@ -54,11 +54,11 @@ void Response::Send(int clientSocket) { ss << c; } } - std::string p = ss.str(); - send(clientSocket, p.data(), p.size(), 0); + return ss.str(); + // ::send(clientSocket, p.data(), p.size(), 0); } -void Response::Print() { +void Response::print() { for (const auto &[key, value] : m_headers) { std::cout << "[" << key << "]: [" << value << "]\n"; } diff --git a/response.hpp b/response.hpp index 318a7c9..7bff9d7 100644 --- a/response.hpp +++ b/response.hpp @@ -20,7 +20,7 @@ public: void set_payload(const std::string data); void set_content_type(const std::string type); void set_status_code(const StatusCode::statusCode status_code); - void send(int client_socket); + std::string compile(); void print(); }; } // namespace http diff --git a/router.cpp b/router.cpp index 57180ac..ef75eea 100644 --- a/router.cpp +++ b/router.cpp @@ -18,9 +18,11 @@ Router::Router(int port) { m_address.sin_family = AF_INET; m_address.sin_port = htons(port); m_address.sin_addr.s_addr = INADDR_ANY; + m_running = false; } int Router::start() { + m_running = true; int err = bind(m_socket, (struct sockaddr *)&m_address, sizeof(m_address)); if (err != 0) return err; @@ -31,14 +33,17 @@ int Router::start() { if (err != 0) return err; - while (true) { + while (m_running.load()) { int client = accept(m_socket, nullptr, nullptr); queue_client(client); } stop_thread_loop(); + return 0; } +void Router::stop() { m_running.store(false); } + void Router::queue_client(int fd) { { std::unique_lock lock(m_mutex); @@ -83,7 +88,8 @@ void Router::thread_loop() { recv(client, buffer.data(), buffer.size(), 0); Request req(buffer); Response res = Route(req); - res.send(client); + auto payload = res.compile(); + send(client, payload.data(), payload.size(), 0); shutdown(client, SHUT_WR); while (recv(client, buffer.data(), buffer.size(), 0) > 0) { diff --git a/router.hpp b/router.hpp index 2b82b1f..edfac06 100644 --- a/router.hpp +++ b/router.hpp @@ -19,6 +19,7 @@ private: int m_socket; sockaddr_in m_address; Response Route(Request req); + std::atomic m_running; private: std::mutex m_mutex; @@ -36,7 +37,7 @@ public: void handle(std::string path_pattern, std::function func); int start(); - int stop(); + void stop(); }; } // namespace http diff --git a/tree.cpp b/tree.cpp index ec45443..ccf0ac0 100644 --- a/tree.cpp +++ b/tree.cpp @@ -25,7 +25,7 @@ Node::Node(std::string sub, bool isValue, Tree::Tree(std::string method) { m_method = method; } -void addNode(std::shared_ptr const &parent, std::string path, +void add_node(std::shared_ptr const &parent, std::string path, std::vector rest, std::function func) { std::shared_ptr curr = parent->m_next[path]; @@ -45,13 +45,13 @@ void addNode(std::shared_ptr const &parent, std::string path, auto newPath = rest.front(); // Ineffiecient, use deque rest.erase(rest.begin()); - addNode(curr, newPath, rest, func); + add_node(curr, newPath, rest, func); } else { auto newPath = rest.front(); rest.erase(rest.begin()); std::shared_ptr leaf = std::make_shared(Node{path}); parent->m_next.insert_or_assign(path, leaf); - addNode(leaf, newPath, rest, func); + add_node(leaf, newPath, rest, func); } } @@ -71,10 +71,10 @@ void Tree::add_path(std::string path, auto newPath = subPaths.front(); subPaths.erase(subPaths.begin()); - addNode(m_root, newPath, subPaths, func); + add_node(m_root, newPath, subPaths, func); } -void printNode(std::shared_ptr node, size_t depth, size_t max_depth) { +void print_node(std::shared_ptr node, size_t depth, size_t max_depth) { if (depth >= max_depth) { return; } @@ -82,7 +82,7 @@ void printNode(std::shared_ptr node, size_t depth, size_t max_depth) { std::cout << std::string(depth, ' ') << "sub: \"" << node->m_sub_path << "\" IsDummy: " << node->m_is_dummy << std::endl; for (auto &next : node->m_next) { - printNode(next.second, depth + 1, max_depth); + print_node(next.second, depth + 1, max_depth); } } @@ -123,4 +123,4 @@ Tree::get(std::string path) { return traverse(m_root, newPath, subs); } -void Tree::debug_Print() { printNode(m_root, 0, 10); } +void Tree::debug_Print() { print_node(m_root, 0, 10); }