diff --git a/srcs/Webserv.cpp b/srcs/Webserv.cpp index 8d2b325..a918509 100644 --- a/srcs/Webserv.cpp +++ b/srcs/Webserv.cpp @@ -38,7 +38,7 @@ void Webserv::bind(in_port_t port) addr.sin_addr.s_addr = ::htonl(INADDR_ANY); if (::bind(_socket_fd, (const sockaddr*)&addr, sizeof addr) == -1) { - ::perror("err bind(): "); + ::perror("err bind()"); throw std::runtime_error("Socket bind"); } } @@ -52,10 +52,6 @@ void Webserv::listen(unsigned int max_connections) } } -#define BUFSIZE 8192 -#define MSG_TEST "Le Webserv / 20 =D\n" -#define MSG_BOUNCE "bounced properly ;)\n" // placeholder - void Webserv::_add_fd(int sd, short event) { struct pollfd new_poll_fd; @@ -66,185 +62,102 @@ void Webserv::_add_fd(int sd, short event) _fds.push_back(new_poll_fd); } -//void Webserv::_accept_sockets(int sd, short event) -//{ -//} - -void Webserv::start(int timeout) +void Webserv::_close_fd(int i) { - int len; - int rc; - int new_sd = -1; - char buffer[80]; - int current_size = 0; - int end_server = FALSE; - int compress_array = FALSE; - int close_conn; - struct pollfd * fds_ptr; + close(_fds[i].fd); + _fds[i].fd = -1; + _fds.erase(_fds.begin() + i); +} - // init first struct +void Webserv::_accept_connection() +{ + int new_sd = 0; + + printf(" Listening socket is readable\n"); + while (new_sd != -1) + { + new_sd = accept(_socket_fd, NULL, NULL); + if (new_sd < 0) + { + if (errno != EWOULDBLOCK && errno != EAGAIN) + { + ::perror("err accept()"); + throw std::runtime_error("Socket accept"); + } + break; + } + printf(" New incoming connection - %d\n", new_sd); + _add_fd(new_sd, POLLIN); + } +} + +void Webserv::_connect_socket(int i, int bufsize) +{ + int len; + int ret; + std::vector buffer(bufsize); + + printf(" Descriptor %d is readable\n", _fds[i].fd); + while (TRUE) + { + ret = recv(_fds[i].fd, &buffer[0], buffer.size(), 0); + if (ret < 0) + { + if (errno != EWOULDBLOCK) + { + ::perror(" recv() failed"); + _close_fd(i); + } + break; + } + + if (ret == 0) + { + printf(" Connection closed\n"); + _close_fd(i); + break; + } + + len = ret; + printf(" %d bytes received\n", len); + + ret = send(_fds[i].fd, &buffer[0], len, 0); + if (ret < 0) + { + ::perror(" send() failed"); + _close_fd(i); + break; + } + } +} + +void Webserv::start(int timeout, int bufsize) +{ _add_fd(_socket_fd, POLLIN); - // init pointer on first element of vector of struct pollfd - fds_ptr = &_fds[0]; std::cout << "Server started\n"; - while (end_server == FALSE) + while (TRUE) { - _nfds = _fds.size(); - poll(fds_ptr, _nfds, timeout); + printf("-----------\npoll\n"); + poll(&_fds[0], _fds.size(), timeout); - current_size = _nfds; - for (int i = 0; i < current_size; i++) + for (unsigned int i = 0; i < _fds.size(); i++) { if(_fds[i].revents == 0) - { -std::cout << "here\n"; continue; - } if(_fds[i].revents != POLLIN) { - printf(" Error! revents = %d\n", _fds[i].revents); - end_server = TRUE; - break; + ::perror("err revents"); + throw std::runtime_error("Socket poll"); } if (_fds[i].fd == _socket_fd) - { - printf(" Listening socket is readable\n"); - do - { - new_sd = accept(_socket_fd, NULL, NULL); - if (new_sd < 0) - { -printf(" new_sd < 0, = %i\n", new_sd); - if (errno != EWOULDBLOCK && errno != EAGAIN) - { - perror(" accept() failed"); - end_server = TRUE; - } - break; - } - - printf(" New incoming connection - %d\n", new_sd); - _add_fd(new_sd, POLLIN); - } while (new_sd != -1); - } + _accept_connection(); else - { - printf(" Descriptor %d is readable\n", _fds[i].fd); - close_conn = FALSE; - - do - { - rc = recv(_fds[i].fd, buffer, sizeof(buffer), 0); - if (rc < 0) - { - if (errno != EWOULDBLOCK) - { - perror(" recv() failed"); - close_conn = TRUE; - } - break; - } - - if (rc == 0) - { - printf(" Connection closed\n"); - close_conn = TRUE; - break; - } - - len = rc; - printf(" %d bytes received\n", len); - - rc = send(_fds[i].fd, buffer, len, 0); - if (rc < 0) - { - perror(" send() failed"); - close_conn = TRUE; - break; - } - - } while(TRUE); - - if (close_conn) - { - close(_fds[i].fd); - _fds[i].fd = -1; - compress_array = TRUE; - } - - - } // else - } // for (i = 0; i < current_size; i++) - - if (compress_array) - { - compress_array = FALSE; - for (int i = 0; i < _nfds; i++) - { - if (_fds[i].fd == -1) - { - // for(int j = i; j < nfds; j++) - // { - // fds[j].fd = fds[j+1].fd; - // } - _fds.erase(_fds.begin() + i); - i--; - // nfds--; - } - } + _connect_socket(i, bufsize); } - - } // while (end_server == FALSE) + } } -/* - - struct sockaddr_in addr; - socklen_t addr_len; - int accepted_fd; - struct pollfd poll_s; - char buf[BUFSIZE]; // WIP buffer. need to try with std::vector or std::string. - int ret; - - std::cout << "----------\n"; - 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 << "poll()\n"; // poll (or equivalent) - poll_s.fd = accepted_fd; - poll_s.events = POLLIN; // We need a way to valid POLLOUT and POLLIN at the same time (both, not one of them) - ::poll(&poll_s, 1, -1); - - 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; - } - 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 db2318e..e61f2a4 100644 --- a/srcs/Webserv.hpp +++ b/srcs/Webserv.hpp @@ -33,16 +33,21 @@ class Webserv void bind(in_port_t port); void listen(unsigned int max_connections); - void start(int timeout); + void start(int timeout, int bufsize); private: int _socket_fd; std::map _request; std::map _response; - std::vector _fds; - int _nfds; - void _add_fd(int sd, short event); + void _add_fd(int sd, short event); + void _accept_connection(); + void _connect_socket(int it, int bufsize); + void _close_fd(int it); + + std::vector _fds; + std::vector::iterator _it; + std::vector::iterator _it_end; }; diff --git a/srcs/main.cpp b/srcs/main.cpp index 58f8209..9cd079c 100644 --- a/srcs/main.cpp +++ b/srcs/main.cpp @@ -13,7 +13,7 @@ int main(void) // https://security.stackexchange.com/questions/169213/how-to-chose-a-port-to-run-an-application-on-localhost serv.bind(4040); serv.listen(20); - serv.start(3 * 60 * 1000); + serv.start(3 * 60 * 1000, 8192); } catch (std::exception& e) { diff --git a/webserv b/webserv index 7136394..2c4c70e 100755 Binary files a/webserv and b/webserv differ