first commit: echo server
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user