From bfe88daf3e000f417ca79242b27ce0f3041ad55f Mon Sep 17 00:00:00 2001 From: ouafabulous Date: Wed, 21 May 2025 21:52:20 +0200 Subject: [PATCH 1/3] I broke something with displaying the clients input plainly --- Makefile | 33 ++++++----- diagram.puml | 4 +- include/PollManager.hpp | 26 ++++----- include/core/core.hpp | 15 +++-- include/server.hpp | 14 +++-- include/user.hpp | 54 ++++++++++-------- sources/core/PollManager.cpp | 96 ++++++++++++++++++------------- sources/core/Server.cpp | 52 +++++++++++++++-- sources/core/user.cpp | 108 +++++++++++++++++++++++++++++++++++ sources/user/user.cpp | 76 ------------------------ 10 files changed, 292 insertions(+), 186 deletions(-) create mode 100644 sources/core/user.cpp delete mode 100644 sources/user/user.cpp diff --git a/Makefile b/Makefile index 3ad7c51..86e4656 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,14 @@ -# **************************************************************************** # +#******************************************************************************# # # # ::: :::::::: # # Makefile :+: :+: :+: # # +:+ +:+ +:+ # -# By: sben-tay +#+ +:+ +#+ # +# By: omoudni +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/02 15:40:00 by rparodi #+# #+# # -# Updated: 2025/05/21 13:01:09 by rparodi ### ########.fr # +# Updated: 2025/05/21 21:51:13 by omoudni ### ########.fr # # # -# **************************************************************************** # +#******************************************************************************# # Name @@ -30,7 +30,7 @@ SRC = sources/core/logs.cpp \ sources/core/parser.cpp \ sources/core/main.cpp \ sources/core/Server.cpp \ - sources/user/user.cpp \ + sources/core/user.cpp \ sources/channel/channel.cpp INC_DIR = include/core \ @@ -85,30 +85,37 @@ debug: CXXFLAGS += -g # debug: CXXFLAGS += -fsanitize=address debug: re +PORT ?= 4243 + test: debug - @printf '$(GREY) now running with\n\t- Port:\t\t$(GREEN)4243$(GREY)\n\t- Password:\t$(GREEN)irc$(END)\n' + @printf '$(GREY) now running with\n\t- Port:\t\t$(GREEN)$(PORT)$(GREY)\n\t- Password:\t$(GREEN)irc$(END)\n' @if tmux has-session -t $(SESSION) 2>/dev/null; then \ tmux kill-session -t $(SESSION); \ fi @tmux new-session -d -s $(SESSION) \ - 'bash -lc "./$(NAME) 4243 irc; exec bash"' + 'bash -lc "./$(NAME) $(PORT) irc; exec bash"' @tmux split-window -h -p 70 -t $(SESSION):0 \ - 'bash -lc "irssi -c localhost -p 4243 -w irc || exec yes \"irssi exit code: $?\""' + 'bash -lc "irssi -c localhost -p $(PORT) -w irc || exec yes \"irssi exit code: $?\""' @tmux split-window -v -p 50 -t $(SESSION):0.1 \ - 'bash -lc "nc localhost 4243 || exec yes \"netcat exit code: $?\""' + 'bash -lc "nc localhost $(PORT) || exec yes \"netcat exit code: $?\""' + @tmux split-window -v -p 50 -t $(SESSION):0.2 \ + 'bash -lc "nc localhost $(PORT) || exec yes \"netcat exit code: $?\""' + @tmux split-window -v -p 50 -t $(SESSION):0.3 \ + 'bash -lc "nc localhost $(PORT) || exec yes \"netcat exit code: $?\""' @tmux attach -t $(SESSION) + run: re - @printf '$(GREY) now running with\n\t- Port:\t\t$(GREEN)4243$(GREY)\n\t- Password:\t$(GREEN)irc$(END)\n' + @printf '$(GREY) now running with\n\t- Port:\t\t$(GREEN)$(PORT)$(GREY)\n\t- Password:\t$(GREEN)irc$(END)\n' @if tmux has-session -t $(SESSION) 2>/dev/null; then \ tmux kill-session -t $(SESSION); \ fi @tmux new-session -d -s $(SESSION) \ - 'bash -lc "./$(NAME) 4243 irc; exec bash"' + 'bash -lc "./$(NAME) $(PORT) irc; exec bash"' @tmux split-window -h -p 70 -t $(SESSION):0 \ - 'bash -lc "irssi -c localhost -p 4243 -w irc || exec yes \"irssi exit code: $?\""' + 'bash -lc "irssi -c localhost -p $(PORT) -w irc || exec yes \"irssi exit code: $?\""' @tmux split-window -v -p 50 -t $(SESSION):0.1 \ - 'bash -lc "nc localhost 4243 || exec yes \"netcat exit code: $?\""' + 'bash -lc "nc localhost $(PORT) || exec yes \"netcat exit code: $?\""' @tmux attach -t $(SESSION) # Header diff --git a/diagram.puml b/diagram.puml index 05ae631..93491fb 100644 --- a/diagram.puml +++ b/diagram.puml @@ -13,6 +13,7 @@ class Server { - _password : string - _server_fd : int - _poll : PollManager + - _users : map + Server(port : int, password : string) + start() : void @@ -25,12 +26,11 @@ class Server { ' ============================ class PollManager { - _fds : vector - - _users : map + addUser(fd : int) : void + removeUser(fd : int) : void + updateUser(fd : int, events : short) : void - + pollLoop(server_fd : int) : void + + pollLoop(server_fd : int, newClients : std::vector, disconnected : std::vector) : void + readFromUser(fd : int) : void + writeToUser(fd : int) : void } diff --git a/include/PollManager.hpp b/include/PollManager.hpp index 008f843..4b7623a 100644 --- a/include/PollManager.hpp +++ b/include/PollManager.hpp @@ -1,14 +1,14 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* PollManager.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: sben-tay +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/19 19:15:13 by omoudni #+# #+# */ -/* Updated: 2025/05/20 17:22:59 by sben-tay ### ########.fr */ +/* Updated: 2025/05/21 21:34:20 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once @@ -16,19 +16,17 @@ #include #include -class PollManager { +class PollManager +{ public: - PollManager(); - ~PollManager(); + PollManager(); + ~PollManager(); - void addClient(int fd); - void removeClient(int fd); - void updateServer(int fd); - void pollLoop(int server_fd); + void addClient(short unsigned fd); + void removeClient(short unsigned fd); + void updateServer(short unsigned fd); + void pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients); private: - std::vector _fds; - std::map _buffers; - }; diff --git a/include/core/core.hpp b/include/core/core.hpp index a50d333..a837f41 100644 --- a/include/core/core.hpp +++ b/include/core/core.hpp @@ -1,14 +1,14 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* core.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: sben-tay +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/12 14:16:03 by rparodi #+# #+# */ -/* Updated: 2025/05/20 17:23:41 by sben-tay ### ########.fr */ +/* Updated: 2025/05/21 21:18:22 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once @@ -28,8 +28,13 @@ enum e_state { CMD, MSG }; - + +// INCLUDES (not to repeat) +#include +#include +#include +#include "user.hpp" #include "PollManager.hpp" #include "color.hpp" #include "server.hpp" diff --git a/include/server.hpp b/include/server.hpp index 96a78b0..27ab3a3 100644 --- a/include/server.hpp +++ b/include/server.hpp @@ -1,26 +1,28 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* server.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: rparodi +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:50:32 by rparodi #+# #+# */ -/* Updated: 2025/05/21 13:03:01 by rparodi ### ########.fr */ +/* Updated: 2025/05/21 21:19:47 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once -#include -#include "PollManager.hpp" +#include "core.hpp" +class User; class Server { private: int _port; int _serverFd; std::string _password; PollManager _pollManager; + std::map _users; + public: Server(int port, const std::string &password); ~Server(); diff --git a/include/user.hpp b/include/user.hpp index b40bfee..4e7b326 100644 --- a/include/user.hpp +++ b/include/user.hpp @@ -1,36 +1,42 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* user.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: rparodi +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:57:49 by rparodi #+# #+# */ -/* Updated: 2025/05/20 22:13:41 by rparodi ### ########.fr */ +/* Updated: 2025/05/21 21:16:56 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #pragma once -#include -#include -#include "color.hpp" +#include "core.hpp" -class User { - private: - int _fd; - bool _registered; - std::string _nickname; - std::string _hostname; - std::string _read_buffer; - std::string _write_buffer; - public: - int getFd() const; - bool isReadyToSend() const; - bool isRegistered() const; - std::string getNickname() const; - std::string extractFullCommand(); - void appendToReadBuffer(const std::string &data); - void appendToWriteBuffer(const std::string &data); - void setNickname(const std::string &nickname); +class User +{ +private: + short unsigned int _fd; + bool _registered; + std::string _nickname; + std::string _hostname; + std::string _read_buffer; + std::string _write_buffer; + std::string _username; + bool _hasNick; + bool _hasUser; + +public: + User(short unsigned fd); + short unsigned int getFd() const; + bool isReadyToSend() const; + bool isRegistered() const; + std::string getNickname() const; + std::string extractFullCommand(); + void appendToReadBuffer(const std::string &data); + void appendToWriteBuffer(const std::string &data); + void setNickname(const std::string &nickname); + void setUsername(const std::string &username); + void checkRegistration(); }; diff --git a/sources/core/PollManager.cpp b/sources/core/PollManager.cpp index 29d8485..9e916be 100644 --- a/sources/core/PollManager.cpp +++ b/sources/core/PollManager.cpp @@ -10,72 +10,86 @@ PollManager::PollManager() {} -PollManager::~PollManager() { - for (size_t i = 0; i < _fds.size(); ++i) { - close(_fds[i].fd); - } +PollManager::~PollManager() +{ + for (size_t i = 0; i < _fds.size(); ++i) + { + close(_fds[i].fd); + } } -void PollManager::pollLoop(int server_fd) { +void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients) +{ - struct pollfd server_pollfd; + struct pollfd server_pollfd; server_pollfd.fd = server_fd; server_pollfd.events = POLLIN; _fds.push_back(server_pollfd); std::cout << "Serveur prêt à accepter des connexions..." << std::endl; - while (true) { - int poll_count = poll(&_fds[0], _fds.size(), -1); - if (poll_count == -1) { - std::cerr << "poll error\n" << std::endl; - continue; - } - for (size_t i = 0; i < _fds.size(); ++i) { - int fd = _fds[i].fd; + // while (true) { + int poll_count = poll(&_fds[0], _fds.size(), -1); + if (poll_count == -1) + { + std::cerr << "poll error\n" + << std::endl; + return; + } + for (size_t i = 0; i < _fds.size(); ++i) + { + short unsigned fd = _fds[i].fd; - if ((fd == server_fd) && (_fds[i].revents & POLLIN)) { - int client_fd = accept(server_fd, NULL, NULL); - if (client_fd == -1) { - std::cerr << "Error accept()" << std::endl; - continue; - } - addClient(client_fd); + if ((fd == server_fd) && (_fds[i].revents & POLLIN)) + { + int client_fd = accept(server_fd, NULL, NULL); + if (client_fd == -1) + { + std::cerr << "Error accept()" << std::endl; + continue; } - else if (_fds[i].revents & POLLIN) { - char buffer[1024]; - ssize_t bytes = recv(fd, buffer, sizeof(buffer) -1, 0); - if (bytes > 0) { - buffer[bytes] = '\0'; - _buffers[fd] += buffer; - std::cout << "Client " << fd << " send : " << buffer; - } else { - std::cout << "Client " << fd << " disconected." << std::endl; - // removeClient(fd); - --i; - } + addClient(client_fd); + newClients.push_back(client_fd); + } + else if (_fds[i].revents & POLLIN) + { + char buffer[1024]; + ssize_t bytes = recv(fd, buffer, sizeof(buffer) - 1, 0); + if (bytes > 0) + { + buffer[bytes] = '\0'; + readyClients.push_back(std::make_pair(fd, std::string(buffer))); + } + else + { + removeClient(fd); + disconnected.push_back(fd); + --i; } } } + // } } -void PollManager::addClient(int fd) { +void PollManager::addClient(short unsigned fd) +{ struct pollfd pfd; pfd.fd = fd; pfd.events = POLLIN; _fds.push_back(pfd); - _buffers[fd] = ""; - std::cout << "Client connecté (fd " << fd << ")" << std::endl; + std::cout << "Client connected (fd " << fd << ")" << std::endl; } -void PollManager::removeClient(int fd) { - for (size_t i = 0; i < _fds.size(); ++i) { - if (_fds[i].fd == fd) { +void PollManager::removeClient(short unsigned fd) +{ + for (size_t i = 0; i < _fds.size(); ++i) + { + if (_fds[i].fd == fd) + { _fds.erase(_fds.begin() + i); break; } } - _buffers.erase(fd); close(fd); - std::cout << "Client retiré (fd " << fd << ")" << std::endl; + std::cout << "Client disconnected (fd " << fd << ")" << std::endl; } diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index 5f0cdbd..a371d15 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -1,14 +1,14 @@ -/* ************************************************************************** */ +/******************************************************************************/ /* */ /* ::: :::::::: */ /* Server.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: sben-tay +#+ +:+ +#+ */ +/* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/05/21 13:03:51 by rparodi ### ########.fr */ +/* Updated: 2025/05/21 21:50:03 by omoudni ### ########.fr */ /* */ -/* ************************************************************************** */ +/******************************************************************************/ #include "color.hpp" #include "server.hpp" @@ -37,6 +37,9 @@ Server::Server(int port, const std::string &password) : _port(port), _password(p */ Server::~Server() { std::cout << CLR_GREY << "Info: Server destructor called" << CLR_RESET << std::endl; + if (_serverFd != -1) { + close(_serverFd); + } } @@ -61,8 +64,47 @@ void Server::start() { } std::cout << "Serveur lancé sur le port " << _port << std::endl; + std::vector newClients; + std::vector disconnected; + std::vector > readyClients; + while (true) + { + newClients.clear(); + disconnected.clear(); + readyClients.clear(); + _pollManager.pollLoop(_serverFd, newClients, disconnected, readyClients); - _pollManager.pollLoop(_serverFd); + // Handle new clients + for (size_t i = 0; i < newClients.size(); ++i) + _users[newClients[i]] = new User(newClients[i]); + // Handle disconnected clients + for (size_t i = 0; i < disconnected.size(); ++i) + { + delete _users[disconnected[i]]; + _users.erase(disconnected[i]); + } + for (size_t i = 0; i < readyClients.size(); ++i) + { + int fd = readyClients[i].first; + const std::string &data = readyClients[i].second; + if (_users.count(fd)) + { + _users[fd]->appendToReadBuffer(data); + //print users + std::cout << "User " << fd << " is registered: " << _users[fd]->isRegistered() << std::endl; + std::cout << "Received data from fd " << fd << ": " << data << std::endl; + std::string cmd; + while (!(cmd = _users[fd]->extractFullCommand()).empty()) + { + // This prints every command/message received from any client + std::cout << "Client " << fd << " says: " << cmd << std::endl; + + } + } + } + + // Optionally: handle server shutdown, signals, etc. + } close(_serverFd); } diff --git a/sources/core/user.cpp b/sources/core/user.cpp new file mode 100644 index 0000000..2ae0172 --- /dev/null +++ b/sources/core/user.cpp @@ -0,0 +1,108 @@ +/******************************************************************************/ +/* */ +/* ::: :::::::: */ +/* user.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: omoudni +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2025/05/21 20:37:12 by omoudni #+# #+# */ +/* Updated: 2025/05/21 21:44:58 by omoudni ### ########.fr */ +/* */ +/******************************************************************************/ + +#include "core.hpp" + +// Constructor +User::User(short unsigned int fd) : _fd(fd), _registered(false), _hasNick(false), _hasUser(false) {} + +// Getter for fd +short unsigned int User::getFd() const +{ + return _fd; +} + +// Getter for nickname +std::string User::getNickname() const +{ + return _nickname; +} + +void User::setUsername(const std::string &username) +{ + _username = username; + _hasUser = true; + checkRegistration(); +} + +// Setter for nickname (with basic checks) +void User::setNickname(const std::string &nickname) +{ + if (nickname.empty()) + { + throw std::invalid_argument("Nickname cannot be empty"); + } + else if (nickname == "anonymous") + { + throw std::invalid_argument("Nickname cannot be 'anonymous'"); + } + else if (nickname.length() > 9) + { + throw std::length_error("Nickname is too long"); + } + else if (nickname == _nickname) + { + throw std::invalid_argument("The nickname is the same"); + } + else + { + _nickname = nickname; + _hasNick = true; + checkRegistration(); + } +} + +// Registration state +bool User::isRegistered() const +{ + return _registered; +} + +// Append to read buffer +void User::appendToReadBuffer(const std::string &data) +{ + _read_buffer += data; +} + +// Append to write buffer +void User::appendToWriteBuffer(const std::string &data) +{ + _write_buffer += data; +} + +// Check registration +void User::checkRegistration() +{ + if (!_registered && _hasNick && _hasUser) + { + _registered = true; + } +} + +// Check if the user is ready to send +bool User::isReadyToSend() const +{ + return !_write_buffer.empty(); +} + +// Extract full command from read buffer +std::string User::extractFullCommand() +{ + std::string command; + size_t pos = _read_buffer.find("\r\n"); + if (pos != std::string::npos) + { + command = _read_buffer.substr(0, pos); + _read_buffer.erase(0, pos + 2); + } + return command; +} \ No newline at end of file diff --git a/sources/user/user.cpp b/sources/user/user.cpp deleted file mode 100644 index 80e1adb..0000000 --- a/sources/user/user.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* user.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: rparodi +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2025/05/20 22:03:36 by rparodi #+# #+# */ -/* Updated: 2025/05/20 22:15:14 by rparodi ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "user.hpp" - -/** - * @brief Getter for the fd of the user - * - * @return the actual fd of the user - */ -int User::getFd() const { - return this->_fd; -} - -/** - * @brief Getter for the nickname of the user - * - * @return the actual nickname of the user - */ -std::string User::getNickname() const { - return this->_nickname; -} - -/** - * @brief Setter for the nickname of the user (also checker) - * - * @param nickname the nickname given to set to the user - */ -void User::setNickname(const std::string &nickname) { - if (nickname.empty()) { - throw std::invalid_argument("Nickname cannot be empty"); - } else if (nickname == "anonymous") { - throw std::invalid_argument("Nickname cannot be 'anonymous'"); - } else if (nickname.length() > 9) { - throw std::length_error("Nickname is too long"); - } else if (nickname == this->_nickname) { - throw std::invalid_argument("The nickname is the same"); - } else { - this->_nickname = nickname; - } -} - -/** - * @brief Getter for the state of the user - * - * @return true if the user is registered, false otherwise - */ -bool User::isRegistered() const { - return this->_registered; -} -void User::appendToReadBuffer(const std::string &data) { - std::cerr << CLR_RED << "Error: Method not found (" << __FILE_NAME__ ":" << __LINE__ << ")" << CLR_RESET << std::endl; - (void)data; -} -void User::appendToWriteBuffer(const std::string &data) { - std::cerr << CLR_RED << "Error: Method not found (" << __FILE_NAME__ ":" << __LINE__ << ")" << CLR_RESET << std::endl; - (void)data; -} -std::string User::extractFullCommand() { - std::cerr << CLR_RED << "Error: Method not found (" << __FILE_NAME__ ":" << __LINE__ << ")" << CLR_RESET << std::endl; - return nullptr; -} - -bool User::isReadyToSend() const { - std::cerr << CLR_RED << "Error: Method not found (" << __FILE_NAME__ ":" << __LINE__ << ")" << CLR_RESET << std::endl; - return (false); -} From 1e66d6c33ebe36d2c0822a49d9125523b1ab42c3 Mon Sep 17 00:00:00 2001 From: ouafabulous Date: Thu, 22 May 2025 17:41:29 +0200 Subject: [PATCH 2/3] fixed data not received from client --- Makefile | 4 +-- diagram.puml | 52 ++++++++++++++++++--------------- include/PollManager.hpp | 3 +- sources/core/PollManager.cpp | 31 ++++++++++---------- sources/core/Server.cpp | 11 ++++--- sources/{core => user}/user.cpp | 17 ++++++----- 6 files changed, 66 insertions(+), 52 deletions(-) rename sources/{core => user}/user.cpp (87%) diff --git a/Makefile b/Makefile index 86e4656..65a86fc 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ # By: omoudni +#+ +:+ +#+ # # +#+#+#+#+#+ +#+ # # Created: 2025/05/02 15:40:00 by rparodi #+# #+# # -# Updated: 2025/05/21 21:51:13 by omoudni ### ########.fr # +# Updated: 2025/05/22 17:35:48 by omoudni ### ########.fr # # # #******************************************************************************# @@ -30,7 +30,7 @@ SRC = sources/core/logs.cpp \ sources/core/parser.cpp \ sources/core/main.cpp \ sources/core/Server.cpp \ - sources/core/user.cpp \ + sources/user/user.cpp \ sources/channel/channel.cpp INC_DIR = include/core \ diff --git a/diagram.puml b/diagram.puml index 93491fb..21e7a04 100644 --- a/diagram.puml +++ b/diagram.puml @@ -10,12 +10,13 @@ class "main()" ' ======================== class Server { - _port : int + - _serverFd : int - _password : string - - _server_fd : int - - _poll : PollManager - - _users : map + - _pollManager : PollManager + - _users : map + Server(port : int, password : string) + + ~Server() + start() : void + getPort() : int + showInfo() : void @@ -27,36 +28,41 @@ class Server { class PollManager { - _fds : vector - + addUser(fd : int) : void - + removeUser(fd : int) : void - + updateUser(fd : int, events : short) : void - + pollLoop(server_fd : int, newClients : std::vector, disconnected : std::vector) : void - + readFromUser(fd : int) : void - + writeToUser(fd : int) : void + + PollManager() + + ~PollManager() + + setServerFd(fd : int) : void + + addClient(fd : short unsigned) : void + + removeClient(fd : short unsigned) : void + + updateServer(fd : short unsigned) : void + + pollLoop(server_fd : int, newClients : vector, disconnected : vector, readyClients : vector>) : void } ' ======================== ' CLASS: User ' ======================== class User { - - _fd : int - - _nickname : string - - _username : string - - _hostname : string - - _readBuffer : string - - _writeBuffer : string + - _fd : short unsigned int - _registered : bool - - + getFd() : int - + getNickname() : string - + setNickname(name : string) : void - + appendToReadBuffer(data : string) : void - + appendToWriteBuffer(data : string) : void - + extractFullCommand() : string + - _nickname : string + - _hostname : string + - _read_buffer : string + - _write_buffer : string + - _username : string + - _hasNick : bool + - _hasUser : bool + + + User(fd : short unsigned int) + + getFd() : short unsigned int + isReadyToSend() : bool + isRegistered() : bool + + getNickname() : string + + extractFullCommand() : string + + appendToReadBuffer(data : string) : void + + appendToWriteBuffer(data : string) : void + + setNickname(nickname : string) : void + + setUsername(username : string) : void + + checkRegistration() : void } - ' ======================== ' CLASS: Channel ' ======================== diff --git a/include/PollManager.hpp b/include/PollManager.hpp index 4b7623a..562614c 100644 --- a/include/PollManager.hpp +++ b/include/PollManager.hpp @@ -6,7 +6,7 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/19 19:15:13 by omoudni #+# #+# */ -/* Updated: 2025/05/21 21:34:20 by omoudni ### ########.fr */ +/* Updated: 2025/05/22 17:30:00 by omoudni ### ########.fr */ /* */ /******************************************************************************/ @@ -22,6 +22,7 @@ public: PollManager(); ~PollManager(); + void setServerFd(int fd); void addClient(short unsigned fd); void removeClient(short unsigned fd); void updateServer(short unsigned fd); diff --git a/sources/core/PollManager.cpp b/sources/core/PollManager.cpp index 9e916be..54d5702 100644 --- a/sources/core/PollManager.cpp +++ b/sources/core/PollManager.cpp @@ -20,15 +20,6 @@ PollManager::~PollManager() void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients) { - - struct pollfd server_pollfd; - server_pollfd.fd = server_fd; - server_pollfd.events = POLLIN; - _fds.push_back(server_pollfd); - - std::cout << "Serveur prêt à accepter des connexions..." << std::endl; - - // while (true) { int poll_count = poll(&_fds[0], _fds.size(), -1); if (poll_count == -1) { @@ -38,8 +29,8 @@ void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vec } for (size_t i = 0; i < _fds.size(); ++i) { - short unsigned fd = _fds[i].fd; - + short unsigned fd = _fds[i].fd; + std::cout << "I'm here 1" << std::endl; if ((fd == server_fd) && (_fds[i].revents & POLLIN)) { int client_fd = accept(server_fd, NULL, NULL); @@ -48,17 +39,19 @@ void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vec std::cerr << "Error accept()" << std::endl; continue; } - addClient(client_fd); + std::cout << "I'm here 2" << std::endl; + addClient(client_fd); newClients.push_back(client_fd); - } - else if (_fds[i].revents & POLLIN) - { + } else if (_fds[i].revents & POLLIN) { + std::cout << "I'm here 3" << std::endl; char buffer[1024]; ssize_t bytes = recv(fd, buffer, sizeof(buffer) - 1, 0); if (bytes > 0) { buffer[bytes] = '\0'; readyClients.push_back(std::make_pair(fd, std::string(buffer))); + std::cout << "Received data from fd " << fd << ": " << buffer << std::endl; + std::cout << std::flush; } else { @@ -93,3 +86,11 @@ void PollManager::removeClient(short unsigned fd) close(fd); std::cout << "Client disconnected (fd " << fd << ")" << std::endl; } + +void PollManager::setServerFd(int fd) +{ + struct pollfd pfd; + pfd.fd = fd; + pfd.events = POLLIN; + _fds.push_back(pfd); +} diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index a371d15..9093ff5 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -6,13 +6,14 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/05/21 21:50:03 by omoudni ### ########.fr */ +/* Updated: 2025/05/22 17:31:42 by omoudni ### ########.fr */ /* */ /******************************************************************************/ #include "color.hpp" #include "server.hpp" #include "core.hpp" +#include "PollManager.hpp" #include #include #include @@ -64,6 +65,7 @@ void Server::start() { } std::cout << "Serveur lancé sur le port " << _port << std::endl; + _pollManager.setServerFd(_serverFd); std::vector newClients; std::vector disconnected; std::vector > readyClients; @@ -72,11 +74,12 @@ void Server::start() { newClients.clear(); disconnected.clear(); readyClients.clear(); - _pollManager.pollLoop(_serverFd, newClients, disconnected, readyClients); - + _pollManager.pollLoop(_serverFd, newClients, disconnected, + readyClients); + std::cout << "Poll loop finished" << std::endl; // Handle new clients for (size_t i = 0; i < newClients.size(); ++i) - _users[newClients[i]] = new User(newClients[i]); + _users[newClients[i]] = new User(newClients[i]); // Handle disconnected clients for (size_t i = 0; i < disconnected.size(); ++i) { diff --git a/sources/core/user.cpp b/sources/user/user.cpp similarity index 87% rename from sources/core/user.cpp rename to sources/user/user.cpp index 2ae0172..3465de6 100644 --- a/sources/core/user.cpp +++ b/sources/user/user.cpp @@ -6,7 +6,7 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/21 20:37:12 by omoudni #+# #+# */ -/* Updated: 2025/05/21 21:44:58 by omoudni ### ########.fr */ +/* Updated: 2025/05/22 17:13:35 by omoudni ### ########.fr */ /* */ /******************************************************************************/ @@ -95,14 +95,17 @@ bool User::isReadyToSend() const } // Extract full command from read buffer -std::string User::extractFullCommand() -{ +std::string User::extractFullCommand() { std::string command; size_t pos = _read_buffer.find("\r\n"); - if (pos != std::string::npos) - { + if (pos == std::string::npos) + pos = _read_buffer.find("\n"); // fallback + + if (pos != std::string::npos) { command = _read_buffer.substr(0, pos); - _read_buffer.erase(0, pos + 2); + _read_buffer.erase(0, pos + 1); + if (_read_buffer[pos] == '\r') // clean up stray \r + _read_buffer.erase(0, 1); } return command; -} \ No newline at end of file +} From a51264cefa40e5d648172076f4257e0fa8c18848 Mon Sep 17 00:00:00 2001 From: ouafabulous Date: Thu, 22 May 2025 18:46:39 +0200 Subject: [PATCH 3/3] little edits --- include/server.hpp | 32 +++++++++--------- sources/core/PollManager.cpp | 11 +++---- sources/core/Server.cpp | 63 +++++++++++++++++++++--------------- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/include/server.hpp b/include/server.hpp index 27ab3a3..1b5dea3 100644 --- a/include/server.hpp +++ b/include/server.hpp @@ -6,7 +6,7 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:50:32 by rparodi #+# #+# */ -/* Updated: 2025/05/21 21:19:47 by omoudni ### ########.fr */ +/* Updated: 2025/05/22 18:44:35 by omoudni ### ########.fr */ /* */ /******************************************************************************/ @@ -15,18 +15,20 @@ #include "core.hpp" class User; -class Server { - private: - int _port; - int _serverFd; - std::string _password; - PollManager _pollManager; - std::map _users; - - public: - Server(int port, const std::string &password); - ~Server(); - void start(); - unsigned short int getPort() const; - void showInfo() const; +class Server +{ +private: + int _port; + int _serverFd; + std::string _password; + PollManager _pollManager; + std::map _users; + +public: + Server(int port, const std::string &password); + ~Server(); + void start(); + unsigned short int getPort() const; + void showInfo() const; + void printUsers() const; }; diff --git a/sources/core/PollManager.cpp b/sources/core/PollManager.cpp index 54d5702..d789bdd 100644 --- a/sources/core/PollManager.cpp +++ b/sources/core/PollManager.cpp @@ -29,8 +29,7 @@ void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vec } for (size_t i = 0; i < _fds.size(); ++i) { - short unsigned fd = _fds[i].fd; - std::cout << "I'm here 1" << std::endl; + short unsigned fd = _fds[i].fd; if ((fd == server_fd) && (_fds[i].revents & POLLIN)) { int client_fd = accept(server_fd, NULL, NULL); @@ -39,11 +38,11 @@ void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vec std::cerr << "Error accept()" << std::endl; continue; } - std::cout << "I'm here 2" << std::endl; - addClient(client_fd); + addClient(client_fd); newClients.push_back(client_fd); - } else if (_fds[i].revents & POLLIN) { - std::cout << "I'm here 3" << std::endl; + } + else if (_fds[i].revents & POLLIN) + { char buffer[1024]; ssize_t bytes = recv(fd, buffer, sizeof(buffer) - 1, 0); if (bytes > 0) diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index 9093ff5..0691c62 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -6,7 +6,7 @@ /* By: omoudni +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/05/22 17:31:42 by omoudni ### ########.fr */ +/* Updated: 2025/05/22 18:45:41 by omoudni ### ########.fr */ /* */ /******************************************************************************/ @@ -29,24 +29,28 @@ * * @note Thanks to check the port / password before give them to the constructor. */ -Server::Server(int port, const std::string &password) : _port(port), _password(password) { - std::cout << CLR_GREY << "Info: Server constructor called" << CLR_RESET << std::endl; +Server::Server(int port, const std::string &password) : _port(port), _password(password) +{ + std::cout << CLR_GREY << "Info: Server constructor called" << CLR_RESET << std::endl; } /** * @brief The default destructor of the Server class. */ -Server::~Server() { - std::cout << CLR_GREY << "Info: Server destructor called" << CLR_RESET << std::endl; - if (_serverFd != -1) { +Server::~Server() +{ + std::cout << CLR_GREY << "Info: Server destructor called" << CLR_RESET << std::endl; + if (_serverFd != -1) + { close(_serverFd); } } - -void Server::start() { +void Server::start() +{ _serverFd = socket(AF_INET, SOCK_STREAM, 0); - if (_serverFd == -1) { + if (_serverFd == -1) + { std::cerr << "Erreur socket" << std::endl; return; } @@ -57,8 +61,9 @@ void Server::start() { addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(_port); - if (bind(_serverFd, (sockaddr*)&addr, sizeof(addr)) == -1 || - listen(_serverFd, 10) == -1) { + if (bind(_serverFd, (sockaddr *)&addr, sizeof(addr)) == -1 || + listen(_serverFd, 10) == -1) + { std::cerr << "Erreur bind/listen" << std::endl; close(_serverFd); return; @@ -71,15 +76,18 @@ void Server::start() { std::vector > readyClients; while (true) { + printUsers(); newClients.clear(); disconnected.clear(); readyClients.clear(); _pollManager.pollLoop(_serverFd, newClients, disconnected, readyClients); std::cout << "Poll loop finished" << std::endl; - // Handle new clients + std::cout << "New clients: " << newClients.size() << std::endl; for (size_t i = 0; i < newClients.size(); ++i) - _users[newClients[i]] = new User(newClients[i]); + { + _users[newClients[i]] = new User(newClients[i]); + } // Handle disconnected clients for (size_t i = 0; i < disconnected.size(); ++i) { @@ -93,15 +101,11 @@ void Server::start() { if (_users.count(fd)) { _users[fd]->appendToReadBuffer(data); - //print users - std::cout << "User " << fd << " is registered: " << _users[fd]->isRegistered() << std::endl; - std::cout << "Received data from fd " << fd << ": " << data << std::endl; std::string cmd; while (!(cmd = _users[fd]->extractFullCommand()).empty()) { // This prints every command/message received from any client std::cout << "Client " << fd << " says: " << cmd << std::endl; - } } } @@ -118,12 +122,12 @@ void Server::start() { * It is used for debug purpose. */ -void Server::showInfo() const { - std::cout << std::endl; - std::cout << CLR_BLUE << "IRCSettings:" << CLR_RESET << std::endl; - std::cout << CLR_BLUE << "\t- Port:\t\t" << CLR_GOLD << this->_port << CLR_RESET << std::endl; - std::cout << CLR_BLUE << "\t- Password:\t" << CLR_GOLD << this->_password << CLR_RESET << std::endl; - +void Server::showInfo() const +{ + std::cout << std::endl; + std::cout << CLR_BLUE << "IRCSettings:" << CLR_RESET << std::endl; + std::cout << CLR_BLUE << "\t- Port:\t\t" << CLR_GOLD << this->_port << CLR_RESET << std::endl; + std::cout << CLR_BLUE << "\t- Password:\t" << CLR_GOLD << this->_password << CLR_RESET << std::endl; } /** @@ -131,7 +135,14 @@ void Server::showInfo() const { * * @return the port of the server */ -unsigned short int Server::getPort() const { - return this->_port; -} +unsigned short int Server::getPort() const { return this->_port; } +void Server::printUsers() const +{ + std::cout << "Connected users:" << std::endl; + for (std::map::const_iterator it = _users.begin(); it != _users.end(); ++it) + { + std::cout << "User fd: " << it->first << std::endl; + std::cout << "Nickname: " << it->second->getNickname() << std::endl; + } +}