first commit: echo server

This commit is contained in:
Antonio Cossari
2026-09-07 00:45:35 +02:00
commit b15ce130f9
47 changed files with 2614 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Server.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: acossari <acossari@student.codam.nl> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2026/09/01 09:13:02 by acossari #+# #+# */
/* Updated: 2026/09/01 19:00:54 by acossari ### ########.fr */
/* */
/* ************************************************************************** */
#pragma once
#include <sys/socket.h>
#include <chrono>
#include <cstdint>
#include <optional>
#include <span>
#include <vector>
#include "event/Epoll.hpp"
#include "net/Listener.hpp"
#include "net/PauseMask.hpp"
#include "net/SlotPool.hpp"
namespace webserv {
class Server final {
public:
// Both constants use direct-list-initialization to call the explicit
// duration constructor. A bare "= 500" would need an implicit conversion
// from int to std::chrono::milliseconds.
// After accept() fails, listeners are temporarily disarmed before
// retrying. Level-triggered epoll would otherwise keep
// reporting the ready listener and create a busy loop. The 500 ms delay
// matches nginx's default.
static constexpr std::chrono::milliseconds ACCEPT_BACKOFF{500};
// A rare, documented race exists if SIGINT arrives after the shutdown
// flag is checked but before epoll_wait begins. "epoll_pwait" closes it
// atomically, but the subject does not allow it. Bounding an idle wait lets
// run() recheck the flag within 500 ms. This interval is a trade-off, not a
// measured optimum, and causes at most two timeout wakeups per idle second.
static constexpr std::chrono::milliseconds MAX_IDLE_WAIT{500};
// TEMP
// Endpoints are hardcoded in main() until the config parser is available.
explicit Server(std::span<const sockaddr_storage> endpoints);
void run();
private:
void dispatch(std::uint64_t packedToken, std::uint32_t events);
void acceptFrom(std::uint32_t listenerIndex);
void handleAcceptFailure(std::uint32_t listenerIndex, int errnoCode);
void startBackoff();
void retire(std::uint32_t slotIndex) noexcept;
void stopListener(std::uint32_t listenerIndex) noexcept;
void updateRegistration(std::uint32_t slotIndex, std::uint32_t events);
void pause(ListenerPause reason);
void resume(ListenerPause reason);
void applyListenerEvents(std::uint32_t events);
void expireBackoff();
int millisUntilDeadline() const;
Epoll epoll_;
std::vector<Listener> listeners_;
SlotPool slotPool_;
PauseMask pauseMask_;
// Stores a fixed deadline because loop iterations have no fixed duration.
// Empty means no resource backoff is scheduled.
std::optional<std::chrono::steady_clock::time_point> backoffExpiry_;
};
} // namespace webserv