Add correctly shutting down server and stopping threads

This commit is contained in:
Pablu23
2024-11-13 16:49:49 +01:00
parent a3a5280f17
commit c18d5f993d
8 changed files with 61 additions and 35 deletions

View File

@@ -22,7 +22,10 @@ fclean:
re: fclean $(NAME) 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 g++ -std=c++20 -o server main.cpp -L. -lhttpablu
./server ./server

View File

@@ -1,18 +1,33 @@
#include "http.hpp" #include "http.hpp"
#include "router.hpp" #include "router.hpp"
#include <csignal>
#include <cstdlib>
#include <iostream>
using namespace http; using namespace http;
void HelloWorld(Request req, Response *res) { void hello_world(Request req, Response *res) {
res->set_payload("Hello World!"); res->set_payload("Hello World!");
res->set_content_type("text/plain"); res->set_content_type("text/plain");
} }
static Router router(8181);
void quit(int s) {
router.stop();
std::cout << "Stopping Server" << std::endl;
}
int main() { 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 // Allow all Methods
router.handle("GET /helloWorld", HelloWorld); router.handle("GET /helloWorld", hello_world);
router.handle("GET /healthz", [](Request req, Response *res) { router.handle("GET /healthz", [](Request req, Response *res) {
res->set_status_code(StatusCode::OK); res->set_status_code(StatusCode::OK);
res->set_payload(std::vector<std::byte>()); res->set_payload(std::vector<std::byte>());
@@ -38,6 +53,7 @@ int main() {
res->set_content_type("text/plain"); res->set_content_type("text/plain");
}); });
std::cout << "Starting Server" << std::endl;
router.start(); router.start();
return 0; return 0;
} }

View File

@@ -10,7 +10,7 @@ bool Request::protocol(std::stringstream *ss, int *procPart, char c) {
m_method = ss->str(); m_method = ss->str();
break; break;
case 1: case 1:
m_pathRaw = ss->str(); m_path_raw = ss->str();
break; break;
case 2: case 2:
m_protocol = ss->str(); m_protocol = ss->str();
@@ -72,17 +72,17 @@ Request::Request(std::vector<std::byte> buf) : path("") {
ss << c; ss << c;
} }
} }
path = Path{m_pathRaw}; path = Path{m_path_raw};
} }
void Request::Print() { void Request::print() {
std::cout << "Protocol: " << m_protocol << "\n" 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) { for (const auto &[key, value] : m_headers) {
std::cout << "[" << key << "]: [" << value << "]\n"; std::cout << "[" << key << "]: [" << value << "]\n";
} }
if (HasData()) { if (has_data()) {
std::cout << "Payload: " << std::endl; std::cout << "Payload: " << std::endl;
for (auto &byte : m_payload) { for (auto &byte : m_payload) {
std::cout << static_cast<char>(byte); std::cout << static_cast<char>(byte);
@@ -91,6 +91,6 @@ void Request::Print() {
} }
} }
std::string Request::Method() { return m_method; } std::string Request::method() { return m_method; }
bool Request::HasData() { return m_payload.size() != 0; } bool Request::has_data() { return m_payload.size() != 0; }
std::vector<std::byte> Request::Data() { return m_payload; } std::vector<std::byte> Request::data() { return m_payload; }

View File

@@ -8,26 +8,26 @@
using namespace http; using namespace http;
Response::Response(statuscode::statusCode statusCode) { Response::Response(StatusCode::statusCode statusCode) {
m_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); m_headers.insert_or_assign(name, value);
} }
void Response::SetPayload(const std::vector<std::byte> data) { void Response::set_payload(const std::vector<std::byte> data) {
m_headers.insert(std::pair<std::string, std::string>( m_headers.insert(std::pair<std::string, std::string>(
"Content-Length", std::to_string(data.size()))); "Content-Length", std::to_string(data.size())));
m_payload = data; m_payload = data;
} }
void Response::SetStatusCode(statuscode::statusCode statuscode) { void Response::set_status_code(StatusCode::statusCode statuscode) {
m_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<std::string, std::string>( m_headers.insert(std::pair<std::string, std::string>(
"Content-Length", std::to_string(std::strlen(data.data())))); "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); }); [](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); m_headers.insert_or_assign("Content-Type", type);
} }
void Response::Send(int clientSocket) { std::string Response::compile() {
std::stringstream ss; std::stringstream ss;
ss << "HTTP/1.1 " << m_statusCode << " " 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) { for (const auto &[key, value] : m_headers) {
ss << key << ": " << value << "\n"; ss << key << ": " << value << "\n";
} }
@@ -54,11 +54,11 @@ void Response::Send(int clientSocket) {
ss << c; ss << c;
} }
} }
std::string p = ss.str(); return ss.str();
send(clientSocket, p.data(), p.size(), 0); // ::send(clientSocket, p.data(), p.size(), 0);
} }
void Response::Print() { void Response::print() {
for (const auto &[key, value] : m_headers) { for (const auto &[key, value] : m_headers) {
std::cout << "[" << key << "]: [" << value << "]\n"; std::cout << "[" << key << "]: [" << value << "]\n";
} }

View File

@@ -20,7 +20,7 @@ public:
void set_payload(const std::string data); void set_payload(const std::string data);
void set_content_type(const std::string type); void set_content_type(const std::string type);
void set_status_code(const StatusCode::statusCode status_code); void set_status_code(const StatusCode::statusCode status_code);
void send(int client_socket); std::string compile();
void print(); void print();
}; };
} // namespace http } // namespace http

View File

@@ -18,9 +18,11 @@ Router::Router(int port) {
m_address.sin_family = AF_INET; m_address.sin_family = AF_INET;
m_address.sin_port = htons(port); m_address.sin_port = htons(port);
m_address.sin_addr.s_addr = INADDR_ANY; m_address.sin_addr.s_addr = INADDR_ANY;
m_running = false;
} }
int Router::start() { int Router::start() {
m_running = true;
int err = bind(m_socket, (struct sockaddr *)&m_address, sizeof(m_address)); int err = bind(m_socket, (struct sockaddr *)&m_address, sizeof(m_address));
if (err != 0) if (err != 0)
return err; return err;
@@ -31,14 +33,17 @@ int Router::start() {
if (err != 0) if (err != 0)
return err; return err;
while (true) { while (m_running.load()) {
int client = accept(m_socket, nullptr, nullptr); int client = accept(m_socket, nullptr, nullptr);
queue_client(client); queue_client(client);
} }
stop_thread_loop(); stop_thread_loop();
return 0;
} }
void Router::stop() { m_running.store(false); }
void Router::queue_client(int fd) { void Router::queue_client(int fd) {
{ {
std::unique_lock<std::mutex> lock(m_mutex); std::unique_lock<std::mutex> lock(m_mutex);
@@ -83,7 +88,8 @@ void Router::thread_loop() {
recv(client, buffer.data(), buffer.size(), 0); recv(client, buffer.data(), buffer.size(), 0);
Request req(buffer); Request req(buffer);
Response res = Route(req); Response res = Route(req);
res.send(client); auto payload = res.compile();
send(client, payload.data(), payload.size(), 0);
shutdown(client, SHUT_WR); shutdown(client, SHUT_WR);
while (recv(client, buffer.data(), buffer.size(), 0) > 0) { while (recv(client, buffer.data(), buffer.size(), 0) > 0) {

View File

@@ -19,6 +19,7 @@ private:
int m_socket; int m_socket;
sockaddr_in m_address; sockaddr_in m_address;
Response Route(Request req); Response Route(Request req);
std::atomic<bool> m_running;
private: private:
std::mutex m_mutex; std::mutex m_mutex;
@@ -36,7 +37,7 @@ public:
void handle(std::string path_pattern, void handle(std::string path_pattern,
std::function<void(Request, Response *)> func); std::function<void(Request, Response *)> func);
int start(); int start();
int stop(); void stop();
}; };
} // namespace http } // namespace http

View File

@@ -25,7 +25,7 @@ Node::Node(std::string sub, bool isValue,
Tree::Tree(std::string method) { m_method = method; } Tree::Tree(std::string method) { m_method = method; }
void addNode(std::shared_ptr<Node> const &parent, std::string path, void add_node(std::shared_ptr<Node> const &parent, std::string path,
std::vector<std::string> rest, std::vector<std::string> rest,
std::function<void(Request, Response *)> func) { std::function<void(Request, Response *)> func) {
std::shared_ptr<Node> curr = parent->m_next[path]; std::shared_ptr<Node> curr = parent->m_next[path];
@@ -45,13 +45,13 @@ void addNode(std::shared_ptr<Node> const &parent, std::string path,
auto newPath = rest.front(); auto newPath = rest.front();
// Ineffiecient, use deque // Ineffiecient, use deque
rest.erase(rest.begin()); rest.erase(rest.begin());
addNode(curr, newPath, rest, func); add_node(curr, newPath, rest, func);
} else { } else {
auto newPath = rest.front(); auto newPath = rest.front();
rest.erase(rest.begin()); rest.erase(rest.begin());
std::shared_ptr<Node> leaf = std::make_shared<Node>(Node{path}); std::shared_ptr<Node> leaf = std::make_shared<Node>(Node{path});
parent->m_next.insert_or_assign(path, leaf); 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(); auto newPath = subPaths.front();
subPaths.erase(subPaths.begin()); subPaths.erase(subPaths.begin());
addNode(m_root, newPath, subPaths, func); add_node(m_root, newPath, subPaths, func);
} }
void printNode(std::shared_ptr<Node> node, size_t depth, size_t max_depth) { void print_node(std::shared_ptr<Node> node, size_t depth, size_t max_depth) {
if (depth >= max_depth) { if (depth >= max_depth) {
return; return;
} }
@@ -82,7 +82,7 @@ void printNode(std::shared_ptr<Node> node, size_t depth, size_t max_depth) {
std::cout << std::string(depth, ' ') << "sub: \"" << node->m_sub_path std::cout << std::string(depth, ' ') << "sub: \"" << node->m_sub_path
<< "\" IsDummy: " << node->m_is_dummy << std::endl; << "\" IsDummy: " << node->m_is_dummy << std::endl;
for (auto &next : node->m_next) { 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); 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); }