From b64a41d84fd435823542c53804a422c746e92357 Mon Sep 17 00:00:00 2001 From: whaffman Date: Fri, 10 Oct 2025 11:03:20 +0200 Subject: [PATCH] feat: implement CGISocket class for handling CGI communication with non-blocking I/O --- webserv/socket/CGISocket.cpp | 74 ++++++++++++++++++++++++++++++++++++ webserv/socket/CGISocket.hpp | 32 ++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 webserv/socket/CGISocket.cpp create mode 100644 webserv/socket/CGISocket.hpp diff --git a/webserv/socket/CGISocket.cpp b/webserv/socket/CGISocket.cpp new file mode 100644 index 0000000..70601db --- /dev/null +++ b/webserv/socket/CGISocket.cpp @@ -0,0 +1,74 @@ +#include + +#include // for strerror +#include // for runtime_error +#include // for string, operator+ +#include // for system_error, error_code + +#include // for fcntl, O_NONBLOCK +#include // 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"); + } +} + diff --git a/webserv/socket/CGISocket.hpp b/webserv/socket/CGISocket.hpp new file mode 100644 index 0000000..e3cc148 --- /dev/null +++ b/webserv/socket/CGISocket.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +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 + +}; \ No newline at end of file