This commit is contained in:
Ladebeze66 2024-05-21 20:47:18 +02:00
parent 0dc9f5c940
commit 9fea48a546
28 changed files with 427 additions and 252 deletions

View File

@ -5,8 +5,8 @@
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/16 15:23:58 by fgras-ca #+# #+# */
/* Updated: 2024/05/19 19:18:11 by fgras-ca ### ########.fr */
/* Created: 2024/05/21 18:09:05 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 19:46:40 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -16,8 +16,11 @@
#include "Client.hpp"
#include "Server.hpp"
#include "Channel.hpp"
#include "CommandHandler.hpp"
#include "Utils.hpp"
#include "RPL.hpp"
#include "Who.hpp"
#include <sstream>
#include <string>
#include <fstream>
@ -26,12 +29,20 @@
class Server;
class Client;
class Channel;
class CommandHandler;
void sendWelcomeMessages(Client *client, Server *server);
void sendMotd(Client *client, Server *server);
void broadcastChannelList(Client *client, Server *server);
void handlePartCommand(Server *server, Client *client, const std::string &command);
void handleNickCommand(Server *server, Client *client, const std::string &command);
void handlePrivmsgCommand(Server *server, Client *client, const std::string &command);
class AdditionalCommands
{
private:
Server *_server;
CommandHandler *_commandhandler;
public:
AdditionalCommands(Server *server);
void processCommand(Client *client, const std::string &command);
void broadcastChannelList(Client *client, Server *server);
void handlePartCommand(Server *server, Client *client, const std::string &command);
void handleNickCommand(Server *server, Client *client, const std::string &command);
void handlePrivmsgCommand(Server *server, Client *client, const std::string &command);
};
#endif // ADDITIONALCOMMANDS_HPP

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 12:41:35 by fgras-ca #+# #+# */
/* Updated: 2024/05/19 15:14:50 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 19:26:51 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -17,11 +17,16 @@
#include <vector>
#include <algorithm>
#include <set>
#include "RPL.hpp"
#include "RPL.hpp"
#include "Client.hpp"
#include "Server.hpp"
class Server;
class Client;
class Channel {
class Channel
{
public:
Channel(const std::string &name);
~Channel();
@ -33,6 +38,8 @@ public:
const std::vector<Client *> &getClients() const;
void addOperator(Client *client);
bool isOperator(Client *client) const;
bool hasClient(Client *client) const; // Ajouté
void broadcast(const std::string &message, Client *_client, Server *_server); // Ajouté
private:
std::string _name;
@ -40,4 +47,4 @@ private:
std::vector<Client *> _operators;
};
#endif
#endif // CHANNEL_HPP

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 12:15:42 by fgras-ca #+# #+# */
/* Updated: 2024/05/19 15:38:28 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 18:03:09 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 18:30:07 by fgras-ca #+# #+# */
/* Updated: 2024/05/19 18:56:44 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 18:01:47 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -19,7 +19,6 @@
#include "Channel.hpp"
#include "Server.hpp"
#include "CommandHandler.hpp"
#include "AdditionalCommands.hpp"
#include "RPL.hpp"
#include "Utils.hpp"

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 18:14:12 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 13:47:12 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 20:15:58 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -17,39 +17,42 @@
#include "Server.hpp"
#include "Client.hpp"
#include "Channel.hpp"
#include "AdditionalCommands.hpp"
#include "Who.hpp"
#include "CommandHandler.hpp"
#include "AdditionalCommands.hpp"
#include "RPL.hpp"
#include "Join.hpp"
#include "Welcome.hpp"
#include <string>
#include <sstream>
#include <algorithm>
class Server;
class ModeWhoHandler;
class AdditinalCommands;
class Client;
class Channel;
class WhoHandler;
class AdditionalCommands;
class CommandHandler
{
private:
Server *_server;
AdditionalCommands *_additionalCommands;
public:
CommandHandler(Server *server);
bool isValidNickname(const std::string& nickname);
bool isNicknameInUse(const std::string& nickname);
void handleNick(Client* client, const std::vector<std::string>& tokens);
bool isValidNickname(const std::string& nickname);
bool isNicknameInUse(const std::string& nickname);
void handleNick(Client* client, const std::vector<std::string>& tokens);
void handleUser(Client* client, const std::vector<std::string>& tokens);
void handlePingCommand(Client* client, const std::vector<std::string>& tokens);
void handleUser(Client* client, const std::vector<std::string>& tokens);
void handlePingCommand(Client* client, const std::vector<std::string>& tokens);
void handleCommand(Client *client, const std::string &command);
void handleCapCommand(Client* client, const std::vector<std::string>& tokens);
void handlePassCommand(Client* client, const std::vector<std::string>& tokens);
void handleCapCommand(Client* client, const std::vector<std::string>& tokens);
void handlePassCommand(Client* client, const std::vector<std::string>& tokens);
void handleQuitCommand(Client* client, const std::vector<std::string>& tokens);
void handleErrorCommand(Client* client, const std::string &message);
void processCommand(Client *client, const std::string &command);
void handleJoinCommand(Client *client, const std::string &channelName);
std::string getUsersList(Channel *channel);
};
#endif
#endif // COMMANDHANDLER_HPP

34
ft_irc3/includes/Join.hpp Normal file
View File

@ -0,0 +1,34 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Join.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/21 19:51:08 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 20:13:15 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef JOIN_HPP
#define JOIN_HPP
#include "Server.hpp"
#include "Client.hpp"
#include "Channel.hpp"
#include "RPL.hpp"
class Server;
class Client;
class Channel;
class JoinHandler
{
public:
void handleJoinCommand(Client *client, const std::string &channelName, Server *server);
private:
std::string getUsersList(Channel *channel);
};
#endif // JOIN_HPP

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 12:15:13 by fgras-ca #+# #+# */
/* Updated: 2024/05/19 21:13:24 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 19:44:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -38,6 +38,7 @@ class Client;
class Channel;
class ClientManager;
class CommandHandler;
class AdditionalCommands;
class Server
{
@ -56,6 +57,8 @@ public:
Client* getClientByName(const std::string &name); // Ajoutez cette méthode
void sendChannelListToClient(Client *client);
void disconnectClient(int clientFd);
bool MatchFd(const pollfd& pfd, int clientFd);
void removePollFd(int clientFd);
protected:

View File

@ -0,0 +1,27 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Welcome.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/21 19:53:17 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 19:53:24 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#ifndef WELCOME_HPP
#define WELCOME_HPP
#include "Client.hpp"
#include "Server.hpp"
#include <string>
class WelcomeHandler
{
public:
void sendWelcomeMessages(Client *client, Server *server);
void sendMotd(Client *client, Server *server);
};
#endif // WELCOME_HPP

View File

@ -6,7 +6,7 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/17 16:08:48 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 13:47:28 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 18:04:10 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */

BIN
ft_irc3/ircserv Executable file

Binary file not shown.

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
ft_irc3/obj/Join.o Normal file

Binary file not shown.

BIN
ft_irc3/obj/Server.o Normal file

Binary file not shown.

BIN
ft_irc3/obj/Utils.o Normal file

Binary file not shown.

BIN
ft_irc3/obj/Welcome.o Normal file

Binary file not shown.

BIN
ft_irc3/obj/Who.o Normal file

Binary file not shown.

View File

@ -6,44 +6,47 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/16 15:27:29 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 13:52:54 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 20:22:22 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"));
AdditionalCommands::AdditionalCommands(Server *server) : _server(server)
{}
sendMotd(client, server);
void AdditionalCommands::processCommand(Client *client, const std::string &command)
{
if (command.find("PART") == 0)
{
handlePartCommand(_server, client, command);
}
else if (command.find("PRIVMSG") == 0)
{
handlePrivmsgCommand(_server, client, command);
}
else if (command.find("WHO") == 0)
{
WhoHandler whoHandler(_server);
whoHandler.handleWhoCommand(client, command);
}
else if (command.find("WHOIS") == 0)
{
WhoHandler whoHandler(_server);
whoHandler.handleWhoisCommand(client, command);
}
else if (command.find("LIST") == 0)
{
broadcastChannelList(client, _server);
}
else
{
_server->sendToClient(client->getFd(), ERR_UNKNOWNCOMMAND(client, command));
_server->log("Message from client " + client->getNickname() + ": " + command, MAGENTA);
}
}
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)
void AdditionalCommands::broadcastChannelList(Client *client, Server *server)
{
std::map<std::string, Channel *> &channels = server->getChannels();
for (std::map<std::string, Channel *>::iterator it = channels.begin(); it != channels.end(); ++it)
@ -54,7 +57,7 @@ void broadcastChannelList(Client *client, Server *server)
}
// Fonction pour gérer la commande PART
void handlePartCommand(Server *server, Client *client, const std::string &command)
void AdditionalCommands::handlePartCommand(Server *server, Client *client, const std::string &command)
{
std::istringstream iss(command);
std::string cmd, channelName;
@ -87,25 +90,7 @@ void handlePartCommand(Server *server, Client *client, const std::string &comman
}
}
// 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::stringstream nickMsg;
nickMsg << ":" << client->getNickname() << " NICK " << newNick << "\r\n";
server->sendToClient(client->getFd(), nickMsg.str());
client->setNickname(newNick);
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)
void AdditionalCommands::handlePrivmsgCommand(Server *server, Client *client, const std::string &command)
{
std::istringstream iss(command);
std::string cmd, target, message;

View File

@ -6,21 +6,15 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 12:42:57 by fgras-ca #+# #+# */
/* Updated: 2024/05/17 20:08:28 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 19:27:42 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "Channel.hpp"
#include "Client.hpp"
Channel::Channel(const std::string &name)
: _name(name)
{
}
Channel::Channel(const std::string &name) : _name(name) {}
Channel::~Channel()
{
}
Channel::~Channel() {}
const std::string &Channel::getName() const
{
@ -49,13 +43,27 @@ const std::vector<Client *> &Channel::getClients() const
void Channel::addOperator(Client *client)
{
if (std::find(_operators.begin(), _operators.end(), client) == _operators.end())
{
_operators.push_back(client);
}
_operators.push_back(client);
}
bool Channel::isOperator(Client *client) const
{
return std::find(_operators.begin(), _operators.end(), client) != _operators.end();
}
bool Channel::hasClient(Client *client) const
{
return std::find(_clients.begin(), _clients.end(), client) != _clients.end();
}
void Channel::broadcast(const std::string &message, Client *_client, Server *server)
{
for (std::vector<Client *>::iterator it = _clients.begin(); it != _clients.end(); ++it)
{
if (*it != _client)
{
// Send message to each client except the sender
server->sendToClient((*it)->getFd(), message);
}
}
}

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/21 14:09:07 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 20:28:41 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -43,30 +43,50 @@ void ClientManager::handleClient(int client_fd)
char buffer[1024];
std::memset(buffer, 0, sizeof(buffer));
int bytes_received = recv(client_fd, buffer, sizeof(buffer), 0);
if (bytes_received <= 0)
{
std::ostringstream oss;
oss << "Client disconnected: " << client_fd;
_server->log(oss.str(), RED);
removeClient(client_fd);
return;
}
std::string message(buffer);
std::stringstream ss;
ss << "Received from client " << client_fd << ": " << message;
_server->log(ss.str(), BLUE);
std::string message(buffer, bytes_received);
std::ostringstream oss;
oss << "Received from client " << client_fd << ": " << message;
_server->log(oss.str(), BLUE);
Client* client = _server->getClients()[client_fd];
if (!client)
{
std::ostringstream oss;
oss << "Client not found for fd: " << client_fd;
_server->log(oss.str(), RED);
return;
}
Client *client = _server->_clients[client_fd];
std::istringstream message_stream(message);
std::string line;
while (std::getline(message_stream, line))
{
// Remove trailing '\r' and '\n'
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
_server->_commandHandler->handleCommand(client, line);
if (!line.empty())
{
std::ostringstream oss;
oss << "Processing command from client " << client_fd << ": " << line;
_server->log(oss.str(), BLUE);
_server->_commandHandler->handleCommand(client, line);
}
}
}
void ClientManager::removeClient(int clientFd)
{
Client* client = _server->_clients[clientFd];
@ -109,4 +129,3 @@ void ClientManager::removeClient(int clientFd)
ss << "Client disconnected: " << clientFd;
_server->log(ss.str(), YELLOW);
}

View File

@ -6,16 +6,22 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/15 18:26:34 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 14:19:19 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 20:24:52 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "CommandHandler.hpp"
CommandHandler::CommandHandler(Server *server)
: _server(server)
{
}
: _server(server), _additionalCommands(new AdditionalCommands(server))
{
// Ensure that _server is not null
if (!_server)
{
std::cerr << "Server pointer is null in CommandHandler constructor." << std::endl;
exit(EXIT_FAILURE);
}
}
void CommandHandler::handleCommand(Client* client, const std::string& command)
{
@ -34,12 +40,27 @@ void CommandHandler::handleCommand(Client* client, const std::string& command)
handleNick(client, tokens);
} else if (commandType == "USER") {
handleUser(client, tokens);
} else {
} else if (commandType == "QUIT") {
handleQuitCommand(client, tokens);
} else if (commandType == "PING")
{
handlePingCommand(client, tokens);
}
else if (commandType == "ERROR") {
if (tokens.size() > 1) {
handleErrorCommand(client, tokens[1]);
}
}
else if (commandType == "JOIN") {
JoinHandler joinHandler;
joinHandler.handleJoinCommand(client, tokens[1], _server);
}
else {
if (!client->isAuthenticated()) {
_server->sendToClient(client->getFd(), ERR_NOTREGISTERED(client));
_server->log("Client " + client->getNickname() + " attempted to send a command before registering.", RED);
} else {
processCommand(client, command);
_additionalCommands->processCommand(client, command);
}
}
std::cout << "Client " << client->getFd() << " " << client->getNickname() << " " << client->getUser() << " " << client->getPassword() << " " << client->getRealName() << std::endl;
@ -146,144 +167,105 @@ void CommandHandler::handleNick(Client* client, const std::vector<std::string>&
return;
}
std::string oldNick = client->getNickname();
client->setNickname(newNick);
_server->sendToClient(client->getFd(), ":" + newNick + " NICK " + newNick + "\r\n");
// Envoyer le message NICK à tous les clients connectés
std::string nickMessage = ":" + oldNick + " NICK " + newNick + "\r\n";
for (std::map<int, Client*>::iterator it = _server->_clients.begin(); it != _server->_clients.end(); ++it) {
_server->sendToClient(it->second->getFd(), nickMessage);
}
std::ostringstream oss;
oss << "Client " << client->getFd() << " changed nickname to " << newNick;
oss << "Client " << client->getFd() << " changed nickname from " << oldNick << " to " << newNick;
_server->log(oss.str(), GREEN);
}
void CommandHandler::handleUser(Client* client, const std::vector<std::string>& tokens)
{
// Set the user and realname fields
client->setUser(tokens[1]);
std::string realname = tokens[4];
if (realname[0] == ':')
{
realname = realname.substr(1); // Remove leading ':'
if (tokens.size() < 5) {
_server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client->getFd(), "USER"));
std::ostringstream oss;
oss << "Client " << client->getFd() << ": USER command failed - not enough parameters.";
_server->log(oss.str(), RED);
return;
}
if (client->isAuthenticated()) {
_server->sendToClient(client->getFd(), ERR_ALREADYREGISTERED(client));
std::ostringstream oss;
oss << "Client " << client->getFd() << ": USER command failed - already registered.";
_server->log(oss.str(), RED);
return;
}
std::string username = tokens[1];
std::string realname = tokens[4].substr(1); // remove leading ':'
client->setUser(username);
client->setRealName(realname);
// Log the values for debugging
std::ostringstream logMsg;
logMsg << "Client " << client->getFd() << ": USER command set username to " << tokens[1] << " and real name to " << realname;
_server->log(logMsg.str(), BLUE);
std::ostringstream oss;
oss << "Client " << client->getFd() << ": USER command set username to " << username << " and real name to " << realname;
_server->log(oss.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);
WelcomeHandler welcomeHandler;
welcomeHandler.sendWelcomeMessages(client, _server);
_server->log("Client " + client->getNickname() + " authenticated.", GREEN);
} else {
std::ostringstream oss;
oss << "Client " << client->getFd() << ": USER command failed - authentication conditions not met.";
_server->log(oss.str(), RED);
}
else
{
std::ostringstream authFailMsg;
authFailMsg << "Client " << client->getFd() << ": USER command failed - authentication conditions not met.";
_server->log(authFailMsg.str(), RED);
}
}
void CommandHandler::processCommand(Client *client, const std::string &command)
{
if (command.find("JOIN") == 0)
{
std::string channelName = command.substr(5);
handleJoinCommand(client, channelName);
}
else if (command.find("PART") == 0)
{
handlePartCommand(_server, client, command);
}
/*else if (command.find("NICK") == 0)
{
handleNickCommand(_server, client, command);
}*/
else if (command.find("PRIVMSG") == 0)
{
handlePrivmsgCommand(_server, client, command);
}
else if (command.find("WHO") == 0)
{
WhoHandler whoHandler(_server);
whoHandler.handleWhoCommand(client, command);
}
else if (command.find("WHOIS") == 0)
{
WhoHandler whoHandler(_server);
whoHandler.handleWhoisCommand(client, command);
}
else if (command.find("PING") == 0)
{
std::vector<std::string> tokens = split(command, " ");
handlePingCommand(client, tokens);
}
else if (command.find("LIST") == 0)
{
broadcastChannelList(client, _server);
}
else
{
_server->sendToClient(client->getFd(), ERR_UNKNOWNCOMMAND(client, command));
_server->log("Message from client " + client->getNickname() + ": " + command, MAGENTA);
}
}
void CommandHandler::handleJoinCommand(Client *client, const std::string &channelName)
{
if (_server->getChannels().find(channelName) == _server->getChannels().end())
{
_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);
std::stringstream joinMsg;
joinMsg << ":" << client->getNickname() << " JOIN :" << channelName << "\r\n";
_server->sendToClient(client->getFd(), joinMsg.str());
std::string usersList = getUsersList(channel);
_server->sendToClient(client->getFd(), usersList);
std::stringstream endOfNamesMsg;
endOfNamesMsg << ":server 366 " << client->getNickname() << " " << channelName << " :End of /NAMES list.\r\n";
_server->sendToClient(client->getFd(), endOfNamesMsg.str());
std::stringstream ss;
ss << "Client " << client->getNickname() << " joined channel " << channelName;
_server->log(ss.str(), MAGENTA);
}
std::string CommandHandler::getUsersList(Channel *channel)
{
std::vector<Client *> clients = channel->getClients();
std::stringstream ss;
ss << ":server 353 " << clients[0]->getNickname() << " = " << channel->getName() << " :";
for (size_t i = 0; i < clients.size(); ++i)
{
if (i > 0)
ss << " ";
ss << clients[i]->getNickname();
}
ss << "\r\n";
return ss.str();
}
void CommandHandler::handlePingCommand(Client* client, const std::vector<std::string>& tokens)
{
if (tokens.size() < 2) {
_server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client, "PING"));
if (tokens.size() < 2)
{
_server->sendToClient(client->getFd(), ERR_NEEDMOREPARAMS(client->getFd(), "PING"));
return;
}
std::string token = tokens[1];
_server->sendToClient(client->getFd(), RPL_PONG(token));
std::string serverName = tokens[1];
std::string pongMessage = ":" + serverName + " PONG " + serverName + "\r\n";
_server->sendToClient(client->getFd(), pongMessage);
}
void CommandHandler::handleQuitCommand(Client* client, const std::vector<std::string>& tokens)
{
std::string reason = "Quit: ";
if (tokens.size() > 1)
{
reason += tokens[1];
}
std::string quitMessage = ":" + client->getNickname() + " QUIT :" + reason + "\r\n";
std::map<std::string, Channel*>::iterator it;
for (it = _server->getChannels().begin(); it != _server->getChannels().end(); ++it)
{
if (it->second->hasClient(client))
{
it->second->broadcast(quitMessage, client, _server);
it->second->removeClient(client);
}
}
_server->sendToClient(client->getFd(), "ERROR :" + reason + "\r\n");
_server->disconnectClient(client->getFd());
}
void CommandHandler::handleErrorCommand(Client* client, const std::string &message)
{
_server->sendToClient(client->getFd(), "ERROR :" + message + "\r\n");
_server->disconnectClient(client->getFd());
}

47
ft_irc3/src/Join.cpp Normal file
View File

@ -0,0 +1,47 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Join.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/21 19:51:31 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 20:13:30 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "Join.hpp"
void JoinHandler::handleJoinCommand(Client *client, const std::string &channelName, Server *server)
{
std::map<std::string, Channel *> &channels = server->getChannels();
Channel *channel;
if (channels.find(channelName) == channels.end())
{
channel = new Channel(channelName);
channels[channelName] = channel;
}
else
{
channel = channels[channelName];
}
channel->addClient(client);
std::string joinMessage = ":" + client->getNickname() + " JOIN " + channelName + "\r\n";
server->sendToClient(client->getFd(), joinMessage);
std::string usersList = getUsersList(channel);
server->sendToClient(client->getFd(), usersList);
}
std::string JoinHandler::getUsersList(Channel *channel)
{
std::vector<Client *> clients = channel->getClients();
std::string usersList = ":server 353 " + clients[0]->getNickname() + " = " + channel->getName() + " :";
for (std::vector<Client *>::iterator it = clients.begin(); it != clients.end(); ++it)
{
usersList += (*it)->getNickname() + " ";
}
usersList += "\r\n:server 366 " + clients[0]->getNickname() + " " + channel->getName() + " :End of /NAMES list.\r\n";
return usersList;
}

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/21 14:18:03 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 20:31:51 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -183,6 +183,10 @@ void Server::sendToClient(int client_fd, const std::string &message)
log(ss.str(), BLUE);
}
}
std::map<int, Client *> &Server::getClients()
{
return _clients;
}
void Server::broadcast(const std::string &message)
{
@ -214,26 +218,31 @@ void Server::sendChannelListToClient(Client *client)
sendToClient(client->getFd(), RPL_LISTEND(client->getFd()));
}
bool Server::MatchFd(const pollfd& pfd, int clientFd)
{
return pfd.fd == clientFd;
}
void Server::removePollFd(int clientFd)
{
for (std::vector<struct pollfd>::iterator it = _poll_fds.begin(); it != _poll_fds.end(); ++it)
{
if (MatchFd(*it, clientFd))
{
_poll_fds.erase(it);
break;
}
}
}
void Server::disconnectClient(int clientFd)
{
Client* client = _clients[clientFd];
if (client)
{
log("Disconnecting client: " + client->getNickname(), YELLOW);
_clients.erase(clientFd);
delete client;
}
close(clientFd);
struct MatchFd
{
int fd;
MatchFd(int fd) : fd(fd) {}
bool operator()(const pollfd& pfd) const { return pfd.fd == fd; }
};
_clients.erase(clientFd);
removePollFd(clientFd);
_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);
std::ostringstream oss;
oss << "Client disconnected: " << clientFd;
log(oss.str(), YELLOW);
}

44
ft_irc3/src/Welcome.cpp Normal file
View File

@ -0,0 +1,44 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Welcome.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/21 17:53:52 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 19:54:48 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "Welcome.hpp"
void WelcomeHandler::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 WelcomeHandler::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));
}
}

View File

@ -6,14 +6,11 @@
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* Created: 2024/05/17 16:09:20 by fgras-ca #+# #+# */
/* Updated: 2024/05/21 13:48:51 by fgras-ca ### ########.fr */
/* Updated: 2024/05/21 18:03:56 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
#include "Who.hpp"
#include "Channel.hpp"
#include "RPL.hpp"
#include <sstream>
WhoHandler::WhoHandler(Server *server)
: _server(server)