diff --git a/Makefile b/Makefile index 0f5cb74..959c5cf 100644 --- a/Makefile +++ b/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/Socket.cpp srcs/load/Sock6.cpp srcs/load/Route.cpp \ srcs/json/Nodes.cpp srcs/json/Token.cpp srcs/json/Parser.cpp OBJS= $(SRCS:.cpp=.o) CXX=c++ diff --git a/default.json b/default.json index f83869e..a108003 100644 --- a/default.json +++ b/default.json @@ -4,7 +4,7 @@ "servers": [ { "server_name": "localhost", - "listens": ["8080", "localhost:8080", "localhost", "[::]:443"], + "listens": ["80", "localhost:80", "localhost", "[::]:5555"], "return": "301 https://$host$uri" }, { diff --git a/includes/Sock6.hpp b/includes/Sock6.hpp new file mode 100644 index 0000000..792c904 --- /dev/null +++ b/includes/Sock6.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "webserv.hpp" + +class Sock6: public Socket { + struct sockaddr_in6 _addr6; +public: + Sock6(listen_t listen); + ~Sock6(); + int launch(); + void refresh(Env *env); +}; diff --git a/includes/Socket.hpp b/includes/Socket.hpp index 15c30fc..7a63432 100644 --- a/includes/Socket.hpp +++ b/includes/Socket.hpp @@ -2,10 +2,12 @@ #include "webserv.hpp" class Socket { + struct sockaddr_in _addr; + protected: int _master_socket; - struct sockaddr_in _address; int _clients_amount; std::vector _clients; + int _type; public: listen_t _listen; @@ -13,7 +15,7 @@ class Socket { static int _max_fd; static int _min_fd; static int _amount; - Socket(string def); + Socket(listen_t listen); ~Socket(); int launch(); void set_fds(); diff --git a/includes/webserv.hpp b/includes/webserv.hpp index 9f0d43f..e8805b1 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -44,6 +44,7 @@ typedef std::vector JSONList; typedef struct listen_s { string ip; int port; + int type; } listen_t; void *ft_memset(void *b, int c, size_t len); @@ -57,5 +58,6 @@ listen_t get_listen_t(string listen); #include "Route.hpp" #include "Socket.hpp" +#include "Sock6.hpp" #include "Server.hpp" #include "Env.hpp" diff --git a/srcs/load/Route.cpp b/srcs/load/Route.cpp index d72d930..e63dc18 100644 --- a/srcs/load/Route.cpp +++ b/srcs/load/Route.cpp @@ -33,7 +33,7 @@ string Route::getAutoindex(string uri) { struct stat info; if ((dir = opendir(path.c_str())) == NULL) - ret << " 19\n\nFolder unaccesible."; + page << "Folder unaccesible."; else { page << path << " files :\n"; while ((entry = readdir(dir)) != NULL) { diff --git a/srcs/load/Server.cpp b/srcs/load/Server.cpp index 427ab7c..2229093 100644 --- a/srcs/load/Server.cpp +++ b/srcs/load/Server.cpp @@ -15,27 +15,32 @@ Server::Server(JSONNode *server) : Route(server) { } std::vector Server::get_sockets(JSONNode *server) { - JSONObject datas = server->obj(); - std::vector ret; - if (datas["listens"]) { + JSONObject datas = server->obj(); + std::vector ret; + listen_t listen; + if (datas["listens"]) { JSONList listens = datas["listens"]->lst(); for (JSONList::iterator it = listens.begin(); it < listens.end(); it++) { - _listens.push_back(get_listen_t((*it)->str())); - Socket *sock = new Socket((*it)->str()); + listen = get_listen_t((*it)->str()); + _listens.push_back(listen); + Socket *sock; + if (listen.type == AF_INET) + sock = new Socket(listen); + else + sock = new Sock6(listen); if (sock->launch() == EXIT_SUCCESS) ret.push_back(sock); else delete sock; } } else { - Socket *sock = new Socket("localhost:80"); - if (sock->launch() == EXIT_SUCCESS) { - ret.push_back(sock); - } - } - return ret; - + Socket *sock = new Socket(get_listen_t("localhost:80")); + if (sock->launch() == EXIT_SUCCESS) { + ret.push_back(sock); + } + } + return ret; } Server::~Server(void) { cout << "Server destroyed!\n"; } @@ -49,10 +54,10 @@ Route *Server::get_route(string uri) { root = split((*rit).first, '/'); std::vector::iterator root_it = root.begin(); - for (std::vector::iterator it = req.begin(); - it < req.end(); it++) { + for (std::vector::iterator it = req.begin(); it < req.end(); + it++) { if (*it == "") - continue ; + continue; cout << *it << " - " << *root_it << "\n"; if (*it != *(root_it++)) break; diff --git a/srcs/load/Sock6.cpp b/srcs/load/Sock6.cpp new file mode 100644 index 0000000..b69d139 --- /dev/null +++ b/srcs/load/Sock6.cpp @@ -0,0 +1,82 @@ +#include "webserv.hpp" + +Sock6::Sock6(listen_t listen) : Socket(listen) { _type = AF_INET6; } + +int Sock6::launch() { + int opt = 1; + string ip = _listen.ip; + int port = _listen.port; + + _addr6.sin6_family = AF_INET6; + inet_pton(AF_INET6, ip.c_str(), (void *)&(_addr6.sin6_addr.s6_addr)); + _addr6.sin6_port = htons(port); + _master_socket = socket(_addr6.sin6_family, SOCK_STREAM, 0); + + if (_master_socket == 0) { + cout << "Socket creation: " << strerror(errno) << "\n"; + return (EXIT_FAILURE); + } + int opt_ret = setsockopt(_master_socket, SOL_SOCKET, SO_REUSEADDR, + (char *)&opt, sizeof(opt)); + if (opt_ret < 0) { + cout << "Sockopt: " << strerror(errno) << "\n"; + return (EXIT_FAILURE); + } + + if (bind(_master_socket, (struct sockaddr *)&_addr6, sizeof(_addr6)) < 0) { + cout << "Bind: " << strerror(errno) << "\n"; + return (EXIT_FAILURE); + } + cout << "Listener " << ip << " on port " << port << "\n"; + + if (listen(_master_socket, 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; + _amount++; + return (EXIT_SUCCESS); +} + +void Sock6::refresh(Env *env) { + + std::vector::iterator it; + int valread; + int addrlen = sizeof(_addr6); + char buffer[10000]; + if (FD_ISSET(_master_socket, &_readfds)) { + int new_socket = accept(_master_socket, (struct sockaddr *)&_addr6, + (socklen_t *)&addrlen); + if (new_socket < 0) { + cout << "Accept: " << strerror(errno) << "\n"; + exit(EXIT_FAILURE); + } +#ifdef __APPLE__ + fcntl(new_socket, F_GETNOSIGPIPE); +#endif + cout << "New connection, socket fd is " + << new_socket + // << ", ip is : " << inet_ntoa(_addr6.sin6_addr) + << ", port : " << ntohs(_addr6.sin6_port) << "\n"; + _clients.push_back(new_socket); + } + for (it = _clients.begin(); it < _clients.end(); it++) { + if (FD_ISSET(*it, &_readfds)) { + valread = read(*it, buffer, 10000); + if (valread == 0) { + getpeername(*it, (struct sockaddr *)&_addr6, + (socklen_t *)&addrlen); + // cout << "Host disconnected, ip " << + //inet_ntoa(_addr6.sin6_addr) + // << ", port " << ntohs(_addr6.sin6_port) << "\n"; + close(*it); + _clients.erase(it); + } else { + buffer[valread] = '\0'; + answer(env, *it, buffer); + } + } + } +} diff --git a/srcs/load/Socket.cpp b/srcs/load/Socket.cpp index 4f62ce6..826027e 100644 --- a/srcs/load/Socket.cpp +++ b/srcs/load/Socket.cpp @@ -1,9 +1,9 @@ #include "webserv.hpp" -Socket::Socket(string def) { - _listen = get_listen_t(def); +Socket::Socket(listen_t listen) : _listen(listen) { _clients_amount = 0; + _type = AF_INET; } Socket::~Socket() { close(_master_socket); @@ -12,9 +12,15 @@ Socket::~Socket() { int Socket::launch() { int opt = 1; - string ip = _listen.ip; - int port = _listen.port; - _master_socket = socket(AF_INET, SOCK_STREAM, 0); + string ip = _listen.ip; + int port = _listen.port; + + _type = AF_INET; + _addr.sin_family = AF_INET; + _addr.sin_addr.s_addr = inet_addr(ip.c_str()); + _addr.sin_port = htons(port); + _master_socket = socket(_addr.sin_family, SOCK_STREAM, 0); + if (_master_socket == 0) { cout << "Socket creation: " << strerror(errno) << "\n"; return (EXIT_FAILURE); @@ -26,15 +32,7 @@ int Socket::launch() { return (EXIT_FAILURE); } - if (ip.at(0) == '[') - _address.sin_family = AF_INET6; - else - _address.sin_family = AF_INET; - _address.sin_addr.s_addr = inet_addr(ip.c_str()); - _address.sin_port = htons(port); - - if (bind(_master_socket, (struct sockaddr *)&_address, sizeof(_address)) < - 0) { + if (bind(_master_socket, (struct sockaddr *)&_addr, sizeof(_addr)) < 0) { cout << "Bind: " << strerror(errno) << "\n"; return (EXIT_FAILURE); } @@ -65,10 +63,10 @@ void Socket::set_fds() { void Socket::refresh(Env *env) { std::vector::iterator it; int valread; - int addrlen = sizeof(_address); + int addrlen = sizeof(_addr); char buffer[10000]; if (FD_ISSET(_master_socket, &_readfds)) { - int new_socket = accept(_master_socket, (struct sockaddr *)&_address, + int new_socket = accept(_master_socket, (struct sockaddr *)&_addr, (socklen_t *)&addrlen); if (new_socket < 0) { cout << "Accept: " << strerror(errno) << "\n"; @@ -78,18 +76,18 @@ void Socket::refresh(Env *env) { fcntl(new_socket, F_GETNOSIGPIPE); #endif cout << "New connection, socket fd is " << new_socket - << ", ip is : " << inet_ntoa(_address.sin_addr) - << ", port : " << ntohs(_address.sin_port) << "\n"; + << ", ip is : " << inet_ntoa(_addr.sin_addr) + << ", port : " << ntohs(_addr.sin_port) << "\n"; _clients.push_back(new_socket); } for (it = _clients.begin(); it < _clients.end(); it++) { if (FD_ISSET(*it, &_readfds)) { valread = read(*it, buffer, 10000); if (valread == 0) { - getpeername(*it, (struct sockaddr *)&_address, + getpeername(*it, (struct sockaddr *)&_addr, (socklen_t *)&addrlen); - cout << "Host disconnected, ip " << inet_ntoa(_address.sin_addr) - << ", port " << ntohs(_address.sin_port) << "\n"; + cout << "Host disconnected, ip " << inet_ntoa(_addr.sin_addr) + << ", port " << ntohs(_addr.sin_port) << "\n"; close(*it); _clients.erase(it); } else { @@ -101,7 +99,7 @@ void Socket::refresh(Env *env) { } void Socket::answer(Env *env, int fd, string request) { - std::vector lines = split(request, '\n'); + std::vector lines = split(request, '\n'); string uri = split(lines.at(0), ' ').at(1); cout << uri << "\n"; @@ -109,7 +107,7 @@ void Socket::answer(Env *env, int fd, string request) { std::stringstream answer; answer << "HTTP/1.1 200 OK\nContent-Type: text/plain\nContent-Length: "; - Server *server = env->choose_server(this, split(lines.at(1), ' ').at(1)); + Server *server = env->choose_server(this, split(lines.at(1), ' ').at(1)); Route *route = server->get_route(uri); answer << route->getAutoindex(uri); cout << answer.str() << "\n|===|===|===|\n"; diff --git a/srcs/tools.cpp b/srcs/tools.cpp index 9fb63f8..03d55dd 100644 --- a/srcs/tools.cpp +++ b/srcs/tools.cpp @@ -20,24 +20,33 @@ bool isInt(string str) { std::vector split(string str, char delim) { std::vector tokens; - std::string token; - std::stringstream ss(str); - while (getline(ss, token, delim)){ - tokens.push_back(token); - } + std::string token; + std::stringstream ss(str); + while (getline(ss, token, delim)) { + tokens.push_back(token); + } return tokens; } listen_t get_listen_t(string listen) { - listen_t ret; + listen_t ret; size_t sep_pos = listen.rfind(':'); size_t ip6_endpos = listen.rfind(']'); string tmp = listen.substr(0, sep_pos); if (ip6_endpos > sep_pos) - ret.ip = listen; + ret.ip = listen; else - ret.ip = isInt(tmp) || tmp == "localhost" ? "0.0.0.0" : tmp; + ret.ip = isInt(tmp) ? "0.0.0.0" : \ + (tmp == "localhost" ? "127.0.0.1" : \ + (tmp == "[::]" ? "[0000:0000:0000:0000:0000:0000:0000:0000]" : tmp)); tmp = listen.substr(sep_pos + 1, listen.length() - sep_pos - 1).c_str(); ret.port = !isInt(tmp) ? 80 : std::atoi(tmp.c_str()); - return ret; + if (ret.ip.at(0) == '[') { + ret.type = AF_INET6; + ret.ip.erase(ret.ip.length() - 1, ret.ip.length()); + ret.ip.erase(0, 1); + } + else + ret.type = AF_INET; + return ret; }