diff --git a/include/Client.hpp b/include/Client.hpp index fcdf797..c0c6cd0 100644 --- a/include/Client.hpp +++ b/include/Client.hpp @@ -32,6 +32,9 @@ class Client HTTPRequest &getRequest(void); void setState(ClientState state); + FileManager &getFileManager(); + HTTPResponse &getResponse(); + bool cgiBodyIsSent; bool cgiHasBeenRead; bool KO; diff --git a/include/Poll.hpp b/include/Poll.hpp index d65c3c1..f1111f6 100644 --- a/include/Poll.hpp +++ b/include/Poll.hpp @@ -19,7 +19,7 @@ class Poll ~Poll(); void addPollFD(int fd, short events); - void pollFDs(void); + bool pollFDs(void); void removeFD(int fd); void setEvents(int fd, short events); void checkREvents(short revents) const; diff --git a/src/Client.cpp b/src/Client.cpp index 63fad51..66ac6a5 100644 --- a/src/Client.cpp +++ b/src/Client.cpp @@ -3,6 +3,7 @@ #include "LocationSettings.hpp" #include "Poll.hpp" #include "ReturnException.hpp" +#include "StatusCode.hpp" #include #include #include @@ -89,6 +90,16 @@ void Client::setState(ClientState state) _state = state; } +FileManager &Client::getFileManager() +{ + return (_file_manager); +} + +HTTPResponse &Client::getResponse() +{ + return (_response); +} + void Client::checkCGI(const std::string &request_target, HTTPMethod method) { const LocationSettings &loc = @@ -127,6 +138,8 @@ ClientState Client::handleConnection( resolveServerSetting(); if (_request.getBody().size() > _request.getMaxBodySize()) throw ClientException(StatusCode::RequestBodyTooLarge); + if (_request.getBody().size() >= _request.getBodyLength()) + return (ClientState::Loading); checkCGI(_request.getRequestTarget(), _request.getMethodType()); } return (_state); @@ -177,6 +190,7 @@ ClientState Client::handleConnection( } else if (events & POLLOUT && _state == ClientState::Error) { + logger.log(DEBUG, "ClientState::Error"); _state = _file_manager.loadErrorPage(); return (_state); } @@ -193,6 +207,10 @@ ClientState Client::handleConnection( _response.send(_socket.getFD(), _file_manager.getResponse()); return (_state); } + else + { + throw ClientException(StatusCode::BadRequest); + } } catch (ClientException &e) { @@ -221,5 +239,6 @@ ClientState Client::handleConnection( _state = ClientState::Sending; return (_state); } + logger.log(DEBUG, "ClientState::UNKNOWN"); return (ClientState::Unknown); } diff --git a/src/HTTPRequest.cpp b/src/HTTPRequest.cpp index 2a59237..edea9ca 100644 --- a/src/HTTPRequest.cpp +++ b/src/HTTPRequest.cpp @@ -188,6 +188,9 @@ ClientState HTTPRequest::receive(int client_fd) if (_bytes_read == SYSTEM_ERROR) throw ClientException(StatusCode::InternalServerError); logger.log(DEBUG, "in receive _bytes_read is: %", _bytes_read); + if (_bytes_read == 0) + return (ClientState::Receiving); + if (_content_length != 0) { _body += std::string(buffer, _bytes_read); diff --git a/src/HTTPServer.cpp b/src/HTTPServer.cpp index 9004d71..1b05892 100644 --- a/src/HTTPServer.cpp +++ b/src/HTTPServer.cpp @@ -1,5 +1,8 @@ #include "ClientException.hpp" +#include "ClientState.hpp" #include "HTTPRequest.hpp" +#include "HTTPStatus.hpp" +#include "StatusCode.hpp" #include #include #include @@ -84,16 +87,31 @@ void HTTPServer::handleActivePollFDs() Logger &logger = Logger::getInstance(); logger.log(DEBUG, "HTTPServer::handleActivePollFDs"); - _poll.pollFDs(); + if (!_poll.pollFDs()) + { + logger.log(DEBUG, "HTTPServer::Clearup ClientFD's"); + for (auto &pair : _active_clients) + { + _poll.setEvents(pair.second->getFD(), POLLOUT); + pair.second->getResponse().clear(); + HTTPStatus status(StatusCode::RequestTimeout); + pair.second->getFileManager().setResponse( + status.getStatusLine("HTTP/1.1") + status.getHTMLStatus()); + pair.second->setState(ClientState::Sending); + } + } + for (const auto &poll_fd : _poll.getPollFDs()) { if (poll_fd.revents == 0) continue; + + logger.log(DEBUG, "poll fd: " + std::to_string(poll_fd.fd) + + " revents: " + + _poll.pollEventsToString(poll_fd.revents)); try { if (poll_fd.revents & POLLHUP) - // this code block is solving a thrown exception from - // the cgi's child process { Client &client = getClientByPipeFd(poll_fd.fd); if (client.getRequest().CGITrue() && @@ -118,9 +136,6 @@ void HTTPServer::handleActivePollFDs() _active_clients.erase(poll_fd.fd); continue; } - logger.log(DEBUG, "poll fd: " + std::to_string(poll_fd.fd) + - " revents: " + - _poll.pollEventsToString(poll_fd.revents)); if (_active_servers.find(poll_fd.fd) != _active_servers.end()) handleNewConnection( poll_fd.fd, diff --git a/src/Poll.cpp b/src/Poll.cpp index 92b807e..769c669 100644 --- a/src/Poll.cpp +++ b/src/Poll.cpp @@ -37,15 +37,18 @@ std::vector Poll::getPollFDs(void) const return (_poll_fds); } -void Poll::pollFDs(void) +bool Poll::pollFDs(void) { Logger &logger = Logger::getInstance(); logger.log(INFO, "Polling " + std::to_string(_poll_fds.size()) + " file descriptors"); - int poll_count = poll(_poll_fds.data(), _poll_fds.size(), NO_TIMEOUT); - if (poll_count == SYSTEM_ERROR || poll_count == 0) + int poll_count = poll(_poll_fds.data(), _poll_fds.size(), 5000); + if (poll_count == SYSTEM_ERROR) throw SystemException("poll"); // TODO: change poll_count 0 handler + if (poll_count == 0) + return (false); + return (true); } std::string Poll::pollEventsToString(short events) const