Browse Source

missing files

master
nicolas-arnaud 2 years ago
parent
commit
50ad8fd560
  1. 1
      .gitignore
  2. 5
      includes/Client.hpp
  3. 149
      srcs/sock/Client.cpp
  4. 147
      srcs/sock/Master.cpp
  5. 10
      srcs/tools.cpp

1
.gitignore

@ -21,4 +21,5 @@
!srcs/*.cpp !srcs/*.cpp
!srcs/load/ !srcs/load/
!srcs/json/ !srcs/json/
!srcs/sock/
!srcs/*/*.cpp !srcs/*/*.cpp

5
includes/Client.hpp

@ -16,9 +16,8 @@ class Client {
bool getRequest(string paquet); bool getRequest(string paquet);
bool parseHeader(); bool parseHeader();
int answer(Env *env); int answer(Env *env);
void call_cgi(string cgi, string path); void send_cgi(string cgi, string path);
void send_404(); void send_error(int error_code);
void send_answer(string msg); void send_answer(string msg);
bool waitHeader();
friend class Master; friend class Master;
}; };

149
srcs/sock/Client.cpp

@ -0,0 +1,149 @@
#include "webserv.hpp"
Client::Client(int fd, Master *parent) : _fd(fd), _parent(parent) {}
Client::~Client(void) {
close(_fd);
cout << "Destroyed client socket\n";
}
bool Client::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;
}
bool Client::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;
}
int Client::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;
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_error(405);
else if ((allowed = route->_headers).size() > 0) {
if (std::find(allowed.begin(), allowed.end(), method) == allowed.end())
send_error(405);
} else if ((allowed = server->_headers).size() > 0) {
if (std::find(allowed.begin(), allowed.end(), method) == allowed.end())
send_error(405);
}
string path = route->correctUri(_request["Method:"].at(1));
string cgi = route->_cgi.size() ? route->_cgi[get_extension(path)] : "";
if (cgi == "") {
if ((ret = route->getIndex(_request["Method:"].at(1), path)) == "" &&
(ret = read_file(path)) == "")
send_error(404);
else
send_answer("HTTP/1.1 200 OK\r\n" + ret);
} else
send_cgi(cgi, path);
_content = "";
_header = "";
return EXIT_SUCCESS;
}
void Client::send_cgi(string cgi, string path) {
int status;
int fd[2];
std::stringstream ss;
string ret;
if (!std::ifstream(cgi.c_str()).good())
send_error(404); // another error else ?
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);
char buffer[10000];
buffer[read(fd[0], buffer, 10000)] = 0;
ret = string(buffer);
ss << "HTTP/1.1 200 OK\r\nContent-length: "
<< ret.length() - ret.find("\r\n\r\n") - 4 << "\r\n"
<< ret;
send_answer(ss.str());
}
void Client::send_error(int error_code) {
switch (error_code) {
case 404:
return send_answer(
"HTTP/1.1 404 Not Found\r\nContent-length: 0\r\n\r\n");
case 405:
return send_answer(
"HTTP/1.1 405 Method Not Allowed\r\nContent-length: 0\r\n\r\n");
}
}
void Client::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
}

147
srcs/sock/Master.cpp

@ -0,0 +1,147 @@
#include "webserv.hpp"
Master::Master(listen_t listen) : _listen(listen) {}
Master::~Master(void) {
close(_fd);
cout << "Destroyed master socket\n";
}
int Master::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 Master::set_fds(void) {
FD_SET(_fd, &_readfds);
int child_fd;
for (std::vector< Client * >::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 Master::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 Client(new_socket, this));
}
int child_fd;
for (std::vector< Client * >::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 *Master::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();
}

10
srcs/tools.cpp

@ -221,15 +221,15 @@ string read_file(string path) {
string str; string str;
string content; string content;
std::stringstream ret; std::stringstream ret;
struct stat info; // struct stat info;
if (stat(path.c_str(), &info) != 0 || S_ISDIR(info.st_mode)) { /*if (stat(path.c_str(), &info) != 0 || S_ISDIR(info.st_mode)) {
std::cerr << "stat() error on " << path << ": " << strerror(errno) std::cerr << "stat() error on " << path << ": " << strerror(errno)
<< "\n"; << "\n";
return ""; return "";
} }*/
std::ifstream file(path.c_str()); std::ifstream file(path.c_str());
// if (!file.good()) if (!file.good())
// return ""; return "";
while (file) { while (file) {
std::getline(file, str); std::getline(file, str);
content += str + "\n"; content += str + "\n";

Loading…
Cancel
Save