diff --git a/webserv/client/Client.cpp b/webserv/client/Client.cpp index f249d2e..7244aa1 100644 --- a/webserv/client/Client.cpp +++ b/webserv/client/Client.cpp @@ -1,3 +1,4 @@ +#include "webserv/socket/ASocket.hpp" #include "webserv/socket/CgiSocket.hpp" #include @@ -24,6 +25,7 @@ Client::Client(std::unique_ptr socket, Server &server) { Log::trace(LOCATION); Log::info("New client connected, fd: " + std::to_string(client_socket_->getFd())); + client_socket_->setCallback([this]() { request(); }); } Client::~Client() @@ -43,6 +45,20 @@ void Client::setStatusCode(int code) statusCode_ = code; } +ASocket &Client::getSocket(int fd) const +{ + if (fd == -1 || client_socket_->getFd() == fd) + { + return *client_socket_; + } + if (cgi_socket_ && cgi_socket_->getFd() == fd) + { + return *client_socket_; // TODO return cgi socket + } + Log::error("Socket not found for fd: " + std::to_string(fd)); + throw std::runtime_error("Socket not found for fd: " + std::to_string(fd)); +} + void Client::request() { Log::trace(LOCATION); @@ -101,14 +117,23 @@ void Client::poll() const if (httpResponse_->isComplete()) { Log::info("Response is ready to be sent to client, fd: " + std::to_string(client_socket_->getFd())); + client_socket_->setCallback([this]() { respond(); }); server_.responseReady(client_socket_->getFd()); } } -std::vector Client::getResponse() const +void Client::respond() const { - - return httpResponse_->toBytes(); + auto payload = httpResponse_->toBytes(); + ssize_t bytesSent = send(client_socket_->getFd(), payload.data(), payload.size(), 0); + if (bytesSent < 0) + { + Log::error("Send failed for fd: " + std::to_string(client_socket_->getFd())); + } + else + { + Log::debug("Sent " + std::to_string(bytesSent) + " bytes to fd: " + std::to_string(client_socket_->getFd())); + } } HttpRequest &Client::getHttpRequest() const diff --git a/webserv/client/Client.hpp b/webserv/client/Client.hpp index f68c9ef..55ebb01 100644 --- a/webserv/client/Client.hpp +++ b/webserv/client/Client.hpp @@ -35,12 +35,12 @@ class Client ~Client(); void request(); + void respond() const; void poll() const; - [[nodiscard]] std::vector getResponse() const; [[nodiscard]] int getStatusCode() const; - [[nodiscard]] ClientSocket &getSocket() const { return *client_socket_; } + [[nodiscard]] ASocket &getSocket(int fd = -1) const; void setStatusCode(int code); void setCgiSocket(std::unique_ptr cgiSocket); diff --git a/webserv/handler/URI.cpp b/webserv/handler/URI.cpp index 9cae07c..f098a62 100644 --- a/webserv/handler/URI.cpp +++ b/webserv/handler/URI.cpp @@ -156,16 +156,16 @@ bool URI::isCgi() const std::string URI::getCgiPath() const { - Log::debug("BaseName: " + baseName_ + ", FullPath: " + fullPath_ + ", Dir: " + dir_ + ", PathInfo: " + pathInfo_ + - ", Extension: " + getExtension()); + // Log::debug("BaseName: " + baseName_ + ", FullPath: " + fullPath_ + ", Dir: " + dir_ + ", PathInfo: " + pathInfo_ + + // ", Extension: " + getExtension()); if (!isFile() || getExtension().empty() || !config_->get("cgi_enabled").has_value() || !config_->get("cgi_enabled").value()) { - Log::debug("CGI not enabled or not a file or no extension", - {{"isFile", isFile() ? "true" : "false"}, - {"extension", getExtension()}, - {"cgi_enabled", config_->get("cgi_enabled").has_value() ? "true" : "false"}, - {"cgi_enabled_value", config_->get("cgi_enabled").value() ? "true" : "false"}}); + // Log::debug("CGI not enabled or not a file or no extension", + // {{"isFile", isFile() ? "true" : "false"}, + // {"extension", getExtension()}, + // {"cgi_enabled", config_->get("cgi_enabled").has_value() ? "true" : "false"}, + // {"cgi_enabled_value", config_->get("cgi_enabled").value() ? "true" : "false"}}); return ""; } auto cgiPath = config_->getCGIPath(getExtension()); diff --git a/webserv/server/Server.cpp b/webserv/server/Server.cpp index d610c06..4a86fbe 100644 --- a/webserv/server/Server.cpp +++ b/webserv/server/Server.cpp @@ -163,8 +163,10 @@ void Server::handleRequest(struct epoll_event *event) const Log::trace(LOCATION); int client_fd = event->data.fd; + Client &client = getClient(client_fd); - client.request(); + client.getSocket().callback(); + } void Server::responseReady(int client_fd) const @@ -185,16 +187,7 @@ void Server::handleResponse(struct epoll_event *event) { Log::debug("Attempting to send data to fd: " + std::to_string(event->data.fd)); Client &client = getClient(event->data.fd); - auto payload = client.getResponse(); - ssize_t bytesSent = send(event->data.fd, payload.data(), payload.size(), 0); - if (bytesSent < 0) - { - Log::error("Send failed for fd: " + std::to_string(event->data.fd) + " with error: " + std::strerror(errno)); - } - else - { - Log::debug("Sent " + std::to_string(bytesSent) + " bytes to fd: " + std::to_string(event->data.fd)); - } + client.getSocket().callback(); disconnect(client); } diff --git a/webserv/socket/ASocket.cpp b/webserv/socket/ASocket.cpp index e02406e..4c31650 100644 --- a/webserv/socket/ASocket.cpp +++ b/webserv/socket/ASocket.cpp @@ -68,4 +68,17 @@ int ASocket::getFd() const void ASocket::setFd(int fd) { fd_ = fd; -} \ No newline at end of file +} + +void ASocket::callback() const +{ + if (callback_ != nullptr) + { + callback_(); + } +} + +void ASocket::setCallback(std::function callback) +{ + callback_ = std::move(callback); +} diff --git a/webserv/socket/ASocket.hpp b/webserv/socket/ASocket.hpp index b5029ed..4beaf51 100644 --- a/webserv/socket/ASocket.hpp +++ b/webserv/socket/ASocket.hpp @@ -1,5 +1,7 @@ #pragma once +#include // for function + #include // for size_t #include @@ -27,6 +29,9 @@ class ASocket [[nodiscard]] virtual Type getType() const = 0; [[nodiscard]] int getFd() const; + + void callback() const; + void setCallback(std::function callback); ssize_t read(void *buf, size_t len) const; ssize_t write(const void *buf, size_t len) const; @@ -37,4 +42,5 @@ class ASocket private: int fd_; + std::function callback_ = nullptr; };