nicolas-arnaud
2 years ago
4 changed files with 217 additions and 213 deletions
@ -1,169 +1,170 @@ |
|||||
|
|
||||
#include "webserv.hpp" |
#include "webserv.hpp" |
||||
|
|
||||
Socket::Socket(listen_t listen) : _listen(listen) {} |
Socket::Socket(listen_t listen) : _listen(listen) {} |
||||
Socket::Socket(int fd, Socket *parent) : _fd(fd),_parent(parent) {} |
Socket::Socket(int fd, Socket *parent) : _fd(fd), _parent(parent) {} |
||||
|
|
||||
Socket::~Socket(void) { |
Socket::~Socket(void) { |
||||
close(_fd); |
close(_fd); |
||||
cout << "Socket destroyed!\n"; |
cout << "Socket destroyed!\n"; |
||||
} |
} |
||||
|
|
||||
int Socket::launch(void) { |
int Socket::launch(void) { |
||||
int opt = 1; |
int opt = 1; |
||||
string ip = _listen.ip; |
string ip = _listen.ip; |
||||
int port = _listen.port; |
int port = _listen.port; |
||||
|
|
||||
_fd = socket(AF_INET, SOCK_STREAM, 0); |
_fd = socket(AF_INET, SOCK_STREAM, 0); |
||||
if (_fd == 0) { |
if (_fd == 0) { |
||||
cout << "Socket creation: " << strerror(errno) << "\n"; |
cout << "Socket creation: " << strerror(errno) << "\n"; |
||||
return (EXIT_FAILURE); |
return (EXIT_FAILURE); |
||||
} |
} |
||||
int opt_ret = setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, |
int opt_ret = |
||||
(char *)&opt, sizeof(opt)); |
setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); |
||||
if (opt_ret < 0) { |
if (opt_ret < 0) { |
||||
cout << "Sockopt: " << strerror(errno) << "\n"; |
cout << "Sockopt: " << strerror(errno) << "\n"; |
||||
return (EXIT_FAILURE); |
return (EXIT_FAILURE); |
||||
} |
} |
||||
|
|
||||
_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)) < 0) { |
||||
0) { |
cout << "Bind: " << strerror(errno) << "\n"; |
||||
cout << "Bind: " << strerror(errno) << "\n"; |
return (EXIT_FAILURE); |
||||
return (EXIT_FAILURE); |
} |
||||
} |
cout << "Listener " << ip << " on port " << port << "\n"; |
||||
cout << "Listener " << ip << " on port " << port << "\n"; |
|
||||
|
|
||||
if (listen(_fd, 3) < 0) { |
if (listen(_fd, 3) < 0) { |
||||
cout << "Listen: " << strerror(errno) << "\n"; |
cout << "Listen: " << strerror(errno) << "\n"; |
||||
return (EXIT_FAILURE); |
return (EXIT_FAILURE); |
||||
} |
} |
||||
cout << "Master: " << _fd << "\n"; |
cout << "Master: " << _fd << "\n"; |
||||
if (_fd < _min_fd) |
if (_fd < _min_fd) |
||||
_min_fd = _fd; |
_min_fd = _fd; |
||||
_amount++; |
_amount++; |
||||
return (EXIT_SUCCESS); |
return (EXIT_SUCCESS); |
||||
} |
} |
||||
|
|
||||
void Socket::set_fds(void) { |
void Socket::set_fds(void) { |
||||
int child_fd; |
int child_fd; |
||||
FD_SET(_fd, &_readfds); |
FD_SET(_fd, &_readfds); |
||||
for (std::vector<Socket *>::iterator it = _childs.begin(); it < _childs.end(); |
for (std::vector<Socket *>::iterator it = _childs.begin(); it < _childs.end(); |
||||
it++) { |
it++) { |
||||
child_fd = (*it)->_fd; |
child_fd = (*it)->_fd; |
||||
FD_SET(child_fd, &_readfds); |
FD_SET(child_fd, &_readfds); |
||||
if (child_fd > _max_fd) |
if (child_fd > _max_fd) |
||||
_max_fd = child_fd; |
_max_fd = child_fd; |
||||
} |
} |
||||
} |
} |
||||
|
|
||||
void Socket::refresh(Env *env) { |
void Socket::refresh(Env *env) { |
||||
int valread; |
int valread; |
||||
int addrlen = sizeof(_address); |
int addrlen = sizeof(_address); |
||||
char buffer[10000]; |
char buffer[10000]; |
||||
if (FD_ISSET(_fd, &_readfds)) { |
if (FD_ISSET(_fd, &_readfds)) { |
||||
int new_socket = accept(_fd, (struct sockaddr *)&_address, |
int new_socket = |
||||
(socklen_t *)&addrlen); |
accept(_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen); |
||||
if (new_socket < 0) { |
if (new_socket < 0) { |
||||
cout << "Accept: " << strerror(errno) << "\n"; |
cout << "Accept: " << strerror(errno) << "\n"; |
||||
exit(EXIT_FAILURE); |
exit(EXIT_FAILURE); |
||||
} |
} |
||||
#ifdef __APPLE__ |
#ifdef __APPLE__ |
||||
//fcntl(new_socket, F_GETNOSIGPIPE);
|
// fcntl(new_socket, F_GETNOSIGPIPE);
|
||||
fcntl(new_socket, F_SETFL, O_NONBLOCK); |
fcntl(new_socket, F_SETFL, O_NONBLOCK); |
||||
#endif |
#endif |
||||
cout << "New connection, socket fd is " << new_socket |
cout << "New connection, socket fd is " << new_socket |
||||
<< ", ip is : " << inet_ntoa(_address.sin_addr) |
<< ", ip is : " << inet_ntoa(_address.sin_addr) |
||||
<< ", port : " << ntohs(_address.sin_port) << "\n"; |
<< ", port : " << ntohs(_address.sin_port) << "\n"; |
||||
_childs.push_back(new Socket(new_socket, this)); |
_childs.push_back(new Socket(new_socket, this)); |
||||
} |
} |
||||
int child_fd; |
int child_fd; |
||||
for (std::vector<Socket *>::iterator it = _childs.begin(); it < _childs.end(); it++) { |
for (std::vector<Socket *>::iterator it = _childs.begin(); it < _childs.end(); |
||||
child_fd = (*it)->_fd; |
it++) { |
||||
if (FD_ISSET(child_fd, &_readfds)) { |
child_fd = (*it)->_fd; |
||||
valread = read(child_fd, buffer, 10000); |
if (FD_ISSET(child_fd, &_readfds)) { |
||||
if (valread == 0) { |
valread = read(child_fd, buffer, 10000); |
||||
getpeername(child_fd, (struct sockaddr *)&_address, |
if (valread == 0) { |
||||
(socklen_t *)&addrlen); |
getpeername(child_fd, (struct sockaddr *)&_address, |
||||
cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr) |
(socklen_t *)&addrlen); |
||||
<< ", port " << ntohs(_address.sin_port) << "\n"; |
cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr) |
||||
delete (*it); |
<< ", port " << ntohs(_address.sin_port) << "\n"; |
||||
_childs.erase(it); |
delete (*it); |
||||
} else { |
_childs.erase(it); |
||||
buffer[valread] = '\0'; |
} else { |
||||
(*it)->answer(env, buffer); |
buffer[valread] = '\0'; |
||||
} |
(*it)->answer(env, buffer); |
||||
} |
} |
||||
} |
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
bool Socket::waitHeader() { |
bool Socket::waitHeader() { |
||||
if (_header.length() < 1) |
if (_tmp.length() < 1) |
||||
return false; |
return false; |
||||
std::vector<string> lines = split(header, '\r\n'); |
std::vector<string> lines = split(_tmp, '\n'); |
||||
bool is_valid = false; |
bool is_valid = false; |
||||
for (std::vector<string>::iterator it = lines.begin(); |
for (std::vector<string>::iterator it = lines.begin(); it < lines.end(); |
||||
it < lines.end(); it++) { |
it++) { |
||||
if (*it == "") |
if (*it == "\r") |
||||
is_valid = true; |
is_valid = true; |
||||
} |
} |
||||
if (!is_valid || lines.at(0) == "") |
if (!is_valid) |
||||
return false; |
return false; |
||||
std::vector<string> head = split(lines.at(0), ' '); |
_header = _tmp; |
||||
if ((head.at(0) != "GET" && head.at(0) != "POST" && head.at(0) != "DELETE") |
_tmp = ""; |
||||
|| head.size() < 2) |
return true; |
||||
return false; |
|
||||
|
|
||||
return true; |
|
||||
} |
} |
||||
|
|
||||
int Socket::answer(Env *env, string request) { |
int Socket::answer(Env *env, string request) { |
||||
tmp += request; |
_tmp += request; |
||||
cout << "|===|request|===>"<< _request << "|===||\n"; |
cout << "|===|request|===>" << _tmp << "|===||\n"; |
||||
if (_header == "") { |
if (_header == "") { |
||||
waitHeader(); |
waitHeader(); |
||||
cout << "Bad request recieved\n"; |
} |
||||
return EXIT_FAILURE; |
std::vector<string> lines = split(_header, '\n'); |
||||
} |
std::vector<string> head = split(lines.at(0), ' '); |
||||
std::vector<string> lines = split(_request, '\n'); |
string uri = head.at(1); |
||||
std::vector<string> head = split(lines.at(0), ' '); |
cout << uri << "\n"; |
||||
string uri = head.at(1); |
string ret; |
||||
cout << uri << "\n"; |
std::stringstream answer; |
||||
string ret; |
answer << "HTTP/1.1"; |
||||
std::stringstream answer; |
|
||||
answer << "HTTP/1.1"; |
Server *server = env->choose_server(_parent, split(lines.at(1), ' ').at(1)); |
||||
|
Route *route = server->get_route(uri); |
||||
|
std::vector<string> headers; |
||||
|
|
||||
Server *server = env->choose_server(_parent, split(lines.at(1), ' ').at(1)); |
if ((head.at(0) != "GET" && head.at(0) != "POST" && head.at(0) != "DELETE") || |
||||
Route *route = server->get_route(uri); |
head.size() < 2) |
||||
std::vector<string> headers; |
send_answer("HTTP/1.1 405 Method Not Allowed\r\nContent-length: 0\r\n\r\n"); |
||||
if ((headers = route->getHeadersLst()).size() > 0) { |
else if ((headers = route->getHeadersLst()).size() > 0) { |
||||
if (std::find(headers.begin(), headers.end(), head.at(0)) == headers.end()) |
if (std::find(headers.begin(), headers.end(), head.at(0)) == headers.end()) |
||||
send_answer("HTTP/1.1 405 Method Not Allowed"); |
send_answer("HTTP/1.1 405 Method Not Allowed\r\nContent-length: 0\r\n\r\n"); |
||||
} else if ((headers = server->getHeadersLst()).size() > 0) { |
} else if ((headers = server->getHeadersLst()).size() > 0) { |
||||
if (std::find(headers.begin(), headers.end(), head.at(0)) == headers.end()) |
if (std::find(headers.begin(), headers.end(), head.at(0)) == headers.end()) |
||||
send_answer("HTTP/1.1 405 Method Not Allowed"); |
send_answer("HTTP/1.1 405 Method Not Allowed\r\nContent-length: 0\r\n\r\n"); |
||||
} |
} |
||||
|
|
||||
string path = route->correctUri(uri); |
string path = route->correctUri(uri); |
||||
cout << "Path: " << path << "\n"; |
cout << "Path: " << path << "\n"; |
||||
ret = route->getIndex(uri, path); |
ret = route->getIndex(uri, path); |
||||
if (ret == "") { |
if (ret == "") { |
||||
cout << "No index: lf file\n"; |
cout << "No index: lf file\n"; |
||||
ret = read_file(path); |
ret = read_file(path); |
||||
} |
} |
||||
answer << (ret == "" ? " 404 Not Found\nContent-length: 0\n\n" : " 200 OK\n") << ret; |
answer << (ret == "" ? " 404 Not Found\r\nContent-length: 0\r\n\r\n" : " 200 OK\r\n") |
||||
cout << "|===|Answer|===>" << answer.str() << "|===||\n"; |
<< ret; |
||||
send_answer(answer.str()); |
cout << "|===|Answer|===>" << answer.str() << "|===||\n"; |
||||
_request = ""; |
send_answer(answer.str()); |
||||
return EXIT_SUCCESS; |
_content = ""; |
||||
|
_header = ""; |
||||
|
return EXIT_SUCCESS; |
||||
} |
} |
||||
|
|
||||
void Socket::send_answer(string msg) { |
void Socket::send_answer(string 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__ |
||||
send(_fd, msg.c_str(), msg.length(), 0); |
send(_fd, msg.c_str(), msg.length(), 0); |
||||
#endif |
#endif |
||||
} |
} |
||||
|
Loading…
Reference in new issue