/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* server.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: adjoly +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/04/11 16:11:40 by adjoly #+# #+# */ /* Updated: 2025/04/17 12:37:45 by adjoly ### ########.fr */ /* */ /* ************************************************************************** */ #include #include #include #include #include #include #include #include #include using namespace webserv; std::string getMethod(std::string &data) { return (data.substr(0, data.substr(0, 4).find_last_not_of(" ") + 1)); } void Server::_handle_client(int fd) { std::string received_data; char buffer[BUFFER_SIZE]; ssize_t bytes_received; do { std::memset(buffer, 0, BUFFER_SIZE); bytes_received = recv(fd, buffer, BUFFER_SIZE - 1, 0); if (bytes_received == -1) { _log->error("failed to receive request"); continue; } received_data += std::string(buffer, bytes_received); } while (buffer[bytes_received]); std::string response; if (getMethod(received_data) == "GET") { _log->info("get request received"); http::Get request(received_data); response = request.execute().str(); } else if (getMethod(received_data) == "DELETE") { _log->info("delete request received"); http::Delete request(received_data); response = request.execute().str(); } else if (getMethod(received_data) == "POST") { _log->info("post request received"); http::Post request(received_data); response = request.execute().str(); } else { response = "HTTP/1.1 501 Not Implemented\r\nContent-Type: " "text/html\r\n\r\n

501 Not " "Implemented

"; } send(fd, response.c_str(), response.length(), 0); } int Server::_fillHostsPorts(std::vector &hosts, std::vector &ports) { std::vector *config = _conf->getServers(); for (std::vector::iterator it = config->begin(); it != config->end(); it++) { hosts.push_back((*it)->getHost()); ports.push_back((*it)->getPort()); } return config->size(); } void Server::_setup(void) { std::vector hosts; std::vector ports; int size = _fillHostsPorts(hosts, ports); if (size < 1) throw std::runtime_error("no server present in the config file"); std::vector::iterator itH = hosts.begin(); for (std::vector::iterator itP = ports.begin(); itP != ports.end(); itP++, itH++) { try { int fd = _createSocket(*itH, *itP); _fds_server.push_back(fd); } catch (std::exception &e) { throw e; } } } void Server::_run(void) { struct pollfd fd; fd.fd = _fd_server; fd.events = POLLIN; _client_fds.clear(); _client_fds.push_back(fd); int nbr_client = 0; while (727) { int ret = poll(_client_fds.data(), nbr_client + 1, -1); if (ret < 0) { close(_fd_server); throw std::runtime_error("poll failed :("); } if (_client_fds[0].revents & POLLIN) { struct sockaddr_in client_addr; socklen_t addrlen = sizeof(client_addr); int client_fd = accept(_fd_server, (struct sockaddr *)&client_addr, &addrlen); if (client_fd < 0) { _log->error("accept failed"); continue; } struct pollfd client_pollfd; client_pollfd.fd = client_fd; client_pollfd.events = POLLIN; _client_fds.push_back(client_pollfd); ++nbr_client; // if (nbr_client) TODO do we need a max client probably not :D } for (int i = 1; i <= nbr_client;) { if (_client_fds[i].revents & POLLIN) { _handle_client(_client_fds[i].fd); close(_client_fds[i].fd); _client_fds[i] = _client_fds[nbr_client--]; _client_fds.pop_back(); } else ++i; } } } Server::Server(config::Config *conf) : _conf(conf) { log("➕", "Server::Server", "config constructor called"); _log = conf->getLogger(); _setup(); _run(); } Server::~Server(void) { log("➖", "Server::Server", "destructor called"); for (std::vector::iterator it = _client_fds.begin(); it != _client_fds.end(); it++) close(it->fd); close(_fd_server); }