diff --git a/.gitignore b/.gitignore index a9f2ccf..0137954 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ Thumbs.db ubuntu_tester ubuntu_cgi_tester +webserv diff --git a/Makefile b/Makefile index 9c67075..17f51b6 100644 --- a/Makefile +++ b/Makefile @@ -5,19 +5,19 @@ CXX = c++ CXXFLAGS = -Wall -Wextra -Werror CXXFLAGS += -std=c++98 CXXFLAGS += -I$(HEADERS_D) -#CXXFLAGS += -g +CXXFLAGS += -g #CXXFLAGS += -O3 -SHELL = /bin/zsh +#SHELL = /bin/zsh VPATH = $(DIR_SRCS) -DIR_SRCS = tests +DIR_SRCS = srcs -HEADERS_D = ./templates -HEADERS = +HEADERS_D = ./srcs +HEADERS = Webserv.hpp DEPENDENCIES = $(HEADERS:%=$(HEADERS_D)/%) -SRCS = main.cpp +SRCS = main.cpp Webserv.cpp DIR_OBJS = builds OBJS = $(SRCS:%.cpp=$(DIR_OBJS)/%.o) @@ -28,7 +28,7 @@ OBJS = $(SRCS:%.cpp=$(DIR_OBJS)/%.o) all: $(NAME) -$(DIR_OBJS)/%.o: $(SRCS) | $(DIR_OBJS) +$(DIR_OBJS)/%.o: %.cpp | $(DIR_OBJS) $(CXX) $(CXXFLAGS) -c $< -o $@ $(DIR_OBJS): @@ -37,7 +37,7 @@ $(DIR_OBJS): $(OBJS): $(DEPENDENCIES) #$(OBJS): $(DEPENDENCIES) Makefile -$(NAME) : +$(NAME) : $(OBJS) $(CXX) $(OBJS) -o $(NAME) clean: diff --git a/include_memo.hpp b/include_memo.hpp index 2ed2454..79cc3de 100644 --- a/include_memo.hpp +++ b/include_memo.hpp @@ -3,7 +3,9 @@ # include # include // errno # include // perror - +# include +# include +# include // close // -------------------------------------------- // Verifier si les fonctions sont dispos dans des headers C++ diff --git a/srcs/Webserv.cpp b/srcs/Webserv.cpp index d446827..884218a 100644 --- a/srcs/Webserv.cpp +++ b/srcs/Webserv.cpp @@ -3,25 +3,119 @@ Webserv::Webserv() { - _socket_fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); + std::cout << "Server init\n"; + _socket_fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); if (_socket_fd == -1) { - perror("socket(): "); + ::perror("err socket(): "); throw std::runtime_error("Socket init"); } } -Webserv::Webserv(Webserv const &src) +/* Webserv::Webserv(Webserv const &src) { -} +} */ Webserv::~Webserv() { - + std::cout << "Server destroyed\n"; } -Webserv & Webserv::operator=(Webserv const &rhs) +/* Webserv & Webserv::operator=(Webserv const &rhs) { -} \ No newline at end of file +} */ + + /////////////// + // Functions // + +void Webserv::bind(in_port_t port) +{ + // cast invalid ? how to ? + // const struct sockaddr* cast_test = static_cast(addr); + + struct sockaddr_in addr; + addr.sin_family = AF_INET; + addr.sin_port = ::htons(port); + addr.sin_addr.s_addr = ::htonl(INADDR_ANY); // htonl useless with 0 value (INADDR_ANY) + + if (::bind(_socket_fd, (const sockaddr*)&addr, sizeof addr) == -1) + { + ::perror("err bind(): "); + throw std::runtime_error("Socket bind"); + } +} + +void Webserv::listen(unsigned int max_connections) +{ + if (::listen(_socket_fd, max_connections) == -1) + { + ::perror("err listen(): "); + throw std::runtime_error("Socket listen"); + } +} + +#define BUFSIZE 8192 +#define MSG_TEST "Le Webserv / 20 =D\n" +#define MSG_BOUNCE "bounced properly ;)\n" // placeholder + +void Webserv::start() +{ + struct sockaddr_in addr; + socklen_t addr_len; + int accepted_fd; + + // poll (or equivalent) + struct pollfd poll_s; + poll_s.fd = _socket_fd; + poll_s.events = POLLIN; + + char buf[BUFSIZE]; // WIP buffer. need to try with std::vector or std::string. + int ret; + + std::cout << "Server started\n"; + while (1) + { + std::cout << "----------\n"; + std::cout << "poll()\n"; // poll (or equivalent) + ::poll(&poll_s, 1, -1); + + std::cout << "accept()\n"; + addr_len = sizeof addr; + accepted_fd = ::accept(_socket_fd, (sockaddr*)&addr, &addr_len); + if (accepted_fd == -1) + { + ::perror("err accept(): "); + continue; + } + + // "Your server must never block and the client can be bounced properly if necessary". + // NO-Block OK, but how to handle it ? Miss the bouncing part. + ::fcntl(accepted_fd, F_SETFL, O_NONBLOCK); + + std::cout << "recv()\n"; + ret = ::recv(accepted_fd, buf, BUFSIZE, 0); + if (ret == -1) + { + ::perror("err recv(): "); + if (::send(accepted_fd, MSG_BOUNCE, sizeof MSG_BOUNCE - 1, 0) == -1) + ::perror("err send(): "); + ::close(accepted_fd); + continue; + } + /* + if (ret == BUFSIZE) + // send error like "request too long" to client + */ + buf[ret] = '\0'; + + std::cout << "send()\n"; + if (::send(accepted_fd, buf, ret, 0) == -1) // echo the read + ::perror("err send(): "); + if (::send(accepted_fd, MSG_TEST, sizeof MSG_TEST - 1, 0) == -1) + ::perror("err send(): "); + + ::close(accepted_fd); + } +} diff --git a/srcs/Webserv.hpp b/srcs/Webserv.hpp index fed19a2..01f87f1 100644 --- a/srcs/Webserv.hpp +++ b/srcs/Webserv.hpp @@ -8,17 +8,28 @@ # include // perror # include # include +# include // close +# include // cout, cin # include // socket, accept, listen, send, recv, bind, connect, setsockopt, getsockname +# include // sockaddr_in +// # include // usefull for what ? +# include // htonl, htons, ntohl, ntohs, inet_addr + +# include // poll +# include // fcntl class Webserv { public: - //Webserv(Placeholder); Webserv(); - Webserv(Webserv const &src); + // Webserv(Webserv const &src); ~Webserv(); - Webserv &operator=(Webserv const &rhs); + // Webserv &operator=(Webserv const &rhs); + + void bind(in_port_t port); + void listen(unsigned int max_connections); + void start(); private: int _socket_fd; @@ -27,4 +38,4 @@ class Webserv }; -#endif \ No newline at end of file +#endif diff --git a/srcs/main.cpp b/srcs/main.cpp index 8b13789..7fe8d61 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -1 +1,22 @@ +#include +#include +#include +#include + +int main(void) +{ + try + { + Webserv serv; + + serv.bind(80); + serv.listen(512); // 512 max connections arbitrary + serv.start(); + } + catch (std::exception& e) + { + std::cout << e.what() << '\n'; + } + return (0); +}