161 lines
4.5 KiB
C++
161 lines
4.5 KiB
C++
|
|
#include "Webserv.hpp"
|
|
|
|
void Webserv::_close_client(int fd)
|
|
{
|
|
std::vector<Client>::iterator it = _clients.begin();
|
|
std::vector<Client>::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<Client>::iterator it = _clients.begin();
|
|
std::vector<Client>::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<Client>::iterator it = _clients.begin();
|
|
std::vector<Client>::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<listen_socket>::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<listen_socket>::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);
|
|
}
|