Browse Source

refactor sockets

master
nicolas-arnaud 2 years ago
parent
commit
d613dab836
  1. 2
      Makefile
  2. 24
      includes/Client.hpp
  3. 8
      includes/Env.hpp
  4. 25
      includes/Master.hpp
  5. 32
      includes/Route.hpp
  6. 13
      includes/Server.hpp
  7. 34
      includes/Socket.hpp
  8. 34
      includes/webserv.hpp
  9. 0
      public/images/file
  10. 34
      srcs/load/Env.cpp
  11. 50
      srcs/load/Route.cpp
  12. 49
      srcs/load/Server.cpp
  13. 282
      srcs/load/Socket.cpp
  14. 33
      srcs/tools.cpp
  15. 59
      srcs/webserv.cpp

2
Makefile

@ -1,6 +1,6 @@
NAME= server
SRCS= srcs/webserv.cpp srcs/tools.cpp srcs/load/Env.cpp srcs/load/Server.cpp \
srcs/load/Socket.cpp srcs/load/Route.cpp \
srcs/load/Route.cpp srcs/sock/Master.cpp srcs/sock/Client.cpp \
srcs/json/Nodes.cpp srcs/json/Token.cpp srcs/json/Parser.cpp
OBJS= $(SRCS:.cpp=.o)
CXX=c++

24
includes/Client.hpp

@ -0,0 +1,24 @@
#pragma once
#include "webserv.hpp"
typedef std::map< string, std::vector< string > > request_t;
class Client {
int _fd;
Master *_parent;
string _header;
string _content;
request_t _request;
public:
Client(int fd, Master *parent);
~Client(void);
bool getRequest(string paquet);
bool parseHeader();
int answer(Env *env);
void call_cgi(string cgi, string path);
void send_404();
void send_answer(string msg);
bool waitHeader();
friend class Master;
};

8
includes/Env.hpp

@ -3,11 +3,11 @@
class Env {
public:
std::vector<Server *> _servers;
std::vector<Socket *> _sockets;
std::vector< Server * > _servers;
std::vector< Master * > _masters;
Env(JSONNode *conf);
void cycle(void);
void set_fds(void);
void refresh(void);
Server *choose_server(Socket *sock, string host);
~Env();
~Env(void);
};

25
includes/Master.hpp

@ -0,0 +1,25 @@
#pragma once
#include "webserv.hpp"
class Master {
// int _clients_amount;
int _fd;
std::vector< Client * > _childs;
struct sockaddr_in _address;
public:
Master(listen_t listen);
Master(int fd, Master *parent);
~Master(void);
int launch(void);
void set_fds(void);
void refresh(Env *env);
Server *choose_server(Env *env, string host);
listen_t _listen;
static fd_set _readfds;
static int _max_fd;
static int _min_fd;
static int _amount;
};

32
includes/Route.hpp

@ -4,25 +4,25 @@
class Route {
protected:
Server *_server;
string _location;
string _root;
string _ret;
bool _autoindex;
string _location;
string _root;
string _ret;
bool _autoindex;
public:
std::vector<string> _indexs;
std::vector<string> _headers;
std::map<string, string> _cgi;
std::vector< string > _indexs;
std::vector< string > _headers;
std::map< string, string > _cgi;
Route(Server *server, string location, JSONNode *datas);
~Route(void);
string getLocation(void);
string getRoot(void);
string getReturn(void);
std::vector<string> getIndexsLst(void);
std::vector<string> getHeadersLst(void);
Server *getServer(void);
string getIndex(string uri, string path);
string correctUri(string uri);
friend class Socket;
string getLocation(void);
string getRoot(void);
string getReturn(void);
std::vector< string > getIndexsLst(void);
std::vector< string > getHeadersLst(void);
Server *getServer(void);
string getIndex(string uri, string path);
string correctUri(string uri);
friend class Socket;
};

13
includes/Server.hpp

@ -2,13 +2,14 @@
#include "webserv.hpp"
class Server : public Route {
string _name;
std::map<string, Route *> _routes;
string _name;
std::map< string, Route * > _routes;
public:
std::vector<listen_t> _listens;
std::vector< listen_t > _listens;
Server(JSONNode *server);
~Server(void);
std::vector<Socket *> get_sockets(JSONNode *server);
Route *choose_route(string uri);
string getName(void);
std::vector< Master * > get_sockets(JSONNode *server);
Route *choose_route(string uri);
string getName(void);
};

34
includes/Socket.hpp

@ -1,34 +0,0 @@
#pragma once
#include "webserv.hpp"
class Socket {
int _fd;
//int _clients_amount;
Socket *_parent;
std::vector<Socket *> _childs;
struct sockaddr_in _address;
string _header;
string _content;
std::map<string,std::vector<string> > _request;
bool getRequest(string paquet);
bool parseHeader();
int answer(Env *env);
void send_answer(string msg);
bool waitHeader();
Server *choose_server(Env *env, string host);
public:
Socket(listen_t listen);
Socket(int fd, Socket *parent);
~Socket(void);
listen_t _listen;
static fd_set _readfds;
static int _max_fd;
static int _min_fd;
static int _amount;
int launch(void);
void set_fds(void);
void refresh(Env *env);
};

34
includes/webserv.hpp

@ -1,5 +1,7 @@
#pragma once
#define DEBUG 0
#include <arpa/inet.h>
#include <dirent.h>
#include <fcntl.h>
@ -11,6 +13,7 @@
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <algorithm>
#include <cctype>
#include <cerrno>
@ -26,38 +29,39 @@
#include <map>
#include <vector>
#define DEBUG 0
using std::cout;
using std::strerror;
using std::string;
typedef struct listen_s {
string ip;
int port;
int port;
} listen_t;
class JSONNode;
class Env;
class Server;
class Socket;
class Route;
class JSONNode;
class Master;
class Client;
typedef std::map< string, JSONNode * > JSONObject;
typedef std::vector< JSONNode * > JSONList;
typedef std::map<string, JSONNode *> JSONObject;
typedef std::vector<JSONNode *> JSONList;
void *ft_memset(void *b, int c, size_t len);
bool isInt(string str);
std::vector< string > split(string str, char delim);
listen_t get_listen_t(string listen);
string getMime(string path);
string get_extension(string str);
string read_file(string path);
void *ft_memset(void *b, int c, size_t len);
bool isInt(string str);
std::vector<string> split(string str, char delim);
listen_t get_listen_t(string listen);
string getMime(string path);
string get_extension(string str);
string read_file(string path);
#include "Client.hpp"
#include "Master.hpp"
#include "Nodes.hpp"
#include "Token.hpp"
#include "Parser.hpp"
#include "Route.hpp"
#include "Socket.hpp"
#include "Server.hpp"
#include "Env.hpp"

0
public/images/file

34
srcs/load/Env.cpp

@ -10,27 +10,39 @@
Env::Env(JSONNode *conf) {
try {
JSONList servers = conf->obj()["servers"]->lst();
for (std::vector<JSONNode *>::iterator it = servers.begin();
for (std::vector< JSONNode * >::iterator it = servers.begin();
it < servers.end(); it++) {
Server *server = new Server(*it);
_servers.push_back(server);
std::vector<Socket *> tmp_s = server->get_sockets(*it);
_sockets.insert(_sockets.end(), tmp_s.begin(), tmp_s.end());
std::vector< Master * > tmp_s = server->get_sockets(*it);
_masters.insert(_masters.end(), tmp_s.begin(), tmp_s.end());
}
} catch (std::exception &e) {
cout << e.what();
}
delete conf;
}
void Env::cycle(void) {
FD_ZERO(&Master::_readfds);
Master::_max_fd = Master::_min_fd;
cout << "==> Check sockets still alive to listen\n";
set_fds();
cout << "|===||===| Waiting some HTTP request... |===||===|\n";
int activity = select(Master::_max_fd + Master::_amount,
&(Master::_readfds), NULL, NULL, NULL);
if ((activity < 0) && (errno != EINTR))
cout << "Select: " << strerror(errno) << "\n";
cout << "==> Handle requests and answers:\n";
refresh();
}
/*|=======================|
* Append each master_sockets and their clients to list of fds SELECT must look
* at.
*/
void Env::set_fds(void) {
for (std::vector<Socket *>::iterator it = _sockets.begin();
it < _sockets.end(); it++)
for (std::vector< Master * >::iterator it = _masters.begin();
it < _masters.end(); it++)
(*it)->set_fds();
}
@ -40,8 +52,8 @@ void Env::set_fds(void) {
*/
void Env::refresh(void) {
for (std::vector<Socket *>::iterator it = _sockets.begin();
it < _sockets.end(); it++)
for (std::vector< Master * >::iterator it = _masters.begin();
it < _masters.end(); it++)
(*it)->refresh(this);
}
@ -51,12 +63,12 @@ void Env::refresh(void) {
* The destructor call all servers and sockets destructors.
*/
Env::~Env() {
for (std::vector<Server *>::iterator it = _servers.begin();
for (std::vector< Server * >::iterator it = _servers.begin();
it < _servers.end(); it++) {
delete *it;
}
for (std::vector<Socket *>::iterator it = _sockets.begin();
it < _sockets.end(); it++) {
for (std::vector< Master * >::iterator it = _masters.begin();
it < _masters.end(); it++) {
delete *it;
}
}

50
srcs/load/Route.cpp

@ -3,7 +3,7 @@
Route::Route(Server *server, string location, JSONNode *datas)
: _server(server), _location(location) {
JSONObject object = datas->obj();
JSONNode *tmp;
JSONNode *tmp;
if ((tmp = object["root"]))
_root = tmp->str();
if ((tmp = object["return"]))
@ -24,29 +24,29 @@ Route::Route(Server *server, string location, JSONNode *datas)
}
}
if ((tmp = object["cgi"])) {
JSONObject cgis = tmp->obj();
for (JSONObject::iterator it = cgis.begin(); it != cgis.end(); it++) {
_cgi[(*it).first] = (*it).second->str();
}
}
JSONObject cgis = tmp->obj();
for (JSONObject::iterator it = cgis.begin(); it != cgis.end(); it++) {
_cgi[(*it).first] = (*it).second->str();
}
}
}
Route::~Route(void) {}
string Route::getLocation(void) { return _location; }
string Route::getRoot(void) { return _root; }
string Route::getReturn(void) { return _ret; }
std::vector<string> Route::getIndexsLst(void) { return _indexs; }
std::vector<string> Route::getHeadersLst(void) { return _headers; }
string Route::getLocation(void) { return _location; }
string Route::getRoot(void) { return _root; }
string Route::getReturn(void) { return _ret; }
std::vector< string > Route::getIndexsLst(void) { return _indexs; }
std::vector< string > Route::getHeadersLst(void) { return _headers; }
string Route::getIndex(string uri, string path) {
std::stringstream content;
std::stringstream ret;
DIR *dir;
struct dirent *entry;
struct stat info;
std::vector<string> indexs = getIndexsLst();
std::vector<string>::iterator it;
std::stringstream content;
std::stringstream ret;
DIR *dir;
struct dirent *entry;
struct stat info;
std::vector< string > indexs = getIndexsLst();
std::vector< string >::iterator it;
if ((dir = opendir(path.c_str())) == NULL)
return "";
@ -78,17 +78,17 @@ string Route::getIndex(string uri, string path) {
}
string Route::correctUri(string uri) {
std::stringstream ret;
std::vector<string>::iterator it;
std::vector<string>::iterator it2;
std::stringstream ret;
std::vector< string >::iterator it;
std::vector< string >::iterator it2;
cout << "Correcting request: " << uri << " with root: " << _root << "\n";
ret << "./" << _root;
std::vector<string> loc_split = split(_location, '/');
std::vector<string> uri_split = split(uri, '/');
std::vector< string > loc_split = split(_location, '/');
std::vector< string > uri_split = split(uri, '/');
it2 = uri_split.begin();
for (it = loc_split.begin(); it < loc_split.end(); it++) {
while ( it2 < uri_split.end() && *it2 == "")
while (it2 < uri_split.end() && *it2 == "")
it2++;
while (it < loc_split.end() && *it == "")
it++;
@ -99,7 +99,7 @@ string Route::correctUri(string uri) {
while (it2 < uri_split.end()) {
ret << "/" << *(it2++);
}
cout << "result: " << ret.str() << "\n";
return ret.str();
}

49
srcs/load/Server.cpp

@ -1,12 +1,12 @@
#include "webserv.hpp"
/*|=======================|
* Server constructor:
*
*
* Input: A server block node given by JSONParser.
* Output: A Server class object and also a Route one as Server herite from Route.
* The Route constructor scrap the routing informations (index, root, autoindex ...) and the Server one the others ones (server_name, sub-routes)
* Output: A Server class object and also a Route one as Server herite from
* Route. The Route constructor scrap the routing informations (index, root,
* autoindex ...) and the Server one the others ones (server_name, sub-routes)
*/
Server::Server(JSONNode *server) : Route(NULL, "/", server) {
JSONObject datas = server->obj();
@ -22,21 +22,20 @@ Server::Server(JSONNode *server) : Route(NULL, "/", server) {
}
}
/* Get the server name (_server_name)*/
string Server::getName(void) { return _name; }
/*|=======================|
* Create server's defined sockets:
*
* Input: A server block node from JSONParser.
* Output: A vector containing all the succesfull created sockets using listens from the server block.
* Output: A vector containing all the succesfull created sockets using listens
* from the server block.
*/
std::vector<Socket *> Server::get_sockets(JSONNode *server) {
JSONObject datas = server->obj();
std::vector<Socket *> ret;
listen_t listen;
std::vector< Master * > Server::get_sockets(JSONNode *server) {
JSONObject datas = server->obj();
std::vector< Master * > ret;
listen_t listen;
if (datas["listens"]) {
JSONList listens = datas["listens"]->lst();
for (JSONList::iterator it = listens.begin(); it != listens.end();
@ -48,7 +47,7 @@ std::vector<Socket *> Server::get_sockets(JSONNode *server) {
continue;
}
_listens.push_back(listen);
Socket *sock = new Socket(listen);
Master *sock = new Master(listen);
if (sock->launch() == EXIT_SUCCESS)
ret.push_back(sock);
else
@ -56,7 +55,7 @@ std::vector<Socket *> Server::get_sockets(JSONNode *server) {
}
} else {
listen = get_listen_t("localhost:80");
Socket *sock = new Socket(listen);
Master *sock = new Master(listen);
_listens.push_back(listen);
if (sock->launch() == EXIT_SUCCESS) {
ret.push_back(sock);
@ -69,18 +68,19 @@ std::vector<Socket *> Server::get_sockets(JSONNode *server) {
* Choose the route an uri asked to the server must lead to.
*
* Intput: The uri asked by the client to the server.
* Output: The route object choosen or the server itself if no location block is adapted.
* Output: The route object choosen or the server itself if no location block is
* adapted.
*/
Route *Server::choose_route(string uri) {
// cout << uri << "\n";
std::vector<string> req = split(uri, '/');
std::vector<string> root;
for (std::map<string, Route *>::iterator rit = _routes.begin();
std::vector< string > req = split(uri, '/');
std::vector< string > root;
for (std::map< string, Route * >::iterator rit = _routes.begin();
rit != _routes.end(); rit++) {
root = split((*rit).first, '/');
std::vector<string>::iterator root_it = root.begin();
std::vector< string >::iterator root_it = root.begin();
for (std::vector<string>::iterator it = req.begin(); it < req.end();
for (std::vector< string >::iterator it = req.begin(); it < req.end();
it++) {
if (*it == "")
continue;
@ -94,15 +94,14 @@ Route *Server::choose_route(string uri) {
return this;
}
/*|=======================|
* Server destructor:
*
* delete all routes owned by the server;
*/
* Server destructor:
*
* delete all routes owned by the server;
*/
Server::~Server(void) {
for (std::map<string, Route *>::iterator it = _routes.begin();
for (std::map< string, Route * >::iterator it = _routes.begin();
it != _routes.end(); it++)
delete (*it).second;
cout << "Server destroyed!\n";

282
srcs/load/Socket.cpp

@ -1,282 +0,0 @@
#include "webserv.hpp"
Socket::Socket(listen_t listen) : _listen(listen) {}
Socket::Socket(int fd, Socket *parent) : _fd(fd), _parent(parent) {}
Socket::~Socket(void) {
close(_fd);
cout << "Socket destroyed!\n";
}
int Socket::launch(void) {
int opt = 1;
string ip = _listen.ip;
int port = _listen.port;
_fd = socket(AF_INET, SOCK_STREAM, 0);
if (_fd == 0) {
cout << "Socket creation: " << strerror(errno) << "\n";
return (EXIT_FAILURE);
}
int opt_ret =
setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
if (opt_ret < 0) {
cout << "Sockopt: " << strerror(errno) << "\n";
return (EXIT_FAILURE);
}
_address.sin_family = AF_INET;
_address.sin_addr.s_addr = inet_addr(ip.c_str());
_address.sin_port = htons(port);
if (bind(_fd, (struct sockaddr *)&_address, sizeof(_address)) < 0) {
cout << "Bind: " << strerror(errno) << "\n";
return (EXIT_FAILURE);
}
cout << "Listener " << ip << " on port " << port << "\n";
if (listen(_fd, 3) < 0) {
cout << "Listen: " << strerror(errno) << "\n";
return (EXIT_FAILURE);
}
cout << "Master: " << _fd << "\n";
if (_fd < _min_fd)
_min_fd = _fd;
_amount++;
return (EXIT_SUCCESS);
}
void Socket::set_fds(void) {
FD_SET(_fd, &_readfds);
int child_fd;
for (std::vector<Socket *>::iterator it = _childs.begin();
it < _childs.end(); it++) {
child_fd = (*it)->_fd;
FD_SET(child_fd, &_readfds);
if (child_fd > _max_fd)
_max_fd = child_fd;
}
}
void Socket::refresh(Env *env) {
int valread;
int addrlen = sizeof(_address);
char buffer[10000];
if (FD_ISSET(_fd, &_readfds)) {
int new_socket =
accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen);
if (new_socket < 0) {
cout << "Accept: " << strerror(errno) << "\n";
exit(EXIT_FAILURE);
}
#ifdef __APPLE__
// fcntl(new_socket, F_GETNOSIGPIPE);
fcntl(new_socket, F_SETFL, O_NONBLOCK);
#endif
cout << "New connection, socket fd is " << new_socket
<< ", ip is : " << inet_ntoa(_address.sin_addr)
<< ", port : " << ntohs(_address.sin_port) << "\n";
_childs.push_back(new Socket(new_socket, this));
}
int child_fd;
for (std::vector<Socket *>::iterator it = _childs.begin();
it < _childs.end(); it++) {
child_fd = (*it)->_fd;
if (FD_ISSET(child_fd, &_readfds)) {
valread = read(child_fd, buffer, 10000);
if (valread == 0) {
getpeername(child_fd, (struct sockaddr *)&_address,
(socklen_t *)&addrlen);
cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr)
<< ", port " << ntohs(_address.sin_port) << "\n";
delete (*it);
_childs.erase(it);
} else {
buffer[valread] = '\0';
if ((*it)->getRequest(buffer))
(*it)->answer(env);
}
}
}
}
Server *Socket::choose_server(Env *env, string host) {
std::vector<Server *> exact;
std::vector<Server *> inrange;
std::vector<string> ip_listen;
std::vector<string> ip_required;
// string ip = inet_ntoa(sock->_address.sin_addr);
// int port = ntohs(sock->_address.sin_port);
// cout << "Which server for " << ip << ":" << port << "?\n";
cout << "Socket: " << _listen.ip << ":" << _listen.port << "\n";
ip_required = split(_listen.ip, '.');
for (std::vector<Server *>::iterator sit = env->_servers.begin();
sit < env->_servers.end(); sit++) {
std::vector<listen_t> serv_listens = (*sit)->_listens;
for (std::vector<listen_t>::iterator it = serv_listens.begin();
it < serv_listens.end(); it++) {
if (_listen.port != (*it).port)
continue;
if (_listen.ip == (*it).ip) {
exact.push_back(*sit);
continue;
}
bool is_inrange = true;
ip_listen = split((*it).ip, '.');
std::vector<string>::iterator r = ip_required.begin();
for (std::vector<string>::iterator l = ip_listen.begin();
l < ip_listen.end(); l++) {
if (*l != *r && *l != "0")
is_inrange = false;
}
if (is_inrange == true)
inrange.push_back(*sit);
}
}
if (exact.size() == 0) {
for (std::vector<Server *>::iterator sit = inrange.begin();
sit < inrange.end(); sit++) {
if (host == (*sit)->getName())
return *sit;
}
return inrange.front();
} else
return exact.front();
}
bool Socket::parseHeader() {
std::vector<string> lines = split(_header, '\n');
std::vector<string> line;
if (lines.size() > 0) {
for (std::vector<string>::iterator it = lines.begin() + 1;
it < lines.end(); it++) {
line = split(*it, ' ');
cout << line.at(0) << "scraped from header\n";
_request[line.at(0)] =
std::vector<string>(line.begin() + 1, line.end());
}
}
std::vector<string> method = split(lines.at(0), ' ');
if (method.at(0) == "POST" &&
_request.find("Content-Length:") == _request.end() &&
_request.find("Transfer-Encoding:") == _request.end())
return false;
_request["Method:"] = method;
return true;
}
bool Socket::getRequest(string paquet) {
cout << "|===|paquet|===>" << paquet << "|===||\n";
if (paquet.length() < 1) // HTTPS?
return false;
std::vector<string> lines = split(paquet, '\n');
long chunk_len =
(_content.length() > 0 && _request["Transfer-Encoding:"].size() &&
_request["Transfer-Encoding:"].at(0) == "chunked")
? std::strtol(lines.at(0).substr(1).c_str(), 0, 16)
: -1;
cout << "Chunk length: " << chunk_len << "\n";
for (std::vector<string>::iterator it = lines.begin(); it < lines.end();
it++) {
if (*it == "\r" && _content.length() == 0)
this->parseHeader();
if (*it != "\r" && _content.length() == 0)
_header += *it + "\n";
else if (chunk_len == -1 || it != lines.begin())
_content += *it + "\n";
}
cout << "Header: \n-|" << _header << "|-\n";
cout << "Content: \n-|" << _content << "|-\n";
if (_content.length() > 0) {
_content.resize(_content.length() - 1);
if (_request["Method:"].at(0) == "GET" ||
(chunk_len == 0 ||
std::strtoul(_request["Content-Length:"].at(0).c_str(), 0, 10) <=
_content.length())) {
cout << "Request received\n";
return true;
}
} else
_header.resize(_header.length() - 1);
return false;
}
int Socket::answer(Env *env) {
cout << "Method: " << _request["Method:"].at(0) << "\n";
cout << "URI: " << _request["Method:"].at(1) << "\n";
cout << "Host: " << _request["Host:"].at(0) << "\n";
string ret;
std::stringstream answer;
answer << "HTTP/1.1";
Server *server = _parent->choose_server(env, _request["Host:"].at(0));
Route *route = server->choose_route(_request["Method:"].at(1));
string method = _request["Method:"].at(0);
std::vector<string> allowed;
if (method != "GET" && method != "POST" && method != "DELETE")
send_answer("HTTP/1.1 405 Method Not Allowed\r\n\r\n");
else if ((allowed = route->_headers).size() > 0) {
if (std::find(allowed.begin(), allowed.end(), method) == allowed.end())
send_answer("HTTP/1.1 405 Method Not Allowed\r\n\r\n");
} else if ((allowed = server->_headers).size() > 0) {
if (std::find(allowed.begin(), allowed.end(), method) == allowed.end())
send_answer("HTTP/1.1 405 Method Not Allowed\r\n\r\n");
}
string path = route->correctUri(_request["Method:"].at(1));
cout << "Path: " << path << "\n";
string cgi;
if (route->_cgi.size())
cgi = route->_cgi[get_extension(path)];
cout << "Cgi:" << cgi << "\n";
if (cgi != "") {
int status;
int fd[2];
pipe(fd);
int pid = fork();
if (pid == 0) {
const char **args = new const char *[cgi.length() + path.length() + 2];
args[0] = cgi.c_str();
args[1] = path.c_str();
args[2] = NULL;
dup2(fd[1], STDOUT_FILENO);
close(fd[1]);
close(fd[0]);
execve(cgi.c_str(), (char **)args, NULL);
}
close(fd[1]);
waitpid(pid, &status, 0);
cout << "Cgi finished\n";
char buffer[10000];
size_t len = read(fd[0], buffer, 10000);
buffer[len] = 0;
ret = string(buffer);
len = ret.length() - ret.find("\r\n\r\n") - 4;
answer << " 200 OK\r\nContent-length: " << len << "\r\n";
answer << ret;
} else {
ret = route->getIndex(_request["Method:"].at(1), path);
if (ret == "") {
cout << "No index: lf file\n";
ret = read_file(path);
}
answer << (ret == "" ? " 404 Not Found\r\nContent-length: 0\r\n\r\n"
: " 200 OK\r\n")
<< ret;
}
cout << "|===|Answer|===|\n" << answer.str() << "|===|End of answer|===|\n";
send_answer(answer.str());
_content = "";
_header = "";
return EXIT_SUCCESS;
}
void Socket::send_answer(string msg) {
#ifdef __linux__
send(_fd, msg.c_str(), msg.length(), MSG_NOSIGNAL);
#elif __APPLE__
send(_fd, msg.c_str(), msg.length(), 0);
#endif
}

33
srcs/tools.cpp

@ -1,7 +1,7 @@
#include "webserv.hpp"
void *ft_memset(void *b, int c, size_t len) {
size_t i;
size_t i;
unsigned char *b_cpy;
b_cpy = (unsigned char *)b;
@ -18,10 +18,11 @@ bool isInt(string str) {
return true;
}
std::vector<string> split(string str, char delim) {
std::vector<std::string> tokens;
std::string token;
std::stringstream ss(str);
std::vector< string > split(string str, char delim) {
std::vector< std::string > tokens;
string token;
std::stringstream ss(str);
while (getline(ss, token, delim))
tokens.push_back(token);
return tokens;
@ -29,8 +30,8 @@ std::vector<string> split(string str, char delim) {
listen_t get_listen_t(string listen) {
listen_t ret;
size_t sep_pos = listen.rfind(':');
string tmp = listen.substr(0, sep_pos);
size_t sep_pos = listen.rfind(':');
string tmp = listen.substr(0, sep_pos);
ret.ip = isInt(tmp) ? "0.0.0.0" : (tmp == "localhost" ? "127.0.0.1" : tmp);
tmp = listen.substr(sep_pos + 1, listen.length() - sep_pos - 1).c_str();
@ -39,9 +40,9 @@ listen_t get_listen_t(string listen) {
}
string getMime(string path) {
string extension;
size_t pos = path.rfind('.');
extension = (pos == string::npos) ? "txt" : path.substr(pos + 1);
string extension = (pos == string::npos) ? "txt" : path.substr(pos + 1);
if ((extension == "html") || (extension == "htm") || (extension == "shtml"))
return ("text/html");
else if ((extension == "css"))
@ -210,17 +211,17 @@ string getMime(string path) {
}
string get_extension(string str) {
int dot_pos = str.rfind('.');
string ret = str.substr(dot_pos);
cout << ret << "\n";
return ret;
int dot_pos = str.rfind('.');
string ret = str.substr(dot_pos);
cout << ret << "\n";
return ret;
}
string read_file(string path) {
string str;
string content;
string str;
string content;
std::stringstream ret;
struct stat info;
struct stat info;
if (stat(path.c_str(), &info) != 0 || S_ISDIR(info.st_mode)) {
std::cerr << "stat() error on " << path << ": " << strerror(errno)
<< "\n";

59
srcs/webserv.cpp

@ -1,45 +1,28 @@
#include "webserv.hpp"
fd_set Socket::_readfds;
int Socket::_max_fd;
int Socket::_min_fd = INT_MAX;
int Socket::_amount = 0;
fd_set Master::_readfds;
int Master::_max_fd;
int Master::_min_fd = INT_MAX;
int Master::_amount = 0;
int main(int ac, char **av) {
if (ac <= 2) {
std::string config = "default.json";
if (ac == 2){
std::ifstream file(av[1]);
if (file.good())
config = av[1];
else {
std::cout << "Error: " << av[1] << " is not a valid file" << std::endl;
return EXIT_FAILURE;
}
config = av[1];
}
cout << "Parsing configuration file from JSON conf file.\n";
cout << "You must be sure the syntax is correct\n";
JSONParser parser(config);
JSONNode *conf = parser.parse();
cout << "Initialization of server...\n";
Env env(conf);
if (ac != 2) {
cout << "Usage:\n./webserv CONF.json\n";
return EXIT_SUCCESS;
}
while (1) {
FD_ZERO(&Socket::_readfds);
Socket::_max_fd = Socket::_min_fd;
cout << "==> Check sockets still alive to listen\n";
env.set_fds();
cout << "|===||===| Waiting some HTTP request... |===||===|\n";
int activity = select(Socket::_max_fd + Socket::_amount,
&(Socket::_readfds), NULL, NULL, NULL);
if ((activity < 0) && (errno != EINTR))
cout << "Select: " << strerror(errno) << "\n";
cout << "==> Handle requests and answers:\n";
env.refresh();
}
std::ifstream file(av[1]);
if (!file.good()) {
cout << "Error: " << av[1] << " is not a valid file\n";
return EXIT_FAILURE;
}
else
cout << "Usage:\n./webserv CONF.json\n";
return (0);
cout << "Parsing configuration file from JSON conf file.\n";
cout << "You must be sure the syntax is correct\n";
JSONParser parser(av[1]);
JSONNode *conf = parser.parse();
cout << "Initialization of server...\n";
Env env(conf);
while (1)
env.cycle();
return EXIT_SUCCESS;
}

Loading…
Cancel
Save