This commit is contained in:
2024-05-17 20:29:22 +02:00
parent aaa1457b61
commit 3660d41dea
45 changed files with 359 additions and 1091 deletions

View File

@@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<std::string, Channel *> &channels = server->getChannels();
std::map<int, Client *> &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());
}
}
}

View File

@@ -6,16 +6,15 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <algorithm>
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<Client *> &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();
}

View File

@@ -6,72 +6,83 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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;
}

View File

@@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<std::string, Channel *> &channels = _server->getChannels();
for (std::map<std::string, Channel *>::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]);
}
}

View File

@@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<Client *> clients = channel->getClients();

View File

@@ -0,0 +1,95 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* ModeWhoHandler.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <sstream>
#include <iostream>
// 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<std::string, Channel *> &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<std::string, Channel *> &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<Client *> 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());
}

View File

@@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<int, Client *> &Server::getClients()
const std::string &Server::getPassword() const
{
return _clients;
return _password;
}
void Server::broadcast(const std::string &message)
{
for (std::map<int, Client *>::iterator it = _clients.begin(); it != _clients.end(); ++it)
{
sendToClient(it->first, message);
}
}
std::map<std::string, Channel *> &Server::getChannels()
@@ -175,11 +183,38 @@ std::map<std::string, Channel *> &Server::getChannels()
return _channels;
}
const std::string &Server::getPassword() const
std::map<int, Client *> &Server::getClients()
{
return _password;
return _clients;
}
Client* Server::getClientByName(const std::string &name)
{
for (std::map<int, Client *>::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<std::string, Channel *> &channels = getChannels();
for (std::map<std::string, Channel *>::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)