Review parsing Eric and Luke.

Combined the config parser with Webserv class.
This commit is contained in:
LuckyLaszlo
2022-07-31 00:27:48 +02:00
parent 2d91b704c3
commit e5c2869172
10 changed files with 76 additions and 391 deletions

View File

@@ -3,10 +3,10 @@
/* ::: :::::::: */
/* ConfigParser.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: me <erlazo@student.42.fr> +#+ +:+ +#+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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);
}

View File

@@ -1,32 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Server.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <iostream>
# include <string>
class Server
{
public:
// Server(Placeholder);
// Server();
// Server(Server const &src);
// ~Server();
// Server &operator=(Server const &rhs);
private:
};
#endif

View File

@@ -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<ServerConfig>* 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<Client*>(events[i].data.ptr));
else if (events[i].events & EPOLLOUT)
_send_response(static_cast<Client*>(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<Client>::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<const struct sockaddr*>(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");
}
}

View File

@@ -24,21 +24,25 @@
# include <fcntl.h> // 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 <csignal> // signal
# include <unistd.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <cstdlib> // itoa
# include <cstdlib> // atoi, itoa
# include <fstream> // ifstream
char *ft_itoa(int n);
# include <unistd.h> // access
# include <algorithm> // 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<ServerConfig>* servers);
// run_loop.cpp
void run();
private:
int _epfd;
int _socket_fd; // temp, to replace with std::vector<Server>
// std::vector<Server> _servers;
std::vector<int> _listen_sockets;
std::vector<ServerConfig> _servers;
std::vector<Client> _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);
};

View File

@@ -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)
{

View File

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

View File

@@ -1,23 +1,43 @@
#include "Webserv.hpp"
void Webserv::init_virtual_servers() // ADD config param
void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
{
_socket_fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); // (SOCK_CLOEXEC) for CGI fork ?
if (_socket_fd == -1)
int ret;
std::vector<int> _open_ports;
_servers = *servers;
_listen_sockets.clear();
std::vector<ServerConfig>::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<const struct sockaddr*>(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)
{

View File

@@ -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<Client*>(events[i].data.ptr));