timeout, but please refactor yes thankyou
This commit is contained in:
parent
c148636b1e
commit
e7e913a32d
@ -13,6 +13,8 @@ if (!isset($_SESSION['request_count'])) {
|
|||||||
// Increment on each request
|
// Increment on each request
|
||||||
$_SESSION['request_count']++;
|
$_SESSION['request_count']++;
|
||||||
|
|
||||||
|
sleep(8); // Simulate some processing delay
|
||||||
|
|
||||||
?>
|
?>
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|||||||
@ -93,7 +93,7 @@ void Client::request()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ErrorHandler::createErrorResponse(500, *httpResponse_);
|
ErrorHandler::createErrorResponse(500, *httpResponse_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -149,7 +149,7 @@ void Client::poll() const
|
|||||||
Log::info("Response is ready to be sent to client, fd: " + std::to_string(clientSocket_->getFd()));
|
Log::info("Response is ready to be sent to client, fd: " + std::to_string(clientSocket_->getFd()));
|
||||||
clientSocket_->setCallback([this]() { respond(); });
|
clientSocket_->setCallback([this]() { respond(); });
|
||||||
// server_.writable(clientSocket_->getFd());
|
// server_.writable(clientSocket_->getFd());
|
||||||
clientSocket_->setIOState(ASocket::IOState::WRITE);
|
clientSocket_->setIOState(ASocket::IoState::WRITE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,31 @@
|
|||||||
|
#include "webserv/log/Log.hpp"
|
||||||
#include <webserv/handler/AHandler.hpp>
|
#include <webserv/handler/AHandler.hpp>
|
||||||
|
|
||||||
#include <webserv/http/HttpRequest.hpp>
|
#include <webserv/http/HttpRequest.hpp>
|
||||||
#include <webserv/http/HttpResponse.hpp>
|
#include <webserv/http/HttpResponse.hpp>
|
||||||
|
#include <webserv/client/Client.hpp>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
AHandler::AHandler(const HttpRequest &request, HttpResponse &response) : request_(request), response_(response) {}
|
AHandler::AHandler(const HttpRequest &request, HttpResponse &response) : request_(request), response_(response) {}
|
||||||
|
|
||||||
|
void AHandler::startTimer()
|
||||||
|
{
|
||||||
|
timerSocket_ = std::make_unique<TimerSocket>(std::chrono::milliseconds(5000));
|
||||||
|
|
||||||
|
timerSocket_->setCallback([this]() { handleTimeout(); });
|
||||||
|
timerSocket_->activate();
|
||||||
|
|
||||||
|
request_.getClient().addSocket(timerSocket_.get());
|
||||||
|
Log::debug("Timer started for handler: " + std::to_string(timerSocket_->getFd()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AHandler::cancelTimer()
|
||||||
|
{
|
||||||
|
if (timerSocket_)
|
||||||
|
{
|
||||||
|
request_.getClient().removeSocket(timerSocket_.get());
|
||||||
|
timerSocket_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,26 +1,31 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "webserv/socket/TimerSocket.hpp"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
class HttpRequest;
|
class HttpRequest;
|
||||||
class HttpResponse;
|
class HttpResponse;
|
||||||
|
|
||||||
class AHandler
|
class AHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AHandler(const HttpRequest &request, HttpResponse &response);
|
AHandler(const HttpRequest &request, HttpResponse &response);
|
||||||
virtual ~AHandler() = default;
|
virtual ~AHandler() = default;
|
||||||
|
|
||||||
AHandler(const AHandler &other) = delete;
|
AHandler(const AHandler &other) = delete;
|
||||||
AHandler &operator=(const AHandler &other) = delete;
|
AHandler &operator=(const AHandler &other) = delete;
|
||||||
AHandler(AHandler &&other) noexcept = delete;
|
AHandler(AHandler &&other) noexcept = delete;
|
||||||
AHandler &operator=(AHandler &&other) noexcept = delete;
|
AHandler &operator=(AHandler &&other) noexcept = delete;
|
||||||
|
|
||||||
virtual void handle() = 0;
|
virtual void handle() = 0;
|
||||||
|
|
||||||
protected:
|
void startTimer();
|
||||||
const HttpRequest &request_;
|
void cancelTimer();
|
||||||
HttpResponse &response_;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void handleTimeout() = 0;
|
||||||
|
|
||||||
|
const HttpRequest &request_;
|
||||||
|
HttpResponse &response_;
|
||||||
|
std::unique_ptr<TimerSocket> timerSocket_;
|
||||||
};
|
};
|
||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "webserv/handler/ErrorHandler.hpp"
|
||||||
#include <webserv/client/Client.hpp> // for Client
|
#include <webserv/client/Client.hpp> // for Client
|
||||||
#include <webserv/handler/CgiHandler.hpp>
|
#include <webserv/handler/CgiHandler.hpp>
|
||||||
#include <webserv/handler/CgiProcess.hpp> // for CgiProcess
|
#include <webserv/handler/CgiProcess.hpp> // for CgiProcess
|
||||||
@ -20,6 +21,8 @@ void CgiHandler::handle()
|
|||||||
// Initialize CGI process
|
// Initialize CGI process
|
||||||
cgiProcess_ = std::make_unique<CgiProcess>(request_, *this);
|
cgiProcess_ = std::make_unique<CgiProcess>(request_, *this);
|
||||||
|
|
||||||
|
startTimer();
|
||||||
|
|
||||||
Log::info("CGI process started and sockets registered");
|
Log::info("CGI process started and sockets registered");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,6 +74,7 @@ void CgiHandler::read()
|
|||||||
{
|
{
|
||||||
Log::info("CGI process closed stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
Log::info("CGI process closed stdout, fd: " + std::to_string(cgiStdOut_->getFd()));
|
||||||
request_.getClient().removeSocket(cgiStdOut_.get());
|
request_.getClient().removeSocket(cgiStdOut_.get());
|
||||||
|
request_.getClient().removeSocket(timerSocket_.get());
|
||||||
cgiStdOut_ = nullptr;
|
cgiStdOut_ = nullptr;
|
||||||
parseCgiOutput();
|
parseCgiOutput();
|
||||||
return;
|
return;
|
||||||
@ -103,6 +107,7 @@ void CgiHandler::error()
|
|||||||
{
|
{
|
||||||
Log::info("CGI process closed stderr, fd: " + std::to_string(cgiStdErr_->getFd()));
|
Log::info("CGI process closed stderr, fd: " + std::to_string(cgiStdErr_->getFd()));
|
||||||
request_.getClient().removeSocket(cgiStdErr_.get());
|
request_.getClient().removeSocket(cgiStdErr_.get());
|
||||||
|
request_.getClient().removeSocket(timerSocket_.get()); // todo maybe this dangerous
|
||||||
cgiStdErr_ = nullptr;
|
cgiStdErr_ = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -213,6 +218,21 @@ void CgiHandler::parseCgiHeaders(std::string &headers)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CgiHandler::handleTimeout()
|
||||||
|
{
|
||||||
|
Log::warning("CGI handler timeout occurred for PID: " + std::to_string(pid_));
|
||||||
|
|
||||||
|
// Terminate the CGI process if it's still running
|
||||||
|
if (cgiProcess_)
|
||||||
|
{
|
||||||
|
cgiProcess_->kill();
|
||||||
|
Log::info("Terminated CGI process with PID: " + std::to_string(pid_));
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorHandler::createErrorResponse(504, response_);
|
||||||
|
// cancelTimer();
|
||||||
|
}
|
||||||
|
|
||||||
void CgiHandler::parseCgiBody()
|
void CgiHandler::parseCgiBody()
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
|
|||||||
@ -24,6 +24,9 @@ class CgiHandler : public AHandler
|
|||||||
void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut, std::unique_ptr<CgiSocket> cgiStdErr);
|
void setCgiSockets(std::unique_ptr<CgiSocket> cgiStdIn, std::unique_ptr<CgiSocket> cgiStdOut, std::unique_ptr<CgiSocket> cgiStdErr);
|
||||||
void setPid(int pid);
|
void setPid(int pid);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void handleTimeout() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager
|
constexpr static size_t bufferSize_ = 8192; // TODO: remove duplicate definition and move to configmanager
|
||||||
std::vector<uint8_t> buffer_;
|
std::vector<uint8_t> buffer_;
|
||||||
|
|||||||
@ -82,9 +82,9 @@ void CgiProcess::spawn()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Parent process
|
// Parent process
|
||||||
auto cgiStdIn = std::make_unique<CgiSocket>(pipeStdin[1], ASocket::IOState::WRITE);
|
auto cgiStdIn = std::make_unique<CgiSocket>(pipeStdin[1], ASocket::IoState::WRITE);
|
||||||
auto cgiStdOut = std::make_unique<CgiSocket>(pipeStdout[0], ASocket::IOState::READ);
|
auto cgiStdOut = std::make_unique<CgiSocket>(pipeStdout[0], ASocket::IoState::READ);
|
||||||
auto cgiStdErr = std::make_unique<CgiSocket>(pipeStderr[0], ASocket::IOState::READ);
|
auto cgiStdErr = std::make_unique<CgiSocket>(pipeStderr[0], ASocket::IoState::READ);
|
||||||
|
|
||||||
close(pipeStdin[0]);
|
close(pipeStdin[0]);
|
||||||
close(pipeStdout[1]);
|
close(pipeStdout[1]);
|
||||||
|
|||||||
@ -20,6 +20,12 @@ FileHandler::FileHandler(const HttpRequest &request, HttpResponse &response)
|
|||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileHandler::handleTimeout()
|
||||||
|
{
|
||||||
|
Log::warning("File handler timeout occurred for path: " + uri_.getFullPath());
|
||||||
|
ErrorHandler::createErrorResponse(504, response_, config_);
|
||||||
|
}
|
||||||
|
|
||||||
void FileHandler::handleFile(const std::string &filepath) const
|
void FileHandler::handleFile(const std::string &filepath) const
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
|
|||||||
@ -29,6 +29,9 @@ class FileHandler : public AHandler
|
|||||||
|
|
||||||
void handle() override;
|
void handle() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void handleTimeout() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const URI &uri_;
|
const URI &uri_;
|
||||||
const AConfig *config_;
|
const AConfig *config_;
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class Log
|
|||||||
|
|
||||||
void log(Level level, const std::string &message, const std::map<std::string, std::string> &context);
|
void log(Level level, const std::string &message, const std::map<std::string, std::string> &context);
|
||||||
|
|
||||||
static constexpr Log::Level COMPILE_TIME_LOG_LEVEL = Log::Level::Trace;
|
static constexpr Log::Level COMPILE_TIME_LOG_LEVEL = Log::Level::Debug;
|
||||||
|
|
||||||
static void setFileChannel(const std::string &filename, std::ios_base::openmode mode = std::ios_base::app);
|
static void setFileChannel(const std::string &filename, std::ios_base::openmode mode = std::ios_base::app);
|
||||||
static void setStdoutChannel();
|
static void setStdoutChannel();
|
||||||
|
|||||||
@ -89,7 +89,12 @@ void Server::remove(ASocket &socket)
|
|||||||
int fd = socket.getFd();
|
int fd = socket.getFd();
|
||||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1)
|
if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, fd, nullptr) == -1)
|
||||||
{
|
{
|
||||||
Log::error("epoll_ctl DEL failed for fd: " + std::to_string(fd));
|
if (errno == EBADF || errno == ENOENT)
|
||||||
|
{
|
||||||
|
Log::debug("Socket fd " + std::to_string(fd) + " was already closed or removed from epoll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::error("epoll_ctl DEL failed for fd: " + std::to_string(fd) + " with error: " + std::strerror(errno));
|
||||||
throw std::runtime_error("epoll_ctl DEL failed");
|
throw std::runtime_error("epoll_ctl DEL failed");
|
||||||
}
|
}
|
||||||
socketToClient_.erase(fd);
|
socketToClient_.erase(fd);
|
||||||
@ -133,7 +138,7 @@ void Server::handleConnection(struct epoll_event *event)
|
|||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
ServerSocket &listener = getListener(event->data.fd);
|
ServerSocket &listener = getListener(event->data.fd);
|
||||||
std::unique_ptr<ClientSocket> clientSocket = listener.accept();
|
std::unique_ptr<ClientSocket> clientSocket = listener.accept();
|
||||||
|
clientSocket->setIOState(ASocket::IoState::READ);
|
||||||
auto client = std::make_unique<Client>(std::move(clientSocket), *this);
|
auto client = std::make_unique<Client>(std::move(clientSocket), *this);
|
||||||
add(client->getSocket(), client.get());
|
add(client->getSocket(), client.get());
|
||||||
clients_.emplace_back(std::move(client));
|
clients_.emplace_back(std::move(client));
|
||||||
@ -198,7 +203,12 @@ void Server::update(const ASocket &socket) const
|
|||||||
evt.data.fd = socketFd;
|
evt.data.fd = socketFd;
|
||||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, socketFd, &evt) == -1)
|
if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, socketFd, &evt) == -1)
|
||||||
{
|
{
|
||||||
Log::error("epoll_ctl MOD failed for fd: " + std::to_string(socketFd));
|
if (errno == EBADF || errno == ENOENT)
|
||||||
|
{
|
||||||
|
Log::debug("Socket fd " + std::to_string(socketFd) + " was already closed or removed from epoll");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Log::error("epoll_ctl MOD failed for fd: " + std::to_string(socketFd) + " with error: " + std::strerror(errno));
|
||||||
throw std::runtime_error("epoll_ctl MOD failed");
|
throw std::runtime_error("epoll_ctl MOD failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
#include <sys/socket.h> // for recv, send
|
#include <sys/socket.h> // for recv, send
|
||||||
#include <unistd.h> // for close
|
#include <unistd.h> // for close
|
||||||
|
|
||||||
ASocket::ASocket(int fd, IOState event) : fd_(fd), ioState_(event)
|
ASocket::ASocket(int fd, IoState event) : fd_(fd), ioState_(event)
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
if (fd_ == -1)
|
if (fd_ == -1)
|
||||||
@ -65,7 +65,7 @@ int ASocket::getFd() const noexcept
|
|||||||
return fd_;
|
return fd_;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASocket::IOState ASocket::getEvent() const noexcept
|
ASocket::IoState ASocket::getEvent() const noexcept
|
||||||
{
|
{
|
||||||
return ioState_;
|
return ioState_;
|
||||||
}
|
}
|
||||||
@ -75,7 +75,7 @@ bool ASocket::isDirty() const noexcept
|
|||||||
return dirty_;
|
return dirty_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASocket::setIOState(IOState event)
|
void ASocket::setIOState(IoState event)
|
||||||
{
|
{
|
||||||
if (event == ioState_)
|
if (event == ioState_)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -13,10 +13,11 @@ class ASocket
|
|||||||
{
|
{
|
||||||
CLIENT_SOCKET,
|
CLIENT_SOCKET,
|
||||||
SERVER_SOCKET,
|
SERVER_SOCKET,
|
||||||
CGI_SOCKET
|
CGI_SOCKET,
|
||||||
|
TIMER_SOCKET
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IOState : uint32_t
|
enum class IoState : uint32_t
|
||||||
{
|
{
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
READ = 1 << 0,
|
READ = 1 << 0,
|
||||||
@ -24,7 +25,7 @@ class ASocket
|
|||||||
};
|
};
|
||||||
|
|
||||||
ASocket() = delete;
|
ASocket() = delete;
|
||||||
explicit ASocket(int fd, IOState state = IOState::READ);
|
explicit ASocket(int fd, IoState state = IoState::NONE);
|
||||||
|
|
||||||
ASocket(const ASocket &other) = delete;
|
ASocket(const ASocket &other) = delete;
|
||||||
ASocket &operator=(const ASocket &other) = delete;
|
ASocket &operator=(const ASocket &other) = delete;
|
||||||
@ -35,7 +36,7 @@ class ASocket
|
|||||||
|
|
||||||
[[nodiscard]] virtual Type getType() const noexcept = 0;
|
[[nodiscard]] virtual Type getType() const noexcept = 0;
|
||||||
[[nodiscard]] int getFd() const noexcept;
|
[[nodiscard]] int getFd() const noexcept;
|
||||||
[[nodiscard]] IOState getEvent() const noexcept;
|
[[nodiscard]] IoState getEvent() const noexcept;
|
||||||
[[nodiscard]] bool isDirty() const noexcept;
|
[[nodiscard]] bool isDirty() const noexcept;
|
||||||
|
|
||||||
void callback() const;
|
void callback() const;
|
||||||
@ -44,7 +45,7 @@ class ASocket
|
|||||||
virtual ssize_t read(void *buf, size_t len) const;
|
virtual ssize_t read(void *buf, size_t len) const;
|
||||||
virtual ssize_t write(const void *buf, size_t len) const;
|
virtual ssize_t write(const void *buf, size_t len) const;
|
||||||
|
|
||||||
void setIOState(IOState event);
|
void setIOState(IoState event);
|
||||||
void processed();
|
void processed();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -54,6 +55,6 @@ class ASocket
|
|||||||
private:
|
private:
|
||||||
int fd_;
|
int fd_;
|
||||||
bool dirty_ = false;
|
bool dirty_ = false;
|
||||||
IOState ioState_;
|
IoState ioState_;
|
||||||
std::function<void()> callback_ = nullptr;
|
std::function<void()> callback_ = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
CgiSocket::CgiSocket(int fd, ASocket::IOState event) : ASocket(fd, event)
|
CgiSocket::CgiSocket(int fd, ASocket::IoState event) : ASocket(fd, event)
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
class CgiSocket : public ASocket
|
class CgiSocket : public ASocket
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit CgiSocket(int fd, ASocket::IOState event);
|
explicit CgiSocket(int fd, ASocket::IoState event);
|
||||||
|
|
||||||
[[nodiscard]] ASocket::Type getType() const noexcept override;
|
[[nodiscard]] ASocket::Type getType() const noexcept override;
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@
|
|||||||
#include <sys/socket.h> // for AF_INET, accept, bind, listen, setsockopt, socket, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
|
#include <sys/socket.h> // for AF_INET, accept, bind, listen, setsockopt, socket, SOCK_STREAM, SOL_SOCKET, SO_REUSEADDR
|
||||||
#include <unistd.h> // for close
|
#include <unistd.h> // for close
|
||||||
|
|
||||||
ServerSocket::ServerSocket() : ASocket(socket(AF_INET, SOCK_STREAM, 0))
|
ServerSocket::ServerSocket() : ASocket(socket(AF_INET, SOCK_STREAM, 0), ASocket::IoState::READ)
|
||||||
{
|
{
|
||||||
Log::trace(LOCATION);
|
Log::trace(LOCATION);
|
||||||
if (getFd() == -1)
|
if (getFd() == -1)
|
||||||
|
|||||||
46
webserv/socket/TimerSocket.cpp
Normal file
46
webserv/socket/TimerSocket.cpp
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include "webserv/log/Log.hpp"
|
||||||
|
#include "webserv/socket/ASocket.hpp"
|
||||||
|
|
||||||
|
#include <webserv/socket/TimerSocket.hpp>
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
|
||||||
|
TimerSocket::TimerSocket(std::chrono::milliseconds timeout)
|
||||||
|
: ASocket(timerfd_create(CLOCK_MONOTONIC, 0), ASocket::IoState::NONE), timeout_(timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void TimerSocket::activate()
|
||||||
|
{
|
||||||
|
Log::trace(LOCATION);
|
||||||
|
struct itimerspec timerSpec;
|
||||||
|
|
||||||
|
auto seconds = std::chrono::duration_cast<std::chrono::seconds>(timeout_);
|
||||||
|
auto nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(timeout_ - seconds);
|
||||||
|
|
||||||
|
timerSpec.it_value.tv_sec = seconds.count();
|
||||||
|
timerSpec.it_value.tv_nsec = nanoseconds.count();
|
||||||
|
timerSpec.it_interval.tv_sec = 0;
|
||||||
|
timerSpec.it_interval.tv_nsec = 0;
|
||||||
|
|
||||||
|
if (timerfd_settime(getFd(), 0, &timerSpec, nullptr) == -1)
|
||||||
|
{
|
||||||
|
throw std::runtime_error("Failed to set timerfd time");
|
||||||
|
}
|
||||||
|
|
||||||
|
active_ = true;
|
||||||
|
setIOState(IoState::READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASocket::Type TimerSocket::getType() const noexcept
|
||||||
|
{
|
||||||
|
return ASocket::Type::TIMER_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TimerSocket::isActive() const noexcept
|
||||||
|
{
|
||||||
|
return active_;
|
||||||
|
}
|
||||||
18
webserv/socket/TimerSocket.hpp
Normal file
18
webserv/socket/TimerSocket.hpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "webserv/socket/ASocket.hpp"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
class TimerSocket : public ASocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit TimerSocket(std::chrono::milliseconds timeout);
|
||||||
|
|
||||||
|
[[nodiscard]] ASocket::Type getType() const noexcept override;
|
||||||
|
[[nodiscard]] bool isActive() const noexcept;
|
||||||
|
|
||||||
|
void activate();
|
||||||
|
private:
|
||||||
|
bool active_ = false;
|
||||||
|
std::chrono::milliseconds timeout_;
|
||||||
|
};
|
||||||
@ -139,15 +139,15 @@ std::string implode(const std::vector<std::string> &elements, const std::string
|
|||||||
return stream.str();
|
return stream.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t stateToEpoll(const ASocket::IOState &event)
|
uint32_t stateToEpoll(const ASocket::IoState &event)
|
||||||
{
|
{
|
||||||
uint32_t epollEvents = 0;
|
uint32_t epollEvents = 0;
|
||||||
using EventType = std::underlying_type_t<ASocket::IOState>;
|
using EventType = std::underlying_type_t<ASocket::IoState>;
|
||||||
if ((static_cast<EventType>(event) & static_cast<EventType>(ASocket::IOState::READ)) != 0U)
|
if ((static_cast<EventType>(event) & static_cast<EventType>(ASocket::IoState::READ)) != 0U)
|
||||||
{
|
{
|
||||||
epollEvents |= EPOLLIN;
|
epollEvents |= EPOLLIN;
|
||||||
}
|
}
|
||||||
if ((static_cast<EventType>(event) & static_cast<EventType>(ASocket::IOState::WRITE)) != 0U)
|
if ((static_cast<EventType>(event) & static_cast<EventType>(ASocket::IoState::WRITE)) != 0U)
|
||||||
{
|
{
|
||||||
epollEvents |= EPOLLOUT;
|
epollEvents |= EPOLLOUT;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,5 +18,5 @@ void removeComments(std::string &str);
|
|||||||
std::vector<std::string> split(const std::string &str, char delimiter);
|
std::vector<std::string> split(const std::string &str, char delimiter);
|
||||||
std::string implode(const std::vector<std::string> &elements, const std::string &delimiter);
|
std::string implode(const std::vector<std::string> &elements, const std::string &delimiter);
|
||||||
|
|
||||||
uint32_t stateToEpoll(const ASocket::IOState &event);
|
uint32_t stateToEpoll(const ASocket::IoState &event);
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
Loading…
Reference in New Issue
Block a user