resolved merge conflicts, now ConfigParser is even more intertwined with other parts
This commit is contained in:
25
Makefile
25
Makefile
@@ -3,7 +3,7 @@ NAME = webserv
|
||||
CXX = c++
|
||||
|
||||
CXXFLAGS = -Wall -Wextra #-Werror
|
||||
CXXFLAGS += -I$(HEADERS_D)
|
||||
CXXFLAGS += $(HEADERS_I)
|
||||
CXXFLAGS += -std=c++98
|
||||
CXXFLAGS += -g
|
||||
CXXFLAGS += -MMD -MP #header dependencie
|
||||
@@ -12,19 +12,20 @@ CXXFLAGS += -MMD -MP #header dependencie
|
||||
#SHELL = /bin/zsh
|
||||
VPATH = $(SRCS_D)
|
||||
|
||||
# HEADERS = $(HEADERS_D:%=-I%)
|
||||
HEADERS_D = ./srcs
|
||||
HEADERS = Webserv.hpp \
|
||||
ConfigParser.hpp \
|
||||
ServerConfig.hpp \
|
||||
LocationConfig.hpp \
|
||||
Client.hpp \
|
||||
MethodType.hpp \
|
||||
utils.hpp \
|
||||
HEADERS_I = $(HEADERS_D:%=-I%)
|
||||
HEADERS_D = srcs \
|
||||
headers
|
||||
HEADERS = Webserv.hpp \
|
||||
ConfigParser.hpp \
|
||||
ServerConfig.hpp \
|
||||
LocationConfig.hpp \
|
||||
Client.hpp \
|
||||
MethodType.hpp \
|
||||
utils.hpp \
|
||||
|
||||
SRCS_D = srcs srcs/webserv
|
||||
SRCS_D = srcs \
|
||||
srcs/webserv
|
||||
SRCS = main.cpp \
|
||||
ft_itoa.cpp \
|
||||
base.cpp init.cpp close.cpp epoll_update.cpp signal.cpp \
|
||||
accept.cpp request.cpp response.cpp \
|
||||
run_loop.cpp \
|
||||
|
||||
@@ -6,19 +6,19 @@
|
||||
# include <string>
|
||||
# include <map>
|
||||
|
||||
struct Client
|
||||
class Client
|
||||
{
|
||||
// public:
|
||||
public:
|
||||
// Client(Placeholder);
|
||||
// Client();
|
||||
// Client(Client const &src);
|
||||
// ~Client();
|
||||
// Client &operator=(Client const &rhs);
|
||||
// Client &operator=(int);
|
||||
|
||||
int fd;
|
||||
std::string raw_request;
|
||||
std::map<std::string, std::string> request;
|
||||
// std::map<std::string, std::string> response;
|
||||
std::string response;
|
||||
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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
/* By: lperrey <lperrey@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* 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);
|
||||
|
||||
std::vector<std::string> tmp_val = split(value, ' ');
|
||||
std::vector<std::string> tmp_val = ::split(value, ' ');
|
||||
size_t size = tmp_val.size();
|
||||
|
||||
if (size < 1)
|
||||
@@ -239,7 +239,7 @@ void ConfigParser::_set_server_values(ServerConfig *server, \
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string> tmp2 = split(tmp_val[0], ':');
|
||||
std::vector<std::string> tmp2 = ::split(tmp_val[0], ':');
|
||||
if (!(isNumeric(tmp2[1])))
|
||||
throw std::invalid_argument("value not a number");
|
||||
|
||||
|
||||
@@ -2,26 +2,28 @@
|
||||
#ifndef WEBSERV_HPP
|
||||
# define WEBSERV_HPP
|
||||
|
||||
# include <iostream> // cout, cin
|
||||
# include <string>
|
||||
# include <map>
|
||||
# include <vector>
|
||||
# include <cerrno> // errno
|
||||
# include <cstdio> // perror
|
||||
# include <exception>
|
||||
# include <stdexcept>
|
||||
# include <unistd.h> // close
|
||||
# include <cstring> // memset
|
||||
# include <fstream>
|
||||
# include <sstream>
|
||||
|
||||
# include <sys/socket.h> // socket, accept, listen, send, recv, bind, connect, setsockopt, getsockname
|
||||
# include <netinet/in.h> // sockaddr_in
|
||||
// # include <netinet/ip.h> // usefull for what ?
|
||||
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr
|
||||
|
||||
# include <sys/epoll.h> // epoll
|
||||
# include <fcntl.h> // fcntl
|
||||
# include <exception> // exception, what
|
||||
# include <stdexcept> // runtime_error, invalid_argument
|
||||
# include <sys/epoll.h> // epoll
|
||||
# include <fcntl.h> // fcntl
|
||||
# include <sys/wait.h> // waitpid
|
||||
# include <csignal> // signal
|
||||
# include <fstream> // ifstream
|
||||
# include <sstream> // stringstream
|
||||
# include <cerrno> // errno
|
||||
# include <unistd.h> // close, access
|
||||
# include <iostream> // cout, cin
|
||||
# include <cstring> // memset
|
||||
# include <sys/socket.h> // socket, accept, listen, send, recv, bind, connect, setsockopt, getsockname
|
||||
# include <arpa/inet.h> // htonl, htons, ntohl, ntohs, inet_addr
|
||||
# include <netinet/in.h> // sockaddr_in
|
||||
// # 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 "ServerConfig.hpp"
|
||||
@@ -33,17 +35,6 @@
|
||||
# include "utils.hpp"
|
||||
// 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 int g_last_signal;
|
||||
void signal_handler(int signum);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -1,8 +1,5 @@
|
||||
|
||||
|
||||
#include "Webserv.hpp"
|
||||
|
||||
|
||||
#include "utils.hpp"
|
||||
|
||||
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)
|
||||
return false;
|
||||
}
|
||||
int n = atoi(str.c_str());
|
||||
int n = std::atoi(str.c_str());
|
||||
if (n < low || n > high)
|
||||
return false;
|
||||
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() ) );
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
|
||||
|
||||
|
||||
#ifndef UTILS_HPP
|
||||
# define UTILS_HPP
|
||||
|
||||
# include <vector>
|
||||
# include <string>
|
||||
# include <sstream>
|
||||
|
||||
std::vector<std::string> split(std::string input, char delimiter);
|
||||
bool isNumeric(std::string str);
|
||||
bool isNumeric_btw(int low, int high, std::string str);
|
||||
bool isNumeric(std::string str);
|
||||
bool isNumeric_btw(int low, int high, std::string str);
|
||||
char* itoa(int n);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,5 +22,5 @@ void Webserv::_accept_connection(int fd)
|
||||
_clients.push_back(Client());
|
||||
_clients.back().fd = accepted_fd;
|
||||
|
||||
_epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD, &_clients.back());
|
||||
_epoll_update(accepted_fd, EPOLLIN, EPOLL_CTL_ADD);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,18 @@ void Webserv::init_virtual_servers(std::vector<ServerConfig>* servers)
|
||||
std::perror("err socket()");
|
||||
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);
|
||||
|
||||
_bind(_listen_sockets.back(), std::atoi(it->port.data()), it->host);
|
||||
|
||||
@@ -15,8 +15,8 @@ void Webserv::_read_request(Client *client)
|
||||
char buf[BUFSIZE+1];
|
||||
ssize_t ret;
|
||||
|
||||
std::cerr << "recv()\n";
|
||||
ret = ::recv(client->fd, buf, BUFSIZE, 0);
|
||||
std::cerr << "recv() on fd(" << client->fd << ") returned = " << ret << "\n" ;
|
||||
if (ret == -1)
|
||||
{
|
||||
std::perror("err recv()");
|
||||
@@ -25,6 +25,11 @@ void Webserv::_read_request(Client *client)
|
||||
_close_client(client->fd);
|
||||
return ;
|
||||
}
|
||||
if (ret == 0) // Not sure what to do in case of 0. Just close ?
|
||||
{
|
||||
_close_client(client->fd);
|
||||
return ;
|
||||
}
|
||||
/*
|
||||
if (ret == BUFSIZE)
|
||||
// send error like "request too long" to client
|
||||
@@ -33,5 +38,5 @@ void Webserv::_read_request(Client *client)
|
||||
buf[ret] = '\0';
|
||||
client->raw_request.append(buf);
|
||||
|
||||
_epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD, client);
|
||||
_epoll_update(client->fd, EPOLLOUT, EPOLL_CTL_MOD);
|
||||
}
|
||||
|
||||
@@ -27,15 +27,14 @@ void Webserv::_send_response(Client *client)
|
||||
return ;
|
||||
}
|
||||
|
||||
_close_client(client->fd);
|
||||
/* if (client->raw_request.find("Connection: keep-alive") == std::string::npos)
|
||||
if (client->raw_request.find("Connection: close") != std::string::npos)
|
||||
_close_client(client->fd);
|
||||
else
|
||||
{
|
||||
_epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD, client);
|
||||
_epoll_update(client->fd, EPOLLIN, EPOLL_CTL_MOD);
|
||||
client->raw_request.clear();
|
||||
client->response.clear();
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
void Webserv::_construct_response(Client *client)
|
||||
@@ -43,13 +42,17 @@ void Webserv::_construct_response(Client *client)
|
||||
client->status = 200;
|
||||
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);
|
||||
|
||||
_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 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)
|
||||
@@ -63,6 +66,10 @@ void Webserv::_insert_status_line(Client *client)
|
||||
case (200):
|
||||
status_line.append("200 OK");
|
||||
break;
|
||||
case (400):
|
||||
status_line.append("400 Not Found");
|
||||
client->response.append(E400);
|
||||
break;
|
||||
case (404):
|
||||
status_line.append("404 Not Found");
|
||||
client->response.append(E404);
|
||||
@@ -88,12 +95,21 @@ void Webserv::_get_ressource(Client *client)
|
||||
|
||||
// Mini parsing à l'arrache du PATH
|
||||
std::string path;
|
||||
path = client->raw_request.substr(0, client->raw_request.find("\r\n"));
|
||||
path = path.substr(0, path.rfind(" "));
|
||||
path = path.substr(path.find("/"));
|
||||
if (path == "/")
|
||||
path.append(INDEX);
|
||||
path.insert(0, ROOT);
|
||||
try
|
||||
{
|
||||
path = client->raw_request.substr(0, client->raw_request.find("\r\n"));
|
||||
path = path.substr(0, path.rfind(" "));
|
||||
path = path.substr(path.find("/"));
|
||||
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)
|
||||
{
|
||||
@@ -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-Length: ");
|
||||
tmp = ::ft_itoa(ifd.gcount());
|
||||
tmp = ::itoa(ifd.gcount());
|
||||
client->response.append(tmp);
|
||||
delete tmp;
|
||||
client->response.append("\r\n");
|
||||
|
||||
// Body
|
||||
|
||||
@@ -4,6 +4,14 @@
|
||||
#define MAX_EVENTS 42 // arbitrary
|
||||
#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()
|
||||
{
|
||||
std::cerr << "Server started\n";
|
||||
@@ -33,15 +41,14 @@ void Webserv::run()
|
||||
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))
|
||||
// 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);
|
||||
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)
|
||||
_response(static_cast<Client*>(events[i].data.ptr));
|
||||
_response( &(*std::find(_clients.begin(), _clients.end(), events[i].data.fd)) );
|
||||
++i;
|
||||
if (!g_run)
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user