diff --git a/ft_irc/.vscode/settings.json b/ft_irc/.vscode/settings.json deleted file mode 100644 index c875477..0000000 --- a/ft_irc/.vscode/settings.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "files.associations": { - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "cctype": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "compare": "cpp", - "concepts": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "map": "cpp", - "string": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "random": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "initializer_list": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "new": "cpp", - "numbers": "cpp", - "ostream": "cpp", - "sstream": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "typeinfo": "cpp" - } -} \ No newline at end of file diff --git a/ft_irc/Makefile b/ft_irc/Makefile deleted file mode 100644 index 2b1e7a2..0000000 --- a/ft_irc/Makefile +++ /dev/null @@ -1,53 +0,0 @@ -# **************************************************************************** # -# # -# ::: :::::::: # -# Makefile :+: :+: :+: # -# +:+ +:+ +:+ # -# By: fgras-ca +#+ +:+ +#+ # -# +#+#+#+#+#+ +#+ # -# Created: 2024/05/09 13:54:36 by fgras-ca #+# #+# # -# Updated: 2024/05/12 18:19:36 by fgras-ca ### ########.fr # -# # -# **************************************************************************** # - -# Nom de l'exécutable à générer -NAME := ircserv - -# Compilateur C++ et options de compilation -CXX := g++ -CXXFLAGS := -Wall -Wextra -Werror -std=c++98 - -# Dossiers -SRC_DIR := src -OBJ_DIR := build -INC_DIR := include - -# Trouver les fichiers source (.cpp) et les transformer en fichiers objet (.o) -SOURCES := $(wildcard $(SRC_DIR)/*.cpp) -OBJECTS := $(SOURCES:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o) - -# Inclure les headers du dossier 'include' -CPPFLAGS := -I$(INC_DIR) - -# L'exécutable final dépend des fichiers objet -$(NAME): $(OBJECTS) - $(CXX) $(OBJECTS) -o $@ - -# Compilation des fichiers source en fichiers objet -$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp - @mkdir -p $(OBJ_DIR) - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -g -c $< -o $@ - -# Commande pour nettoyer le projet (supprimer les fichiers objet et l'exécutable) -clean: - @rm -rf $(OBJ_DIR) - -# Commande pour supprimer tout ce qui a été construit, reconstruire tout -fclean: clean - @rm -f $(NAME) - -# Commande pour recompiler tout le projet -re: fclean $(NAME) - -# Éviter les conflits de noms avec des fichiers -.PHONY: clean fclean re diff --git a/ft_irc/build/Channel.o b/ft_irc/build/Channel.o deleted file mode 100644 index 7ea8f38..0000000 Binary files a/ft_irc/build/Channel.o and /dev/null differ diff --git a/ft_irc/build/Client.o b/ft_irc/build/Client.o deleted file mode 100644 index 9394c62..0000000 Binary files a/ft_irc/build/Client.o and /dev/null differ diff --git a/ft_irc/build/CommandHandler.o b/ft_irc/build/CommandHandler.o deleted file mode 100644 index 89ea189..0000000 Binary files a/ft_irc/build/CommandHandler.o and /dev/null differ diff --git a/ft_irc/build/Server.o b/ft_irc/build/Server.o deleted file mode 100644 index a9b3a58..0000000 Binary files a/ft_irc/build/Server.o and /dev/null differ diff --git a/ft_irc/build/main.o b/ft_irc/build/main.o deleted file mode 100644 index 75ee419..0000000 Binary files a/ft_irc/build/main.o and /dev/null differ diff --git a/ft_irc/build/utilities.o b/ft_irc/build/utilities.o deleted file mode 100644 index 9d392e5..0000000 Binary files a/ft_irc/build/utilities.o and /dev/null differ diff --git a/ft_irc/include/Client.hpp b/ft_irc/include/Client.hpp deleted file mode 100644 index ad81e52..0000000 --- a/ft_irc/include/Client.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Client.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:07:00 by fgras-ca #+# #+# */ -/* Updated: 2024/05/13 17:48:53 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef CLIENT_HPP -#define CLIENT_HPP - -#include -#include -#include -#include -#include -#include "Server.hpp" - - - -class Client { -public: - Client(); - Client(int socket, const std::string& nickname = "defaultNickName", const std::string& username = "defaultUserName"); - ~Client(); - - void sendMessage(const std::string& message); - std::string receiveMessage(); - void setNickname(const std::string& newNickname); - std::string getNickname() const; // Ajout de la méthode getNickname - int getSocket() const; - void setUsername(const std::string& newUsername); - void setRealname(const std::string& newRealname); - -private: - - int socket; - std::string nickname; // Assurez-vous que cette donnée membre est accessible via getNickname - std::string username; -}; - -#endif diff --git a/ft_irc/include/CommandHandler.hpp b/ft_irc/include/CommandHandler.hpp deleted file mode 100644 index cd0ed1d..0000000 --- a/ft_irc/include/CommandHandler.hpp +++ /dev/null @@ -1,51 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* CommandHandler.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:19:30 by fgras-ca #+# #+# */ -/* Updated: 2024/05/12 17:48:14 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef COMMANDHANDLER_HPP -#define COMMANDHANDLER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Client.hpp" -#include "Channel.hpp" -#include "Utilities.hpp" - - -class Client; -class Channel; - -class CommandHandler -{ -public: - CommandHandler(); - ~CommandHandler(); - void handleCommand(const std::string& commandLine, Client* client); - -private: - std::map channels; - std::vector split(const std::string& s, char delimiter); - - void handleJoin(const std::string& command, Client* client); - void handlePart(const std::string& command, Client* client); - void handleNick(const std::string& command, Client* client); - void handlePrivmsg(const std::string& command, Client* client); - //void handleQuit(Client* client); -}; - -#endif // COMMANDHANDLER_HPP diff --git a/ft_irc/include/Server.hpp b/ft_irc/include/Server.hpp deleted file mode 100644 index cb2057e..0000000 --- a/ft_irc/include/Server.hpp +++ /dev/null @@ -1,72 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Server.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:01:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/13 19:00:18 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef SERVER_HPP -#define SERVER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // Include this for fcntl and O_NONBLOCK -#include - - -#include "color.hpp" -#include "Client.hpp" -#include "CommandHandler.hpp" - -class Client; -class CommandHandler; - -class Server -{ -public: - Server(int port, const std::string& password); - ~Server(); - void run(); - bool initialize(); - void closeClient(int sockfd); - -private: - int port; // Port d'écoute - std::string password; // Mot de passe pour les clients se connectant - - bool running; // État d'exécution du serveur - int listener; // Socket d'écoute du serveur - int fdmax; - int epoll_fd; // Descripteur pour l'instance epoll - static const int MAX_EVENTS = 10; // Nombre maximal d'événements traités à chaque appel à epoll_wait - fd_set master_set; // Ensemble principal des descripteurs de fichiers pour select - std::map clients; // Mapping de socket à Client - std::map handlers; // CommandHandler pour chaque client - - void acceptNewClient(); - bool handleClientActivity(int sockfd); - bool getlineFromClient(Client* client, std::string& line); - void handleIRCMessages(Client* client, CommandHandler& cmdHandler); - bool processInitialCommands(Client* client); - void handleNickAndUserCommands(const std::string& line, size_t passEnd, Client* client); - void setNonBlocking(int sockfd); -}; - -#endif // SERVER_HPP diff --git a/ft_irc/include/Utilities.hpp b/ft_irc/include/Utilities.hpp deleted file mode 100644 index 0b5ef13..0000000 --- a/ft_irc/include/Utilities.hpp +++ /dev/null @@ -1,28 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Utilities.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:22:54 by fgras-ca #+# #+# */ -/* Updated: 2024/05/11 13:34:54 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef UTILITIES_HPP -#define UTILITIES_HPP - -#include -#include -#include -#include -#include -#include - -namespace Utilities { - // Split a string by a delimiter and return a vector of substrings - std::vector split(const std::string& str, char delimiter); -} - -#endif // UTILITIES_HPP diff --git a/ft_irc/include/color.hpp b/ft_irc/include/color.hpp deleted file mode 100644 index 09ee27d..0000000 --- a/ft_irc/include/color.hpp +++ /dev/null @@ -1,27 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* color.hpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/12 16:31:27 by fgras-ca #+# #+# */ -/* Updated: 2024/05/12 16:35:03 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#ifndef COLOR_HPP -#define COLOR_HPP - -# define RESET "\033[0m" -# define GRAY "\033[0;90m" -# define RED "\033[0;91m" -# define GREEN "\033[0;92m" -# define YELLOW "\033[0;93m" -# define BLUE "\033[0;94m" -# define MAGENTA "\033[0;95m" -# define CYAN "\033[0;96m" -# define WHITE "\033[0;97m" -# define ORANGE "\033[38;5;214m" - -#endif \ No newline at end of file diff --git a/ft_irc/ircserv b/ft_irc/ircserv deleted file mode 100755 index 406f5f6..0000000 Binary files a/ft_irc/ircserv and /dev/null differ diff --git a/ft_irc/src/Channel.cpp b/ft_irc/src/Channel.cpp deleted file mode 100644 index d50b9d1..0000000 --- a/ft_irc/src/Channel.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Channel.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:08:13 by fgras-ca #+# #+# */ -/* Updated: 2024/05/12 17:56:26 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "Channel.hpp" -#include - -Channel::Channel(const std::string& name) : name(name) {} - -void Channel::addClient(Client* client) { - std::cout << "Adding client to channel " << name << std::endl; - clients.push_back(client); - std::cout << "Client added. Total clients: " << clients.size() << std::endl; -} -void Channel::removeClient(Client* client) { - clients.erase(std::remove(clients.begin(), clients.end(), client), clients.end()); -} - -void Channel::broadcastMessage(const std::string& message, Client* sender) { - std::cout << "Broadcasting message in channel " << name << " from " << sender->getNickname() << std::endl; - for (size_t i = 0; i < clients.size(); ++i) { - if (clients[i] != sender) { - std::cout << "Sending message to " << clients[i]->getNickname() << std::endl; - clients[i]->sendMessage(message); - } - } -} diff --git a/ft_irc/src/Client.cpp b/ft_irc/src/Client.cpp deleted file mode 100644 index b693821..0000000 --- a/ft_irc/src/Client.cpp +++ /dev/null @@ -1,70 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Client.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */ -/* Updated: 2024/05/13 16:59:32 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "Client.hpp" -#include -#include - -Client::Client() {} - -Client::Client(int socket, const std::string& nickname, const std::string& username) - : socket(socket), nickname(nickname), username(username) {} - -Client::~Client() { - close(socket); -} - -void Client::sendMessage(const std::string& message) { - std::cout << "Sending message: " << message << std::endl; - send(socket, message.c_str(), message.size(), 0); -} - -std::string Client::receiveMessage() { - char buffer[1024]; - std::memset(buffer, 0, sizeof(buffer)); - int len = recv(socket, buffer, sizeof(buffer) - 1, 0); - if (len > 0) { - buffer[len] = '\0'; - std::string received(buffer); - received.erase(std::remove(received.begin(), received.end(), '\r'), received.end()); - received.erase(std::remove(received.begin(), received.end(), '\n'), received.end()); - std::cout << "Received message: [" << received << "]" << std::endl; - return received; - } else if (len == 0) { - std::cout << "Connection closed by the peer." << std::endl; - } else { - std::cerr << "recv error: " << strerror(errno) << std::endl; - } - return ""; -} - - -void Client::setNickname(const std::string& newNickname) { - nickname = newNickname; -} - -std::string Client::getNickname() const { - return nickname; -} - -int Client::getSocket() const { - return socket; -} - -void Client::setUsername(const std::string& newUsername) { - nickname = newUsername; -} - -void Client::setRealname(const std::string& newRealname) { - // Assurez-vous d'avoir un membre `realname` dans Client - username = newRealname; -} \ No newline at end of file diff --git a/ft_irc/src/CommandHandler.cpp b/ft_irc/src/CommandHandler.cpp deleted file mode 100644 index db38271..0000000 --- a/ft_irc/src/CommandHandler.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* CommandHandler.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:19:15 by fgras-ca #+# #+# */ -/* Updated: 2024/05/12 18:07:48 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "CommandHandler.hpp" - -CommandHandler::CommandHandler() {} - -CommandHandler::~CommandHandler() { - for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { - delete it->second; - } - channels.clear(); -} - -void CommandHandler::handleCommand(const std::string& commandLine, Client* client) { - std::istringstream stream(commandLine); - std::string command; - stream >> command; - - if (command == "JOIN") { - handleJoin(commandLine, client); - } else if (command == "PART") { - handlePart(commandLine, client); - } else if (command == "NICK") { - handleNick(commandLine, client); - } else if (command == "PRIVMSG") { - handlePrivmsg(commandLine, client); - } -} - -void CommandHandler::handleJoin(const std::string& command, Client* client) { - std::cout << "Entering handleJoin with command: " << command << std::endl; - std::vector tokens = split(command, ' '); - if (tokens.size() > 1) { - std::string channelName = tokens[1]; - - // Log before accessing the map - std::cout << "Checking if channel exists: " << channelName << std::endl; - - // Check if channel exists - std::map::iterator it = channels.find(channelName); - if (it == channels.end()) { - // If not, create a new channel - std::cout << "Creating new channel: " << channelName << std::endl; - channels[channelName] = new Channel(channelName); - } else { - std::cout << "Channel already exists: " << channelName << std::endl; - } - - // Add client to channel and send join message - channels[channelName]->addClient(client); - channels[channelName]->broadcastMessage("JOIN " + channelName, client); - } else { - std::cerr << "Invalid JOIN command format." << std::endl; - } -} - - - -void CommandHandler::handlePart(const std::string& command, Client* client) { - std::vector tokens = split(command, ' '); - if (tokens.size() > 1) { - std::string channelName = tokens[1]; - if (channels.find(channelName) != channels.end()) { - channels[channelName]->removeClient(client); - } - } -} - -void CommandHandler::handleNick(const std::string& command, Client* client) { - std::vector tokens = split(command, ' '); - if (tokens.size() > 1) { - client->setNickname(tokens[1]); - } -} - -void CommandHandler::handlePrivmsg(const std::string& command, Client* client) { - std::vector tokens = split(command, ' '); - if (tokens.size() > 2) { - std::string target = tokens[1]; - std::string message = command.substr(command.find(':') + 1); - if (channels.find(target) != channels.end()) { - channels[target]->broadcastMessage("PRIVMSG " + target + " :" + message, client); - } - } -} - -std::vector CommandHandler::split(const std::string& s, char delimiter) { - std::vector tokens; - std::string token; - std::istringstream tokenStream(s); - while (std::getline(tokenStream, token, delimiter)) { - tokens.push_back(token); - } - return tokens; -} diff --git a/ft_irc/src/Server.cpp b/ft_irc/src/Server.cpp deleted file mode 100644 index 0ba6f90..0000000 --- a/ft_irc/src/Server.cpp +++ /dev/null @@ -1,351 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* Server.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:01:34 by fgras-ca #+# #+# */ -/* Updated: 2024/05/13 19:19:46 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "Server.hpp" - -Server::Server(int port, const std::string& password) : port(port), password(password), running(false) - { - FD_ZERO(&master_set); - std::cout << GREEN << "Server constructed for port: " << RESET << port << std::endl; - } - -Server::~Server() -{ - std::map::iterator it; - for (it = clients.begin(); it != clients.end(); ++it) - { - delete it->second; - close(it->first); - } - std::map::iterator itHandler; - for (itHandler = handlers.begin(); itHandler != handlers.end(); ++itHandler) - { - delete itHandler->second; - } - std::cout << RED << "Server destroyed, all clients closed." << RESET << std::endl; -} - -bool Server::initialize() -{ - struct sockaddr_in server_addr; - listener = socket(AF_INET, SOCK_STREAM, 0); - if (listener == -1) - { - std::cerr << RED << "Error creating socket: " << strerror(errno) << RESET << std::endl; - return false; - } - - int opt = 1; - if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1) - { - std::cerr << RED << "Error setting socket options: " << strerror(errno) << RESET << std::endl; - close(listener); - return false; - } - - 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(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) - { - std::cerr << RED << "Error binding socket: " << strerror(errno) << RESET << std::endl; - close(listener); - return false; - } - - if (listen(listener, 10) == -1) - { - std::cerr << RED << "Error listening: " << strerror(errno) << RESET << std::endl; - close(listener); - return false; - } - - FD_SET(listener, &master_set); - fdmax = listener; // Set the initial max file descriptor to listener - running = true; - - std::cout << GREEN << "Server initialized and listening on port: " << RESET << port << std::endl; - return true; -} - -bool Server::getlineFromClient(Client* client, std::string& line) { - char buffer[1024]; - while (true) { - memset(buffer, 0, sizeof(buffer)); - int len = recv(client->getSocket(), buffer, sizeof(buffer) - 1, 0); - - if (len > 0) { - buffer[len] = '\0'; - line = std::string(buffer); - line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); - line.erase(std::remove(line.begin(), line.end(), '\n'), line.end()); - std::cout << GREEN << "Received line: " << line << RESET << std::endl; - return true; - } else if (len == 0) { - std::cout << RED << "Client disconnected." << RESET << std::endl; - return false; - } else { - if (errno == EWOULDBLOCK || errno == EAGAIN) { - // Si non-bloquant et aucune donnée n'est disponible, attendez un peu et réessayez - std::cout << YELLOW << "No data available yet, non-blocking mode." << RESET << std::endl; - usleep(100000); // attendre 100 ms - continue; // Continuez à essayer de lire - } else { - std::cerr << RED << "Error reading from client socket: " << strerror(errno) << RESET << std::endl; - return false; - } - } - } -} - - - - -bool Server::processInitialCommands(Client* client) { - std::string line; - bool isAuthenticated = false; - - if (!getlineFromClient(client, line) || line.empty()) { - std::cout << RED << "No initial commands received or connection lost." << RESET << std::endl; - return false; - } - - std::cout << MAGENTA << "Processing initial line: " << RESET << line << std::endl; - - // Extrait les parties nécessaires de la ligne - size_t passIndex = line.find("PASS"); - size_t nickIndex = line.find("NICK"); - size_t userIndex = line.find("USER"); - - if (passIndex == std::string::npos || nickIndex == std::string::npos || userIndex == std::string::npos) { - std::cerr << "Command format error." << std::endl; - return false; - } - - // Extraction des données - std::string password = line.substr(passIndex + 4, nickIndex - (passIndex + 4)); - std::string nickname = line.substr(nickIndex + 4, userIndex - (nickIndex + 4)); - std::string userAndRealName = line.substr(userIndex + 4); // Contient le username et le realname - size_t spaceIndex = userAndRealName.find(' '); - std::string username = userAndRealName.substr(0, spaceIndex); - std::string realname = userAndRealName.substr(spaceIndex + 1); - - // Retire les espaces potentiels autour des informations - password.erase(remove(password.begin(), password.end(), ' '), password.end()); - nickname.erase(remove(nickname.begin(), nickname.end(), ' '), nickname.end()); - username.erase(remove(username.begin(), username.end(), ' '), username.end()); - - // Validation du mot de passe - if (password != this->password) { - client->sendMessage("ERROR :Wrong password\r\n"); - std::cout << RED << "Authentication failed for password: " << password << RESET << std::endl; - return false; - } - - // Set up client details if password is correct - client->setNickname(nickname); - client->setUsername(username); - client->setRealname(realname); - isAuthenticated = true; - - std::cout << GREEN << "Authentication successful, client setup complete." << RESET << std::endl; - std::cout << GREEN << "Client details - Nickname: " << nickname << ", Username: " << username << ", Realname: " << realname << RESET << std::endl; - - // Proceed to handle IRC messages if authenticated - if (isAuthenticated) { - handleIRCMessages(client, *new CommandHandler()); - } - return isAuthenticated; -} - - - - -// Handle IRC commands -void Server::handleIRCMessages(Client* client, CommandHandler& cmdHandler) -{ - std::string line; - while (getlineFromClient(client, line) && !line.empty()) - { - std::cout << YELLOW << "Handling IRC message: " << RESET << line << std::endl; - cmdHandler.handleCommand(line, client); - if (line.find("QUIT") != std::string::npos) - { - std::cout << RED << "Client Socket (" << client->getSocket() << ") requested to quit." << RESET << std::endl; - closeClient(client->getSocket()); // Assuming you have a method to close clients - break; - } - } -} - -void Server::run() -{ - fd_set read_fds; - struct timeval timeout; - - if (!initialize()) - { - std::cerr << RED << "Server initialization failed. Exiting..." << RESET << std::endl; - return; - } - - std::cout << GREEN << "Server is running on port: " << RESET << port << std::endl; - while (running) - { - FD_ZERO(&read_fds); - FD_SET(listener, &read_fds); - std::map::iterator it; - for (it = clients.begin(); it != clients.end(); ++it) - { - FD_SET(it->first, &read_fds); - } - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - std::cout << ORANGE << "Waiting for select..." << RESET << std::endl; - int selectResult = select(fdmax + 1, &read_fds, NULL, NULL, &timeout); - - if (selectResult == -1) - { - perror("Select error"); - continue; - } - else if (selectResult == 0) - { - std::cout << GRAY << "Select timeout occurred, no activity." << RESET << std::endl; - continue; - } - - if (FD_ISSET(listener, &read_fds)) - { - acceptNewClient(); - } - - for (int i = 0; i <= fdmax; i++) - { - if (i != listener && FD_ISSET(i, &read_fds)) - { - if (!handleClientActivity(i)) - { - closeClient(i); - } - } - } - } -} - -void Server::acceptNewClient() { - struct sockaddr_in client_addr; - socklen_t addrlen = sizeof(client_addr); - std::cout << CYAN << "Prêt à accepter une nouvelle connexion..." << RESET << std::endl; - int newfd = accept(listener, (struct sockaddr *)&client_addr, &addrlen); - - if (newfd == -1) { - perror("Échec de l'acceptation"); - return; - } - - int flags = fcntl(newfd, F_GETFL, 0); - if (flags == -1) flags = 0; - fcntl(newfd, F_SETFL, flags | O_NONBLOCK); - - Client* newClient = new Client(newfd); - if (!newClient) { - std::cerr << RED << "Échec de la création d'une nouvelle instance Client." << RESET << std::endl; - close(newfd); - return; - } - - CommandHandler* newHandler = new CommandHandler(); - if (!newHandler) { - std::cerr << RED << "Échec de la création d'une nouvelle instance de CommandHandler." << RESET << std::endl; - delete newClient; - close(newfd); - return; - } - - clients[newfd] = newClient; - handlers[newfd] = newHandler; - FD_SET(newfd, &master_set); - if (newfd > fdmax) { - fdmax = newfd; - } - - std::cout << GREEN << "Nouveau client accepté: " << inet_ntoa(client_addr.sin_addr) << " sur fd: " << newfd << RESET << std::endl; - - if (!processInitialCommands(newClient)) { - std::cerr << "Échec du traitement des commandes initiales, fermeture de la connexion." << std::endl; - closeClient(newfd); - } -} - - - - -bool Server::handleClientActivity(int sockfd) { - Client* client = clients[sockfd]; - CommandHandler* cmdHandler = handlers[sockfd]; // Assurez-vous que cmdHandler est récupéré correctement - - if (!client || !cmdHandler) { - std::cerr << RED << "Client or CommandHandler not found for socket " << RESET << sockfd << std::endl; - return false; - } - - std::string line; - if (getlineFromClient(client, line) && !line.empty()) { - std::cout << GREEN << "Received message: [" << line << "]" << RESET << std::endl; - cmdHandler->handleCommand(line, client); - return true; - } else { - std::cerr << RED << "Client disconnected or error on socket: " << RESET << sockfd << std::endl; - return false; - } -} - - -void Server::closeClient(int sockfd) -{ - std::map::iterator it = clients.find(sockfd); - if (it != clients.end()) - { - delete it->second; - clients.erase(it); - } - - std::map::iterator handlerIt = handlers.find(sockfd); - if (handlerIt != handlers.end()) - { - delete handlerIt->second; - handlers.erase(handlerIt); - } - - close(sockfd); // Close the socket - FD_CLR(sockfd, &master_set); // Remove from the master set - - // Recalculate fdmax - if (sockfd == fdmax) - { - fdmax = listener; // Reset fdmax to the listener's socket - for (it = clients.begin(); it != clients.end(); ++it) - { - if (it->first > fdmax) - { - fdmax = it->first; - } - } - } - - std::cout << RED << "Closed client on socket: " << RESET << sockfd << std::endl; -} diff --git a/ft_irc/src/main.cpp b/ft_irc/src/main.cpp deleted file mode 100644 index da2371e..0000000 --- a/ft_irc/src/main.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* main.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:00:46 by fgras-ca #+# #+# */ -/* Updated: 2024/05/11 17:16:28 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "Server.hpp" - -int main(int argc, char* argv[]) { - if (argc != 3) { - std::cerr << "Usage: " << argv[0] << " " << std::endl; - return 1; - } - int port = std::atoi(argv[1]); - std::string password = argv[2]; - - Server ircServer(port, password); - ircServer.run(); // initialize() sera appelée au début de run() - - return 0; -} diff --git a/ft_irc/src/utilities.cpp b/ft_irc/src/utilities.cpp deleted file mode 100644 index c48b07c..0000000 --- a/ft_irc/src/utilities.cpp +++ /dev/null @@ -1,27 +0,0 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* utilities.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: fgras-ca +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:23:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/11 13:35:49 by fgras-ca ### ########.fr */ -/* */ -/* ************************************************************************** */ - -#include "Utilities.hpp" - -namespace Utilities { - -std::vector split(const std::string& str, char delimiter) { - std::vector tokens; - std::stringstream ss(str); - std::string token; - while (getline(ss, token, delimiter)) { - tokens.push_back(token); - } - return tokens; -} - -} diff --git a/ft_irc3/.vscode/settings.json b/ft_irc3/.vscode/settings.json index 137f792..4649905 100644 --- a/ft_irc3/.vscode/settings.json +++ b/ft_irc3/.vscode/settings.json @@ -48,7 +48,17 @@ "stdexcept": "cpp", "streambuf": "cpp", "typeinfo": "cpp", - "list": "cpp" + "list": "cpp", + "chrono": "cpp", + "condition_variable": "cpp", + "ctime": "cpp", + "set": "cpp", + "ratio": "cpp", + "mutex": "cpp", + "semaphore": "cpp", + "stop_token": "cpp", + "thread": "cpp", + "cinttypes": "cpp" }, "C_Cpp_Runner.cCompilerPath": "gcc", "C_Cpp_Runner.cppCompilerPath": "g++", diff --git a/ft_irc3/logs/irc_server.log b/ft_irc3/cmd similarity index 100% rename from ft_irc3/logs/irc_server.log rename to ft_irc3/cmd diff --git a/ft_irc3/includes/Channel.hpp b/ft_irc3/includes/Channel.hpp index 07693f1..66f689c 100644 --- a/ft_irc3/includes/Channel.hpp +++ b/ft_irc3/includes/Channel.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:41:35 by fgras-ca #+# #+# */ -/* Updated: 2024/05/15 12:48:40 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:08:13 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -16,23 +16,27 @@ #include #include #include +#include class Client; class Channel { public: - Channel(const std::string &name); - ~Channel(); + Channel(const std::string &name); + ~Channel(); - const std::string &getName() const; - void addClient(Client *client); - void removeClient(Client *client); - bool isEmpty() const; - const std::vector &getClients() const; + const std::string &getName() const; + void addClient(Client *client); + void removeClient(Client *client); + bool isEmpty() const; + const std::vector &getClients() const; + void addOperator(Client *client); + bool isOperator(Client *client) const; private: - std::string _name; - std::vector _clients; + std::string _name; + std::vector _clients; + std::vector _operators; }; #endif diff --git a/ft_irc3/includes/Client.hpp b/ft_irc3/includes/Client.hpp index 26fc493..0f7a33e 100644 --- a/ft_irc3/includes/Client.hpp +++ b/ft_irc3/includes/Client.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:15:42 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 18:18:02 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 17:21:39 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,32 +18,30 @@ class Client { public: - Client(int fd); + Client(int fd, const std::string &nickname, const std::string &user); - void setPassword(const std::string &password); - const std::string &getPassword() const; - - void setNickname(const std::string &nickname); - const std::string &getNickname() const; - - void setUser(const std::string &user); - const std::string &getUser() const; - - void setRealName(const std::string &realname); - const std::string &getRealName() const; - - bool isAuthenticated() const; - void authenticate(); - - int getFd() const; + int getFd() const; + const std::string &getNickname() const; + void setNickname(const std::string &nickname); + const std::string &getUser() const; + void setUser(const std::string &user); + const std::string &getPassword() const; + void setPassword(const std::string &password); + const std::string &getRealName() const; + void setRealName(const std::string &realname); + bool isAuthenticated() const; + void authenticate(); + bool isOperator() const; + void setOperator(bool isOperator); private: - int _fd; - std::string _password; - std::string _nickname; - std::string _user; - std::string _realname; - bool _authenticated; + int _fd; + std::string _nickname; + std::string _user; + std::string _password; + std::string _realname; + bool _authenticated; + bool _operator; }; #endif diff --git a/ft_irc3/includes/ClientManager.hpp b/ft_irc3/includes/ClientManager.hpp index 43e637b..4e6a1d9 100644 --- a/ft_irc3/includes/ClientManager.hpp +++ b/ft_irc3/includes/ClientManager.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 18:30:07 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 16:26:03 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 18:51:44 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -35,9 +35,11 @@ class ClientManager public: ClientManager(Server *server); void acceptClient(); + void broadcastChannelList(Client *client); void handleClient(int client_fd); void removeClient(int client_fd); + private: Server *_server; }; diff --git a/ft_irc3/includes/CommandHandler.hpp b/ft_irc3/includes/CommandHandler.hpp index d727419..1ae423b 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/16 17:35:46 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 17:10:38 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -18,12 +18,15 @@ #include "Client.hpp" #include "Channel.hpp" #include "AdditionalCommands.hpp" +#include "ModeWhoHandler.hpp" +#include "CommandHandler.hpp" #include #include #include class Server; +class ModeWhoHandler; class CommandHandler { diff --git a/ft_irc/include/Channel.hpp b/ft_irc3/includes/ModeWhoHandler.hpp similarity index 57% rename from ft_irc/include/Channel.hpp rename to ft_irc3/includes/ModeWhoHandler.hpp index f0b3895..6aa083b 100644 --- a/ft_irc/include/Channel.hpp +++ b/ft_irc3/includes/ModeWhoHandler.hpp @@ -1,36 +1,34 @@ /* ************************************************************************** */ /* */ /* ::: :::::::: */ -/* Channel.hpp :+: :+: :+: */ +/* ModeWhoHandler.hpp :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ -/* Created: 2024/05/09 14:07:50 by fgras-ca #+# #+# */ -/* Updated: 2024/05/11 16:20:58 by fgras-ca ### ########.fr */ +/* Created: 2024/05/17 16:08:48 by fgras-ca #+# #+# */ +/* Updated: 2024/05/17 18:08:06 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ -#ifndef CHANNEL_HPP -#define CHANNEL_HPP +#ifndef MODEWHOHANDLER_HPP +#define MODEWHOHANDLER_HPP +#include "Server.hpp" #include "Client.hpp" -#include -#include -#include +#include "Channel.hpp" +#include "Utils.hpp" -class Client; +class Server; - -class Channel { +class ModeWhoHandler +{ public: - Channel(const std::string& name); - void addClient(Client* client); - void removeClient(Client* client); - void broadcastMessage(const std::string& message, Client* sender); + ModeWhoHandler(Server *server); + void handleModeCommand(Client *client, const std::string &command); + void handleWhoCommand(Client *client, const std::string &command); private: - std::string name; - std::vector clients; + Server *_server; }; #endif diff --git a/ft_irc3/includes/Server.hpp b/ft_irc3/includes/Server.hpp index c4d0dda..3dd93e3 100644 --- a/ft_irc3/includes/Server.hpp +++ b/ft_irc3/includes/Server.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:15:13 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 17:40:34 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:03:06 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -51,6 +51,9 @@ public: std::map &getChannels(); std::map &getClients(); const std::string &getPassword() const; + void broadcast(const std::string &message); + Client* getClientByName(const std::string &name); // Ajoutez cette méthode + void sendChannelListToClient(Client *client); protected: diff --git a/ft_irc3/ircserv b/ft_irc3/ircserv deleted file mode 100755 index ac98a32..0000000 Binary files a/ft_irc3/ircserv and /dev/null differ diff --git a/ft_irc3/obj/AdditionalCommands.o b/ft_irc3/obj/AdditionalCommands.o deleted file mode 100644 index 75cfa4b..0000000 Binary files a/ft_irc3/obj/AdditionalCommands.o and /dev/null differ diff --git a/ft_irc3/obj/Channel.o b/ft_irc3/obj/Channel.o deleted file mode 100644 index 6fa4de2..0000000 Binary files a/ft_irc3/obj/Channel.o and /dev/null differ diff --git a/ft_irc3/obj/Client.o b/ft_irc3/obj/Client.o deleted file mode 100644 index f5bdb3d..0000000 Binary files a/ft_irc3/obj/Client.o and /dev/null differ diff --git a/ft_irc3/obj/ClientManager.o b/ft_irc3/obj/ClientManager.o deleted file mode 100644 index 2ff931a..0000000 Binary files a/ft_irc3/obj/ClientManager.o and /dev/null differ diff --git a/ft_irc3/obj/CommandHandler.o b/ft_irc3/obj/CommandHandler.o deleted file mode 100644 index b954b0e..0000000 Binary files a/ft_irc3/obj/CommandHandler.o and /dev/null differ diff --git a/ft_irc3/obj/Server.o b/ft_irc3/obj/Server.o deleted file mode 100644 index 58a0b4d..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/obj/main.o b/ft_irc3/obj/main.o deleted file mode 100644 index 3beabb4..0000000 Binary files a/ft_irc3/obj/main.o and /dev/null differ diff --git a/ft_irc3/src/AdditionalCommands.cpp b/ft_irc3/src/AdditionalCommands.cpp index 148f0cb..ddec897 100644 --- a/ft_irc3/src/AdditionalCommands.cpp +++ b/ft_irc3/src/AdditionalCommands.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/16 15:27:29 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 16:41:53 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:15:14 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -64,19 +64,21 @@ void handleNickCommand(Server *server, Client *client, const std::string &comman server->log(ss.str(), GREEN); } -// Fonction pour gérer la commande PRIVMSG 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); + + // 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(); - std::map &clients = server->getClients(); + // Si la cible est un canal if (channels.find(target) != channels.end()) { Channel *channel = channels[target]; @@ -84,6 +86,7 @@ void handlePrivmsgCommand(Server *server, Client *client, const std::string &com 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; @@ -92,17 +95,23 @@ void handlePrivmsgCommand(Server *server, Client *client, const std::string &com } } } - else if (clients.find(atoi(target.c_str())) != clients.end()) - { - Client *targetClient = clients[atoi(target.c_str())]; - std::stringstream privMsg; - privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n"; - server->sendToClient(targetClient->getFd(), privMsg.str()); - } + // Si la cible est un utilisateur else { - std::stringstream ss; - ss << ":server 401 " << client->getNickname() << " " << target << " :No such nick/channel\r\n"; - server->sendToClient(client->getFd(), ss.str()); + 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()); + } } } diff --git a/ft_irc3/src/Channel.cpp b/ft_irc3/src/Channel.cpp index 9a2bf89..1f5b010 100644 --- a/ft_irc3/src/Channel.cpp +++ b/ft_irc3/src/Channel.cpp @@ -6,16 +6,15 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:42:57 by fgras-ca #+# #+# */ -/* Updated: 2024/05/15 12:54:40 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:08:28 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Channel.hpp" #include "Client.hpp" -#include Channel::Channel(const std::string &name) - : _name(name) + : _name(name) { } @@ -25,25 +24,38 @@ Channel::~Channel() const std::string &Channel::getName() const { - return _name; + return _name; } void Channel::addClient(Client *client) { - _clients.push_back(client); + _clients.push_back(client); } void Channel::removeClient(Client *client) { - _clients.erase(std::remove(_clients.begin(), _clients.end(), client), _clients.end()); + _clients.erase(std::remove(_clients.begin(), _clients.end(), client), _clients.end()); } bool Channel::isEmpty() const { - return _clients.empty(); + return _clients.empty(); } const std::vector &Channel::getClients() const { - return _clients; + return _clients; +} + +void Channel::addOperator(Client *client) +{ + if (std::find(_operators.begin(), _operators.end(), client) == _operators.end()) + { + _operators.push_back(client); + } +} + +bool Channel::isOperator(Client *client) const +{ + return std::find(_operators.begin(), _operators.end(), client) != _operators.end(); } diff --git a/ft_irc3/src/Client.cpp b/ft_irc3/src/Client.cpp index f071dbd..caaa524 100644 --- a/ft_irc3/src/Client.cpp +++ b/ft_irc3/src/Client.cpp @@ -6,72 +6,83 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:42 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 18:18:19 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 17:20:02 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Client.hpp" -Client::Client(int fd) - : _fd(fd), _authenticated(false) +Client::Client(int fd, const std::string &nickname, const std::string &user) + : _fd(fd), _nickname(nickname), _user(user), _authenticated(false), _operator(false) { } -void Client::setPassword(const std::string &password) -{ - _password = password; -} - -const std::string &Client::getPassword() const -{ - return _password; -} - -void Client::setNickname(const std::string &nickname) -{ - _nickname = nickname; -} - -const std::string &Client::getNickname() const -{ - return _nickname; -} - -void Client::setUser(const std::string &user) -{ - _user = user; -} - -const std::string &Client::getUser() const -{ - return _user; -} - -void Client::setRealName(const std::string &realname) -{ - _realname = realname; -} - -const std::string &Client::getRealName() const -{ - return _realname; -} - -bool Client::isAuthenticated() const -{ - return _authenticated; -} - -void Client::authenticate() -{ - _authenticated = true; -} - int Client::getFd() const { - return _fd; + return _fd; } +const std::string &Client::getNickname() const +{ + return _nickname; +} + +void Client::setNickname(const std::string &nickname) +{ + _nickname = nickname; +} + +const std::string &Client::getUser() const +{ + return _user; +} + +void Client::setUser(const std::string &user) +{ + _user = user; +} + +const std::string &Client::getPassword() const +{ + return _password; +} + +void Client::setPassword(const std::string &password) +{ + _password = password; +} + +const std::string &Client::getRealName() const +{ + return _realname; +} + +void Client::setRealName(const std::string &realname) +{ + _realname = realname; +} + +bool Client::isAuthenticated() const +{ + return _authenticated; +} + +void Client::authenticate() +{ + _authenticated = true; +} + +bool Client::isOperator() const +{ + return _operator; +} + +void Client::setOperator(bool isOperator) +{ + _operator = isOperator; +} + + diff --git a/ft_irc3/src/ClientManager.cpp b/ft_irc3/src/ClientManager.cpp index 451d870..9f39981 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/16 16:25:50 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 18:53:09 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -22,11 +22,11 @@ void ClientManager::acceptClient() int client_fd = accept(_server->_server_fd, NULL, NULL); if (client_fd < 0) { - _server->log("Accept failed.", RED); + _server->log("Failed to accept client.", RED); return; } - fcntl(client_fd, F_SETFL, O_NONBLOCK); - _server->_clients[client_fd] = new Client(client_fd); + + _server->_clients[client_fd] = new Client(client_fd, "", ""); // Initialize with default values struct pollfd client_pollfd; client_pollfd.fd = client_fd; client_pollfd.events = POLLIN; @@ -35,7 +35,16 @@ void ClientManager::acceptClient() std::stringstream ss; ss << "Client connected: " << client_fd; _server->log(ss.str(), GREEN); - _server->sendToClient(client_fd, ":server NOTICE * :Connected to the server\r\n"); // Debug message +} + +void ClientManager::broadcastChannelList(Client *client) { + std::map &channels = _server->getChannels(); + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { + std::stringstream channelMsg; + channelMsg << ":server 322 " << client->getNickname() << " " << it->first << " :Existing channel\r\n"; + _server->sendToClient(client->getFd(), channelMsg.str()); + } + _server->sendToClient(client->getFd(), ":server 323 " + client->getNickname() + " :End of /LIST\r\n"); } void ClientManager::handleClient(int client_fd) @@ -65,6 +74,7 @@ void ClientManager::handleClient(int client_fd) line.erase(std::remove(line.begin(), line.end(), '\n'), line.end()); _server->_commandHandler->handleCommand(client, line); + broadcastChannelList(_server->_clients[client_fd]); } } diff --git a/ft_irc3/src/CommandHandler.cpp b/ft_irc3/src/CommandHandler.cpp index fecc912..36d3a07 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/16 19:34:36 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:05:16 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -27,14 +27,16 @@ void CommandHandler::handleCommand(Client *client, const std::string &command) } std::string commandType = tokens[0]; - - if (commandType == "PASS") + if (commandType == "CAP") + {} + else if (commandType == "PASS") { if (tokens.size() > 1 && tokens[1] == _server->_password) { client->setPassword(tokens[1]); - _server->sendToClient(client->getFd(), ":server 001 " + client->getNickname() + " :Password accepted\r\n"); + _server->sendToClient(client->getFd(), ":server 001 " + client->getNickname() + " :Password accepted!\r\n"); _server->log("Client " + client->getNickname() + " provided correct password.", GREEN); + _server->sendChannelListToClient(client); } else { @@ -62,8 +64,12 @@ void CommandHandler::handleCommand(Client *client, const std::string &command) if (client->getPassword() == _server->_password && !client->getNickname().empty()) { client->authenticate(); - _server->sendToClient(client->getFd(), ":server 001 " + client->getNickname() + " :Welcome to the IRC server\r\n"); + std::stringstream welcomeMsg; + welcomeMsg << ":server 001 " << client->getNickname() << " :Welcome to the IRC server!\r\n"; + _server->sendToClient(client->getFd(), welcomeMsg.str()); + _server->log("Client " + client->getNickname() + " authenticated.", GREEN); + _server->sendChannelListToClient(client); } } } @@ -101,6 +107,16 @@ void CommandHandler::processCommand(Client *client, const std::string &command) { 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.handleWhoCommand(client, command); + } else { std::stringstream ss; @@ -116,6 +132,9 @@ void CommandHandler::handleJoinCommand(Client *client, const std::string &channe { _server->getChannels()[channelName] = new Channel(channelName); _server->log("Channel created: " + channelName, GREEN); + + // Notifier tous les clients de la création du canal + _server->broadcast(":server NOTICE * :New channel created: " + channelName + "\r\n"); } Channel *channel = _server->getChannels()[channelName]; channel->addClient(client); @@ -136,6 +155,9 @@ void CommandHandler::handleJoinCommand(Client *client, const std::string &channe _server->log(ss.str(), MAGENTA); } + + + std::string CommandHandler::getUsersList(Channel *channel) { std::vector clients = channel->getClients(); diff --git a/ft_irc3/src/ModeWhoHandler.cpp b/ft_irc3/src/ModeWhoHandler.cpp new file mode 100644 index 0000000..cbc98a2 --- /dev/null +++ b/ft_irc3/src/ModeWhoHandler.cpp @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ModeWhoHandler.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/17 16:09:20 by fgras-ca #+# #+# */ +/* Updated: 2024/05/17 18:24:34 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ModeWhoHandler.hpp" +#include "Channel.hpp" +#include +#include + +// Couleurs ANSI pour les logs +#define RESET "\033[0m" +#define GREEN "\033[32m" +#define YELLOW "\033[33m" +#define RED "\033[31m" +#define BLUE "\033[34m" +#define MAGENTA "\033[35m" + +ModeWhoHandler::ModeWhoHandler(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(), ":server 403 " + client->getNickname() + " " + channelName + " :No such channel\r\n"); + 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(), ":" + client->getNickname() + " MODE " + channelName + " +o " + user + "\r\n"); + _server->log(GREEN "Client " + user + " is now an operator in channel " + channelName + RESET, GREEN); + } + else + { + _server->sendToClient(client->getFd(), ":server 401 " + client->getNickname() + " " + user + " :No such nick/channel\r\n"); + } + } + else + { + _server->sendToClient(client->getFd(), ":server 482 " + client->getNickname() + " " + channelName + " :You're not channel operator\r\n"); + } + } +} + +void ModeWhoHandler::handleWhoCommand(Client *client, const std::string &command) +{ + std::istringstream iss(command); + std::string cmd, channelName; + iss >> cmd >> channelName; + + std::map &channels = _server->getChannels(); + if (channels.find(channelName) == channels.end()) + { + _server->sendToClient(client->getFd(), ":server 403 " + client->getNickname() + " " + channelName + " :No such channel\r\n"); + return; + } + + Channel *channel = channels[channelName]; + std::vector channelClients = channel->getClients(); + + for (size_t i = 0; i < channelClients.size(); ++i) + { + std::stringstream whoMsg; + whoMsg << ":server 352 " << client->getNickname() << " " << channelName << " " << channelClients[i]->getNickname() << " " + << channelClients[i]->getUser() << " " << _server->getPassword() << " " << channelClients[i]->getRealName() << "\r\n"; + _server->sendToClient(client->getFd(), whoMsg.str()); + } + + std::stringstream endOfWhoMsg; + endOfWhoMsg << ":server 315 " << client->getNickname() << " " << channelName << " :End of /WHO list.\r\n"; + _server->sendToClient(client->getFd(), endOfWhoMsg.str()); +} diff --git a/ft_irc3/src/Server.cpp b/ft_irc3/src/Server.cpp index c40eb54..9f7d52e 100644 --- a/ft_irc3/src/Server.cpp +++ b/ft_irc3/src/Server.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/15 12:17:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/16 18:52:19 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/17 20:03:44 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -144,9 +144,10 @@ void Server::handleServerCommands() void Server::log(const std::string &message, const std::string &color) { - std::cout << color << message << RESET << 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); @@ -164,10 +165,17 @@ void Server::sendToClient(int client_fd, const std::string &message) } } - -std::map &Server::getClients() +const std::string &Server::getPassword() const { - return _clients; + return _password; +} + +void Server::broadcast(const std::string &message) +{ + for (std::map::iterator it = _clients.begin(); it != _clients.end(); ++it) + { + sendToClient(it->first, message); + } } std::map &Server::getChannels() @@ -175,11 +183,38 @@ std::map &Server::getChannels() return _channels; } -const std::string &Server::getPassword() const +std::map &Server::getClients() { - return _password; + return _clients; } +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 +} + +void Server::sendChannelListToClient(Client *client) +{ + std::map &channels = getChannels(); + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) + { + std::stringstream channelMsg; + channelMsg << ":server 322 " << client->getNickname() << " " << it->first << " :" << it->second->getClients().size() << "\r\n"; + sendToClient(client->getFd(), channelMsg.str()); + } + std::stringstream endOfListMsg; + endOfListMsg << ":server 323 " << client->getNickname() << " :End of /LIST\r\n"; + sendToClient(client->getFd(), endOfListMsg.str()); +} + + /* Explications des Fonctions Server::Server(int port, const std::string &password) diff --git a/ft_irc3/target b/ft_irc3/target new file mode 100644 index 0000000..e69de29