#include "Webserv.hpp" Webserv::Webserv() { std::cout << "Server init\n"; _socket_fd = ::socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0); //_socket_fd = ::socket(AF_INET, SOCK_STREAM, 0); if (_socket_fd == -1) { std::perror("err socket(): "); throw std::runtime_error("Socket init"); } } /* Webserv::Webserv(Webserv const &src) { } */ Webserv::~Webserv() { std::cout << "Server destroyed\n"; } /* Webserv & Webserv::operator=(Webserv const &rhs) { } */ /////////////// // Functions // void Webserv::bind(in_port_t port) { // cast invalid ? how to ? // const struct sockaddr* cast_test = static_cast(addr); struct sockaddr_in addr; std::memset(&addr, 0, sizeof 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) { std::perror("err bind(): "); throw std::runtime_error("Socket bind"); } } void Webserv::listen(unsigned int max_connections) { if (::listen(_socket_fd, max_connections) == -1) { std::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; char buf[BUFSIZE+1]; // WIP buffer. need to try with std::vector or std::string. int ret; int timeout = 3000; int i = 1; int nfds = 1; int ret_nfds; _poll_s[0].fd = _socket_fd; _poll_s[0].events = POLLIN; std::cout << "Server started\n"; int i_loop = 0; ++i_loop; std::cout << i_loop << "----------\n"; std::cout << "loop poll()\n"; while ( (ret_nfds = ::poll(_poll_s, nfds, timeout)) != -1) { i = 1; while (i < nfds) { if (ret_nfds == 0) { std::cout << "timeout\n"; ::close(_poll_s[i].fd); _poll_s[i].fd = -1; --nfds; } else if (_poll_s[i].revents & POLLIN) // READ { std::cout << "recv()\n"; ret = ::recv(_poll_s[i].fd, buf, BUFSIZE, 0); if (ret == -1) { std::perror("err recv(): "); if (::send(_poll_s[i].fd, MSG_BOUNCE, sizeof MSG_BOUNCE - 1, 0) == -1) std::perror("err send(): "); ::close(_poll_s[i].fd); _poll_s[i].fd = -1; --nfds; continue; } /* if (ret == BUFSIZE) // send error like "request too long" to client */ buf[ret] = '\0'; _poll_s[i].events = POLLOUT; } else if (_poll_s[i].revents & POLLOUT) // WRITE { std::cout << "send()\n"; if (::send(_poll_s[i].fd, buf, ret, 0) == -1) // echo the read std::perror("err send(): "); if (::send(_poll_s[i].fd, MSG_TEST, sizeof MSG_TEST - 1, 0) == -1) std::perror("err send(): "); ::close(_poll_s[i].fd); _poll_s[i].fd = -1; --nfds; } ++i; } if ((_poll_s[0].fd == _socket_fd) && (_poll_s[0].revents & POLLIN)) // ACCEPT { std::cout << "accept()\n"; addr_len = sizeof addr; accepted_fd = ::accept(_socket_fd, (sockaddr*)&addr, &addr_len); if (accepted_fd == -1) { std::perror("err accept(): "); continue; } ::fcntl(accepted_fd, F_SETFL, O_NONBLOCK); _poll_s[nfds].fd = accepted_fd; _poll_s[nfds].events = POLLIN; ++nfds; } ++i_loop; std::cout << i_loop << "----------\n"; std::cout << "loop poll()\n"; } }