From e5c286917228ab90bf2dcf9b71bc24d4e4efe6c6 Mon Sep 17 00:00:00 2001 From: LuckyLaszlo Date: Sun, 31 Jul 2022 00:27:48 +0200 Subject: [PATCH] Review parsing Eric and Luke. Combined the config parser with Webserv class. --- Makefile | 5 +- default.config | 21 ++- srcs/ConfigParser.cpp | 6 +- srcs/Server.hpp | 32 ---- srcs/Webserv.cpp | 324 -------------------------------------- srcs/Webserv.hpp | 18 ++- srcs/main.cpp | 7 +- srcs/webserv/base.cpp | 3 +- srcs/webserv/init.cpp | 47 ++++-- srcs/webserv/run_loop.cpp | 4 +- 10 files changed, 76 insertions(+), 391 deletions(-) delete mode 100644 srcs/Server.hpp delete mode 100644 srcs/Webserv.cpp diff --git a/Makefile b/Makefile index e454828..912ee6b 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ NAME = webserv CXX = c++ CXXFLAGS = -Wall -Wextra #-Werror -CXXFLAGS += $(HEADERS) +CXXFLAGS += -I$(HEADERS_D) CXXFLAGS += -std=c++98 CXXFLAGS += -g CXXFLAGS += -MMD -MP #header dependencie @@ -12,14 +12,13 @@ CXXFLAGS += -MMD -MP #header dependencie #SHELL = /bin/zsh VPATH = $(SRCS_D) -HEADERS = $(HEADERS_D:%=-I%) +# HEADERS = $(HEADERS_D:%=-I%) HEADERS_D = ./srcs HEADERS = Webserv.hpp \ ConfigParser.hpp \ ServerConfig.hpp \ LocationConfig.hpp \ Client.hpp \ - Server.hpp \ MethodType.hpp \ utils.hpp \ diff --git a/default.config b/default.config index 3912ba6..395acfc 100644 --- a/default.config +++ b/default.config @@ -4,15 +4,26 @@ server { server_name our_server; - listen 0.0.0.0:80; + listen 0.0.0.0:4040; + + + index index.html; # this is another comment + root ./www/; + + allow_methods GET; +} + +server { + +# this is a comment + + server_name our_server; + + listen 0.0.0.0:4047; index index.html; # this is another comment root ./www/; allow_methods GET; - - - - } diff --git a/srcs/ConfigParser.cpp b/srcs/ConfigParser.cpp index 8fa9e70..d7a24a3 100644 --- a/srcs/ConfigParser.cpp +++ b/srcs/ConfigParser.cpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* ConfigParser.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: me +#+ +:+ +#+ */ +/* By: lperrey +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2022/07/13 22:11:17 by me #+# #+# */ -/* Updated: 2022/07/27 19:27:55 by me ### ########.fr */ +/* Updated: 2022/07/30 23:07:42 by lperrey ### ########.fr */ /* */ /* ************************************************************************** */ @@ -447,7 +447,7 @@ std::string ConfigParser::_get_rest_of_line(size_t *curr) std::string values = _content.substr(start, *curr - start); // std::cout << "curr + 4 = " << _content.substr(*curr, 4) << "\n"; - std::cout << "rest of Line values: " << values << "\n"; +// std::cout << "rest of Line values: " << values << "\n"; return (values); } diff --git a/srcs/Server.hpp b/srcs/Server.hpp deleted file mode 100644 index a9063d1..0000000 --- a/srcs/Server.hpp +++ /dev/null @@ -1,32 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Server.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: lperrey +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/07/24 12:11:07 by lperrey #+# #+# */ -/* Updated: 2022/07/24 12:11:13 by lperrey ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef SERVER_HPP -# define SERVER_HPP - -# include -# include - -class Server -{ - public: - // Server(Placeholder); - // Server(); - // Server(Server const &src); - // ~Server(); - // Server &operator=(Server const &rhs); - - private: - -}; - -#endif \ No newline at end of file diff --git a/srcs/Webserv.cpp b/srcs/Webserv.cpp deleted file mode 100644 index b26964d..0000000 --- a/srcs/Webserv.cpp +++ /dev/null @@ -1,324 +0,0 @@ - -#include "Webserv.hpp" - -int g_last_signal; -bool g_run; -void signal_handler(int signum) -{ - g_last_signal = signum; -} - -Webserv::Webserv() -{ - std::cerr << "Server init\n"; - - _epfd = ::epoll_create1(0); // (EPOLL_CLOEXEC) for CGI fork ? - if (_epfd == -1) - { - std::perror("err epoll_create1(): "); - throw std::runtime_error("Epoll init"); - } - - std::signal(SIGPIPE, signal_handler); - std::signal(SIGINT, signal_handler); -} - -/* Webserv::Webserv(Webserv const &src) -{ - -} */ - -// we'll come back to this -/* -Webserv::Webserv(std::vector* servers) -: _servers(servers) -{ - // talk to luke about what all this does - // the Param Constructor might need to do dif stuff - std::cout << "Server init\n"; - - _epfd = ::epoll_create1(0); // (EPOLL_CLOEXEC) for CGI fork ? - if (_epfd == -1) - { - std::perror("err epoll_create1(): "); - throw std::runtime_error("Epoll init"); - } -} -*/ - -Webserv::~Webserv() -{ - close(_socket_fd); - close(_epfd); - _close_all_clients(); - std::cerr << "Server destroyed\n"; -} - -/* Webserv & Webserv::operator=(Webserv const &rhs) -{ - -} */ - - /////////////// - // Functions // - -void Webserv::init_virtual_servers() // ADD config param -{ - _socket_fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ? - if (_socket_fd == -1) - { - std::perror("err socket(): "); - throw std::runtime_error("Socket init"); - } - - _bind(_socket_fd, 80); - _listen(_socket_fd, 512); // 512 arbitrary - - if (_epoll_update(_socket_fd, EPOLLIN, EPOLL_CTL_ADD) == -1) - throw std::runtime_error("Socket init"); -} - -void Webserv::start() -{ - std::cerr << "Server started\n"; - struct epoll_event events[MAX_EVENTS]; - int nfds; - int i; - int count_loop = 0; - - g_run = true; - while (g_run) - { - std::cerr << ++count_loop << "----loop epoll()\n"; - nfds = ::epoll_wait(_epfd, events, MAX_EVENTS, TIMEOUT); - if (nfds == -1) - { - std::perror("err epoll_wait(): "); - throw std::runtime_error("Epoll wait"); - } - else if (nfds == 0) - { - if (!_clients.empty()) - { - std::cerr << "Timeout " << TIMEOUT << "ms\n"; - _close_all_clients(); - } - } - i = 0; - while (i < nfds) - { - // if ((events[i].data.u32 == SERVER_FD) && (events[i].events & EPOLLIN)) // Dont work, see "SERVER_FD" define - if ((events[i].data.fd == _socket_fd) && (events[i].events & EPOLLIN)) - _accept_connection(events[i].data.fd); - else if (events[i].events & EPOLLIN) - _read_request(static_cast(events[i].data.ptr)); - else if (events[i].events & EPOLLOUT) - _send_response(static_cast(events[i].data.ptr)); - ++i; - _actual_client = NULL; - } - } - -} - - - /////////////////////// - // Private Functions // - -void Webserv::_accept_connection(int fd) -{ - struct sockaddr_in addr; - socklen_t addr_len; - int accepted_fd; - - std::cerr << "accept()\n"; - addr_len = sizeof addr; - accepted_fd = ::accept(fd, (sockaddr*)&addr, &addr_len); - if (accepted_fd == -1) - { - std::perror("err accept(): "); - return ; - } - ::fcntl(accepted_fd, F_SETFL, O_NONBLOCK); - - _clients.push_back(Client()); - _clients.back().fd = accepted_fd; - - _epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD, &_clients.back()); -} - - ////////// - // READ // -void Webserv::_read_request(Client *client) -{ - char buf[BUFSIZE+1]; - ssize_t ret; - _actual_client = client; - - std::cerr << "recv()\n"; - ret = ::recv(client->fd, buf, BUFSIZE, 0); - if (ret == -1) - { - std::perror("err recv(): "); - // if (g_last_signal) - // _handle_last_signal(); - // else - // _close_client(client->fd); - - std::cerr << "client ptr =" << client << "\n"; // DEBUG - std::cerr << "client.fd =" << client->fd << "\n"; // DEBUG - return ; - } - /* - if (ret == BUFSIZE) - // send error like "request too long" to client - */ - - buf[ret] = '\0'; - client->raw_request.append(buf); - - _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD, client); -} - - /////////// - // WRITE // -void Webserv::_send_response(Client *client) -{ - ssize_t ret; - _actual_client = client; - - std::cerr << "send()\n"; - std::cerr << "RAW_REQUEST\n|\n" << client->raw_request << "|\n"; - - ret = ::send(client->fd, MSG_TEST, sizeof MSG_TEST - 1, 0); - if (ret == -1) - { - std::perror("err send(): "); - if (g_last_signal) - _handle_last_signal(); - // else - // _close_client(client->fd); - return ; - } - - _close_client(client->fd); - // if (client->raw_request.find("Connection: keep-alive") == std::string::npos) - // _close_client(client->fd); - // else - // _epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD, client); - - client->raw_request.clear(); -} - - - //////////////////// - // Misc functions // - -int Webserv::_epoll_update(int fd, uint32_t events, int op) -{ - struct epoll_event ev; - std::memset(&ev, 0, sizeof ev); - ev.events = events; - ev.data.fd = fd; - if (::epoll_ctl(_epfd, op, fd, &ev) == -1) - { - std::perror("err _epoll_update(): "); - return (-1); - } - return (0); -} - -int Webserv::_epoll_update(int fd, uint32_t events, int op, void *ptr) -{ - struct epoll_event ev; - std::memset(&ev, 0, sizeof ev); - ev.events = events; - ev.data.ptr = ptr; - if (::epoll_ctl(_epfd, op, fd, &ev) == -1) - { - std::perror("err _epoll_update(): "); - return (-1); - } - return (0); -} - -void Webserv::_handle_last_signal() -{ - if (g_last_signal == SIGPIPE) - { - std::cerr << "SIGPIPE\n"; - if (_actual_client) - { - _close_client(_actual_client->fd); - _actual_client = NULL; - } - } - else if (g_last_signal == SIGINT) - { - g_run = false; - } - g_last_signal = 0; -} - -void Webserv::_close_client(int fd) -{ - std::vector::iterator it = _clients.begin(); - while (it != _clients.end()) - { - if (it->fd == fd) - { - // _epoll_update(fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG - if (::close(fd) == -1) - std::perror("err close(): "); - else - std::cerr << "close fd " << fd << "\n"; - _clients.erase(it); - break; - } - ++it; - } -} - -void Webserv::_close_all_clients() -{ - while (!_clients.empty()) - { - // _epoll_update(_clients.back().fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG - if (::close(_clients.back().fd) == -1) - std::perror("err close(): "); - else - std::cerr << "close fd " << _clients.back().fd << "\n"; - _clients.pop_back(); - } -} - - - //////////////////// - // Init functions // - -void Webserv::_bind(int socket_fd, in_port_t port) -{ - // cast invalid ? how to ? - // const struct sockaddr* cast_test = static_cast(addr); - - struct sockaddr_in addr; - std::memset(&addr, 0, sizeof addr); - addr.sin_family = AF_INET; - addr.sin_port = ::htons(port); - addr.sin_addr.s_addr = ::htonl(INADDR_ANY); // htonl useless with 0 value (INADDR_ANY) ? - - if (::bind(socket_fd, (const sockaddr*)&addr, sizeof addr) == -1) - { - std::perror("err bind(): "); - throw std::runtime_error("Socket bind"); - } -} - -void Webserv::_listen(int socket_fd, unsigned int max_connections) -{ - if (::listen(socket_fd, max_connections) == -1) - { - std::perror("err listen(): "); - throw std::runtime_error("Socket listen"); - } -} diff --git a/srcs/Webserv.hpp b/srcs/Webserv.hpp index 015669b..6ba2970 100644 --- a/srcs/Webserv.hpp +++ b/srcs/Webserv.hpp @@ -24,21 +24,25 @@ # include // fcntl # include "Client.hpp" -# include "Server.hpp" -# include "ConfigParser.hpp" # include "ServerConfig.hpp" + +// TODO: A virer +# include "ConfigParser.hpp" # include "LocationConfig.hpp" # include "MethodType.hpp" # include "utils.hpp" +// TODO: A virer + # include // signal # include # include # include # include -# include // itoa +# include // atoi, itoa # include // ifstream char *ft_itoa(int n); # include // access +# include // find extern bool g_run; extern int g_last_signal; @@ -75,14 +79,14 @@ class Webserv // Webserv &operator=(Webserv const &rhs); // init.cpp - void init_virtual_servers(); // ADD config param + void init_virtual_servers(std::vector* servers); // run_loop.cpp void run(); private: int _epfd; - int _socket_fd; // temp, to replace with std::vector - // std::vector _servers; + std::vector _listen_sockets; + std::vector _servers; std::vector _clients; // accept.cpp @@ -105,7 +109,7 @@ class Webserv void _close_client(int fd); void _close_all_clients(); // init.cpp - void _bind(int socket_fd, in_port_t port); + void _bind(int socket_fd, in_port_t port, std::string host); void _listen(int socket_fd, unsigned int max_connections); }; diff --git a/srcs/main.cpp b/srcs/main.cpp index c0d1d71..4c580f3 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -34,9 +34,12 @@ int main(int ac, char **av) // Webserv serv(configParser.parse()); // is this better or worse than using -// serv.init_virtual_servers(); -// serv.start(); + Webserv serv; + + // serv.init_virtual_servers(); + serv.init_virtual_servers(servers); delete servers; + serv.run(); } catch (std::exception& e) { diff --git a/srcs/webserv/base.cpp b/srcs/webserv/base.cpp index f4d4e0d..6267ec9 100644 --- a/srcs/webserv/base.cpp +++ b/srcs/webserv/base.cpp @@ -42,7 +42,8 @@ Webserv::Webserv(std::vector* servers) Webserv::~Webserv() { - close(_socket_fd); + //close(_socket_fd); + // TODO : CLOSE ALL _listen_sockets close(_epfd); _close_all_clients(); std::cerr << "Server destroyed\n"; diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index 97a3b90..b773964 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -1,23 +1,43 @@ #include "Webserv.hpp" -void Webserv::init_virtual_servers() // ADD config param +void Webserv::init_virtual_servers(std::vector* servers) { - _socket_fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ? - if (_socket_fd == -1) + int ret; + std::vector _open_ports; + + _servers = *servers; + _listen_sockets.clear(); + std::vector::iterator it = _servers.begin(); + + while (it != _servers.end()) { - std::perror("err socket()"); - throw std::runtime_error("Socket init"); + if ( std::find(_open_ports.begin(), _open_ports.end(), std::atoi(it->port.data()) ) != _open_ports.end() ) + { + ++it; + continue; + } + + ret = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ? + if (ret == -1) + { + std::perror("err socket()"); + throw std::runtime_error("Socket init"); + } + _listen_sockets.push_back(ret); + + _bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host); + _listen(_listen_sockets.back(), 512); // 512 arbitrary + + if (_epoll_update(_listen_sockets.back(), EPOLLIN, EPOLL_CTL_ADD) == -1) + throw std::runtime_error("Socket init"); + + _open_ports.push_back(std::atoi(it->port.data())); + ++it; } - - _bind(_socket_fd, 4040); - _listen(_socket_fd, 512); // 512 arbitrary - - if (_epoll_update(_socket_fd, EPOLLIN, EPOLL_CTL_ADD) == -1) - throw std::runtime_error("Socket init"); } -void Webserv::_bind(int socket_fd, in_port_t port) +void Webserv::_bind(int socket_fd, in_port_t port, std::string host) { // cast invalid ? how to ? // const struct sockaddr* cast_test = static_cast(addr); @@ -26,7 +46,8 @@ void Webserv::_bind(int socket_fd, in_port_t port) std::memset(&addr, 0, sizeof addr); addr.sin_family = AF_INET; addr.sin_port = ::htons(port); - addr.sin_addr.s_addr = ::htonl(INADDR_ANY); // htonl useless with 0 value (INADDR_ANY) ? + addr.sin_addr.s_addr = ::htonl(::inet_addr(host.c_str())); + // addr.sin_addr.s_addr = ::htonl(INADDR_ANY); // htonl useless with 0 value (INADDR_ANY) ? if (::bind(socket_fd, (const sockaddr*)&addr, sizeof addr) == -1) { diff --git a/srcs/webserv/run_loop.cpp b/srcs/webserv/run_loop.cpp index 9b466b5..f8ce7cb 100644 --- a/srcs/webserv/run_loop.cpp +++ b/srcs/webserv/run_loop.cpp @@ -34,7 +34,9 @@ void Webserv::run() while (i < nfds) { // if ((events[i].data.u32 == SERVER_FD) && (events[i].events & EPOLLIN)) // Dont work, see "SERVER_FD" define - if ((events[i].data.fd == _socket_fd) && (events[i].events & EPOLLIN)) + // if ((events[i].data.fd == _socket_fd) && (events[i].events & EPOLLIN)) + if ((std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd) != _listen_sockets.end()) + && (events[i].events & EPOLLIN)) _accept_connection(events[i].data.fd); else if (events[i].events & EPOLLIN) _request(static_cast(events[i].data.ptr));