feat: implement CGISocket class for handling CGI communication with non-blocking I/O

This commit is contained in:
whaffman 2025-10-10 11:03:20 +02:00
parent f8a273ec84
commit b64a41d84f
2 changed files with 106 additions and 0 deletions

View File

@ -0,0 +1,74 @@
#include <webserv/socket/CGISocket.hpp>
#include <cstring> // for strerror
#include <stdexcept> // for runtime_error
#include <string> // for string, operator+
#include <system_error> // for system_error, error_code
#include <fcntl.h> // for fcntl, O_NONBLOCK
#include <unistd.h> // for close, read, write
CGISocket::CGISocket(int readFd, int writeFd) : _readFd(readFd), _writeFd(writeFd)
{
if (_readFd == -1 || _writeFd == -1)
{
throw std::runtime_error("CGISocket: Invalid file descriptors");
}
setNonBlocking();
}
CGISocket::~CGISocket()
{
if (_readFd != -1)
{
close(_readFd);
}
if (_writeFd != -1)
{
close(_writeFd);
}
}
int CGISocket::getReadFd() const
{
return _readFd;
}
int CGISocket::getWriteFd() const
{
return _writeFd;
}
ssize_t CGISocket::read(void *buffer, size_t size) const
{
ssize_t bytesRead = ::read(_readFd, buffer, size);
if (bytesRead == -1)
{
throw std::system_error(errno, std::generic_category(), "CGISocket: Read error");
}
return bytesRead;
}
ssize_t CGISocket::write(const void *buffer, size_t size) const
{
ssize_t bytesWritten = ::write(_writeFd, buffer, size);
if (bytesWritten == -1)
{
throw std::system_error(errno, std::generic_category(), "CGISocket: Write error");
}
return bytesWritten;
}
void CGISocket::setNonBlocking() const
{
if (fcntl(_readFd, F_SETFL, O_NONBLOCK) == -1)
{
throw std::system_error(errno, std::generic_category(), "CGISocket: Failed to set read FD non-blocking");
}
if (fcntl(_writeFd, F_SETFL, O_NONBLOCK) == -1)
{
throw std::system_error(errno, std::generic_category(), "CGISocket: Failed to set write FD non-blocking");
}
}

View File

@ -0,0 +1,32 @@
#pragma once
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
class CGISocket
{
public:
CGISocket(int readFd, int writeFd);
CGISocket(const CGISocket &) = delete;
CGISocket &operator=(const CGISocket &) = delete;
CGISocket(CGISocket &&other) noexcept = default;
CGISocket &operator=(CGISocket &&other) noexcept = default;
~CGISocket();
// Get FDs for server epoll registration
[[nodiscard]] int getReadFd() const; // Server reads CGI output
[[nodiscard]] int getWriteFd() const; // Server writes to CGI input
// Handler interface
ssize_t read(void *buffer, size_t size) const;
ssize_t write(const void *buffer, size_t size) const;
void setNonBlocking() const;
private:
int _readFd = -1; // Server side of output pipe
int _writeFd = -1; // Server side of input pipe
};