#include "Webserv.hpp" void Webserv::_close_client(int fd) { std::vector::iterator it = _clients.begin(); std::vector::iterator it_end = _clients.end(); while (it != it_end) { if (*it == fd) { std::cout << family << "| (" << std::setw(2) << it->get_cl_fd() << ") close client fd " << fd << std::endl; if (::close(fd) == -1) std::perror("err close()"); _close_client_cgi_pipes(&(*it)); _clients.erase(it); break; } ++it; } } void Webserv::_close_client_cgi_pipes(Client *client) { if (client->cgi_state) { // No need to reset the fd to -1 normaly std::cerr << family << "| (" << std::setw(2) << client->get_cl_fd() << ") close pipe wtc [" << client->cgi_pipe_w_to_child << "]\n"; if (client->cgi_pipe_w_to_child != -1) if (::close(client->cgi_pipe_w_to_child) == -1) std::perror("err close()"); client->cgi_pipe_w_to_child = -1; std::cerr << family << "| (" << std::setw(2) << client->get_cl_fd() << ") close pipe rfc [" << client->cgi_pipe_r_from_child << "]\n"; if (client->cgi_pipe_r_from_child != -1) if (::close(client->cgi_pipe_r_from_child) == -1) std::perror("err close()"); client->cgi_pipe_r_from_child = -1; std::cerr << family << "| (" << std::setw(2) << client->get_cl_fd() << ") close pipe wtp [" << client->cgi_pipe_w_to_parent << "]\n"; if (client->cgi_pipe_w_to_parent != -1) if (::close(client->cgi_pipe_w_to_parent) == -1) std::perror("err close()"); client->cgi_pipe_w_to_parent = -1; std::cerr << family << "| (" << std::setw(2) << client->get_cl_fd() << ") close pipe rfp [" << client->cgi_pipe_r_from_parent << "]\n"; if (client->cgi_pipe_r_from_parent != -1) if (::close(client->cgi_pipe_r_from_parent) == -1) std::perror("err close()"); client->cgi_pipe_r_from_parent = -1; } } void Webserv::_close_all_clients() { _close_all_clients_fd(); _clients.clear(); } void Webserv::_close_all_clients_fd() { _close_all_clients_cgi_pipes(); std::vector::iterator it = _clients.begin(); std::vector::iterator it_end = _clients.end(); while (it != it_end) { std::cout << family << "| (" << std::setw(2) << it->get_cl_fd() << ") close client fd " << it->get_cl_fd() << std::endl; if (::close(it->get_cl_fd()) == -1) std::perror("err close()"); ++it; } } void Webserv::_close_all_clients_cgi_pipes() { std::vector::iterator it = _clients.begin(); std::vector::iterator it_end = _clients.end(); while (it != it_end) { _close_client_cgi_pipes(&(*it)); ++it; } } void Webserv::_close_all_listen_sockets() { // TODO : change like clients (clear in place of pop_back) while (!_listen_sockets.empty()) { std::cerr << "close lsocket fd " << _listen_sockets.back().fd << "\n"; if (::close(_listen_sockets.back().fd) == -1) std::perror("err close()"); _listen_sockets.pop_back(); } } /* ** Many common code with init_virtual_servers(). Could refactor it. */ void Webserv::_reopen_lsocket(std::vector::iterator it) { int ret; std::cerr << "close lsocket " << it->fd << "\n"; if (::close(it->fd) == -1) std::perror("err close()"); std::cerr << "try to reopen lsocket\n"; ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (ret == -1) { std::perror("err socket()"); _listen_sockets.erase(it); return; } it->fd = ret; // From : https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select // allow socket descriptor to be reuseable int on = 1; if (setsockopt(it->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { ::perror("err setsockopt()"); _listen_sockets.erase(it); return; } try { _bind(it->fd, std::strtoul(it->port.c_str(), NULL, 10), it->host); _listen(it->fd, 42); // 42 arbitrary } catch (const std::exception& e) { std::cerr << e.what() << '\n'; _listen_sockets.erase(it); return; } if (_epoll_update(it->fd, EPOLLIN, EPOLL_CTL_ADD) == -1) { _listen_sockets.erase(it); return; } std::cerr << "reopen success\n"; } void Webserv::_handle_epoll_error_lsocket(uint32_t events, std::vector::iterator it) { if (events & EPOLLERR) std::cerr << "EPOLLERR on lsocket fd " << it->fd << "\n"; // DEBUG if (events & EPOLLHUP) std::cerr << "EPOLLHUP on lsocket fd " << it->fd << "\n"; // DEBUG _reopen_lsocket(it); } void Webserv::_handle_epoll_error_client(uint32_t events, int fd) { if (events & EPOLLERR) std::cerr << "EPOLLERR on client fd " << fd << "\n"; // DEBUG if (events & EPOLLHUP) std::cerr << "EPOLLHUP on client fd " << fd << "\n"; // DEBUG _close_client(fd); }