#include "Server.hpp" bool Server::_signal = false; Server::Server() {} Server::~Server() {} void Server::parseArgs(int ac, char **av) { if (ac != 3) throw std::runtime_error("Usage: ./ircserv "); std::string port(av[1]); std::string pwd(av[2]); if (port.empty() || port.find_first_not_of("0123456789") != std::string::npos) throw std::runtime_error("Error: Invalid arguments"); long _port = atol(av[1]); if (!(_port >= 1 && _port <= 65535)) throw std::runtime_error("Error: Invalid arguments"); if (pwd.empty()) throw std::runtime_error("Error: Invalid arguments"); this->_port = _port; this->_password = pwd; } void Server::receiveSignal(int signum) { _signal = true; (void)signum; } void Server::init() { signal(SIGINT, receiveSignal); signal(SIGQUIT, receiveSignal); createServerSocket(); std::cout << ">>> SERVER STARTED <<<" << std::endl; std::cout << "Waiting for connections..." << std::endl; } void Server::run() { while (!_signal) { int ret = poll(&_fds[0], _fds.size(), -1); if (ret == -1) throw std::runtime_error("Error: poll() failed"); for (size_t i = 0; i < _fds.size(); ++i) { if (_fds[i].revents & POLLIN) { if (_fds[i].fd == _serverSocketFd) handleClientConnection(); else handleClientData(_fds[i].fd); } } } } void Server::createServerSocket() { _serverSocketFd = socket(AF_INET, SOCK_STREAM, 0); if (_serverSocketFd == -1) throw std::runtime_error("Error: failed to create socket"); int optval = 1; if (setsockopt(_serverSocketFd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) throw std::runtime_error("Error: setsockopt() failed"); if (fcntl(_serverSocketFd, F_SETFL, O_NONBLOCK) == -1) throw std::runtime_error("Error: fcntl() failed"); bindServerSocket(); if (listen(_serverSocketFd, SOMAXCONN) == -1) throw std::runtime_error("Error: listen() failed"); addPollfd(_serverSocketFd, POLLIN, 0); } void Server::bindServerSocket() { struct sockaddr_in sa; sa.sin_family = AF_INET; sa.sin_port = htons(_port); sa.sin_addr.s_addr = INADDR_ANY; if (bind(_serverSocketFd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { throw std::runtime_error("Error: failed to bind socket"); } } void Server::addPollfd(int fd, short events, short revents) { struct pollfd newPollfd; newPollfd.fd = fd; newPollfd.events = events; newPollfd.revents = revents; _fds.push_back(newPollfd); } void Server::handleClientConnection() { for (size_t i = 0; i < _fds.size(); ++i) { if (_fds[i].fd == _serverSocketFd && (_fds[i].revents & POLLIN)) { struct sockaddr_in client_addr; socklen_t clientAddrSize = sizeof(sockaddr_in); int newFd = accept(_serverSocketFd, (struct sockaddr *)&client_addr, &clientAddrSize); if (newFd == -1) { throw std::runtime_error("Error: accept() failed"); } addPollfd(newFd, POLLIN, 0); _clients.push_back(Client(newFd, inet_ntoa((client_addr.sin_addr)))); std::cout << "Client <" << newFd << "> Connected" << std::endl; } } } void Server::handleClientData(int fd) { char buffer[BUFFER_SIZE] = {0}; // Receive the data ssize_t bytes = recv(fd, buffer, BUFFER_SIZE - 1 , 0); // Check if the client disconnected if (bytes <= 0) { std::cout << "Client <" << fd << "> Disconnected" << std::endl; clientCleanup(fd); } else { buffer[bytes] = '\0'; std::cout << "Client <" << fd << "> Data: " << buffer; // parse, check, and handle the received data here } } void Server::clientCleanup(int fd) { for (std::vector::iterator it = _fds.begin(); it != _fds.end(); ++it) { if (it->fd == fd) { _fds.erase(it); break; } } for (std::vector::iterator it = _clients.begin(); it != _clients.end(); ++it) { if (it->getFd() == fd) { _clients.erase(it); break; } } }