From 2b3b6654e7036f1c45266f9951ba80874cc79757 Mon Sep 17 00:00:00 2001 From: Samy BEN TAYEB Date: Tue, 17 Jun 2025 23:55:17 +0200 Subject: [PATCH 1/3] JOIN created. compile, need implement MSGPRIVATE --- include/channel.hpp | 32 ++++++++++------- include/commands.hpp | 2 +- include/server.hpp | 4 +-- sources/channel/channel.cpp | 12 +++++-- sources/commands/join.cpp | 69 +++++++++++++++++++++++++++--------- sources/commands/userCmd.cpp | 2 +- sources/core/Server.cpp | 4 +-- 7 files changed, 89 insertions(+), 36 deletions(-) diff --git a/include/channel.hpp b/include/channel.hpp index 18dc958..cd10c89 100644 --- a/include/channel.hpp +++ b/include/channel.hpp @@ -3,10 +3,10 @@ /* ::: :::::::: */ /* channel.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: rparodi +#+ +:+ +#+ */ +/* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:18:17 by rparodi #+# #+# */ -/* Updated: 2025/06/17 17:52:19 by rparodi ### ########.fr */ +/* Updated: 2025/06/17 23:38:49 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,17 +17,9 @@ #include class Channel { - private: - std::string _name; - std::string _password; - std::string _topic; - User *_owner; - bool _needInvite; - size_t _maxUsers; - std::list _operators; - std::list _users; - std::list _invited; public: + Channel(const std::string &name, User *owner, size_t maxUsers, bool needInvite); + // getters std::string getName() const; std::string getTopic() const; @@ -50,4 +42,20 @@ class Channel { void addUser(User *user); void removeUser(User *user); void removeOperator(User *user); + + // utility functions + void sendAllClientInAChannel(const std::string toSend); + + private: + std::string _name; + User *_owner; + std::string _password; + size_t _maxUsers; + bool _needInvite; + std::string _topic; + std::list _operators; + std::list _users; + std::list _invited; }; + + diff --git a/include/commands.hpp b/include/commands.hpp index 9107ab5..438c8db 100644 --- a/include/commands.hpp +++ b/include/commands.hpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 23:31:58 by rparodi #+# #+# */ -/* Updated: 2025/06/17 17:36:38 by sben-tay ### ########.fr */ +/* Updated: 2025/06/17 23:14:07 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/include/server.hpp b/include/server.hpp index 87626a9..cf059f1 100644 --- a/include/server.hpp +++ b/include/server.hpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:50:32 by rparodi #+# #+# */ -/* Updated: 2025/06/17 17:36:46 by sben-tay ### ########.fr */ +/* Updated: 2025/06/17 23:16:58 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -38,7 +38,7 @@ public: void start(); unsigned short int getPort() const; std::list getUsersList() const; - std::list getChannelsList() const; + std::list& getChannelsList(); std::string getPassword() const; void showInfo() const; void printUsers() const; diff --git a/sources/channel/channel.cpp b/sources/channel/channel.cpp index 0c263e1..cc0e044 100644 --- a/sources/channel/channel.cpp +++ b/sources/channel/channel.cpp @@ -3,16 +3,19 @@ /* ::: :::::::: */ /* channel.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: rparodi +#+ +:+ +#+ */ +/* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:43:24 by rparodi #+# #+# */ -/* Updated: 2025/06/17 17:22:09 by rparodi ### ########.fr */ +/* Updated: 2025/06/17 23:51:54 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ #include "channel.hpp" #include +Channel::Channel(const std::string &name, User *owner, size_t maxUsers, bool needInvite) + :_name(name), _owner(owner), _maxUsers(maxUsers), _needInvite(needInvite) {} + /** * @brief Get the name of the channel * @@ -216,3 +219,8 @@ void Channel::removeOperator(User *user) { } } +void Channel::sendAllClientInAChannel(const std::string toSend) { + for(std::list::iterator it = this->_users.begin(); it != this->_users.end(); ++it) { + (*it)->appendToWriteBuffer(toSend); + } +} \ No newline at end of file diff --git a/sources/commands/join.cpp b/sources/commands/join.cpp index a751339..a5d5650 100644 --- a/sources/commands/join.cpp +++ b/sources/commands/join.cpp @@ -6,13 +6,14 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/24 17:29:48 by rparodi #+# #+# */ -/* Updated: 2025/06/17 18:48:08 by rparodi ### ########.fr */ +/* Updated: 2025/06/17 23:50:28 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ #include "join.hpp" #include "commands.hpp" #include "logs.hpp" +#include using namespace cmd; @@ -27,20 +28,6 @@ e_code Join::checkArgs() { return ERR_NOSUCHCHANNEL; } else _args[1].erase(0, 1); - _cTarget = searchList(_channels, _args.at(1)); - if (_cTarget == NULL) { - WARNING_MSG("Channel not found for Join command"); - INFO_MSG("You can only Join users to channels you are in"); - return ERR_NOSUCHCHANNEL; - } - if (searchList(_cTarget->getOperators(), _sender->getName()) != NULL) { - WARNING_MSG("You are not an operator in the channel for Join command"); - return ERR_NOPRIVILEGES; - } - if (searchList(_cTarget->getInvited(), _sender->getName()) != NULL) { - WARNING_MSG("This channel is private and ur not invited"); - return ERR_INVITEONLYCHAN; - } return _PARSING_OK; } @@ -48,9 +35,59 @@ e_code Join::checkArgs() { * @brief Execute the join command * @note To join a new channel */ + void Join::execute() { if (checkArgs() != _PARSING_OK) { ERROR_MSG("Invalid arguments for Join command (see warning message)"); return; } -} + + // Récupérer la liste des channels par référence + std::list& allChannels = _server->getChannelsList(); + + // msgJoin, msg332, msg353 + + // Vérifier si le channel existe déjà + _cTarget = searchList(allChannels, _args.at(1)); + if (_cTarget == NULL) { + // Le channel n'existe pas, on le crée + _cTarget = new Channel(_args[1], _sender, 50, false); // false = public + allChannels.push_back(_cTarget); + + // Ajout automatique du créateur dans le channel + _cTarget->addUser(_sender); + _cTarget->addOperator(_sender); + + std::string msgJoin = ":" + _sender->getPrefix() + " JOIN #" + _cTarget->getName() + "\r\n"; + std:: string msg332 = ":" + _sender->getPrefix() + " 332 " + _sender->getNickname() + " #" + _cTarget->getName() + " :" + _cTarget->getTopic() + "\r\n"; + std::string msg353 = ":" + _sender->getPrefix() + " 353 " + _sender->getNickname() + " = #" + _cTarget->getName() + " :"; + for (std::list::iterator it = _cTarget->getUsers().begin(); it != _cTarget->getUsers().end(); ++it) { + msg353 += (*it)->getNickname() + " "; + } + _sender->appendToWriteBuffer(msgJoin + msg332 + msg353 + "\r\n"); + return; + } + + // Si le channel est privé, vérifier que l'utilisateur est invité + + if (_cTarget->getNeedInvite() == true) { + if (!searchList(_cTarget->getInvited(), _sender->getName())) { + std::string msgErr = ":localhost 473 " + _sender->getNickname() + " #" + _cTarget->getName() + " :Cannot join channel (+i)\r\n"; + _sender->appendToWriteBuffer(msgErr); + return; + } + } + + // Ajouter le user au channel + _cTarget->addUser(_sender); + + // Envoyer le JOIN à tous les membres du channel + std::string msgJoin = ":" + _sender->getPrefix() + " JOIN #" + _cTarget->getName() + "\r\n"; + std:: string msg332 = ":" + _sender->getPrefix() + " 332 " + _sender->getNickname() + " #" + _cTarget->getName() + " :" + _cTarget->getTopic() + "\r\n"; + std::string msg353 = ":" + _sender->getPrefix() + " 353 " + _sender->getNickname() + " = #" + _cTarget->getName() + " :"; + for (std::list::iterator it = _cTarget->getUsers().begin(); it != _cTarget->getUsers().end(); ++it) { + msg353 += (*it)->getNickname() + " "; + } + _cTarget->sendAllClientInAChannel(msgJoin + msg332 + msg353 + "\r\n"); + +} \ No newline at end of file diff --git a/sources/commands/userCmd.cpp b/sources/commands/userCmd.cpp index eb587b7..3ec72a5 100644 --- a/sources/commands/userCmd.cpp +++ b/sources/commands/userCmd.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/06/08 19:16:10 by sben-tay #+# #+# */ -/* Updated: 2025/06/17 15:41:25 by sben-tay ### ########.fr */ +/* Updated: 2025/06/17 23:17:54 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index 0995527..47bdb02 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/06/17 17:38:39 by sben-tay ### ########.fr */ +/* Updated: 2025/06/17 23:16:55 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -194,7 +194,7 @@ std::list Server::getUsersList() const { return userList; } -std::list Server::getChannelsList() const { +std::list& Server::getChannelsList() { return this->_channels; } From 150ada2f4ec2dd89900062d30871b0ee2b84a507 Mon Sep 17 00:00:00 2001 From: Samy BEN TAYEB Date: Wed, 18 Jun 2025 00:20:54 +0200 Subject: [PATCH 2/3] segfault in function JOIN Fixed --- include/channel.hpp | 4 ++-- sources/channel/channel.cpp | 4 ++-- sources/commands/join.cpp | 5 ++--- sources/core/Server.cpp | 15 +++++++-------- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/include/channel.hpp b/include/channel.hpp index cd10c89..16a042f 100644 --- a/include/channel.hpp +++ b/include/channel.hpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:18:17 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:38:49 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 00:10:56 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -26,7 +26,7 @@ class Channel { size_t getMaxUsers() const; User *getOwner() const; std::list getOperators() const; - std::list getUsers() const; + std::list& getUsers(); std::list getInvited() const; std::string getPassword() const; bool isOperator(User *user) const; diff --git a/sources/channel/channel.cpp b/sources/channel/channel.cpp index cc0e044..fbbaede 100644 --- a/sources/channel/channel.cpp +++ b/sources/channel/channel.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:43:24 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:51:54 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 00:10:48 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -48,7 +48,7 @@ User *Channel::getOwner() const { * * @return list of Users in the channel */ -std::list Channel::getUsers() const { +std::list& Channel::getUsers() { return this->_users; } diff --git a/sources/commands/join.cpp b/sources/commands/join.cpp index a5d5650..c81392e 100644 --- a/sources/commands/join.cpp +++ b/sources/commands/join.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/24 17:29:48 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:50:28 by sben-tay ### ########.fr */ +/* Updated: 2025/06/17 23:55:31 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -89,5 +89,4 @@ void Join::execute() { msg353 += (*it)->getNickname() + " "; } _cTarget->sendAllClientInAChannel(msgJoin + msg332 + msg353 + "\r\n"); - -} \ No newline at end of file +} diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index 47bdb02..4b49c8b 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:16:55 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 00:10:14 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -185,7 +185,6 @@ void Server::printUsers() const std::string Server::getPassword() const { return this->_password; } std::list Server::getUsersList() const { - // to_delete when done WARNING_MSG("TO DO FILL") std::list userList; for (std::map::const_iterator it = _users.begin(); it != _users.end(); ++it) { @@ -212,10 +211,10 @@ std::vector splitLines(const std::string& input) { } void Server::disconnectClient(int fd) { - _pollManager.removeClient(fd); - close(fd); - if (_users.count(fd)) { - delete _users[fd]; - _users.erase(fd); - } + User *user = _users[fd]; + for (std::list::iterator it = _channels.begin(); it != _channels.end(); ++it) + (*it)->removeUser(user); + + delete user; + _users.erase(fd); } \ No newline at end of file From 3aad000a49dc14a703a335a02df88bb1c063376f Mon Sep 17 00:00:00 2001 From: Samy BEN TAYEB Date: Wed, 18 Jun 2025 01:41:23 +0200 Subject: [PATCH 3/3] update server.start(), server.poll().polloop() and /JOIN ok --- include/PollManager.hpp | 11 ++--- include/channel.hpp | 5 ++- include/server.hpp | 7 ++-- include/user.hpp | 8 +++- sources/channel/channel.cpp | 9 ++-- sources/commands/join.cpp | 4 +- sources/commands/privmsg.cpp | 53 ++++++++++++++++-------- sources/core/PollManager.cpp | 16 +++++++- sources/core/Server.cpp | 79 +++++++++++++++++++----------------- sources/user/user.cpp | 7 ++-- 10 files changed, 122 insertions(+), 77 deletions(-) diff --git a/include/PollManager.hpp b/include/PollManager.hpp index 562614c..bf5238c 100644 --- a/include/PollManager.hpp +++ b/include/PollManager.hpp @@ -1,14 +1,14 @@ -/******************************************************************************/ +/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* PollManager.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: omoudni +#+ +:+ +#+ */ +/* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/19 19:15:13 by omoudni #+# #+# */ -/* Updated: 2025/05/22 17:30:00 by omoudni ### ########.fr */ +/* Updated: 2025/06/18 01:26:38 by sben-tay ### ########.fr */ /* */ -/******************************************************************************/ +/* ************************************************************************** */ #pragma once @@ -26,7 +26,8 @@ public: 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); + void pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients, std::vector &readyToWrite); + void setWritable(short unsigned fd, bool enable); private: std::vector _fds; diff --git a/include/channel.hpp b/include/channel.hpp index 16a042f..edbbd29 100644 --- a/include/channel.hpp +++ b/include/channel.hpp @@ -6,13 +6,14 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:18:17 by rparodi #+# #+# */ -/* Updated: 2025/06/18 00:10:56 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:18:05 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ #pragma once #include "user.hpp" +#include "server.hpp" #include #include @@ -44,7 +45,7 @@ class Channel { void removeOperator(User *user); // utility functions - void sendAllClientInAChannel(const std::string toSend); + void sendAllClientInAChannel(const std::string toSend, User *sender); private: std::string _name; diff --git a/include/server.hpp b/include/server.hpp index cf059f1..44ffda7 100644 --- a/include/server.hpp +++ b/include/server.hpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:50:32 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:16:58 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:09:21 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -36,9 +36,10 @@ public: Server(int port, const std::string &password); ~Server(); void start(); - unsigned short int getPort() const; - std::list getUsersList() const; std::list& getChannelsList(); + std::list getUsersList() const; + PollManager& getPollManager(); + unsigned short int getPort() const; std::string getPassword() const; void showInfo() const; void printUsers() const; diff --git a/include/user.hpp b/include/user.hpp index fcae8b3..a1fa57f 100644 --- a/include/user.hpp +++ b/include/user.hpp @@ -6,13 +6,14 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 21:57:49 by rparodi #+# #+# */ -/* Updated: 2025/06/17 15:59:19 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:19:32 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ #pragma once #include +#include "PollManager.hpp" class User { @@ -26,14 +27,17 @@ class User std::string _username; std::string _realname; std::string _ipAdress; + bool _hasNick; bool _hasUser; bool _hasPass; bool _passReceived; bool _passIsValid; + + PollManager& _poll; public: - User(short unsigned fd); + User(short unsigned fd, PollManager& poll); short unsigned int getFd() const; bool isReadyToSend() const; bool isRegistered() const; diff --git a/sources/channel/channel.cpp b/sources/channel/channel.cpp index fbbaede..c9acd75 100644 --- a/sources/channel/channel.cpp +++ b/sources/channel/channel.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/20 22:43:24 by rparodi #+# #+# */ -/* Updated: 2025/06/18 00:10:48 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:17:37 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -219,8 +219,11 @@ void Channel::removeOperator(User *user) { } } -void Channel::sendAllClientInAChannel(const std::string toSend) { +void Channel::sendAllClientInAChannel(const std::string toSend, User *sender) { for(std::list::iterator it = this->_users.begin(); it != this->_users.end(); ++it) { - (*it)->appendToWriteBuffer(toSend); + if (*it == sender) { + continue; + } + (*it)->appendToWriteBuffer(toSend); } } \ No newline at end of file diff --git a/sources/commands/join.cpp b/sources/commands/join.cpp index c81392e..2bfe86d 100644 --- a/sources/commands/join.cpp +++ b/sources/commands/join.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/24 17:29:48 by rparodi #+# #+# */ -/* Updated: 2025/06/17 23:55:31 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 00:58:16 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -88,5 +88,5 @@ void Join::execute() { for (std::list::iterator it = _cTarget->getUsers().begin(); it != _cTarget->getUsers().end(); ++it) { msg353 += (*it)->getNickname() + " "; } - _cTarget->sendAllClientInAChannel(msgJoin + msg332 + msg353 + "\r\n"); + _cTarget->sendAllClientInAChannel(msgJoin + msg332 + msg353 + "\r\n", _sender); } diff --git a/sources/commands/privmsg.cpp b/sources/commands/privmsg.cpp index c13e52a..a1df043 100644 --- a/sources/commands/privmsg.cpp +++ b/sources/commands/privmsg.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/24 17:29:48 by rparodi #+# #+# */ -/* Updated: 2025/06/12 13:25:02 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 00:56:49 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,30 +16,31 @@ using namespace cmd; +// exemple: +// PRIVMSG #samy :salut + e_code PrivMsg::checkArgs() { if (_args.size() < 3) { WARNING_MSG("Not enough arguments for PRIVMSG command"); return ERR_NEEDMOREPARAMS; } - if (_args.at(1).at(0) != '#') { - _uTarget = searchList(this->_users, _args.at(2)); - if (this->_uTarget == NULL) { - WARNING_MSG("User not found"); - return ERR_NOSUCHNICK; - } - if (this->_uTarget->isRegistered() == false) { - WARNING_MSG("User is not registered for PRIVMSG command"); - INFO_MSG("You can only privmsg registered users"); - return ERR_NOSUCHNICK; - } - } else { - _cTarget = searchList(_channels, _args.at(1)); + + std::string target = _args.at(1); + + if (target[0] == '#') { + target.erase(0, 1); // Enlève le '#' + _cTarget = searchList(_server->getChannelsList(), target); if (_cTarget == NULL) { WARNING_MSG("Channel not found for PRIVMSG command"); - INFO_MSG("You can only privmsg users to channels you are in"); return ERR_NOSUCHCHANNEL; - } else - _args.at(1).erase(0, 1); + } + } + else { + _uTarget = searchList(_users, target); + if (_uTarget == NULL || !_uTarget->isRegistered()) { + WARNING_MSG("User not found or not registered"); + return ERR_NOSUCHNICK; + } } return _PARSING_OK; } @@ -48,10 +49,26 @@ e_code PrivMsg::checkArgs() { * @brief Execute the PrivMsg command * @note To send a private message to a user / a channel */ + void PrivMsg::execute() { if (checkArgs() != _PARSING_OK) { ERROR_MSG("Invalid arguments for PRIVMSG command (see warning message)"); return; } - // check how the com + + std::string target = _args.at(1); + std::string content = _args.at(2); + std::string msg = ":" + _sender->getPrefix() + " PRIVMSG " + target + " :" + content + "\r\n"; + + // Envoi vers un channel + if (target[0] == '#') { + target.erase(0, 1); // Enlève le # + if (_cTarget) + _cTarget->sendAllClientInAChannel(msg, _sender); // Optionnel: évite d'envoyer au sender + } + // Envoi vers un user + else { + if (_uTarget) + _uTarget->appendToWriteBuffer(msg); + } } diff --git a/sources/core/PollManager.cpp b/sources/core/PollManager.cpp index ff6a152..f71a763 100644 --- a/sources/core/PollManager.cpp +++ b/sources/core/PollManager.cpp @@ -18,7 +18,7 @@ PollManager::~PollManager() } } -void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients) +void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vector &disconnected, std::vector > &readyClients, std::vector &readyToWrite) { int poll_count = poll(&_fds[0], _fds.size(), -1); if (poll_count == -1) @@ -59,6 +59,8 @@ void PollManager::pollLoop(int server_fd, std::vector &newClients, std::vec --i; } } + else if (_fds[i].revents & POLLOUT) + readyToWrite.push_back(fd); } // } } @@ -94,3 +96,15 @@ void PollManager::setServerFd(int fd) pfd.events = POLLIN; _fds.push_back(pfd); } + +void PollManager::setWritable(short unsigned fd, bool enable) { + for (size_t i = 0; i < _fds.size(); ++i) { + if (_fds[i].fd == fd) { + if (enable) + _fds[i].events |= POLLOUT; + else + _fds[i].events &= ~POLLOUT; + break; + } + } +} diff --git a/sources/core/Server.cpp b/sources/core/Server.cpp index 4b49c8b..8ef76b7 100644 --- a/sources/core/Server.cpp +++ b/sources/core/Server.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/13 11:11:07 by rparodi #+# #+# */ -/* Updated: 2025/06/18 00:10:14 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:34:56 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -54,8 +54,7 @@ std::vector splitLines(const std::string& input); void Server::start() { _serverFd = socket(AF_INET, SOCK_STREAM, 0); - if (_serverFd == -1) - { + if (_serverFd == -1) { std::cerr << "Erreur socket" << std::endl; return; } @@ -67,73 +66,76 @@ void Server::start() addr.sin_port = htons(_port); if (bind(_serverFd, (sockaddr *)&addr, sizeof(addr)) == -1 || - listen(_serverFd, 10) == -1) - { + listen(_serverFd, 10) == -1) { std::cerr << "Erreur bind/listen" << std::endl; close(_serverFd); return; } std::cout << "Serveur lancé sur le port " << _port << std::endl; + _pollManager.setServerFd(_serverFd); std::vector newClients; std::vector disconnected; - std::vector > readyClients; - while (true) - { + std::vector > readyClients; + std::vector readyToWrite; + + while (true) { printUsers(); + newClients.clear(); disconnected.clear(); readyClients.clear(); - _pollManager.pollLoop(_serverFd, newClients, disconnected, - readyClients); - std::cout << "New clients: " << newClients.size() << std::endl; - for (size_t i = 0; i < newClients.size(); ++i) - { - _users[newClients[i]] = new User(newClients[i]); + readyToWrite.clear(); + + _pollManager.pollLoop(_serverFd, newClients, disconnected, readyClients, readyToWrite); + + for (size_t i = 0; i < newClients.size(); ++i) { + _users[newClients[i]] = new User(newClients[i], _pollManager); } - // Handle disconnected clients - for (size_t i = 0; i < disconnected.size(); ++i) - { + + for (size_t i = 0; i < disconnected.size(); ++i) { disconnectClient(disconnected[i]); } - for (size_t i = 0; i < readyClients.size(); ++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)) - { + + if (_users.count(fd)) { _users[fd]->appendToReadBuffer(data); std::string rawCmd; - while (!(rawCmd = _users[fd]->extractFullCommand()).empty()) - { + + while (!(rawCmd = _users[fd]->extractFullCommand()).empty()) { std::vector lines = splitLines(rawCmd); for (size_t i = 0; i < lines.size(); ++i) { std::cout << "Client " << fd << " says: " << lines[i] << std::endl; cmd::dispatch(_users[fd], NULL, this, lines[i]); } - // This prints every command/message received from any client } } } - for (std::vector > ::iterator it = readyClients.begin(); it != readyClients.end(); ++it) - { - int fd = it->first; - if (_users.count(fd) && _users[fd]->isReadyToSend()) - { + + for (size_t i = 0; i < readyToWrite.size(); ++i) { + int fd = readyToWrite[i]; + if (_users.count(fd)) { std::string writeBuffer = _users[fd]->getWriteBuffer(); - ssize_t bytesSent = send(fd, writeBuffer.c_str(), writeBuffer.size(), 0); - if (bytesSent < 0) - { - std::cerr << "Erreur send" << std::endl; - } - else { - _users[fd]->clearWriteBuffer(); + if (!writeBuffer.empty()) { + ssize_t bytesSent = send(fd, writeBuffer.c_str(), writeBuffer.size(), MSG_NOSIGNAL); + if (bytesSent < 0) { + std::cerr << "Erreur send sur fd " << fd << std::endl; + disconnectClient(fd); + } else { + _users[fd]->clearWriteBuffer(); + _pollManager.setWritable(fd, false); + } } } } + std::cout << "Poll loop finished" << std::endl; } + close(_serverFd); } @@ -185,7 +187,6 @@ void Server::printUsers() const std::string Server::getPassword() const { return this->_password; } std::list Server::getUsersList() const { - WARNING_MSG("TO DO FILL") std::list userList; for (std::map::const_iterator it = _users.begin(); it != _users.end(); ++it) { userList.push_back(it->second); @@ -217,4 +218,6 @@ void Server::disconnectClient(int fd) { delete user; _users.erase(fd); -} \ No newline at end of file +} + +PollManager& Server::getPollManager() { return _pollManager; } \ No newline at end of file diff --git a/sources/user/user.cpp b/sources/user/user.cpp index 6279b62..30b6b34 100644 --- a/sources/user/user.cpp +++ b/sources/user/user.cpp @@ -6,7 +6,7 @@ /* By: sben-tay +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2025/05/21 20:37:12 by omoudni #+# #+# */ -/* Updated: 2025/06/17 17:42:40 by sben-tay ### ########.fr */ +/* Updated: 2025/06/18 01:19:52 by sben-tay ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,8 +18,8 @@ #include // Constructor -User::User(short unsigned int fd) : _fd(fd), _registered(false), _hasNick(false), _hasUser(false), \ - _hasPass(false), _passReceived(false), _passIsValid(false) {} +User::User(short unsigned int fd, PollManager& poll) : _fd(fd), _registered(false), _hasNick(false), _hasUser(false), \ + _hasPass(false), _passReceived(false), _passIsValid(false), _poll(poll) {} /** * @brief Getter for the fd @@ -81,6 +81,7 @@ void User::appendToReadBuffer(const std::string &data) void User::appendToWriteBuffer(const std::string &data) { _write_buffer += data; + _poll.setWritable(_fd, true); } // Check registration