#include "Webserv.hpp" #define MAX_EVENTS 42 // arbitrary #define TIMEOUT 3000 void Webserv::run() { std::cerr << "Server started\n"; struct epoll_event events[MAX_EVENTS]; int nfds; int i; int count_loop = 0; std::vector::iterator it_lsocket; std::vector::iterator it_client; Client *client_cgi_input = NULL; Client *client_cgi_output = NULL; std::signal(SIGPIPE, signal_handler); std::signal(SIGINT, signal_handler); g_run = true; family = PARENT; while (g_run) { std::cout << family << "|" << ++count_loop << "-----loop epoll() "; nfds = ::epoll_wait(_epfd, events, MAX_EVENTS, TIMEOUT); std::cerr << "(nfds=" << nfds << ")" << std::endl; if (nfds == -1) { int errno_copy = errno; std::perror("err epoll_wait()"); if (errno_copy == EINTR) g_run = false; else { std::signal(SIGPIPE, SIG_DFL); std::signal(SIGINT, SIG_DFL); throw std::runtime_error("Epoll wait"); } } else if (nfds == 0 && !_clients.empty()) _timeout(); i = 0; while (i < nfds) { try { it_lsocket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd); it_client = std::find(_clients.begin(), _clients.end(), events[i].data.fd); client_cgi_input = _find_cgi_input_fd(events[i].data.fd); client_cgi_output = _find_cgi_output_fd(events[i].data.fd); if (it_lsocket != _listen_sockets.end()) { if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) _handle_epoll_error_lsocket(events[i].events, it_lsocket); else if (events[i].events & EPOLLIN) _accept_connection(*it_lsocket); } else if (it_client != _clients.end()) { if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) _handle_epoll_error_client(events[i].events, events[i].data.fd); else if (events[i].events & EPOLLIN) _request( &(*it_client) ); else if (events[i].events & EPOLLOUT) _response( &(*it_client) ); } else if (client_cgi_input) { if (events[i].events & EPOLLERR || events[i].events & EPOLLHUP) _handle_epollerr_cgi_input(events[i].events, client_cgi_input); else if (events[i].events & EPOLLOUT) _cgi_input_ready(client_cgi_input); } else if (client_cgi_output) { if (events[i].events & EPOLLERR) _handle_epollerr_cgi_output(events[i].events, client_cgi_output); else if (events[i].events & EPOLLIN) _read_cgi_output(client_cgi_output); else if ( (events[i].events & EPOLLHUP) && !(events[i].events & EPOLLIN) ) _handle_epollhup_cgi_output(events[i].events, client_cgi_output); } else { std::cerr << "NOTHING FOR FD = " << events[i].data.fd << "\n"; // DEBUG } ++i; if (!g_run) break; } catch (const std::bad_alloc& e) { std::cerr << e.what() << '\n'; _close_all_clients(); /* Swap to free the memory From : http://www.uml.org.cn/c%2B%2B/pdf/EffectiveSTL.pdf#page=66 */ std::vector().swap(_clients); break; } catch (const Webserv::ExecFail& e) { std::cerr << e.what() << '\n'; throw; } catch (const std::exception& e) { std::cerr << e.what() << '\n'; ++i; } } } std::signal(SIGPIPE, SIG_DFL); std::signal(SIGINT, SIG_DFL); }