diff --git a/Makefile b/Makefile index 0f5cb74..b92949f 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ CXXFLAGS= -g -I includes -Werror -Wextra -Wall -std=c++98 all : $(NAME) $(NAME): $(OBJS) - $(CXX) -g $(OBJS) -o $(NAME) + $(CXX) -g $(OBJS) -o $(NAME) clean: rm -rf $(OBJS) diff --git a/includes/Socket.hpp b/includes/Socket.hpp index f43df40..62ba30b 100644 --- a/includes/Socket.hpp +++ b/includes/Socket.hpp @@ -2,10 +2,11 @@ #include "webserv.hpp" class Socket { - int _master_socket; - int _clients_amount; - std::vector _clients; - + int _fd; + //int _clients_amount; + Socket *_parent; + std::vector _childs; + string _request; public: struct sockaddr_in _address; listen_t _listen; @@ -14,10 +15,12 @@ class Socket { static int _min_fd; static int _amount; Socket(listen_t listen); + Socket(int fd, Socket *parent); ~Socket(void); int launch(void); void set_fds(void); void refresh(Env *env); - int answer(Env *env, int fd, string request); - void send_answer(int fd, string msg); + bool isRequestValid(string request); + int answer(Env *env, string request); + void send_answer(string msg); }; diff --git a/srcs/load/Socket.cpp b/srcs/load/Socket.cpp index c6effd2..6d89f3b 100644 --- a/srcs/load/Socket.cpp +++ b/srcs/load/Socket.cpp @@ -1,9 +1,10 @@ #include "webserv.hpp" -Socket::Socket(listen_t listen) : _listen(listen) { _clients_amount = 0; } +Socket::Socket(listen_t listen) : _listen(listen) {} +Socket::Socket(int fd, Socket *parent) : _fd(fd),_parent(parent) {} Socket::~Socket(void) { - close(_master_socket); + close(_fd); cout << "Socket destroyed!\n"; } @@ -12,12 +13,12 @@ int Socket::launch(void) { string ip = _listen.ip; int port = _listen.port; - _master_socket = socket(AF_INET, SOCK_STREAM, 0); - if (_master_socket == 0) { + _fd = socket(AF_INET, SOCK_STREAM, 0); + if (_fd == 0) { cout << "Socket creation: " << strerror(errno) << "\n"; return (EXIT_FAILURE); } - int opt_ret = setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, + int opt_ret = setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt)); if (opt_ret < 0) { cout << "Sockopt: " << strerror(errno) << "\n"; @@ -28,92 +29,111 @@ int Socket::launch(void) { _address.sin_addr.s_addr = inet_addr(ip.c_str()); _address.sin_port = htons(port); - if (bind(_master_socket, (struct sockaddr *)&_address, sizeof(_address)) < + 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(_master_socket, 3) < 0) { + if (listen(_fd, 3) < 0) { cout << "Listen: " << strerror(errno) << "\n"; return (EXIT_FAILURE); } - cout << "Socket::_master_socket: " << _master_socket << "\n"; - if (_master_socket < _min_fd) - _min_fd = _master_socket; + cout << "Master: " << _fd << "\n"; + if (_fd < _min_fd) + _min_fd = _fd; _amount++; return (EXIT_SUCCESS); } void Socket::set_fds(void) { - FD_SET(_master_socket, &_readfds); - - for (std::vector::iterator it = _clients.begin(); it < _clients.end(); + int child_fd; + FD_SET(_fd, &_readfds); + for (std::vector::iterator it = _childs.begin(); it < _childs.end(); it++) { - FD_SET(*it, &_readfds); - if (*it > _max_fd) - _max_fd = *it; + child_fd = (*it)->_fd; + FD_SET(child_fd, &_readfds); + if (child_fd > _max_fd) + _max_fd = child_fd; } } void Socket::refresh(Env *env) { - std::vector::iterator it; int valread; int addrlen = sizeof(_address); char buffer[10000]; - if (FD_ISSET(_master_socket, &_readfds)) { - int new_socket = accept(_master_socket, (struct sockaddr *)&_address, + 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_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"; - _clients.push_back(new_socket); + _childs.push_back(new Socket(new_socket, this)); } - for (it = _clients.begin(); it < _clients.end(); it++) { - if (FD_ISSET(*it, &_readfds)) { - valread = read(*it, buffer, 10000); + int child_fd; + for (std::vector::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(*it, (struct sockaddr *)&_address, + getpeername(child_fd, (struct sockaddr *)&_address, (socklen_t *)&addrlen); cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr) << ", port " << ntohs(_address.sin_port) << "\n"; - close(*it); - _clients.erase(it); + delete (*it); + _childs.erase(it); } else { buffer[valread] = '\0'; - if (answer(env, *it, buffer) == EXIT_FAILURE) { - _clients.erase(it); - close(*it); - } - + (*it)->answer(env, buffer); } } } } -int Socket::answer(Env *env, int fd, string request) { - cout << "|===|Request|===|\n"<< request << "\n|===|===|===|\n"; - std::vector lines = split(request, '\n'); +bool Socket::isRequestValid(string request) { + _request += request; + if (_request.length() < 1) + return false; + std::vector lines = split(_request, '\n'); + bool is_valid = false; + for (std::vector::iterator it = lines.begin(); + it < lines.end(); it++) { + if (*it == "\r" || *it == "") is_valid = true; + } + if (!is_valid || lines.at(0) == "") + return false; std::vector head = split(lines.at(0), ' '); - string uri; - if (head.size() < 2) + if ((head.at(0) != "GET" && head.at(0) != "POST" && head.at(0) != "DELETE") + || head.size() < 2) + return false; + return true; +} + +int Socket::answer(Env *env, string request) { + cout << "|===|Request|===|\n"<< request << "\n|===|===|===|\n"; + if (!isRequestValid(request)) { + cout << "Bad request recieved\n"; + send_answer("HTTP/1.1 400 Bad Request\n\n"); return EXIT_FAILURE; - uri = head.at(1); + } + std::vector lines = split(_request, '\n'); + std::vector head = split(lines.at(0), ' '); + string uri = head.at(1); cout << uri << "\n"; string ret; - std::stringstream answer; answer << "HTTP/1.1"; - Server *server = env->choose_server(this, split(lines.at(1), ' ').at(1)); + Server *server = env->choose_server(_parent, split(lines.at(1), ' ').at(1)); Route *route = server->get_route(uri); string path = route->correctUri(uri); cout << "Path: " << path << "\n"; @@ -124,14 +144,15 @@ int Socket::answer(Env *env, int fd, string request) { } answer << (ret == "" ? " 404 Not Found\nContent-length: 0\n\n" : " 200 OK\n") << ret; cout << "|===|Answer|===|\n" << answer.str() << "\n|===|===|===|\n"; - send_answer(fd, answer.str()); + send_answer(answer.str()); + _request = ""; return EXIT_SUCCESS; } -void Socket::send_answer(int fd, string msg) { +void Socket::send_answer(string msg) { #ifdef __linux__ - send(fd, msg.c_str(), msg.length(), MSG_NOSIGNAL); + send(_fd, msg.c_str(), msg.length(), MSG_NOSIGNAL); #elif __APPLE__ - send(fd, msg.c_str(), msg.length(), 0); + send(_fd, msg.c_str(), msg.length(), 0); #endif }