Browse Source

reformat

master
nicolas-arnaud 2 years ago
parent
commit
4282a88b8a
  1. 13
      includes/Token.hpp
  2. 73
      srcs/load/Route.cpp
  3. 172
      srcs/sock/Client.cpp
  4. 66
      srcs/sock/Master.cpp

13
includes/Token.hpp

@ -1,18 +1,7 @@
#pragma once #pragma once
#include "webserv.hpp" #include "webserv.hpp"
enum TOKEN { enum TOKEN { CURLY_OPEN, CURLY_CLOSE, COLON, STRING, NUMBER, ARRAY_OPEN, ARRAY_CLOSE, COMMA, BOOLEAN, NULL_TYPE };
CURLY_OPEN,
CURLY_CLOSE,
COLON,
STRING,
NUMBER,
ARRAY_OPEN,
ARRAY_CLOSE,
COMMA,
BOOLEAN,
NULL_TYPE
};
typedef struct Token_s { typedef struct Token_s {
string value; string value;

73
srcs/load/Route.cpp

@ -18,53 +18,41 @@
* @param location The uri associatied to the route. * @param location The uri associatied to the route.
* @param datas The JSONNode giving configuration. * @param datas The JSONNode giving configuration.
*/ */
Route::Route(Server *server, string location, JSONNode *datas) Route::Route(Server *server, string location, JSONNode *datas) : _server(server), _location(location) {
: _server(server), _location(location) {
JSONObject object = datas->obj(); JSONObject object = datas->obj();
JSONNode *tmp; JSONNode *tmp;
_autoindex = false; _autoindex = false;
_client_max_body_size = -1; _client_max_body_size = -1;
if ((tmp = object["root"])) if ((tmp = object["root"])) _root = tmp->str();
_root = tmp->str();
if ((tmp = object["return"])) { if ((tmp = object["return"])) {
_ret_code = tmp->lst()[0]->nbr(); _ret_code = tmp->lst()[0]->nbr();
_ret_uri = tmp->lst()[1]->str(); _ret_uri = tmp->lst()[1]->str();
} }
if ((tmp = object["autoindex"])) if ((tmp = object["autoindex"])) _autoindex = tmp->boo();
_autoindex = tmp->boo(); if ((tmp = object["keepalive_time"])) _timeout = tmp->nbr();
if ((tmp = object["keepalive_time"])) else _timeout = 0;
_timeout = tmp->nbr(); if ((tmp = object["keepalive_requests"])) _max_requests = tmp->nbr();
else else _max_requests = 0;
_timeout = 0;
if ((tmp = object["keepalive_requests"]))
_max_requests = tmp->nbr();
else
_max_requests = 0;
if ((tmp = object["error_pages"])) { if ((tmp = object["error_pages"])) {
JSONObject pages = tmp->obj(); JSONObject pages = tmp->obj();
for (JSONObject::iterator it = pages.begin(); it != pages.end(); it++) { for (JSONObject::iterator it = pages.begin(); it != pages.end(); it++) {
JSONList err = (*it).second->lst(); JSONList err = (*it).second->lst();
for (JSONList::iterator it2 = err.begin(); it2 != err.end(); it2++) for (JSONList::iterator it2 = err.begin(); it2 != err.end(); it2++) _err_page[(*it2)->nbr()] = (*it).first;
_err_page[(*it2)->nbr()] = (*it).first;
} }
} }
if ((tmp = object["indexs"])) { if ((tmp = object["indexs"])) {
JSONList indexs = tmp->lst(); JSONList indexs = tmp->lst();
for (JSONList::iterator it = indexs.begin(); it < indexs.end(); it++) for (JSONList::iterator it = indexs.begin(); it < indexs.end(); it++) _indexs.push_back((*it)->str());
_indexs.push_back((*it)->str());
} }
if ((tmp = object["allowed_methods"])) { if ((tmp = object["allowed_methods"])) {
JSONList headers = tmp->lst(); JSONList headers = tmp->lst();
for (JSONList::iterator it = headers.begin(); it < headers.end(); it++) for (JSONList::iterator it = headers.begin(); it < headers.end(); it++) _allowed_methods.push_back((*it)->str());
_allowed_methods.push_back((*it)->str());
} }
if ((tmp = object["cgi"])) { if ((tmp = object["cgi"])) {
JSONObject cgis = tmp->obj(); JSONObject cgis = tmp->obj();
for (JSONObject::iterator it = cgis.begin(); it != cgis.end(); it++) for (JSONObject::iterator it = cgis.begin(); it != cgis.end(); it++) _cgi[(*it).first] = (*it).second->str();
_cgi[(*it).first] = (*it).second->str();
} }
if ((tmp = object["client_max_body_size"])) if ((tmp = object["client_max_body_size"])) _client_max_body_size = tmp->nbr();
_client_max_body_size = tmp->nbr();
} }
/// @brief Destructor /// @brief Destructor
@ -91,30 +79,21 @@ string Route::getIndex(string uri, string path) {
vec_string::iterator it; vec_string::iterator it;
if ((dir = opendir(path.c_str()))) { if ((dir = opendir(path.c_str()))) {
if (DEBUG) if (DEBUG) cout << "get index(): path=" << path << "\n";
cout << "get index(): path=" << path << "\n"; body << "<h3 style=\"text-align: center;\">" << path << " files :</h3>\n<ul>\n";
body << "<h3 style=\"text-align: center;\">" << path
<< " files :</h3>\n<ul>\n";
while ((entry = readdir(dir)) != NULL) { while ((entry = readdir(dir)) != NULL) {
if (entry->d_name[0] == '.') if (entry->d_name[0] == '.') continue;
continue;
for (it = _indexs.begin(); it < _indexs.end(); it++) { for (it = _indexs.begin(); it < _indexs.end(); it++) {
if (entry->d_name == *it) if (entry->d_name == *it) return (file_answer(path + "/" + *it));
return (file_answer(path + "/" + *it));
} }
body << "<li><a href=\"" << uri + "/" + entry->d_name << "\">" body << "<li><a href=\"" << uri + "/" + entry->d_name << "\">" << entry->d_name << "</a></li>\n";
<< entry->d_name << "</a></li>\n"; if (stat(path.c_str(), &info) != 0) std::cerr << "stat() error on " << path << ": " << strerror(errno) << "\n";
if (stat(path.c_str(), &info) != 0)
std::cerr << "stat() error on " << path << ": " << strerror(errno)
<< "\n";
} }
body << "</ul>"; body << "</ul>";
closedir(dir); closedir(dir);
} }
if (!dir || !_autoindex) if (!dir || !_autoindex) return "";
return ""; if (DEBUG) cout << "Getting autoindex\n";
if (DEBUG)
cout << "Getting autoindex\n";
ret << "Content-type: text/html \r\n"; ret << "Content-type: text/html \r\n";
ret << "Content-length: " << body.str().length() << "\r\n"; ret << "Content-length: " << body.str().length() << "\r\n";
ret << "\r\n" << body.str(); ret << "\r\n" << body.str();
@ -137,15 +116,11 @@ string Route::correctUri(string uri) {
vec_string uri_words = split(uri, "/"); vec_string uri_words = split(uri, "/");
uri_word = uri_words.begin(); uri_word = uri_words.begin();
for (loc_word = loc_words.begin(); loc_word < loc_words.end(); loc_word++) { for (loc_word = loc_words.begin(); loc_word < loc_words.end(); loc_word++) {
while (uri_word < uri_words.end() && *uri_word == "") while (uri_word < uri_words.end() && *uri_word == "") uri_word++;
uri_word++; while (loc_word < loc_words.end() && *loc_word == "") loc_word++;
while (loc_word < loc_words.end() && *loc_word == "") if (loc_word != loc_words.end()) uri_word++;
loc_word++;
if (loc_word != loc_words.end())
uri_word++;
} }
ret << "./" << _root; ret << "./" << _root;
while (uri_word < uri_words.end()) while (uri_word < uri_words.end()) ret << "/" << *(uri_word++);
ret << "/" << *(uri_word++);
return ret.str(); return ret.str();
} }

172
srcs/sock/Client.cpp

@ -12,14 +12,11 @@
inline string get_extension(string str) { inline string get_extension(string str) {
size_t pos = str.rfind('.'); size_t pos = str.rfind('.');
if (pos != string::npos) if (pos != string::npos) return str.substr(pos);
return str.substr(pos); else return "";
else
return "";
} }
Client::Client(int fd, ip_port_t ip_port, Master *parent) Client::Client(int fd, ip_port_t ip_port, Master *parent) : _fd(fd), _ip_port(ip_port), _parent(parent) {
: _fd(fd), _ip_port(ip_port), _parent(parent) {
_requests_done = 0; _requests_done = 0;
_death_time = 0; _death_time = 0;
_finish = false; _finish = false;
@ -27,8 +24,8 @@ Client::Client(int fd, ip_port_t ip_port, Master *parent)
_server = NULL; _server = NULL;
init(); init();
if (!SILENT) if (!SILENT)
cout << "New connection, socket fd is " << fd << ", ip is : " << _ip_port.ip cout << "New connection, socket fd is " << fd << ", ip is : " << _ip_port.ip << ", port : " << _ip_port.port
<< ", port : " << _ip_port.port << "\n"; << "\n";
} }
Client::~Client(void) { Client::~Client(void) {
@ -38,19 +35,15 @@ Client::~Client(void) {
Master::_pollfds[_poll_id].revents = 0; Master::_pollfds[_poll_id].revents = 0;
Master::_poll_id_amount--; Master::_poll_id_amount--;
_headers.clear(); _headers.clear();
if (!SILENT) if (!SILENT) cout << "Host disconnected, ip " << _ip_port.ip << ", port " << _ip_port.port << "\n";
cout << "Host disconnected, ip " << _ip_port.ip << ", port "
<< _ip_port.port << "\n";
} }
void Client::init(void) { void Client::init(void) {
_requests_done++; _requests_done++;
if (_route && _route->_max_requests > 0) { if (_route && _route->_max_requests > 0) {
if (_requests_done > _route->_max_requests) if (_requests_done > _route->_max_requests) _finish = true;
_finish = true;
} else if (_server && _server->_max_requests > 0) { } else if (_server && _server->_max_requests > 0) {
if (_requests_done > _server->_max_requests) if (_requests_done > _server->_max_requests) _finish = true;
_finish = true;
} }
_method = _uri = _host = _header = _body = ""; _method = _uri = _host = _header = _body = "";
_len = 0; _len = 0;
@ -63,8 +56,7 @@ template <typename T> void tab(T t, const int &width) {
void Client::debug(bool head) { void Client::debug(bool head) {
if (head) { if (head) {
std::cout << "Client " << _poll_id std::cout << "Client " << _poll_id << " debug ===================================\n";
<< " debug ===================================\n";
tab("Fd", 4); tab("Fd", 4);
tab("Ip", 12); tab("Ip", 12);
tab("Port", 6); tab("Port", 6);
@ -99,17 +91,13 @@ void Client::debug(bool head) {
} }
bool Client::getRequest(Env *env, string paquet) { bool Client::getRequest(Env *env, string paquet) {
if (DEBUG) if (DEBUG) debug_block("Paquet: ", paquet);
debug_block("Paquet: ", paquet); if (header_pick("Method:", 0) != "") return getBody(paquet);
if (header_pick("Method:", 0) != "")
return getBody(paquet);
vec_string lines = split(paquet, "\r\n"); vec_string lines = split(paquet, "\r\n");
for (vec_string::iterator it = lines.begin(); it < lines.end(); it++) { for (vec_string::iterator it = lines.begin(); it < lines.end(); it++) {
size_t pos = paquet.find("\r\n"); size_t pos = paquet.find("\r\n");
if (pos != string::npos) if (pos != string::npos) paquet.erase(0, pos + 2);
paquet.erase(0, pos + 2); else paquet.clear();
else
paquet.clear();
_header += *it + (it + 1 != lines.end() ? "\r\n" : ""); _header += *it + (it + 1 != lines.end() ? "\r\n" : "");
if (_header.find("\r\n\r\n") != string::npos) if (_header.find("\r\n\r\n") != string::npos)
return !parseHeader(env) ? false : (_len != 0 ? getBody(paquet) : true); return !parseHeader(env) ? false : (_len != 0 ? getBody(paquet) : true);
@ -122,10 +110,8 @@ bool Client::getBody(string paquet) {
vec_string::iterator it; vec_string::iterator it;
for (it = lines.begin(); it < lines.end(); it++) { for (it = lines.begin(); it < lines.end(); it++) {
if (DEBUG) if (DEBUG) cout << "Remaining length: " << _len << "\n";
cout << "Remaining length: " << _len << "\n"; if ((*it).length() && _len <= 0 && header_pick("Transfer-Encoding:", 0) == "chunked") {
if ((*it).length() && _len <= 0 &&
header_pick("Transfer-Encoding:", 0) == "chunked") {
_len = std::strtol((*it).c_str(), 0, 16) + 2; _len = std::strtol((*it).c_str(), 0, 16) + 2;
_last_chunk = _len == 2 ? true : false; _last_chunk = _len == 2 ? true : false;
} else if (_len > 0 || it != lines.begin()) { } else if (_len > 0 || it != lines.begin()) {
@ -141,8 +127,7 @@ bool Client::getBody(string paquet) {
bool Client::parseHeader(Env *env) { bool Client::parseHeader(Env *env) {
vec_string lines, method, line; vec_string lines, method, line;
if (DEBUG) if (DEBUG) cout << "Parsing header...\n";
cout << "Parsing header...\n";
lines = split(_header, "\r\n"); lines = split(_header, "\r\n");
method = split(lines.at(0), " "); method = split(lines.at(0), " ");
_headers["Method:"] = method; _headers["Method:"] = method;
@ -153,57 +138,42 @@ bool Client::parseHeader(Env *env) {
} }
} }
_method = header_pick("Method:", 0); _method = header_pick("Method:", 0);
if ((_method == "POST" || _method == "PUT") && if ((_method == "POST" || _method == "PUT") && header_pick("Content-Length:", 0) == "" &&
header_pick("Content-Length:", 0) == "" &&
header_pick("Transfer-Encoding:", 0) != "chunked") header_pick("Transfer-Encoding:", 0) != "chunked")
return (send_error(400), false); return (send_error(400), false);
vec_string uri_split = split(header_pick("Method:", 1), "?"); vec_string uri_split = split(header_pick("Method:", 1), "?");
_uri = uri_split.at(0); _uri = uri_split.at(0);
if (uri_split.size() > 1) if (uri_split.size() > 1) _query = uri_split.at(1);
_query = uri_split.at(1);
_host = header_pick("Host:", 0); _host = header_pick("Host:", 0);
_keepalive = header_pick("Connection:", 0) == "keep-alive"; _keepalive = header_pick("Connection:", 0) == "keep-alive";
_env = env; _env = env;
struct timeval t; struct timeval t;
gettimeofday(&t, NULL); gettimeofday(&t, NULL);
_server = _parent->choose_server(env, _host); _server = _parent->choose_server(env, _host);
if (_server->_timeout) if (_server->_timeout) _death_time = _server->_timeout + t.tv_sec;
_death_time = _server->_timeout + t.tv_sec;
_route = _server->choose_route(_uri); _route = _server->choose_route(_uri);
if (_route->_timeout) if (_route->_timeout) _death_time = _route->_timeout + t.tv_sec;
_death_time = _route->_timeout + t.tv_sec; if (DEBUG) debug_header();
if (DEBUG)
debug_header();
string len = header_pick("Content-Length:", 0).c_str(); string len = header_pick("Content-Length:", 0).c_str();
if (len != "") { if (len != "") {
_len = std::atoi(len.c_str()); _len = std::atoi(len.c_str());
_last_chunk = true; _last_chunk = true;
int max_len = int max_len = _route->_client_max_body_size > 0 ? _route->_client_max_body_size
_route->_client_max_body_size > 0 ? _route->_client_max_body_size
: _server->_client_max_body_size > 0 ? _server->_client_max_body_size : _server->_client_max_body_size > 0 ? _server->_client_max_body_size
: INT_MAX; : INT_MAX;
if (_len > max_len) if (_len > max_len) return (send_error(413), false);
return (send_error(413), false); } else _len = 0;
} else
_len = 0;
return true; return true;
} }
string Client::header_pick(string key, size_t id) { string Client::header_pick(string key, size_t id) { return _headers[key].size() <= id ? "" : _headers[key].at(id); }
return _headers[key].size() <= id ? "" : _headers[key].at(id);
}
bool Client::check_method(void) { bool Client::check_method(void) {
vec_string allowed; vec_string allowed;
if ((_route && (allowed = _route->_allowed_methods).size() > 0) || if ((_route && (allowed = _route->_allowed_methods).size() > 0) ||
(_server && (allowed = _server->_allowed_methods).size() > 0) || (_server && (allowed = _server->_allowed_methods).size() > 0) || ((allowed = _env->_allowed_methods).size() > 0))
((allowed = _env->_allowed_methods).size() > 0)) return std::find(allowed.begin(), allowed.end(), _method) < allowed.end() ? true : false;
return std::find(allowed.begin(), allowed.end(), _method) < allowed.end() else if (_method == "GET" || _method == "POST" || _method == "DELETE" || _method == "PUT") return (true);
? true
: false;
else if (_method == "GET" || _method == "POST" || _method == "DELETE" ||
_method == "PUT")
return (true);
return (false); return (false);
} }
@ -212,10 +182,8 @@ void Client::handleRequest(void) {
debug_block("Header: ", _header); debug_block("Header: ", _header);
debug_block("Body: ", _body); debug_block("Body: ", _body);
} }
if (_route->_ret_uri != "") if (_route->_ret_uri != "") send_error(_route->_ret_code, _route->_ret_uri);
send_error(_route->_ret_code, _route->_ret_uri); else if (_server->_ret_uri != "") send_error(_server->_ret_code, _server->_ret_uri);
else if (_server->_ret_uri != "")
send_error(_server->_ret_code, _server->_ret_uri);
else { else {
string ret; string ret;
struct timeval t; struct timeval t;
@ -226,40 +194,28 @@ void Client::handleRequest(void) {
return; return;
} }
string req_path = _route->getRoot() + _uri; string req_path = _route->getRoot() + _uri;
if (!SILENT) if (!SILENT) std::cout << "||-> Request for " << req_path << " received <-||\n";
std::cout << "||-> Request for " << req_path << " received <-||\n"; string cgi_path = _route->_cgi.size() ? _route->_cgi[get_extension(req_path)]
string cgi_path =
_route->_cgi.size() ? _route->_cgi[get_extension(req_path)]
: _server->_cgi.size() ? _server->_cgi[get_extension(req_path)] : _server->_cgi.size() ? _server->_cgi[get_extension(req_path)]
: ""; : "";
if (DEBUG) if (DEBUG) cout << "Path: " << req_path << "\n";
cout << "Path: " << req_path << "\n"; if (!check_method()) send_error(405);
if (!check_method())
send_error(405);
else { else {
if ((ret = _route->getIndex(_uri, req_path)) == "") if ((ret = _route->getIndex(_uri, req_path)) == "") ret = file_answer(req_path);
ret = file_answer(req_path);
if (ret == "404") { if (ret == "404") {
if (_method == "POST" || _method == "PUT") if (_method == "POST" || _method == "PUT") create_file(req_path);
create_file(req_path); else send_error(404);
else } else if (ret == "403") send_error(403);
send_error(404); else if (_method == "DELETE") std::remove(req_path.c_str());
} else if (ret == "403") else if (cgi_path != "") cgi(cgi_path, req_path);
send_error(403); else send_answer("HTTP/1.1 200 OK\r\n" + ret);
else if (_method == "DELETE")
std::remove(req_path.c_str());
else if (cgi_path != "")
cgi(cgi_path, req_path);
else
send_answer("HTTP/1.1 200 OK\r\n" + ret);
} }
} }
} }
void Client::create_file(string path) { void Client::create_file(string path) {
std::ofstream file(path.c_str()); std::ofstream file(path.c_str());
if (!file.good()) if (!file.good()) send_error(403);
send_error(403);
else { else {
file << _body; file << _body;
file.close(); file.close();
@ -278,18 +234,15 @@ void Client::cgi(string cgi_path, string path) {
int pipe_in[2]; int pipe_in[2];
send(_fd, "HTTP/1.1 200 OK\r\n", 17, MSG_NOSIGNAL); send(_fd, "HTTP/1.1 200 OK\r\n", 17, MSG_NOSIGNAL);
if (!std::ifstream(cgi_path.c_str()).good()) if (!std::ifstream(cgi_path.c_str()).good()) return send_error(404);
return send_error(404); if (DEBUG) std::cout << "Send cgi\n";
if (DEBUG)
std::cout << "Send cgi\n";
if (fork() == 0) { if (fork() == 0) {
const char **args = new const char *[cgi_path.length() + 1]; const char **args = new const char *[cgi_path.length() + 1];
args[0] = cgi_path.c_str(); args[0] = cgi_path.c_str();
args[1] = NULL; args[1] = NULL;
string path_info = "PATH_INFO=" + _route->getRoot(); string path_info = "PATH_INFO=" + _route->getRoot();
string query = "QUERY_STRING=" + _query; string query = "QUERY_STRING=" + _query;
const char **env = const char **env = new const char *[path_info.length() + query.length() + 2];
new const char *[path_info.length() + query.length() + 2];
env[0] = path_info.c_str(); env[0] = path_info.c_str();
env[1] = query.c_str(); env[1] = query.c_str();
env[2] = NULL; env[2] = NULL;
@ -319,24 +272,18 @@ void Client::send_error(int error_code, string opt) {
error_path = _route->_err_page[error_code]; error_path = _route->_err_page[error_code];
if (error_path == "") { if (error_path == "") {
error_path = _server->_err_page[error_code]; error_path = _server->_err_page[error_code];
if (error_path != "") if (error_path != "") body = file_answer(_server->correctUri(error_path));
body = file_answer(_server->correctUri(error_path)); } else body = file_answer(_route->correctUri(error_path));
} else
body = file_answer(_route->correctUri(error_path));
switch (error_code) { switch (error_code) {
case 301: case 301:
return send_answer("HTTP/1.1 301 Moved Permanently\r\nLocation: " + opt + return send_answer("HTTP/1.1 301 Moved Permanently\r\nLocation: " + opt + "\r\n" + body + "\r\n");
"\r\n" + body + "\r\n");
case 302: case 302:
return send_answer("HTTP/1.1 302 Found\r\nLocation: " + opt + "\r\n" + return send_answer("HTTP/1.1 302 Found\r\nLocation: " + opt + "\r\n" + body + "\r\n");
body + "\r\n");
case 307: case 307:
return send_answer("HTTP/1.1 307 Temporary Redirect\r\nLocation: " + opt + return send_answer("HTTP/1.1 307 Temporary Redirect\r\nLocation: " + opt + "\r\n" + body + "\r\n");
"\r\n" + body + "\r\n");
case 308: case 308:
return send_answer("HTTP/1.1 308 Permanent Redirect\r\nLocation: " + opt + return send_answer("HTTP/1.1 308 Permanent Redirect\r\nLocation: " + opt + "\r\n" + body + "\r\n");
"\r\n" + body + "\r\n");
case 400: case 400:
return send_answer("HTTP/1.1 400 Bad Request\r\n" + body + "\r\n"); return send_answer("HTTP/1.1 400 Bad Request\r\n" + body + "\r\n");
case 403: case 403:
@ -348,16 +295,11 @@ void Client::send_error(int error_code, string opt) {
"close\r\n" + "close\r\n" +
body + "\r\n"); body + "\r\n");
case 408: case 408:
return send_answer("HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n" + return send_answer("HTTP/1.1 408 Request Timeout\r\nConnection: close\r\n" + body + "\r\n");
body + "\r\n");
case 413: case 413:
return send_answer( return send_answer("HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n" + body + "\r\n");
"HTTP/1.1 413 Payload Too Large\r\nConnection: close\r\n" + body +
"\r\n");
case 429: case 429:
return send_answer( return send_answer("HTTP/1.1 429 Too Many Requests\r\nConnection: close\r\n" + body + "\r\n");
"HTTP/1.1 429 Too Many Requests\r\nConnection: close\r\n" + body +
"\r\n");
} }
} }
@ -367,14 +309,12 @@ void Client::send_error(int error_code, string opt) {
* @param msg The HTTP message to send. * @param msg The HTTP message to send.
*/ */
void Client::send_answer(string msg) { void Client::send_answer(string msg) {
if (DEBUG) if (DEBUG) debug_block("ANSWER: ", msg);
debug_block("ANSWER: ", msg);
#ifdef __linux__ #ifdef __linux__
send(_fd, msg.c_str(), msg.length(), MSG_NOSIGNAL); send(_fd, msg.c_str(), msg.length(), MSG_NOSIGNAL);
#elif __APPLE__ #elif __APPLE__
write(_fd, msg.c_str(), msg.length()); write(_fd, msg.c_str(), msg.length());
#endif #endif
init(); init();
if (!_keepalive) if (!_keepalive) _finish = true;
_finish = true;
} }

66
srcs/sock/Master.cpp

@ -12,8 +12,7 @@
*/ */
Master::~Master(void) { Master::~Master(void) {
close(_fd); close(_fd);
if (DEBUG) if (DEBUG) cout << "Destroyed master socket\n";
cout << "Destroyed master socket\n";
} }
/** /**
@ -30,24 +29,19 @@ Master::Master(ip_port_t list) : _listen(list) {
string ip = _listen.ip; string ip = _listen.ip;
_fd = socket(AF_INET, SOCK_STREAM, 0); _fd = socket(AF_INET, SOCK_STREAM, 0);
if (_fd == 0) if (_fd == 0) throw std::runtime_error("socket() error" + string(strerror(errno)));
throw std::runtime_error("socket() error" + string(strerror(errno))); if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&x, sizeof(x)) < 0 && close(_fd) <= 0)
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&x, sizeof(x)) < 0 &&
close(_fd) <= 0)
throw std::runtime_error("setsockopt() error: " + string(strerror(errno))); throw std::runtime_error("setsockopt() error: " + string(strerror(errno)));
_address.sin_family = AF_INET; _address.sin_family = AF_INET;
_address.sin_addr.s_addr = inet_addr(ip.c_str()); _address.sin_addr.s_addr = inet_addr(ip.c_str());
_address.sin_port = htons(port); _address.sin_port = htons(port);
if (bind(_fd, (struct sockaddr *)&_address, sizeof(_address)) && if (bind(_fd, (struct sockaddr *)&_address, sizeof(_address)) && close(_fd) <= 0)
close(_fd) <= 0)
throw std::runtime_error("bind() error: " + string(strerror(errno))); throw std::runtime_error("bind() error: " + string(strerror(errno)));
if (listen(_fd, 3) < 0 && close(_fd) <= 0) if (listen(_fd, 3) < 0 && close(_fd) <= 0) throw std::runtime_error("listen() error: " + string(strerror(errno)));
throw std::runtime_error("listen() error: " + string(strerror(errno)));
#ifdef __APPLE__ #ifdef __APPLE__
fcntl(socket, F_SETFL, O_NONBLOCK); fcntl(socket, F_SETFL, O_NONBLOCK);
#endif #endif
cout << "New master socket with fd " << _fd << " which listen " << ip << ":" cout << "New master socket with fd " << _fd << " which listen " << ip << ":" << port << "\n";
<< port << "\n";
_pollfds[_poll_id_amount].fd = _fd; _pollfds[_poll_id_amount].fd = _fd;
_pollfds[_poll_id_amount].events = POLLIN | POLLPRI; _pollfds[_poll_id_amount].events = POLLIN | POLLPRI;
_poll_id = _poll_id_amount; _poll_id = _poll_id_amount;
@ -61,15 +55,12 @@ void Master::check_socket(void) {
int addrlen = sizeof(_address); int addrlen = sizeof(_address);
if (_pollfds[_poll_id].revents & POLLIN) { /// < incomming master request if (_pollfds[_poll_id].revents & POLLIN) { /// < incomming master request
int new_socket = int new_socket = accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen);
accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen); if (new_socket < 0) throw std::runtime_error("accept() error:" + string(strerror(errno)));
if (new_socket < 0)
throw std::runtime_error("accept() error:" + string(strerror(errno)));
#ifdef __APPLE__ #ifdef __APPLE__
fcntl(new_socket, F_SETFL, O_NONBLOCK); fcntl(new_socket, F_SETFL, O_NONBLOCK);
#endif #endif
ip_port_t cli_listen = ip_port_t cli_listen = get_ip_port_t(inet_ntoa(_address.sin_addr), ntohs(_address.sin_port));
get_ip_port_t(inet_ntoa(_address.sin_addr), ntohs(_address.sin_port));
Client *new_cli = new Client(new_socket, cli_listen, this); Client *new_cli = new Client(new_socket, cli_listen, this);
if (_poll_id_amount > MAX_CLIENTS) { if (_poll_id_amount > MAX_CLIENTS) {
new_cli->send_error(503); new_cli->send_error(503);
@ -77,8 +68,7 @@ void Master::check_socket(void) {
} else { } else {
_childs.push_back(new_cli); _childs.push_back(new_cli);
for (int i = _first_cli_id; i < MAX_CLIENTS; i++) { for (int i = _first_cli_id; i < MAX_CLIENTS; i++) {
if (_pollfds[i].fd != 0) if (_pollfds[i].fd != 0) continue;
continue;
_pollfds[i].fd = new_socket; _pollfds[i].fd = new_socket;
_pollfds[i].events = POLLIN | POLLPRI; _pollfds[i].events = POLLIN | POLLPRI;
new_cli->_poll_id = i; new_cli->_poll_id = i;
@ -102,8 +92,7 @@ void Master::check_socket(void) {
*/ */
void Master::check_childs(Env *env) { void Master::check_childs(Env *env) {
int child_fd; int child_fd;
for (std::vector<Client *>::iterator it = _childs.begin(); it < _childs.end(); for (std::vector<Client *>::iterator it = _childs.begin(); it < _childs.end(); it++) {
it++) {
child_fd = (*it)->_fd; child_fd = (*it)->_fd;
int i = (*it)->_poll_id; int i = (*it)->_poll_id;
if (_pollfds[i].fd > 0 && _pollfds[i].revents & POLLIN) { if (_pollfds[i].fd > 0 && _pollfds[i].revents & POLLIN) {
@ -122,8 +111,7 @@ void Master::check_childs(Env *env) {
delete (*it); delete (*it);
_childs.erase(it); _childs.erase(it);
} }
} else } else _pollfds[i].events = POLLIN | POLLPRI;
_pollfds[i].events = POLLIN | POLLPRI;
} }
} }
} }
@ -151,13 +139,10 @@ Server *Master::choose_server(Env *env, string host) {
vec_string ip_listen, ip_required; vec_string ip_listen, ip_required;
ip_required = split(_listen.ip, "."); ip_required = split(_listen.ip, ".");
for (std::vector<Server *>::iterator server = env->_servers.begin(); for (std::vector<Server *>::iterator server = env->_servers.begin(); server < env->_servers.end(); server++) {
server < env->_servers.end(); server++) {
std::vector<ip_port_t> serv_listens = (*server)->_listens; std::vector<ip_port_t> serv_listens = (*server)->_listens;
for (std::vector<ip_port_t>::iterator it = serv_listens.begin(); for (std::vector<ip_port_t>::iterator it = serv_listens.begin(); it < serv_listens.end(); it++) {
it < serv_listens.end(); it++) { if (_listen.port != (*it).port) continue;
if (_listen.port != (*it).port)
continue;
if (_listen.ip == (*it).ip) { if (_listen.ip == (*it).ip) {
exact.push_back(*server); exact.push_back(*server);
continue; continue;
@ -167,27 +152,20 @@ Server *Master::choose_server(Env *env, string host) {
vec_string::iterator r = ip_required.end(); vec_string::iterator r = ip_required.end();
vec_string::iterator l = ip_listen.end(); vec_string::iterator l = ip_listen.end();
while (r > ip_required.begin()) { while (r > ip_required.begin()) {
if (*(--l) != *(--r) && *l != "0") if (*(--l) != *(--r) && *l != "0") is_inrange = false;
is_inrange = false;
} }
if (is_inrange) if (is_inrange) inrange.push_back(*server);
inrange.push_back(*server);
} }
} }
if (DEBUG) if (DEBUG) std::cout << "req: " << _listen.ip << ":" << _listen.port << "\n";
std::cout << "req: " << _listen.ip << ":" << _listen.port << "\n";
if (exact.size() == 0) { if (exact.size() == 0) {
for (std::vector<Server *>::iterator server = inrange.begin(); for (std::vector<Server *>::iterator server = inrange.begin(); server < inrange.end(); server++) {
server < inrange.end(); server++) { if (host == (*server)->getName()) return *server;
if (host == (*server)->getName())
return *server;
} }
return inrange.front(); return inrange.front();
} else { } else {
for (std::vector<Server *>::iterator server = exact.begin(); for (std::vector<Server *>::iterator server = exact.begin(); server < exact.end(); server++) {
server < exact.end(); server++) { if (host == (*server)->getName()) return *server;
if (host == (*server)->getName())
return *server;
} }
return exact.front(); return exact.front();
} }

Loading…
Cancel
Save