feat(socket): implement callbacks for asynchronous handling of requests and responses
This commit is contained in:
parent
0887acd81a
commit
e1be8d8aa8
@ -1,3 +1,4 @@
|
||||
#include "webserv/socket/ASocket.hpp"
|
||||
#include "webserv/socket/CgiSocket.hpp"
|
||||
|
||||
#include <webserv/client/Client.hpp>
|
||||
@ -24,6 +25,7 @@ Client::Client(std::unique_ptr<ClientSocket> 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<uint8_t> 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
|
||||
|
||||
@ -35,12 +35,12 @@ class Client
|
||||
~Client();
|
||||
|
||||
void request();
|
||||
void respond() const;
|
||||
void poll() const;
|
||||
|
||||
[[nodiscard]] std::vector<uint8_t> 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> cgiSocket);
|
||||
|
||||
@ -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<bool>("cgi_enabled").has_value()
|
||||
|| !config_->get<bool>("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<bool>("cgi_enabled").has_value() ? "true" : "false"},
|
||||
{"cgi_enabled_value", config_->get<bool>("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<bool>("cgi_enabled").has_value() ? "true" : "false"},
|
||||
// {"cgi_enabled_value", config_->get<bool>("cgi_enabled").value() ? "true" : "false"}});
|
||||
return "";
|
||||
}
|
||||
auto cgiPath = config_->getCGIPath(getExtension());
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -69,3 +69,16 @@ void ASocket::setFd(int fd)
|
||||
{
|
||||
fd_ = fd;
|
||||
}
|
||||
|
||||
void ASocket::callback() const
|
||||
{
|
||||
if (callback_ != nullptr)
|
||||
{
|
||||
callback_();
|
||||
}
|
||||
}
|
||||
|
||||
void ASocket::setCallback(std::function<void()> callback)
|
||||
{
|
||||
callback_ = std::move(callback);
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional> // for function
|
||||
|
||||
#include <cstddef> // for size_t
|
||||
#include <cstdint>
|
||||
|
||||
@ -28,6 +30,9 @@ class ASocket
|
||||
[[nodiscard]] virtual Type getType() const = 0;
|
||||
[[nodiscard]] int getFd() const;
|
||||
|
||||
void callback() const;
|
||||
void setCallback(std::function<void()> 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<void()> callback_ = nullptr;
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user