diff --git a/Makefile b/Makefile index 2770b61..3b22784 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,10 @@ CFLAGS = -Wall -Wextra -Werror -std=c++98 RM = rm -f +# SRC_NAME = ./src/main.cpp \ +# ./src/server/Server.cpp \ +# ./src/network/Poller.cpp \ +# ./src/network/Socket.cpp SRC_NAME = $(shell find ./src -iname "*.cpp") OBJ_NAME = $(SRC_NAME:.cpp=.o) diff --git a/include/Config.hpp b/include/Config.hpp index 8cc66c0..d1c1efe 100644 --- a/include/Config.hpp +++ b/include/Config.hpp @@ -6,13 +6,31 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:00 by sanghupa #+# #+# */ -/* Updated: 2024/06/30 16:24:32 by sanghupa ### ########.fr */ +/* Updated: 2024/07/08 23:35:53 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef CONFIG_HPP # define CONFIG_HPP -# include "webserv.hpp" +# include +# include + +class Config +{ + public: + Config(); + ~Config(); + + static void load(const std::string filename); + static std::string get(const std::string key); + static int getInt(const std::string key); + static int getPort(); + + private: + static std::map _configMap; + + static void _parseConfigFile(const std::string filename); +}; #endif \ No newline at end of file diff --git a/include/Poller.hpp b/include/Poller.hpp index 3397018..38659ea 100644 --- a/include/Poller.hpp +++ b/include/Poller.hpp @@ -6,7 +6,7 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:00 by sanghupa #+# #+# */ -/* Updated: 2024/07/05 20:17:00 by sanghupa ### ########.fr */ +/* Updated: 2024/07/09 23:25:27 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ @@ -32,7 +32,7 @@ class Poller void removeSocket(const Socket socket); void removeAllSockets(); std::vector getPollfds() const; - std::vector poll(int timeout); + std::vector poll(int timeout); private: std::vector _pollfds; diff --git a/include/Server.hpp b/include/Server.hpp index edf5732..966c68d 100644 --- a/include/Server.hpp +++ b/include/Server.hpp @@ -6,7 +6,7 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:46 by sanghupa #+# #+# */ -/* Updated: 2024/07/04 16:35:08 by sanghupa ### ########.fr */ +/* Updated: 2024/07/10 21:23:36 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,6 +22,10 @@ # include "RequestHandler.hpp" // class Config; +class Location; +class Socket; +class Poller; +// class RequestHandler; class Server { @@ -68,11 +72,15 @@ class Server bool _running; Socket _listenSocket; Poller _poller; - RequestHandler _requestHandler; + std::vector _pollfds; + // RequestHandler _requestHandler; void _handleNewConnection(); void _handleClientData(Poller::t_event event); + void _acceptNewConnection(); + void _handleClientData_2(int clientSocket, size_t idx); + std::vector _serverNames; std::string _serverHost; std::string _serverPort; diff --git a/src/main.cpp b/src/main.cpp index 2013e3d..a60fcb8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/22 21:05:14 by sanghupa #+# #+# */ -/* Updated: 2024/07/08 22:49:29 by sanghupa ### ########.fr */ +/* Updated: 2024/07/09 23:16:14 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ @@ -50,6 +50,7 @@ int main(int argc, char *argv[]) // Set the signal handler for SIGINT signal signal(SIGINT, ft_sigint_handler); + (void)argv; // try-catch block for error handling // Create a Config object with the provided configuration file // Config config(argv[1]); diff --git a/src/network/Poller.cpp b/src/network/Poller.cpp index 553f7e5..3d3f00b 100644 --- a/src/network/Poller.cpp +++ b/src/network/Poller.cpp @@ -6,13 +6,19 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:00 by sanghupa #+# #+# */ -/* Updated: 2024/07/05 20:25:39 by sanghupa ### ########.fr */ +/* Updated: 2024/07/09 23:46:15 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ #include "webserv.hpp" #include "Poller.hpp" +Poller::Poller() +{} + +Poller::~Poller() +{} + void Poller::addSocket(const Socket socket, short events) { pollfd pfd; @@ -47,7 +53,7 @@ std::vector Poller::poll(int timeout) } for (size_t i = 0; i < pollfds.size(); i++) { - if (pollfds[i].revents & POLLIN) + if (pollfds[i].revents != 0) { t_event event; event.socket = Socket(pollfds[i].fd); diff --git a/src/network/Socket.cpp b/src/network/Socket.cpp index 8598d9f..50de0f0 100644 --- a/src/network/Socket.cpp +++ b/src/network/Socket.cpp @@ -6,12 +6,13 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/07/03 16:23:55 by sanghupa #+# #+# */ -/* Updated: 2024/07/05 20:30:38 by sanghupa ### ########.fr */ +/* Updated: 2024/07/10 23:07:54 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ #include "webserv.hpp" #include "Socket.hpp" +#include "cstring" Socket::Socket() : _socketfd(-1) @@ -56,7 +57,7 @@ void Socket::_bindAddress(int port) { memset(&_address, 0, sizeof(_address)); _address.sin_family = AF_INET; - _address.sin_addr.s_addr = htonl(INADDR_ANY); + _address.sin_addr.s_addr = INADDR_ANY; _address.sin_port = htons(port); if (::bind(_socketfd, (struct sockaddr*)&_address, sizeof(_address)) < 0) { @@ -93,14 +94,16 @@ void Socket::set_nonblocking() Socket Socket::accept() { + std::cout << "\rSocket fd again: " << _socketfd << std::endl; int clientfd = ::accept(_socketfd, NULL, NULL); - if (clientfd < 0) - { - throw std::runtime_error("Failed to accept connection"); - } + // if (clientfd < 0) + // { + // throw std::runtime_error("Failed to accept connection"); + // } return Socket(clientfd); } +/* void Socket::connet(const std::string host, int port) {} @@ -109,6 +112,7 @@ ssize_t Socket::recv(char* buf, size_t len) ssize_t Socket::send(const char* buf, size_t len) {} +*/ void Socket::close() { diff --git a/src/server/Server.cpp b/src/server/Server.cpp index 50cd2f0..15ff78f 100644 --- a/src/server/Server.cpp +++ b/src/server/Server.cpp @@ -6,13 +6,76 @@ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:46 by sanghupa #+# #+# */ -/* Updated: 2024/07/08 22:48:41 by sanghupa ### ########.fr */ +/* Updated: 2024/07/12 14:47:38 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ #include "webserv.hpp" #include "Server.hpp" +// ---------------------------------------------------- + +/// @brief Handle GET request by reading the file and returning an Http response. +/// @param path The path of the file to read. +/// @return The Http response containing the file contents. +/// In case the file is not found, a 404 Not Found response is returned. +static std::string handle_get(const std::string& path) +{ + // Prepend the current directory to the file path + std::string file_path = "./www/static" + path; + + // Open the file + std::ifstream ifs (file_path.data()); + + // Check if the file is open + if (!ifs.is_open()) + { + // If not, return a 404 Not Found response + return "Http/1.1 404 Not Found\r\n\r\n"; + } + + // Create a string stream to hold the Http response + std::stringstream response; + + // Add the Http response headers + response << "Http/1.1 200 OK\r\n"; + response << "Content-Type: text/html\r\n"; + response << "Connection: close\r\n\r\n"; + + // Read the file contents into the response and return it + response << ifs.rdbuf(); + return response.str(); +} + +/// @brief Parses an Http request and handles it. +/// @param request The Http request to parse and handle. +/// @return The Http response to send back to the client. +/// @throws None +static std::string handle_request(const std::string& request) +{ + // Parse the Http request + std::istringstream request_stream(request); + std::string method, path, version; + request_stream >> method >> path >> version; + + // Log the request method, path, and version + std::cout << "\r" << method << " | " << path << " | " << version << std::endl; + + if (method == "GET") + { + // Handle GET request + return handle_get(path); + } + else + { + // Handle other Http methods + // Return a 405 Method Not Allowed response + return "Http/1.1 405 Method Not Allowed\r\n\r\n"; + } +} + +// ---------------------------------------------------- + // TODO: Implement Config // Server::Server(Config config) // : _serverPort(std::to_string(config.getPort())) @@ -20,9 +83,11 @@ // {} Server::Server(int port) - : _serverPort(std::to_string(port)) - , _maxBodySize(0) -{} + : _serverPort(std::string("8080")) + , _maxBodySize(1024) +{ + (void)port; +} Server::~Server() { @@ -31,6 +96,7 @@ Server::~Server() // TODO: Delete all locations } +/* void Server::start() { // TODO: Implement and replace stoi() function @@ -55,29 +121,47 @@ void Server::start() } } } +*/ // Try-Catch implementation for start() void Server::start() { try { // TODO: Implement and replace stoi() function - _listenSocket.bind(stoi(_serverPort)); + // _listenSocket.bind(stoi(_serverPort)); + _listenSocket.bind(8080); _listenSocket.listen(); _listenSocket.set_nonblocking(); - _poller.addSocket(_listenSocket, POLLIN); + // _poller.addSocket(_listenSocket, POLLIN); + _pollfds.push_back((struct pollfd){_listenSocket.getFd(), POLLIN, 0}); _running = true; // Logger::info("Server started on port %d", port); + std::cout << "\rServer started on port " << _serverPort << "..." << std::endl; - while (_running) { - std::vector events = _poller.poll(1000); - for (size_t i = 0; i < events.size(); i++ ) - { - Poller::t_event event = events[i]; - if (event.socket.getFd() == _listenSocket.getFd()) { - _handleNewConnection(); - } else { - _handleClientData(event); + while (_running) + { + // std::vector events = _poller.poll(-1); + // for (size_t i = 0; i < events.size(); i++ ) + // { + // Poller::t_event event = events[i]; + // if (event.events & POLLIN) { + // if (event.socket.getFd() == _listenSocket.getFd()) { + // _handleNewConnection(); + // } else { + // _handleClientData(event); + // } + // } + // } + + poll(_pollfds.data(), _pollfds.size(), -1); + for (size_t i = 0; i < _pollfds.size(); i++) { + if (_pollfds[i].revents & POLLIN) { + if (_pollfds[i].fd == _listenSocket.getFd()) { + _acceptNewConnection(); + } else { + _handleClientData_2(_pollfds[i].fd, i); + } } } } @@ -99,7 +183,101 @@ void Server::stop() _listenSocket.close(); _poller.removeAllSockets(); // Logger::info("Server stopped"); + std::cout << "\rServer stopped" << std::endl; + } +} + +void Server::_acceptNewConnection() +{ + while (true) + { + int clientfd = accept(_listenSocket.getFd(), NULL, NULL); + if (clientfd < 0) + { + // throw std::runtime_error("Failed to accept connection"); + break ; + } + + // Set nonblocking mode + int flags = fcntl(clientfd, F_GETFL, 0); + if (flags == -1) + { + throw std::runtime_error("Failed to get file descriptor flags"); + } + flags |= O_NONBLOCK; + if (fcntl(clientfd, F_SETFL, flags) == -1) + { + throw std::runtime_error("Failed to set file descriptor flags to non-blocking"); + } + + _pollfds.push_back((struct pollfd){clientfd, POLLIN, 0}); + } +} + +void Server::_handleClientData_2(int clientSocket, size_t idx) +{ + char buffer[1024]; + ssize_t count = read(clientSocket, buffer, sizeof(buffer)); + if (count <= 0) + { + close(clientSocket); + _pollfds.erase(_pollfds.begin() + idx); } + + std::string requestData(buffer, count); + std::string responseData = handle_request(requestData); + write(clientSocket, responseData.c_str(), responseData.size()); + close(clientSocket); + _pollfds.erase(_pollfds.begin() + idx); +} + +void Server::_handleNewConnection() +{ + // Suggestion: maybe use try-catch ? + Socket clientSocket = _listenSocket.accept(); + clientSocket.set_nonblocking(); + _poller.addSocket(clientSocket, POLLIN); + // Logger::info("Client accepted: %d", clientSocket.getFd()); + std::cout << "\rClient accepted: " << clientSocket.getFd() << "..." << std::endl; +} + +void Server::_handleClientData(Poller::t_event event) +{ + // Suggestion: maybe use try-catch ? + char buffer[1024]; + ssize_t count = read(event.socket.getFd(), buffer, sizeof(buffer)); + if (count <= 0) + { + _poller.removeSocket(event.socket); + event.socket.close(); + return ; + } + + std::string requestData(buffer, count); + /* + HttpRequest request; + if (!request.parse(requestData)) + { + _poller.removeSocket(event.socket); + event.socket.close(); + return ; + } + + // Process the request and send a response + HttpResponse response = _requestHandler.handleRequest(request); + std::string responseData = response.toString(); + */ + std::string responseData = handle_request(requestData); + write(event.socket.getFd(), responseData.c_str(), responseData.size()); + _poller.removeSocket(event.socket); + event.socket.close(); + /* + if (request.isConnectionClose()) + { + _poller.removeSocket(event.socket); + event.socket.close(); + } + */ } // Getters @@ -219,46 +397,3 @@ void Server::setServerCgiPath(std::string serverCgiPath) { _serverCgiPath = serverCgiPath; } - - -void Server::_handleNewConnection() -{ - // Suggestion: maybe use try-catch ? - Socket clientSocket = _listenSocket.accept(); - clientSocket.set_nonblocking(); - _poller.addSocket(clientSocket, POLLIN); - // Logger::info("Client accepted: %d", clientSocket.getFd()); -} - -void Server::_handleClientData(Poller::t_event event) -{ - // Suggestion: maybe use try-catch ? - char buffer[1024]; - ssize_t count = read(event.socket.getFd(), buffer, sizeof(buffer)); - if (count <= 0) - { - _poller.removeSocket(event.socket); - event.socket.close(); - return ; - } - - std::string requestData(buffer, count); - HttpRequest request; - if (!request.parse(requestData)) - { - _poller.removeSocket(event.socket); - event.socket.close(); - return ; - } - - // Process the request and send a response - HttpResponse response = _requestHandler.handleRequest(request); - std::string responseData = response.toString(); - write(event.socket.getFd(), responseData.c_str(), responseData.size()); - - if (request.isConnectionClose()) - { - _poller.removeSocket(event.socket); - event.socket.close(); - } -} diff --git a/src/util/Config.cpp b/src/util/Config.cpp index 8cc66c0..3ce3476 100644 --- a/src/util/Config.cpp +++ b/src/util/Config.cpp @@ -1,18 +1,39 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* Config.hpp :+: :+: :+: */ +/* Config.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:00 by sanghupa #+# #+# */ -/* Updated: 2024/06/30 16:24:32 by sanghupa ### ########.fr */ +/* Updated: 2024/07/08 23:45:02 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef CONFIG_HPP -# define CONFIG_HPP +#include "webserv.hpp" +#include "Config.hpp" -# include "webserv.hpp" +Config::Config() +{ + // TODO: Set default value at here if necessary +} -#endif \ No newline at end of file +Config::~Config() +{ + // TODO: Destruct at here if necessary +} + +void Config::load(const std::string filename) +{} + +std::string Config::get(const std::string key) +{} + +int Config::getInt(const std::string key) +{} + +int Config::getPort() +{} + +void Config::_parseConfigFile(const std::string filename) +{} diff --git a/src/util/Location.cpp b/src/util/Location.cpp index 46c4dc1..0ee1bf5 100644 --- a/src/util/Location.cpp +++ b/src/util/Location.cpp @@ -1,60 +1,71 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* Location.hpp :+: :+: :+: */ +/* Location.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: sanghupa +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/06/30 16:23:00 by sanghupa #+# #+# */ -/* Updated: 2024/07/02 22:02:42 by sanghupa ### ########.fr */ +/* Updated: 2024/07/08 23:40:55 by sanghupa ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef LOCATION_HPP -# define LOCATION_HPP - -# include "webserv.hpp" -# include "Server.hpp" - -class Server; - -class Location -{ - public: - Location(Server* server, std::string path); - ~Location(); - - // Getters - Server* getServer() const; - std::string getPath() const; - std::string getRootPath() const; - std::string getUploadPath() const; - std::string getIndex() const; - std::vector getAllowedMethods() const; - std::string getRedirectPath() const; - bool isRedirect() const; - int getRedirectCode() const; - std::map getCgi() const; - // Setters - void setPath(std::string path); - void setRootPath(std::string rootPath); - void setUploadPath(std::string uploadPath); - void setIndex(std::string index); - void setAllowedMethods(std::vector allowedMethods); - void setRedirect(std::string redirectPath); - void setCgi(std::string cgi); - - private: - Server* _server; - std::string _path; - std::string _rootPath; - std::string _uploadPath; - std::string _index; - std::vector _allowedMethods; - std::string _redirectPath; - bool _isRedirect; - int _redirectCode; - std::map _cgi; -}; - -#endif \ No newline at end of file +#include "webserv.hpp" +#include "Location.hpp" + +Location::Location(Server* server, std::string path) +{} + +Location::~Location() +{} + +Server* Location::getServer() const +{} + +std::string Location::getPath() const +{} + +std::string Location::getRootPath() const +{} + +std::string Location::getUploadPath() const +{} + +std::string Location::getIndex() const +{} + +std::vector Location::getAllowedMethods() const +{} + +std::string Location::getRedirectPath() const +{} + +bool Location::isRedirect() const +{} + +int Location::getRedirectCode() const +{} + +std::map Location::getCgi() const +{} + +void Location::setPath(std::string path) +{} + +void Location::setRootPath(std::string rootPath) +{} + +void Location::setUploadPath(std::string uploadPath) +{} + +void Location::setIndex(std::string index) +{} + +void Location::setAllowedMethods(std::vector allowedMethods) +{} + +void Location::setRedirect(std::string redirectPath) +{} + +void Location::setCgi(std::string cgi) +{}