79 lines
3.2 KiB
C++
79 lines
3.2 KiB
C++
/* ************************************************************************** */
|
|
/* */
|
|
/* ::: :::::::: */
|
|
/* 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
|