resolved merge conflicts, now ConfigParser is even more intertwined with other parts

This commit is contained in:
Me
2022-07-31 16:30:14 +02:00
12 changed files with 118 additions and 127 deletions

View File

@@ -3,7 +3,7 @@ NAME = webserv
CXX = c++ CXX = c++
CXXFLAGS = -Wall -Wextra #-Werror CXXFLAGS = -Wall -Wextra #-Werror
CXXFLAGS += -I$(HEADERS_D) CXXFLAGS += $(HEADERS_I)
CXXFLAGS += -std=c++98 CXXFLAGS += -std=c++98
CXXFLAGS += -g CXXFLAGS += -g
CXXFLAGS += -MMD -MP #header dependencie CXXFLAGS += -MMD -MP #header dependencie
@@ -12,19 +12,20 @@ CXXFLAGS += -MMD -MP #header dependencie
#SHELL = /bin/zsh #SHELL = /bin/zsh
VPATH = $(SRCS_D) VPATH = $(SRCS_D)
# HEADERS = $(HEADERS_D:%=-I%) HEADERS_I = $(HEADERS_D:%=-I%)
HEADERS_D = ./srcs HEADERS_D = srcs \
HEADERS = Webserv.hpp \ headers
ConfigParser.hpp \ HEADERS = Webserv.hpp \
ServerConfig.hpp \ ConfigParser.hpp \
LocationConfig.hpp \ ServerConfig.hpp \
Client.hpp \ LocationConfig.hpp \
MethodType.hpp \ Client.hpp \
utils.hpp \ MethodType.hpp \
utils.hpp \
SRCS_D = srcs srcs/webserv SRCS_D = srcs \
srcs/webserv
SRCS = main.cpp \ SRCS = main.cpp \
ft_itoa.cpp \
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \ base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
accept.cpp request.cpp response.cpp \ accept.cpp request.cpp response.cpp \
run_loop.cpp \ run_loop.cpp \

View File

@@ -6,19 +6,19 @@
# include <string> # include <string>
# include <map> # include <map>
struct Client class Client
{ {
// public: public:
// Client(Placeholder); // Client(Placeholder);
// Client(); // Client();
// Client(Client const &src); // Client(Client const &src);
// ~Client(); // ~Client();
// Client &operator=(Client const &rhs); // Client &operator=(Client const &rhs);
// Client &operator=(int);
int fd; int fd;
std::string raw_request; std::string raw_request;
std::map<std::string, std::string> request; std::map<std::string, std::string> request;
// std::map<std::string, std::string> response;
std::string response; std::string response;
unsigned int status; unsigned int status;
@@ -26,4 +26,8 @@ struct Client
}; };
#endif bool operator==(const Client& lhs, const Client& rhs);
bool operator==(const Client& lhs, int fd);
bool operator==(int fd, const Client& rhs);
#endif

View File

@@ -6,7 +6,7 @@
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */ /* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2022/07/13 22:11:17 by me #+# #+# */ /* Created: 2022/07/13 22:11:17 by me #+# #+# */
/* Updated: 2022/07/30 23:07:42 by lperrey ### ########.fr */ /* Updated: 2022/07/31 13:18:14 by simplonco ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@@ -216,7 +216,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
value = _pre_set_val_check(key, value); value = _pre_set_val_check(key, value);
std::vector<std::string> tmp_val = split(value, ' '); std::vector<std::string> tmp_val = ::split(value, ' ');
size_t size = tmp_val.size(); size_t size = tmp_val.size();
if (size < 1) if (size < 1)
@@ -239,7 +239,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
} }
else else
{ {
std::vector<std::string> tmp2 = split(tmp_val[0], ':'); std::vector<std::string> tmp2 = ::split(tmp_val[0], ':');
if (!(isNumeric(tmp2[1]))) if (!(isNumeric(tmp2[1])))
throw std::invalid_argument("value not a number"); throw std::invalid_argument("value not a number");

View File

@@ -2,26 +2,28 @@
#ifndef WEBSERV_HPP #ifndef WEBSERV_HPP
# define WEBSERV_HPP # define WEBSERV_HPP
# include <iostream> // cout, cin
# include <string>
# include <map> # include <map>
# include <vector> # include <vector>
# include <cerrno> // errno # include <exception> // exception, what
# include <cstdio> // perror # include <stdexcept> // runtime_error, invalid_argument
# include <exception> # include <sys/epoll.h> // epoll
# include <stdexcept> # include <fcntl.h> // fcntl
# include <unistd.h> // close # include <sys/wait.h> // waitpid
# include <cstring> // memset # include <csignal> // signal
# include <fstream> # include <fstream> // ifstream
# include <sstream> # include <sstream> // stringstream
# include <cerrno> // errno
# include <sys/socket.h> // socket, accept, listen, send, recv, bind, connect, setsockopt, getsockname # include <unistd.h> // close, access
# include <netinet/in.h> // sockaddr_in # include <iostream> // cout, cin
// # include <netinet/ip.h> // usefull for what ? # include <cstring> // memset
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr # include <sys/socket.h> // socket, accept, listen, send, recv, bind, connect, setsockopt, getsockname
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr
# include <sys/epoll.h> // epoll # include <netinet/in.h> // sockaddr_in
# include <fcntl.h> // fcntl // # include <netinet/ip.h> // usefull for what ? -> 'man (7) ip' says it's a superset of 'netinet/in.h'
# include <algorithm> // find
# include <string> // string
# include <cstdio> // perror
# include <cstdlib> // atoi (athough it's already cover by <string>)
# include "Client.hpp" # include "Client.hpp"
# include "ServerConfig.hpp" # include "ServerConfig.hpp"
@@ -33,17 +35,6 @@
# include "utils.hpp" # include "utils.hpp"
// TODO: A virer // TODO: A virer
# include <csignal> // signal
# include <unistd.h>
# include <string.h>
# include <stdio.h>
# include <stdlib.h>
# include <cstdlib> // atoi, itoa
# include <fstream> // ifstream
char *ft_itoa(int n);
# include <unistd.h> // access
# include <algorithm> // find
extern bool g_run; extern bool g_run;
extern int g_last_signal; extern int g_last_signal;
void signal_handler(int signum); void signal_handler(int signum);

View File

@@ -1,50 +0,0 @@
#include <string.h>
static int eval_is_negative(int *n)
{
if (*n < 0)
{
*n = *n * -1;
return (1);
}
return (0);
}
static int eval_digit_nbr(int n)
{
int digit_nbr;
if (n == 0)
return (1);
digit_nbr = 0;
while (n != 0)
{
digit_nbr++;
n = n / 10;
}
return (digit_nbr);
}
char *ft_itoa(int n)
{
int i;
char *str;
int is_negative;
if (n == -2147483648)
return (strdup("-2147483648"));
is_negative = eval_is_negative(&n);
i = eval_digit_nbr(n) + is_negative;
str = new char[i+1];
if (is_negative)
str[0] = '-';
str[i] = '\0';
while (i > 0 + is_negative)
{
i--;
str[i] = (n % 10) + '0';
n = n / 10;
}
return (str);
}

View File

@@ -1,8 +1,5 @@
#include "utils.hpp"
#include "Webserv.hpp"
std::vector<std::string> split(std::string input, char delimiter) std::vector<std::string> split(std::string input, char delimiter)
{ {
@@ -34,10 +31,17 @@ bool isNumeric_btw(int low, int high, std::string str)
if (std::isdigit(str[i]) == false) if (std::isdigit(str[i]) == false)
return false; return false;
} }
int n = atoi(str.c_str()); int n = std::atoi(str.c_str());
if (n < low || n > high) if (n < low || n > high)
return false; return false;
return true; return true;
} }
char* itoa(int n)
{
std::stringstream strs;
strs << n;
// casts : https://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used
return ( const_cast<char*>( strs.str().c_str() ) );
}

View File

@@ -1,12 +1,14 @@
#ifndef UTILS_HPP #ifndef UTILS_HPP
# define UTILS_HPP # define UTILS_HPP
# include <vector>
# include <string>
# include <sstream>
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);
char* itoa(int n);
#endif #endif

View File

@@ -22,5 +22,5 @@ void Webserv::_accept_connection(int fd)
_clients.push_back(Client()); _clients.push_back(Client());
_clients.back().fd = accepted_fd; _clients.back().fd = accepted_fd;
_epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD, &_clients.back()); _epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD);
} }

View File

@@ -24,6 +24,18 @@ 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");
} }
// 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)
{
::perror("err setsockopt()");
throw std::runtime_error("Socket init");
}
//
// HUGO ADD END
_listen_sockets.push_back(ret); _listen_sockets.push_back(ret);
_bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host); _bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host);

View File

@@ -15,8 +15,8 @@ void Webserv::_read_request(Client *client)
char buf[BUFSIZE+1]; char buf[BUFSIZE+1];
ssize_t ret; ssize_t ret;
std::cerr << "recv()\n";
ret = ::recv(client->fd, buf, BUFSIZE, 0); ret = ::recv(client->fd, buf, BUFSIZE, 0);
std::cerr << "recv() on fd(" << client->fd << ") returned = " << ret << "\n" ;
if (ret == -1) if (ret == -1)
{ {
std::perror("err recv()"); std::perror("err recv()");
@@ -25,6 +25,11 @@ void Webserv::_read_request(Client *client)
_close_client(client->fd); _close_client(client->fd);
return ; return ;
} }
if (ret == 0) // Not sure what to do in case of 0. Just close ?
{
_close_client(client->fd);
return ;
}
/* /*
if (ret == BUFSIZE) if (ret == BUFSIZE)
// send error like "request too long" to client // send error like "request too long" to client
@@ -33,5 +38,5 @@ void Webserv::_read_request(Client *client)
buf[ret] = '\0'; buf[ret] = '\0';
client->raw_request.append(buf); client->raw_request.append(buf);
_epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD, client); _epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD);
} }

View File

@@ -27,15 +27,14 @@ void Webserv::_send_response(Client *client)
return ; return ;
} }
_close_client(client->fd); if (client->raw_request.find("Connection: close") != std::string::npos)
/* if (client->raw_request.find("Connection: keep-alive") == std::string::npos)
_close_client(client->fd); _close_client(client->fd);
else else
{ {
_epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD, client); _epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD);
client->raw_request.clear(); client->raw_request.clear();
client->response.clear(); client->response.clear();
} */ }
} }
void Webserv::_construct_response(Client *client) void Webserv::_construct_response(Client *client)
@@ -43,13 +42,17 @@ void Webserv::_construct_response(Client *client)
client->status = 200; client->status = 200;
client->response.append("Server: Webserv/0.1\r\n"); client->response.append("Server: Webserv/0.1\r\n");
client->response.append("Connection: close\r\n"); if (client->raw_request.find("Connection: close") != std::string::npos)
client->response.append("Connection: close\r\n");
else
client->response.append("Connection: keep-alive\r\n");
_get_ressource(client); _get_ressource(client);
_insert_status_line(client); _insert_status_line(client);
} }
#define E400 "\r\n<!DOCTYPE html><html><head><title>400 Bad Request</title></head><body><h1 style=\"text-align:center\">400 Bad Request</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
#define E404 "\r\n<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1 style=\"text-align:center\">404 Not Found</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>" #define E404 "\r\n<!DOCTYPE html><html><head><title>404 Not Found</title></head><body><h1 style=\"text-align:center\">404 Not Found</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
#define E500 "\r\n<!DOCTYPE html><html><head><title>500 Internal Server Error</title></head><body><h1 style=\"text-align:center\">500 Internal Server Error</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>" #define E500 "\r\n<!DOCTYPE html><html><head><title>500 Internal Server Error</title></head><body><h1 style=\"text-align:center\">500 Internal Server Error</h1><hr><p style=\"text-align:center\">Le Webserv/0.1</p></body></html>"
void Webserv::_insert_status_line(Client *client) void Webserv::_insert_status_line(Client *client)
@@ -63,6 +66,10 @@ void Webserv::_insert_status_line(Client *client)
case (200): case (200):
status_line.append("200 OK"); status_line.append("200 OK");
break; break;
case (400):
status_line.append("400 Not Found");
client->response.append(E400);
break;
case (404): case (404):
status_line.append("404 Not Found"); status_line.append("404 Not Found");
client->response.append(E404); client->response.append(E404);
@@ -88,12 +95,21 @@ void Webserv::_get_ressource(Client *client)
// Mini parsing à l'arrache du PATH // Mini parsing à l'arrache du PATH
std::string path; std::string path;
path = client->raw_request.substr(0, client->raw_request.find("\r\n")); try
path = path.substr(0, path.rfind(" ")); {
path = path.substr(path.find("/")); path = client->raw_request.substr(0, client->raw_request.find("\r\n"));
if (path == "/") path = path.substr(0, path.rfind(" "));
path.append(INDEX); path = path.substr(path.find("/"));
path.insert(0, ROOT); if (path == "/")
path.append(INDEX);
path.insert(0, ROOT);
}
catch (std::out_of_range& e)
{
std::cout << e.what() << '\n';
client->status = 400;
return ;
}
if (access(path.data(), R_OK) == -1) if (access(path.data(), R_OK) == -1)
{ {
@@ -128,9 +144,8 @@ void Webserv::_get_ressource(Client *client)
client->response.append("Content-Type: text/html; charset=UTF-8\r\n"); client->response.append("Content-Type: text/html; charset=UTF-8\r\n");
client->response.append("Content-Length: "); client->response.append("Content-Length: ");
tmp = ::ft_itoa(ifd.gcount()); tmp = ::itoa(ifd.gcount());
client->response.append(tmp); client->response.append(tmp);
delete tmp;
client->response.append("\r\n"); client->response.append("\r\n");
// Body // Body

View File

@@ -4,6 +4,14 @@
#define MAX_EVENTS 42 // arbitrary #define MAX_EVENTS 42 // arbitrary
#define TIMEOUT 3000 #define TIMEOUT 3000
// Temp. To move in other file
bool operator==(const Client& lhs, const Client& rhs)
{ return lhs.fd == rhs.fd; }
bool operator==(const Client& lhs, int fd)
{ return lhs.fd == fd; }
bool operator==(int fd, const Client& rhs)
{ return fd == rhs.fd; }
void Webserv::run() void Webserv::run()
{ {
std::cerr << "Server started\n"; std::cerr << "Server started\n";
@@ -33,15 +41,14 @@ void Webserv::run()
i = 0; i = 0;
while (i < nfds) while (i < nfds)
{ {
// if ((events[i].data.u32 == SERVER_FD) && (events[i].events & EPOLLIN)) // Dont work, see "SERVER_FD" define // TODO : handle EPOLLERR and EPOLLHUP
// 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()) if ((std::find(_listen_sockets.begin(), _listen_sockets.end(), events[i].data.fd) != _listen_sockets.end())
&& (events[i].events & EPOLLIN)) && (events[i].events & EPOLLIN))
_accept_connection(events[i].data.fd); _accept_connection(events[i].data.fd);
else if (events[i].events & EPOLLIN) else if (events[i].events & EPOLLIN)
_request(static_cast<Client*>(events[i].data.ptr)); _request( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
else if (events[i].events & EPOLLOUT) else if (events[i].events & EPOLLOUT)
_response(static_cast<Client*>(events[i].data.ptr)); _response( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
++i; ++i;
if (!g_run) if (!g_run)
break; break;