feat: implement CGISocket class for handling CGI communication with non-blocking I/O
This commit is contained in:
parent
f8a273ec84
commit
b64a41d84f
74
webserv/socket/CGISocket.cpp
Normal file
74
webserv/socket/CGISocket.cpp
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
32
webserv/socket/CGISocket.hpp
Normal file
32
webserv/socket/CGISocket.hpp
Normal 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
|
||||||
|
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user