diff --git a/ft_irc3/includes/CommandHandler.hpp b/ft_irc3/includes/CommandHandler.hpp index 303c6e6..6e6fd86 100644 --- a/ft_irc3/includes/CommandHandler.hpp +++ b/ft_irc3/includes/CommandHandler.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:14:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 19:13:53 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 13:47:12 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,7 +18,7 @@ #include "Client.hpp" #include "Channel.hpp" #include "AdditionalCommands.hpp" -#include "ModeWhoHandler.hpp" +#include "Who.hpp" #include "CommandHandler.hpp" #include "RPL.hpp" diff --git a/ft_irc3/includes/RPL.hpp b/ft_irc3/includes/RPL.hpp index bf60160..2ce5756 100644 --- a/ft_irc3/includes/RPL.hpp +++ b/ft_irc3/includes/RPL.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/19 15:12:47 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 22:27:05 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 12:41:51 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -19,9 +19,9 @@ #define SERVER_NAME "IRC_Server" #define SERVER_VERSION "1.0" -#define USER_MODES "iw" -#define CHANNEL_MODES "nt" -#define CHANNEL_MODES_WITH_PARAMS "kl" +#define USER_MODES "" +#define CHANNEL_MODES "" +#define CHANNEL_MODES_WITH_PARAMS "" @@ -35,7 +35,7 @@ // Fonctions pour générer les réponses RPL inline std::string RPL_WELCOME(Client* client) { std::ostringstream oss; - oss << ":" << SERVER_NAME << " 001 " << CLIENT_FD(client) + oss << ":" << SERVER_NAME << " 001 " << CLIENT_NICK(client) << " :Welcome to the Internet Relay Network " << CLIENT_NICK(client) << "!" << CLIENT_USER(client) << "@" << CLIENT_HOST(client) << "\r\n"; return oss.str(); diff --git a/ft_irc3/includes/ModeWhoHandler.hpp b/ft_irc3/includes/Who.hpp similarity index 78% rename from ft_irc3/includes/ModeWhoHandler.hpp rename to ft_irc3/includes/Who.hpp index 80dd316..4335875 100644 --- a/ft_irc3/includes/ModeWhoHandler.hpp +++ b/ft_irc3/includes/Who.hpp @@ -1,17 +1,17 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ModeWhoHandler.hpp :+: :+: :+: */ +/* Who.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/17 16:08:48 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 20:36:23 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 13:47:28 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef MODEWHOHANDLER_HPP -#define MODEWHOHANDLER_HPP +#ifndef WHO_HPP +#define WHO_HPP #include "Server.hpp" #include "Client.hpp" @@ -24,11 +24,10 @@ class Server; -class ModeWhoHandler +class WhoHandler { public: - ModeWhoHandler(Server *server); - void handleModeCommand(Client *client, const std::string &command); + WhoHandler(Server *server); void handleWhoCommand(Client *client, const std::string &command); void handleWhoisCommand(Client *client, const std::string &command); diff --git a/ft_irc3/ircserv b/ft_irc3/ircserv deleted file mode 100755 index 64921c1..0000000 Binary files a/ft_irc3/ircserv and /dev/null differ diff --git a/ft_irc3/logs/irc_server.log b/ft_irc3/logs/irc_server.log deleted file mode 100644 index e69de29..0000000 diff --git a/ft_irc3/motd b/ft_irc3/motd new file mode 100644 index 0000000..ff24924 --- /dev/null +++ b/ft_irc3/motd @@ -0,0 +1,9 @@ + +░▒▓████████▓▒░▒▓████████▓▒░▒▓█▓▒░▒▓███████▓▒░ ░▒▓██████▓▒░ ░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░ +░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ +░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░ +░▒▓██████▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓███████▓▒░░▒▓█▓▒░ ░▒▓████████▓▒░░▒▓██████▓▒░ +░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░ +░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░ +░▒▓█▓▒░ ░▒▓█▓▒░ ░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░░▒▓██████▓▒░ ░▒▓█▓▒░▒▓████████▓▒░ + \ No newline at end of file diff --git a/ft_irc3/obj/AdditionalCommands.o b/ft_irc3/obj/AdditionalCommands.o index d3fed42..24556f2 100644 Binary files a/ft_irc3/obj/AdditionalCommands.o and b/ft_irc3/obj/AdditionalCommands.o differ diff --git a/ft_irc3/obj/ClientManager.o b/ft_irc3/obj/ClientManager.o index 39eac96..cbfef1a 100644 Binary files a/ft_irc3/obj/ClientManager.o and b/ft_irc3/obj/ClientManager.o differ diff --git a/ft_irc3/obj/CommandHandler.o b/ft_irc3/obj/CommandHandler.o index 545fe05..b8d83fc 100644 Binary files a/ft_irc3/obj/CommandHandler.o and b/ft_irc3/obj/CommandHandler.o differ diff --git a/ft_irc3/obj/ModeWhoHandler.o b/ft_irc3/obj/ModeWhoHandler.o deleted file mode 100644 index 5f6d31b..0000000 Binary files a/ft_irc3/obj/ModeWhoHandler.o and /dev/null differ diff --git a/ft_irc3/obj/Server.o b/ft_irc3/obj/Server.o deleted file mode 100644 index bee98a5..0000000 Binary files a/ft_irc3/obj/Server.o and /dev/null differ diff --git a/ft_irc3/obj/Utils.o b/ft_irc3/obj/Utils.o deleted file mode 100644 index 4853158..0000000 Binary files a/ft_irc3/obj/Utils.o and /dev/null differ diff --git a/ft_irc3/src/AdditionalCommands.cpp b/ft_irc3/src/AdditionalCommands.cpp index 3655143..4d71dfb 100644 --- a/ft_irc3/src/AdditionalCommands.cpp +++ b/ft_irc3/src/AdditionalCommands.cpp @@ -6,147 +6,153 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/16 15:27:29 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 19:22:28 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 13:52:54 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "AdditionalCommands.hpp" -void sendWelcomeMessages(Client *client, Server *server) { - server->sendToClient(client->getFd(), RPL_WELCOME(client)); - server->sendToClient(client->getFd(), RPL_YOURHOST(client)); - server->sendToClient(client->getFd(), RPL_CREATED(client)); - server->sendToClient(client->getFd(), RPL_MYINFO(client)); - server->sendToClient(client->getFd(), RPL_ISUPPORT(client, "MODES=EXAMPLE")); +void sendWelcomeMessages(Client *client, Server *server) +{ + server->sendToClient(client->getFd(), RPL_WELCOME(client)); + server->sendToClient(client->getFd(), RPL_YOURHOST(client)); + server->sendToClient(client->getFd(), RPL_CREATED(client)); + server->sendToClient(client->getFd(), RPL_MYINFO(client)); + server->sendToClient(client->getFd(), RPL_ISUPPORT(client, "MODES=EXAMPLE")); sendMotd(client, server); } -void sendMotd(Client *client, Server *server) { - std::ifstream motdFile("motd.txt"); - if (motdFile.is_open()) { - std::string line; - server->sendToClient(client->getFd(), RPL_MOTDSTART(client)); - while (std::getline(motdFile, line)) { - server->sendToClient(client->getFd(), RPL_MOTD(client, line)); - } - server->sendToClient(client->getFd(), RPL_ENDOFMOTD(client)); - motdFile.close(); - } else { - server->sendToClient(client->getFd(), ERR_NOMOTD(client)); - } +void sendMotd(Client *client, Server *server) +{ + std::ifstream motdFile("motd.txt"); + if (motdFile.is_open()) + { + std::string line; + server->sendToClient(client->getFd(), RPL_MOTDSTART(client)); + while (std::getline(motdFile, line)) + { + server->sendToClient(client->getFd(), RPL_MOTD(client, line)); + } + server->sendToClient(client->getFd(), RPL_ENDOFMOTD(client)); + motdFile.close(); + } + else + { + server->sendToClient(client->getFd(), ERR_NOMOTD(client)); + } } void broadcastChannelList(Client *client, Server *server) { - std::map &channels = server->getChannels(); - for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) - { - server->sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); - } - server->sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); + std::map &channels = server->getChannels(); + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) + { + server->sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); + } + server->sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); } // Fonction pour gérer la commande PART void handlePartCommand(Server *server, Client *client, const std::string &command) { - std::istringstream iss(command); - std::string cmd, channelName; - iss >> cmd >> channelName; + std::istringstream iss(command); + std::string cmd, channelName; + iss >> cmd >> channelName; - std::map &channels = server->getChannels(); + std::map &channels = server->getChannels(); - if (channels.find(channelName) != channels.end()) - { - Channel *channel = channels[channelName]; - channel->removeClient(client); + if (channels.find(channelName) != channels.end()) + { + Channel *channel = channels[channelName]; + channel->removeClient(client); - std::stringstream partMsg; - partMsg << ":" << client->getNickname() << " PART " << channelName << "\r\n"; - server->sendToClient(client->getFd(), partMsg.str()); + std::stringstream partMsg; + partMsg << ":" << client->getNickname() << " PART " << channelName << "\r\n"; + server->sendToClient(client->getFd(), partMsg.str()); - if (channel->isEmpty()) - { - delete channel; - channels.erase(channelName); - } + if (channel->isEmpty()) + { + delete channel; + channels.erase(channelName); + } - server->log("Client " + client->getNickname() + " left channel " + channelName, MAGENTA); - } - else - { - std::stringstream ss; - ss << ":server 403 " << client->getNickname() << " " << channelName << " :No such channel\r\n"; - server->sendToClient(client->getFd(), ss.str()); - } + server->log("Client " + client->getNickname() + " left channel " + channelName, MAGENTA); + } + else + { + std::stringstream ss; + ss << ":server 403 " << client->getNickname() << " " << channelName << " :No such channel\r\n"; + server->sendToClient(client->getFd(), ss.str()); + } } // Fonction pour gérer la commande NICK void handleNickCommand(Server *server, Client *client, const std::string &command) { - std::istringstream iss(command); - std::string cmd, newNick; - iss >> cmd >> newNick; + std::istringstream iss(command); + std::string cmd, newNick; + iss >> cmd >> newNick; - std::stringstream nickMsg; - nickMsg << ":" << client->getNickname() << " NICK " << newNick << "\r\n"; - server->sendToClient(client->getFd(), nickMsg.str()); + std::stringstream nickMsg; + nickMsg << ":" << client->getNickname() << " NICK " << newNick << "\r\n"; + server->sendToClient(client->getFd(), nickMsg.str()); - client->setNickname(newNick); + client->setNickname(newNick); - std::stringstream ss; - ss << "Client " << client->getFd() << " changed nickname to " << newNick; - server->log(ss.str(), GREEN); + std::stringstream ss; + ss << "Client " << client->getFd() << " changed nickname to " << newNick; + server->log(ss.str(), GREEN); } void handlePrivmsgCommand(Server *server, Client *client, const std::string &command) { - std::istringstream iss(command); - std::string cmd, target, message; - iss >> cmd >> target; - getline(iss, message); + std::istringstream iss(command); + std::string cmd, target, message; + iss >> cmd >> target; + getline(iss, message); - // Enlever le ':' initial dans le message si présent - if (!message.empty() && message[0] == ':') - message = message.substr(1); + // Enlever le ':' initial dans le message si présent + if (!message.empty() && message[0] == ':') + message = message.substr(1); - // Récupérer les canaux du serveur - std::map &channels = server->getChannels(); + // Récupérer les canaux du serveur + std::map &channels = server->getChannels(); - // Si la cible est un canal - if (channels.find(target) != channels.end()) - { - Channel *channel = channels[target]; - std::vector channelClients = channel->getClients(); + // Si la cible est un canal + if (channels.find(target) != channels.end()) + { + Channel *channel = channels[target]; + std::vector channelClients = channel->getClients(); - for (size_t i = 0; i < channelClients.size(); ++i) - { - // Envoyer le message à tous les clients du canal sauf l'émetteur - if (channelClients[i] != client) - { - std::stringstream privMsg; - privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n"; - server->sendToClient(channelClients[i]->getFd(), privMsg.str()); - } - } - } - // Si la cible est un utilisateur - else - { - Client *targetClient = server->getClientByName(target); // Utiliser getClientByName pour trouver le client par nom + for (size_t i = 0; i < channelClients.size(); ++i) + { + // Envoyer le message à tous les clients du canal sauf l'émetteur + if (channelClients[i] != client) + { + std::stringstream privMsg; + privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n"; + server->sendToClient(channelClients[i]->getFd(), privMsg.str()); + } + } + } + // Si la cible est un utilisateur + else + { + Client *targetClient = server->getClientByName(target); // Utiliser getClientByName pour trouver le client par nom - if (targetClient) - { - std::stringstream privMsg; - privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n"; - server->sendToClient(targetClient->getFd(), privMsg.str()); - } - else - { - // Si la cible n'est ni un canal ni un utilisateur existant, envoyer un message d'erreur - std::stringstream errorMsg; - errorMsg << ":server 401 " << client->getNickname() << " " << target << " :No such nick/channel\r\n"; - server->sendToClient(client->getFd(), errorMsg.str()); - } - } + if (targetClient) + { + std::stringstream privMsg; + privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n"; + server->sendToClient(targetClient->getFd(), privMsg.str()); + } + else + { + // Si la cible n'est ni un canal ni un utilisateur existant, envoyer un message d'erreur + std::stringstream errorMsg; + errorMsg << ":server 401 " << client->getNickname() << " " << target << " :No such nick/channel\r\n"; + server->sendToClient(client->getFd(), errorMsg.str()); + } + } } diff --git a/ft_irc3/src/ClientManager.cpp b/ft_irc3/src/ClientManager.cpp index b76fd33..7473188 100644 --- a/ft_irc3/src/ClientManager.cpp +++ b/ft_irc3/src/ClientManager.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:32:23 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 22:09:39 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 14:09:07 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -67,19 +67,22 @@ void ClientManager::handleClient(int client_fd) } } -void ClientManager::removeClient(int client_fd) +void ClientManager::removeClient(int clientFd) { - Client *client = _server->_clients[client_fd]; + Client* client = _server->_clients[clientFd]; if (client) { - std::map::iterator it = _server->_channels.begin(); + // Log the nickname being freed + _server->log("Removing client: " + client->getNickname(), YELLOW); + + std::map::iterator it = _server->_channels.begin(); while (it != _server->_channels.end()) { it->second->removeClient(client); if (it->second->isEmpty()) { delete it->second; - std::map::iterator it_to_delete = it++; + std::map::iterator it_to_delete = it++; _server->_channels.erase(it_to_delete); } else @@ -88,13 +91,13 @@ void ClientManager::removeClient(int client_fd) } } delete client; - _server->_clients.erase(client_fd); + _server->_clients.erase(clientFd); } std::vector::iterator it_poll = _server->_poll_fds.begin(); while (it_poll != _server->_poll_fds.end()) { - if (it_poll->fd == client_fd) + if (it_poll->fd == clientFd) { _server->_poll_fds.erase(it_poll); break; @@ -103,6 +106,7 @@ void ClientManager::removeClient(int client_fd) } std::stringstream ss; - ss << "Client disconnected: " << client_fd; + ss << "Client disconnected: " << clientFd; _server->log(ss.str(), YELLOW); } + diff --git a/ft_irc3/src/CommandHandler.cpp b/ft_irc3/src/CommandHandler.cpp index cc14fde..14e1309 100644 --- a/ft_irc3/src/CommandHandler.cpp +++ b/ft_irc3/src/CommandHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:26:34 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 23:47:26 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 14:19:19 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -145,10 +145,14 @@ void CommandHandler::handleNick(Client* client, const std::vector& _server->sendToClient(client->getFd(), ERR_NICKNAMEINUSE(client, newNick)); return; } + client->setNickname(newNick); _server->sendToClient(client->getFd(), ":" + newNick + " NICK " + newNick + "\r\n"); - _server->log("Client NickName is " + newNick, GREEN); + + std::ostringstream oss; + oss << "Client " << client->getFd() << " changed nickname to " << newNick; + _server->log(oss.str(), GREEN); } void CommandHandler::handleUser(Client* client, const std::vector& tokens) @@ -156,7 +160,8 @@ void CommandHandler::handleUser(Client* client, const std::vector& // Set the user and realname fields client->setUser(tokens[1]); std::string realname = tokens[4]; - if (realname[0] == ':') { + if (realname[0] == ':') + { realname = realname.substr(1); // Remove leading ':' } client->setRealName(realname); @@ -167,11 +172,14 @@ void CommandHandler::handleUser(Client* client, const std::vector& _server->log(logMsg.str(), BLUE); // Authenticate if password and nickname are already set - if (client->getPassword() == _server->_password && !client->getNickname().empty()) { + if (client->getPassword() == _server->_password && !client->getNickname().empty()) + { client->authenticate(); sendWelcomeMessages(client, _server); _server->log("Client " + client->getNickname() + " authenticated successfully.", GREEN); - } else { + } + else + { std::ostringstream authFailMsg; authFailMsg << "Client " << client->getFd() << ": USER command failed - authentication conditions not met."; _server->log(authFailMsg.str(), RED); @@ -191,27 +199,22 @@ void CommandHandler::processCommand(Client *client, const std::string &command) { handlePartCommand(_server, client, command); } - else if (command.find("NICK") == 0) + /*else if (command.find("NICK") == 0) { handleNickCommand(_server, client, command); - } + }*/ else if (command.find("PRIVMSG") == 0) { handlePrivmsgCommand(_server, client, command); } - else if (command.find("MODE") == 0) - { - ModeWhoHandler modeHandler(_server); - modeHandler.handleModeCommand(client, command); - } else if (command.find("WHO") == 0) { - ModeWhoHandler whoHandler(_server); + WhoHandler whoHandler(_server); whoHandler.handleWhoCommand(client, command); } else if (command.find("WHOIS") == 0) { - ModeWhoHandler whoHandler(_server); + WhoHandler whoHandler(_server); whoHandler.handleWhoisCommand(client, command); } else if (command.find("PING") == 0) diff --git a/ft_irc3/src/Server.cpp b/ft_irc3/src/Server.cpp index bd076c8..8c93d55 100644 --- a/ft_irc3/src/Server.cpp +++ b/ft_irc3/src/Server.cpp @@ -6,321 +6,234 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 22:16:03 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 14:18:03 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Server.hpp" Server::Server(int port, const std::string &password) - : _port(port), _password(password), _clientManager(new ClientManager(this)), _commandHandler(new CommandHandler(this)) + : _port(port), _password(password), _clientManager(new ClientManager(this)), _commandHandler(new CommandHandler(this)) { - initServer(); + initServer(); } Server::~Server() { - delete _clientManager; - delete _commandHandler; + delete _clientManager; + delete _commandHandler; - for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) - { - delete it->second; - } - for (std::map::iterator it = _channels.begin(); it != _channels.end(); ++it) - { - delete it->second; - } - close(_server_fd); + for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + delete it->second; + } + for (std::map::iterator it = _channels.begin(); it != _channels.end(); ++it) + { + delete it->second; + } + close(_server_fd); } void Server::initServer() { - _server_fd = socket(AF_INET, SOCK_STREAM, 0); - if (_server_fd == -1) - { - log("Failed to create socket.", RED); - exit(EXIT_FAILURE); - } + _server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (_server_fd == -1) + { + log("Failed to create socket.", RED); + exit(EXIT_FAILURE); + } - int opt = 1; - if (setsockopt(_server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) - { - log("Failed to set socket options.", RED); - close(_server_fd); - exit(EXIT_FAILURE); - } + int opt = 1; + if (setsockopt(_server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) + { + log("Failed to set socket options.", RED); + close(_server_fd); + exit(EXIT_FAILURE); + } - struct sockaddr_in server_addr; - std::memset(&server_addr, 0, sizeof(server_addr)); - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = htons(_port); + struct sockaddr_in server_addr; + std::memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(_port); - if (bind(_server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) - { - log("Failed to bind socket.", RED); - close(_server_fd); // Close the socket if bind fails - exit(EXIT_FAILURE); - } + if (bind(_server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) + { + log("Failed to bind socket.", RED); + close(_server_fd); // Close the socket if bind fails + exit(EXIT_FAILURE); + } - if (listen(_server_fd, SOMAXCONN) == -1) - { - log("Failed to listen on socket.", RED); - close(_server_fd); // Close the socket if listen fails - exit(EXIT_FAILURE); - } + if (listen(_server_fd, SOMAXCONN) == -1) + { + log("Failed to listen on socket.", RED); + close(_server_fd); // Close the socket if listen fails + exit(EXIT_FAILURE); + } - log("Server initialized.", GREEN); + log("Server initialized.", GREEN); } void Server::run() { - struct pollfd server_pollfd; - server_pollfd.fd = _server_fd; - server_pollfd.events = POLLIN; - server_pollfd.revents = 0; - _poll_fds.push_back(server_pollfd); + struct pollfd server_pollfd; + server_pollfd.fd = _server_fd; + server_pollfd.events = POLLIN; + server_pollfd.revents = 0; + _poll_fds.push_back(server_pollfd); - // Ajout de l'entrée pour les commandes serveur - struct pollfd stdin_pollfd; - stdin_pollfd.fd = STDIN_FILENO; - stdin_pollfd.events = POLLIN; - stdin_pollfd.revents = 0; - _poll_fds.push_back(stdin_pollfd); + // Ajout de l'entrée pour les commandes serveur + struct pollfd stdin_pollfd; + stdin_pollfd.fd = STDIN_FILENO; + stdin_pollfd.events = POLLIN; + stdin_pollfd.revents = 0; + _poll_fds.push_back(stdin_pollfd); - while (true) - { - int poll_count = poll(&_poll_fds[0], _poll_fds.size(), -1); - if (poll_count == -1) - { - log("Poll error.", RED); - exit(EXIT_FAILURE); - } + while (true) + { + int poll_count = poll(&_poll_fds[0], _poll_fds.size(), -1); + if (poll_count == -1) + { + log("Poll error.", RED); + exit(EXIT_FAILURE); + } - for (size_t i = 0; i < _poll_fds.size(); ++i) - { - if (_poll_fds[i].revents & POLLIN) - { - if (_poll_fds[i].fd == _server_fd) - { - _clientManager->acceptClient(); - } - else if (_poll_fds[i].fd == STDIN_FILENO) - { - handleServerCommands(); - } - else - { - _clientManager->handleClient(_poll_fds[i].fd); - } - } - } - } + for (size_t i = 0; i < _poll_fds.size(); ++i) + { + if (_poll_fds[i].revents & POLLIN) + { + if (_poll_fds[i].fd == _server_fd) + { + _clientManager->acceptClient(); + } + else if (_poll_fds[i].fd == STDIN_FILENO) + { + handleServerCommands(); + } + else + { + _clientManager->handleClient(_poll_fds[i].fd); + } + } + } + } } std::map &Server::getChannels() { - return _channels; + return _channels; } const std::string &Server::getPassword() const { - return _password; + return _password; } void Server::handleServerCommands() { - std::string command; - std::getline(std::cin, command); + std::string command; + std::getline(std::cin, command); - if (command == "quit") - { - log("Server shutting down.", YELLOW); - exit(EXIT_SUCCESS); - } - else if (command == "channels") - { - log("Listing all channels:", BLUE); - for (std::map::iterator it = _channels.begin(); it != _channels.end(); ++it) - { - log(it->first, BLUE); - } - } - else if (command == "clients") - { - log("Listing all clients:", BLUE); - for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) - { - log(it->second->getNickname(), BLUE); - } - } - else - { - log("Unknown server command.", RED); - } + if (command == "quit") + { + log("Server shutting down.", YELLOW); + exit(EXIT_SUCCESS); + } + else if (command == "channels") + { + log("Listing all channels:", BLUE); + for (std::map::iterator it = _channels.begin(); it != _channels.end(); ++it) + { + log(it->first, BLUE); + } + } + else if (command == "clients") + { + log("Listing all clients:", BLUE); + for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + log(it->second->getNickname(), BLUE); + } + } + else + { + log("Unknown server command.", RED); + } } void Server::log(const std::string &message, const std::string &color) { - std::cout << color << message << "\033[0m" << std::endl; + std::cout << color << message << "\033[0m" << std::endl; } void Server::sendToClient(int client_fd, const std::string &message) { - int result = send(client_fd, message.c_str(), message.length(), 0); - if (result < 0) - { - std::stringstream ss; - ss << "Failed to send message to client " << client_fd; - log(ss.str(), RED); - } - else - { - std::stringstream ss; - ss << "Sent message to client " << client_fd << ": " << message; - log(ss.str(), BLUE); - } + int result = send(client_fd, message.c_str(), message.length(), 0); + if (result < 0) + { + std::stringstream ss; + ss << "Failed to send message to client " << client_fd; + log(ss.str(), RED); + } + else + { + std::stringstream ss; + ss << "Sent message to client " << client_fd << ": " << message; + log(ss.str(), BLUE); + } } void Server::broadcast(const std::string &message) { - for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) - { - sendToClient(it->first, message); - } + for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + sendToClient(it->first, message); + } } Client* Server::getClientByName(const std::string &name) { - for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) - { - if (it->second->getNickname() == name) - { - return it->second; - } - } - return NULL; // Remplacez nullptr par NULL + for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + if (it->second->getNickname() == name) + { + return it->second; + } + } + return NULL; // Remplacez nullptr par NULL } void Server::sendChannelListToClient(Client *client) { - std::map &channels = getChannels(); - for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) - { - sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); - } - sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); + std::map &channels = getChannels(); + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) + { + sendToClient(client->getFd(), RPL_LIST(client->getFd(), it->first, it->second->getClients().size(), "Existing channel")); + } + sendToClient(client->getFd(), RPL_LISTEND(client->getFd())); } void Server::disconnectClient(int clientFd) { - close(clientFd); - _clients.erase(clientFd); - - for (std::vector::iterator it = _poll_fds.begin(); it != _poll_fds.end(); ++it) + Client* client = _clients[clientFd]; + if (client) { - if (it->fd == clientFd) - { - _poll_fds.erase(it); - break; - } + log("Disconnecting client: " + client->getNickname(), YELLOW); + _clients.erase(clientFd); + delete client; } + struct MatchFd + { + int fd; + MatchFd(int fd) : fd(fd) {} + bool operator()(const pollfd& pfd) const { return pfd.fd == fd; } + }; + + _poll_fds.erase(std::remove_if(_poll_fds.begin(), _poll_fds.end(), MatchFd(clientFd)), _poll_fds.end()); + std::ostringstream oss; oss << "Client disconnected: " << clientFd; log(oss.str(), YELLOW); } - - -/* Explications des Fonctions -Server::Server(int port, const std::string &password) - -Description: Constructeur de la classe Server. Initialise le serveur avec le port et le mot de passe fournis. -Paramètres: -int port: Le port sur lequel le serveur écoute. -const std::string &password: Le mot de passe requis pour se connecter au serveur. -Détails: Appelle initServer() pour initialiser les paramètres du socket et commencer l'écoute des connexions. -Server::~Server() - -Description: Destructeur de la classe Server. Ferme le socket du serveur et libère la mémoire des clients. -Détails: Parcourt la map _clients et delete chaque objet Client. -void Server::initServer() - -Description: Initialise le socket du serveur et configure le binding et l'écoute. -Détails: Crée un socket avec socket(), lie le socket à une adresse avec bind(), et met le socket en mode écoute avec listen(). -void Server::run() - -Description: Boucle principale du serveur qui gère les connexions entrantes et les communications avec les clients. -Détails: Utilise poll() pour surveiller les événements sur les sockets. Accepte les nouvelles connexions avec acceptClient() et gère les communications avec handleClient(). -void Server::acceptClient() - -Description: Accepte une nouvelle connexion client et l'ajoute à la liste des clients. -Détails: Crée un nouvel objet Client et l'ajoute à la map _clients. Ajoute le descripteur de fichier du client à _poll_fds. -void Server::handleClient(int client_fd) - -Description: Gère les messages entrants des clients. -Paramètres: -int client_fd: Le descripteur de fichier du client. -Détails: Reçoit les messages du client et vérifie l'authentification. Si le client n'est pas authentifié, vérifie le mot de passe. Si le client est authentifié, répond au message. -void Server::removeClient(int client_fd) - -Description: Supprime un client de la liste et ferme la connexion. -Paramètres: -int client_fd: Le descripteur de fichier du client. -Détails: Ferme le socket du client et le supprime de la map _clients et du vecteur _poll_fds. -void Server::log(const std::string &message, const std::string &color) - -Description: Enregistre un message dans les logs et l'affiche avec des couleurs dans la console. -Paramètres: -const std::string &message: Le message à enregistrer. -const std::string &color: La couleur du message. -Détails: Utilise logMessage() pour enregistrer et afficher le message. -void Server::sendToClient(int client_fd, const std::string &message) - -Description: Envoie un message à un client. -Paramètres: -int client_fd: Le descripteur de fichier du client. -const std::string &message: Le message à envoyer. -Détails: Utilise send() pour envoyer le message au client. - -Lecture Ligne par Ligne : Utilisez std::istringstream pour lire le message ligne par ligne et traiter chaque commande séparément. -Suppression des Caractères de Fin de Ligne : Utilisez erase et std::remove pour supprimer les caractères \r et \n de chaque ligne avant de traiter la commande. -Vérification du Mot de Passe : Si le client n'est pas authentifié, vérifiez s'il envoie la commande PASS et validez le mot de passe. Sinon, répondez avec un message demandant le mot de passe. -Explications des Modifications -Notification de Jonction : Lorsque le client rejoint un canal, le serveur envoie une notification de jonction avec la commande JOIN. - - -std::stringstream joinMsg; -joinMsg << ":" << client->getFd() << " JOIN " << channelName << "\r\n"; -sendToClient(client->getFd(), joinMsg.str()); -Liste des Utilisateurs : Le serveur envoie la liste des utilisateurs dans le canal en utilisant le code de réponse 353. - - -std::string usersList = getUsersList(channel); -sendToClient(client->getFd(), usersList); -Fin de la Liste des Utilisateurs : Le serveur envoie un message de fin de liste des utilisateurs avec le code de réponse 366. - -std::stringstream endOfNamesMsg; -endOfNamesMsg << ":server 366 " << client->getFd() << " " << channelName << " :End of /NAMES list.\r\n"; -sendToClient(client->getFd(), endOfNamesMsg.str()); -Fonction getUsersList : Cette fonction génère la liste des utilisateurs dans le canal en utilisant le format correct. - -std::string Server::getUsersList(Channel *channel) -{ - std::vector clients = channel->getClients(); - std::stringstream ss; - ss << ":server 353 " << clients[0]->getFd() << " = " << channel->getName() << " :"; - for (size_t i = 0; i < clients.size(); ++i) - { - if (i > 0) - ss << " "; - ss << clients[i]->getFd(); - } - ss << "\r\n"; - return ss.str(); -} -Avec ces modifications, votre serveur IRC devrait maintenant informer correctement le client HexChat des utilisateurs présents dans un canal, ce qui devrait faire apparaître les canaux et leurs utilisateurs correctement dans l'interface du client. - -*/ \ No newline at end of file diff --git a/ft_irc3/src/ModeWhoHandler.cpp b/ft_irc3/src/Who.cpp similarity index 59% rename from ft_irc3/src/ModeWhoHandler.cpp rename to ft_irc3/src/Who.cpp index fc9dce5..bdef91d 100644 --- a/ft_irc3/src/ModeWhoHandler.cpp +++ b/ft_irc3/src/Who.cpp @@ -1,63 +1,26 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* ModeWhoHandler.cpp :+: :+: :+: */ +/* Who.cpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/17 16:09:20 by fgras-ca #+# #+# */ -/* Updated: 2024/05/19 20:52:30 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/21 13:48:51 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ -#include "ModeWhoHandler.hpp" +#include "Who.hpp" #include "Channel.hpp" #include "RPL.hpp" #include -ModeWhoHandler::ModeWhoHandler(Server *server) +WhoHandler::WhoHandler(Server *server) : _server(server) { } -void ModeWhoHandler::handleModeCommand(Client *client, const std::string &command) -{ - std::istringstream iss(command); - std::string cmd, channelName, mode, user; - iss >> cmd >> channelName >> mode >> user; - - std::map &channels = _server->getChannels(); - if (channels.find(channelName) == channels.end()) - { - _server->sendToClient(client->getFd(), ERR_NOSUCHCHANNEL(client->getFd(), channelName)); - return; - } - - Channel *channel = channels[channelName]; - if (mode == "+o") - { - if (client->isOperator()) - { - Client *targetClient = _server->getClientByName(user); - if (targetClient) - { - channel->addOperator(targetClient); - _server->sendToClient(client->getFd(), RPL_CHANNELMODEIS(client->getFd(), channelName, "+o")); - _server->log("Client " + user + " is now an operator in channel " + channelName, GREEN); - } - else - { - _server->sendToClient(client->getFd(), ERR_NOSUCHNICK(client->getFd(), user)); - } - } - else - { - _server->sendToClient(client->getFd(), ERR_CHANOPRIVSNEEDED(client->getFd(), channelName)); - } - } -} - -void ModeWhoHandler::handleWhoCommand(Client *client, const std::string &command) +void WhoHandler::handleWhoCommand(Client *client, const std::string &command) { std::istringstream iss(command); std::string cmd, mask; @@ -86,7 +49,7 @@ void ModeWhoHandler::handleWhoCommand(Client *client, const std::string &command _server->sendToClient(client->getFd(), RPL_ENDOFWHO(client->getFd(), mask)); } -void ModeWhoHandler::handleWhoisCommand(Client *client, const std::string &command) +void WhoHandler::handleWhoisCommand(Client *client, const std::string &command) { std::istringstream iss(command); std::string cmd, target;