remove client when it disconnects
This commit is contained in:
parent
bd01a172c5
commit
1c634ddc02
@ -1,3 +1,4 @@
|
||||
#include "webserv/http/HttpConstants.hpp"
|
||||
#include <webserv/client/Client.hpp>
|
||||
#include <webserv/config/ConfigManager.hpp> // for ConfigManager
|
||||
#include <webserv/config/ServerConfig.hpp> // for ServerConfig
|
||||
@ -18,27 +19,32 @@ Client::Client(std::unique_ptr<Socket> socket, Server &server)
|
||||
: client_socket_(std::move(socket)), server_(std::ref(server)), httpRequest_(std::make_unique<HttpRequest>(this)),
|
||||
httpResponse_(std::make_unique<HttpResponse>())
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::info("New client connected, fd: " + std::to_string(client_socket_->getFd()));
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::info("Client disconnected, fd: " + std::to_string(client_socket_->getFd()));
|
||||
server_.removeFromEpoll(*client_socket_);
|
||||
};
|
||||
|
||||
int Client::getStatusCode() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
return statusCode_;
|
||||
}
|
||||
|
||||
void Client::setStatusCode(int code)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
statusCode_ = code;
|
||||
}
|
||||
|
||||
void Client::request()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
char buffer[bufferSize_] = {}; // NOLINT(cppcoreguidelines-avoid-c-arrays)
|
||||
ssize_t bytesRead =
|
||||
client_socket_->recv(buffer, sizeof(buffer) - 1); // NOLINT(cppcoreguidelines-pro-bounds-array-to-pointer-decay)
|
||||
@ -49,7 +55,8 @@ void Client::request()
|
||||
}
|
||||
if (bytesRead == 0)
|
||||
{
|
||||
Log::info("Client disconnected, fd: " + std::to_string(client_socket_->getFd())); // TODO weird
|
||||
Log::info("Client closed connection, fd: " + std::to_string(client_socket_->getFd())); // TODO weird
|
||||
server_.removeClient(*this); // CRITICAL: RETURN IMMEDIATELY
|
||||
return;
|
||||
}
|
||||
|
||||
@ -74,7 +81,7 @@ void Client::request()
|
||||
{
|
||||
Log::warning("No matching server config found for Host: " +
|
||||
httpRequest_->getHeaders().getHost().value_or("unknown host"));
|
||||
httpRequest_->setState(HttpRequest::State::ParseError);
|
||||
setError(Http::StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
// Example usage, replace with actual host and port extraction from request
|
||||
@ -92,6 +99,7 @@ void Client::request()
|
||||
|
||||
bool Client::isResponseReady() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
// todo: poll the httpResponse_ object
|
||||
return httpResponse_->isComplete();
|
||||
}
|
||||
@ -99,13 +107,23 @@ bool Client::isResponseReady() const
|
||||
std::vector<uint8_t> Client::getResponse() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (httpRequest_->getState() == HttpRequest::State::ParseError)
|
||||
Log::trace(LOCATION);
|
||||
if (statusCode_ == Http::StatusCode::OK)
|
||||
{
|
||||
return ErrorHandler::getErrorResponse(Http::StatusCode::BAD_REQUEST).toBytes();
|
||||
}
|
||||
|
||||
httpResponse_->setStatus(200);
|
||||
httpResponse_->addHeader("Content-Type", "text/plain");
|
||||
httpResponse_->appendBody("Hello, World!\n");
|
||||
}
|
||||
return httpResponse_->toBytes();
|
||||
}
|
||||
|
||||
void Client::setError(int statusCode)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
statusCode_ = statusCode;
|
||||
Log::debug("Setting error response with status code: " + std::to_string(statusCode));
|
||||
auto errorResponse = std::make_unique<HttpResponse>(
|
||||
ErrorHandler::getErrorResponse(statusCode, const_cast<ServerConfig *>(server_config_)));
|
||||
httpResponse_ = std::move(errorResponse);
|
||||
Log::debug("Error response set successfully");
|
||||
}
|
||||
|
||||
@ -39,6 +39,7 @@ class Client
|
||||
[[nodiscard]] int getStatusCode() const;
|
||||
|
||||
[[nodiscard]] Socket &getSocket() const { return *client_socket_; }
|
||||
void setError(int statusCode);
|
||||
|
||||
void setStatusCode(int code);
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "webserv/http/HttpHeaders.hpp"
|
||||
#include "webserv/log/Log.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@ -19,7 +20,7 @@ class HttpResponse
|
||||
HttpResponse(HttpResponse &&other) noexcept = default; // Move constructor
|
||||
HttpResponse &operator=(HttpResponse &&other) noexcept = default; // Move assignment
|
||||
|
||||
~HttpResponse() = default;
|
||||
~HttpResponse() {Log::trace(LOCATION);};
|
||||
|
||||
void addHeader(const std::string &key, const std::string &value);
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ int main(int argc, char **argv)
|
||||
std::cerr << "Usage: " << argv[0] << " <config_file_path>\n"; // NOLINT
|
||||
return 1;
|
||||
}
|
||||
Log::setFileChannel("webserv.log", std::ios_base::app, Log::Level::Trace);
|
||||
Log::setFileChannel("webserv.log", std::ios_base::app, Log::Level::Info);
|
||||
Log::setStdoutChannel(Log::Level::Info);
|
||||
Log::info("\n======================\nStarting webserv...\n======================\n");
|
||||
ConfigManager::getInstance().init(argv[1]); // NOLINT
|
||||
|
||||
@ -22,6 +22,7 @@
|
||||
|
||||
Server::Server(const ConfigManager &configManager) : epoll_fd_(epoll_create1(0)), configManager_(configManager)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
const auto &serverConfigs = configManager.getServerConfigs();
|
||||
if (serverConfigs.empty())
|
||||
{
|
||||
@ -37,6 +38,7 @@ Server::Server(const ConfigManager &configManager) : epoll_fd_(epoll_create1(0))
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (epoll_fd_ != -1)
|
||||
{
|
||||
close(epoll_fd_);
|
||||
@ -45,6 +47,7 @@ Server::~Server()
|
||||
|
||||
void Server::start()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::info("Starting servers...");
|
||||
// 1. Load server configurations
|
||||
|
||||
@ -63,6 +66,7 @@ void Server::start()
|
||||
|
||||
void Server::addToEpoll(const Socket &socket, uint32_t events) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
int fd = socket.getFd();
|
||||
struct epoll_event event{};
|
||||
event.events = events;
|
||||
@ -74,8 +78,18 @@ void Server::addToEpoll(const Socket &socket, uint32_t events) const
|
||||
}
|
||||
}
|
||||
|
||||
void Server::removeClient(const Client &client)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
int client_fd = client.getSocket().getFd();
|
||||
clients_.erase(client_fd);
|
||||
// removeFromEpoll(client.getSocket());
|
||||
// close(client_fd);
|
||||
}
|
||||
|
||||
void Server::removeFromEpoll(const Socket &socket) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
int filedes = socket.getFd();
|
||||
if (epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, filedes, nullptr) == -1)
|
||||
{
|
||||
@ -86,6 +100,7 @@ void Server::removeFromEpoll(const Socket &socket) const
|
||||
|
||||
void Server::setupServerSocket(const ServerConfig &config)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
try
|
||||
{
|
||||
auto host = config.getDirectiveValue<std::string>("host");
|
||||
@ -110,6 +125,7 @@ void Server::setupServerSocket(const ServerConfig &config)
|
||||
|
||||
void Server::handleConnection(struct epoll_event *event)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Socket &listener = getListener(event->data.fd);
|
||||
std::unique_ptr<Socket> clientSocket = listener.accept();
|
||||
addToEpoll(*clientSocket, EPOLLIN);
|
||||
@ -118,6 +134,7 @@ void Server::handleConnection(struct epoll_event *event)
|
||||
|
||||
Socket &Server::getListener(int fd) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
for (const auto &listener : listeners_)
|
||||
{
|
||||
if (listener->getFd() == fd)
|
||||
@ -131,6 +148,7 @@ Socket &Server::getListener(int fd) const
|
||||
|
||||
Client &Server::getClient(int fd) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
auto it = clients_.find(fd);
|
||||
if (it != clients_.end())
|
||||
{
|
||||
@ -142,11 +160,13 @@ Client &Server::getClient(int fd) const
|
||||
|
||||
const ServerConfig &Server::getConfig(const Socket &socket) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
return getConfig(socket.getFd());
|
||||
}
|
||||
|
||||
const ServerConfig &Server::getConfig(int fd) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
auto it = fdToConfig_.find(fd);
|
||||
if (it != fdToConfig_.end())
|
||||
{
|
||||
@ -158,6 +178,7 @@ const ServerConfig &Server::getConfig(int fd) const
|
||||
|
||||
void Server::handleRequest(struct epoll_event *event) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
int client_fd = event->data.fd;
|
||||
|
||||
Client &client = getClient(client_fd);
|
||||
@ -166,6 +187,7 @@ void Server::handleRequest(struct epoll_event *event) const
|
||||
|
||||
void Server::responseReady(int client_fd) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::debug("Response ready for client fd: " + std::to_string(client_fd));
|
||||
struct epoll_event ev{};
|
||||
ev.events = EPOLLOUT;
|
||||
@ -179,6 +201,7 @@ void Server::responseReady(int client_fd) const
|
||||
|
||||
void Server::eventLoop()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
Log::info("Listening...");
|
||||
const int MAX_EVENTS = 10;
|
||||
struct epoll_event events[MAX_EVENTS]; // NOLINT
|
||||
|
||||
@ -33,6 +33,7 @@ class Server
|
||||
|
||||
void start();
|
||||
void addToEpoll(const Socket &socket, uint32_t events) const;
|
||||
void removeClient(const Client &client);
|
||||
void removeFromEpoll(const Socket &socket) const;
|
||||
void setupServerSocket(const ServerConfig &config);
|
||||
void handleConnection(struct epoll_event *event);
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
|
||||
Socket::Socket() : fd_(socket(AF_INET, SOCK_STREAM, 0))
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (fd_ == -1)
|
||||
{
|
||||
Log::error("Socket creation failed");
|
||||
@ -31,6 +32,7 @@ Socket::Socket() : fd_(socket(AF_INET, SOCK_STREAM, 0))
|
||||
|
||||
Socket::Socket(int fd) : fd_(fd) // NOLINT(readability-identifier-naming)
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (fd_ == -1)
|
||||
{
|
||||
Log::error("Invalid file descriptor");
|
||||
@ -41,6 +43,7 @@ Socket::Socket(int fd) : fd_(fd) // NOLINT(readability-identifier-naming)
|
||||
|
||||
Socket::~Socket()
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (fd_ != -1)
|
||||
{
|
||||
close(fd_);
|
||||
@ -49,6 +52,7 @@ Socket::~Socket()
|
||||
|
||||
void Socket::listen(int backlog) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (::listen(fd_, backlog) < 0)
|
||||
{
|
||||
Log::error("Listen failed");
|
||||
@ -58,7 +62,7 @@ void Socket::listen(int backlog) const
|
||||
|
||||
void Socket::bind(const std::string &host, const int port) const
|
||||
{
|
||||
|
||||
Log::trace(LOCATION);
|
||||
struct sockaddr_in address{};
|
||||
address.sin_family = AF_INET;
|
||||
address.sin_addr.s_addr = inet_addr(host.c_str());
|
||||
@ -72,6 +76,7 @@ void Socket::bind(const std::string &host, const int port) const
|
||||
|
||||
std::unique_ptr<Socket> Socket::accept() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
int client_fd = ::accept(fd_, nullptr, nullptr);
|
||||
if (client_fd < 0)
|
||||
{
|
||||
@ -83,16 +88,19 @@ std::unique_ptr<Socket> Socket::accept() const
|
||||
|
||||
ssize_t Socket::recv(void *buf, size_t len) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
return ::recv(fd_, buf, len, 0);
|
||||
}
|
||||
|
||||
ssize_t Socket::send(const void *buf, size_t len) const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
return ::send(fd_, buf, len, 0);
|
||||
}
|
||||
|
||||
void Socket::setNonBlocking() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
if (fcntl(fd_, F_SETFL, O_NONBLOCK) < 0)
|
||||
{
|
||||
Log::error("Failed to set non-blocking mode");
|
||||
@ -102,5 +110,6 @@ void Socket::setNonBlocking() const
|
||||
|
||||
int Socket::getFd() const
|
||||
{
|
||||
Log::trace(LOCATION);
|
||||
return fd_;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user