merged, seems fine

This commit is contained in:
Me
2022-08-07 01:10:05 +02:00
12 changed files with 82 additions and 35 deletions

View File

@@ -7,7 +7,7 @@ char Client::buf[MAX_FILESIZE+1];
* COPLIENS * COPLIENS
*********************************************/ *********************************************/
Client::Client( ) { Client::Client() : fd(0), body_size(0), status(0) {
return; return;
} }

View File

@@ -32,6 +32,7 @@ class Client
static char buf[MAX_FILESIZE+1]; static char buf[MAX_FILESIZE+1];
size_t body_size; size_t body_size;
unsigned int status; unsigned int status;
listen_socket *lsocket;
// const functions ? // const functions ?
http_method get_method(); http_method get_method();

View File

@@ -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; }

View File

@@ -18,7 +18,7 @@
// GET = 0b00000001, // GET = 0b00000001,
// POST = 0b00000010, // POST = 0b00000010,
// DELETE = 0b00000100, // DELETE = 0b00000100,
// ALL_METHODS = 0b11111111, // ANY_METHODS = 0b11111111,
// }; // };
enum http_method enum http_method
@@ -27,9 +27,18 @@ enum http_method
GET = 1 << 0, GET = 1 << 0,
POST = 1 << 1, POST = 1 << 1,
DELETE = 1 << 2, 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<std::string> split(std::string input, char delimiter); std::vector<std::string> split(std::string input, char delimiter);
bool isNumeric(std::string str); bool isNumeric(std::string str);
bool isNumeric_btw(int low, int high, std::string str); bool isNumeric_btw(int low, int high, std::string str);

View File

@@ -58,14 +58,14 @@ class Webserv
private: private:
int _epfd; int _epfd;
std::vector<int> _listen_sockets; std::vector<listen_socket> _listen_sockets;
std::vector<ServerConfig> _servers; std::vector<ServerConfig> _servers;
std::vector<Client> _clients; std::vector<Client> _clients;
std::map<int, std::string> _http_status; std::map<int, std::string> _http_status;
std::map<std::string, std::string> _mime_types; std::map<std::string, std::string> _mime_types;
// accept.cpp // accept.cpp
void _accept_connection(int fd); void _accept_connection(listen_socket &lsocket);
// request.cpp // request.cpp
void _request(Client *client); void _request(Client *client);
void _read_request(Client *client); void _read_request(Client *client);
@@ -106,6 +106,7 @@ class Webserv
// close.cpp // close.cpp
void _close_client(int fd); void _close_client(int fd);
void _close_all_clients(); void _close_all_clients();
void _close_all_listen_sockets();
// init.cpp // init.cpp
void _bind(int socket_fd, in_port_t port, std::string host); void _bind(int socket_fd, in_port_t port, std::string host);
void _listen(int socket_fd, unsigned int max_connections); void _listen(int socket_fd, unsigned int max_connections);

View File

@@ -1,7 +1,7 @@
#include "Webserv.hpp" #include "Webserv.hpp"
void Webserv::_accept_connection(int fd) void Webserv::_accept_connection(listen_socket &lsocket)
{ {
struct sockaddr_in addr; struct sockaddr_in addr;
socklen_t addr_len; socklen_t addr_len;
@@ -9,7 +9,7 @@ void Webserv::_accept_connection(int fd)
std::cerr << "accept()\n"; std::cerr << "accept()\n";
addr_len = sizeof addr; 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) if (accepted_fd == -1)
{ {
std::perror("err accept()"); std::perror("err accept()");
@@ -21,6 +21,7 @@ void Webserv::_accept_connection(int fd)
_clients.push_back(Client()); _clients.push_back(Client());
_clients.back().fd = accepted_fd; _clients.back().fd = accepted_fd;
_clients.back().lsocket = &lsocket;
_epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD); _epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD);
} }

View File

@@ -45,10 +45,9 @@ Webserv::Webserv(std::vector<ServerConfig>* servers)
Webserv::~Webserv() Webserv::~Webserv()
{ {
//close(_socket_fd);
// TODO : CLOSE ALL _listen_sockets
close(_epfd); close(_epfd);
_close_all_clients(); _close_all_clients();
_close_all_listen_sockets();
std::cerr << "Server destroyed\n"; std::cerr << "Server destroyed\n";
} }

View File

@@ -32,3 +32,16 @@ void Webserv::_close_all_clients()
_clients.pop_back(); _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();
}
}

View File

@@ -37,5 +37,6 @@
# define S413 "413 Content Too Large" # define S413 "413 Content Too Large"
# define S500 "500 Internal Server Error" # define S500 "500 Internal Server Error"
# define S501 "501 Not Implemented"
#endif #endif

View File

@@ -4,7 +4,9 @@
void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers) void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
{ {
int ret; int ret;
std::vector<int> _open_ports; std::vector<std::string> open_sockets;
struct listen_socket new_socket;
std::string host_port;
_servers = *servers; _servers = *servers;
_listen_sockets.clear(); _listen_sockets.clear();
@@ -12,7 +14,11 @@ void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
while (it != _servers.end()) 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; ++it;
continue; continue;
@@ -24,27 +30,31 @@ void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
std::perror("err socket()"); std::perror("err socket()");
throw std::runtime_error("Socket init"); 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 // HUGO ADD
// //
// allow socket descriptor to be reuseable // 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 // I just copied it from https://www.ibm.com/docs/en/i/7.2?topic=designs-example-nonblocking-io-select
int on = 1; 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()"); ::perror("err setsockopt()");
throw std::runtime_error("Socket init"); throw std::runtime_error("Socket init");
} }
// //
// HUGO ADD END // HUGO ADD END
_listen_sockets.push_back(ret);
_bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host); _bind(new_socket.fd, std::atoi(it->port.c_str()), it->host);
_listen(_listen_sockets.back(), 512); // 512 arbitrary _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"); throw std::runtime_error("Socket init");
_open_ports.push_back(std::atoi(it->port.data())); open_sockets.push_back(host_port);
++it; ++it;
} }
} }
@@ -90,6 +100,7 @@ void Webserv::_init_http_status_map()
_http_status[413] = S413; _http_status[413] = S413;
_http_status[500] = S500; _http_status[500] = S500;
_http_status[501] = S501;
} }
void Webserv::_init_mime_types_map() void Webserv::_init_mime_types_map()

View File

@@ -66,6 +66,7 @@ void Webserv::_append_base_headers(Client *client)
void Webserv::_construct_response(Client *client, ServerConfig &server) 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) if (client->get_body().size() > server.client_body_limit)
{ {
client->status = 413; 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) 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. // 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) if (client->get_method() == UNKNOWN)
{ {
client->status = 400; client->status = 501;
} }
else if (allow_methods & client->get_method()) else if (allow_methods & client->get_method())
{ {
switch (client->get_method()) switch (client->get_method())
{ {
case (GET): case (GET):
_get(client, server, location); _get(client, server, location); break;
break;
case (POST): case (POST):
_post(client, server, location); _post(client, server, location); break;
break;
case (DELETE): case (DELETE):
_delete(client, server, location); _delete(client, server, location); break;
break;
default: default:
break; break;
} }
@@ -358,24 +356,31 @@ void Webserv::_delete_file(Client *client, const std::string &path)
ServerConfig &Webserv::_determine_process_server(Client *client) 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<ServerConfig> > where the string is "ip_adress::port")
http://nginx.org/en/docs/http/request_processing.html 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::string &server_name = client->get_headers("Host");
std::vector<ServerConfig>::iterator it = _servers.begin(); std::vector<ServerConfig>::iterator it = _servers.begin();
std::vector<ServerConfig>::iterator default_server = _servers.end();
while (it != _servers.end()) while (it != _servers.end())
{
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() ) if ( std::find(it->server_name.begin(), it->server_name.end(), server_name) != it->server_name.end() )
break; break;
else if (default_server == _servers.end())
default_server = it;
}
++it; ++it;
} }
if (it != _servers.end()) if (it != _servers.end())
return (*it); return (*it);
else else
return (_servers.front()); return (*default_server);
} }
LocationConfig &Webserv::_determine_location(ServerConfig &server, std::string &path) LocationConfig &Webserv::_determine_location(ServerConfig &server, std::string &path)

View File

@@ -11,6 +11,7 @@ void Webserv::run()
int nfds; int nfds;
int i; int i;
int count_loop = 0; int count_loop = 0;
std::vector<listen_socket>::iterator it_socket;
g_run = true; g_run = true;
while (g_run) while (g_run)
@@ -34,9 +35,9 @@ void Webserv::run()
while (i < nfds) while (i < nfds)
{ {
// TODO : handle EPOLLERR and EPOLLHUP // TODO : handle EPOLLERR and EPOLLHUP
if ((std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd) != _listen_sockets.end()) it_socket = std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd);
&& (events[i].events & EPOLLIN)) if (it_socket != _listen_sockets.end() && events[i].events & EPOLLIN)
_accept_connection(events[i].data.fd); _accept_connection(*it_socket);
else if (events[i].events & EPOLLIN) else if (events[i].events & EPOLLIN)
_request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) ); _request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
else if (events[i].events & EPOLLOUT) else if (events[i].events & EPOLLOUT)