diff --git a/srcs/Client.cpp b/srcs/Client.cpp index 471da4e..f994d57 100644 --- a/srcs/Client.cpp +++ b/srcs/Client.cpp @@ -7,7 +7,7 @@ char Client::buf[MAX_FILESIZE+1]; * COPLIENS *********************************************/ -Client::Client( ) { +Client::Client() : fd(0), body_size(0), status(0) { return; } diff --git a/srcs/Client.hpp b/srcs/Client.hpp index c23a7de..5a67601 100644 --- a/srcs/Client.hpp +++ b/srcs/Client.hpp @@ -32,6 +32,7 @@ class Client static char buf[MAX_FILESIZE+1]; size_t body_size; unsigned int status; + listen_socket *lsocket; // const functions ? http_method get_method(); diff --git a/srcs/utils.cpp b/srcs/utils.cpp index 063cc98..4d8c472 100644 --- a/srcs/utils.cpp +++ b/srcs/utils.cpp @@ -139,3 +139,8 @@ void replace_all_substr(std::string &str, const std::string &ori_substr, const s } } +bool operator==(const listen_socket& lhs, int fd) + { return lhs.fd == fd; } + +bool operator==(int fd, const listen_socket& rhs) + { return fd == rhs.fd; } diff --git a/srcs/utils.hpp b/srcs/utils.hpp index 1411f46..b981bd5 100644 --- a/srcs/utils.hpp +++ b/srcs/utils.hpp @@ -18,7 +18,7 @@ // GET = 0b00000001, // POST = 0b00000010, // DELETE = 0b00000100, -// ALL_METHODS = 0b11111111, +// ANY_METHODS = 0b11111111, // }; enum http_method @@ -27,9 +27,18 @@ enum http_method GET = 1 << 0, POST = 1 << 1, DELETE = 1 << 2, - ALL_METHODS = 0b11111111, + ANY_METHODS = 0b11111111, }; +struct listen_socket +{ + int fd; + std::string host; + std::string port; +}; +bool operator==(const listen_socket& lhs, int fd); +bool operator==(int fd, const listen_socket& rhs); + std::vector split(std::string input, char delimiter); bool isNumeric(std::string str); bool isNumeric_btw(int low, int high, std::string str); diff --git a/srcs/webserv/Webserv.hpp b/srcs/webserv/Webserv.hpp index 67e2c13..c5d6409 100644 --- a/srcs/webserv/Webserv.hpp +++ b/srcs/webserv/Webserv.hpp @@ -58,14 +58,14 @@ class Webserv private: int _epfd; - std::vector _listen_sockets; + std::vector _listen_sockets; std::vector _servers; std::vector _clients; std::map _http_status; std::map _mime_types; // accept.cpp - void _accept_connection(int fd); + void _accept_connection(listen_socket &lsocket); // request.cpp void _request(Client *client); void _read_request(Client *client); @@ -106,6 +106,7 @@ class Webserv // close.cpp void _close_client(int fd); void _close_all_clients(); + void _close_all_listen_sockets(); // init.cpp 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/webserv/accept.cpp b/srcs/webserv/accept.cpp index f6db17b..ac620db 100644 --- a/srcs/webserv/accept.cpp +++ b/srcs/webserv/accept.cpp @@ -1,7 +1,7 @@ #include "Webserv.hpp" -void Webserv::_accept_connection(int fd) +void Webserv::_accept_connection(listen_socket &lsocket) { struct sockaddr_in addr; socklen_t addr_len; @@ -9,7 +9,7 @@ void Webserv::_accept_connection(int fd) std::cerr << "accept()\n"; addr_len = sizeof addr; - accepted_fd = ::accept(fd, (sockaddr*)&addr, &addr_len); + accepted_fd = ::accept(lsocket.fd, (sockaddr*)&addr, &addr_len); if (accepted_fd == -1) { std::perror("err accept()"); @@ -21,6 +21,7 @@ void Webserv::_accept_connection(int fd) _clients.push_back(Client()); _clients.back().fd = accepted_fd; + _clients.back().lsocket = &lsocket; _epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD); } diff --git a/srcs/webserv/base.cpp b/srcs/webserv/base.cpp index 3392619..ee59bbd 100644 --- a/srcs/webserv/base.cpp +++ b/srcs/webserv/base.cpp @@ -45,10 +45,9 @@ Webserv::Webserv(std::vector* servers) Webserv::~Webserv() { - //close(_socket_fd); - // TODO : CLOSE ALL _listen_sockets close(_epfd); _close_all_clients(); + _close_all_listen_sockets(); std::cerr << "Server destroyed\n"; } diff --git a/srcs/webserv/close.cpp b/srcs/webserv/close.cpp index 70a1e3f..9b28f6b 100644 --- a/srcs/webserv/close.cpp +++ b/srcs/webserv/close.cpp @@ -32,3 +32,16 @@ void Webserv::_close_all_clients() _clients.pop_back(); } } + +void Webserv::_close_all_listen_sockets() +{ + while (!_listen_sockets.empty()) + { + // _epoll_update(_listen_sockets.back().fd, 0, EPOLL_CTL_DEL); // normalement superflu, DEBUG + if (::close(_listen_sockets.back().fd) == -1) + std::perror("err close()"); + else + std::cerr << "close fd " << _listen_sockets.back().fd << "\n"; + _listen_sockets.pop_back(); + } +} diff --git a/srcs/webserv/http_status.hpp b/srcs/webserv/http_status.hpp index 8aa513a..d6017f0 100644 --- a/srcs/webserv/http_status.hpp +++ b/srcs/webserv/http_status.hpp @@ -37,5 +37,6 @@ # define S413 "413 Content Too Large" # define S500 "500 Internal Server Error" +# define S501 "501 Not Implemented" #endif diff --git a/srcs/webserv/init.cpp b/srcs/webserv/init.cpp index ddd0edc..3a33ed1 100644 --- a/srcs/webserv/init.cpp +++ b/srcs/webserv/init.cpp @@ -4,7 +4,9 @@ void Webserv::init_virtual_servers(std::vector* servers) { int ret; - std::vector _open_ports; + std::vector open_sockets; + struct listen_socket new_socket; + std::string host_port; _servers = *servers; _listen_sockets.clear(); @@ -12,7 +14,11 @@ void Webserv::init_virtual_servers(std::vector* servers) while (it != _servers.end()) { - if ( std::find(_open_ports.begin(), _open_ports.end(), std::atoi(it->port.data()) ) != _open_ports.end() ) + host_port.clear(); + host_port.append(it->host); + host_port.append(":"); + host_port.append(it->port); + if ( std::find(open_sockets.begin(), open_sockets.end(), host_port) != open_sockets.end() ) { ++it; continue; @@ -24,27 +30,31 @@ void Webserv::init_virtual_servers(std::vector* servers) std::perror("err socket()"); throw std::runtime_error("Socket init"); } + new_socket.fd = ret; + new_socket.host = it->host; + new_socket.port = it->port; + _listen_sockets.push_back(new_socket); + // HUGO ADD // // allow socket descriptor to be reuseable // I just copied it from https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select int on = 1; - if (setsockopt(ret, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + if (setsockopt(new_socket.fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { ::perror("err setsockopt()"); throw std::runtime_error("Socket init"); } // // HUGO ADD END - _listen_sockets.push_back(ret); - _bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host); - _listen(_listen_sockets.back(), 512); // 512 arbitrary + _bind(new_socket.fd, std::atoi(it->port.c_str()), it->host); + _listen(new_socket.fd, 512); // 512 arbitrary - if (_epoll_update(_listen_sockets.back(), EPOLLIN, EPOLL_CTL_ADD) == -1) + if (_epoll_update(new_socket.fd, EPOLLIN, EPOLL_CTL_ADD) == -1) throw std::runtime_error("Socket init"); - _open_ports.push_back(std::atoi(it->port.data())); + open_sockets.push_back(host_port); ++it; } } @@ -90,6 +100,7 @@ void Webserv::_init_http_status_map() _http_status[413] = S413; _http_status[500] = S500; + _http_status[501] = S501; } void Webserv::_init_mime_types_map() diff --git a/srcs/webserv/response.cpp b/srcs/webserv/response.cpp index 0b6f3fa..134dcff 100644 --- a/srcs/webserv/response.cpp +++ b/srcs/webserv/response.cpp @@ -66,6 +66,7 @@ void Webserv::_append_base_headers(Client *client) void Webserv::_construct_response(Client *client, ServerConfig &server) { + // TODO : Move this in read(), stop read if content too large if (client->get_body().size() > server.client_body_limit) { client->status = 413; @@ -77,27 +78,24 @@ void Webserv::_construct_response(Client *client, ServerConfig &server) void Webserv::_process_method(Client *client, ServerConfig &server, LocationConfig &location) { - unsigned int allow_methods = ALL_METHODS; // TEMP VARIABLE + unsigned int allow_methods = ANY_METHODS; // TEMP VARIABLE // after update in ConfigParser, use the "allow_methods" of location. - // TODO in ConfigParser : by default if no field in config file, "allow_methods" must be set to ALL_METHODS + // TODO in ConfigParser : by default if no field in config file, "allow_methods" must be set to ANY_METHODS if (client->get_method() == UNKNOWN) { - client->status = 400; + client->status = 501; } else if (allow_methods & client->get_method()) { switch (client->get_method()) { case (GET): - _get(client, server, location); - break; + _get(client, server, location); break; case (POST): - _post(client, server, location); - break; + _post(client, server, location); break; case (DELETE): - _delete(client, server, location); - break; + _delete(client, server, location); break; default: break; } @@ -358,24 +356,31 @@ void Webserv::_delete_file(Client *client, const std::string &path) ServerConfig &Webserv::_determine_process_server(Client *client) { /* - TODO : determine virtual server based on ip_address::port and server_name - Ior now its just based on server_name. - (maybe with a map< string, std::vector > where the string is "ip_adress::port") http://nginx.org/en/docs/http/request_processing.html + _determine_process_server() should be complete. + TODO : test it */ std::string &server_name = client->get_headers("Host"); std::vector::iterator it = _servers.begin(); + std::vector::iterator default_server = _servers.end(); + while (it != _servers.end()) { - if ( std::find(it->server_name.begin(), it->server_name.end(), server_name) != it->server_name.end() ) - break; + if (it->host == client->lsocket->host + && it->port == client->lsocket->port) + { + if ( std::find(it->server_name.begin(), it->server_name.end(), server_name) != it->server_name.end() ) + break; + else if (default_server == _servers.end()) + default_server = it; + } ++it; } if (it != _servers.end()) return (*it); else - return (_servers.front()); + return (*default_server); } LocationConfig &Webserv::_determine_location(ServerConfig &server, std::string &path) diff --git a/srcs/webserv/run_loop.cpp b/srcs/webserv/run_loop.cpp index 7f93043..ec9165d 100644 --- a/srcs/webserv/run_loop.cpp +++ b/srcs/webserv/run_loop.cpp @@ -11,6 +11,7 @@ void Webserv::run() int nfds; int i; int count_loop = 0; + std::vector::iterator it_socket; g_run = true; while (g_run) @@ -34,9 +35,9 @@ void Webserv::run() while (i < nfds) { // TODO : handle EPOLLERR and EPOLLHUP - 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); + it_socket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd); + if (it_socket != _listen_sockets.end() && events[i].events & EPOLLIN) + _accept_connection(*it_socket); else if (events[i].events & EPOLLIN) _request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) ); else if (events[i].events & EPOLLOUT)