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

View File

@ -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"
}
}

View File

@ -1,53 +0,0 @@
# **************************************************************************** #
# #
# ::: :::::::: #
# Makefile :+: :+: :+: #
# +:+ +:+ +:+ #
# By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ #
# +#+#+#+#+#+ +#+ #
# 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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,46 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Client.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <string>
#include <sys/socket.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#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

View File

@ -1,51 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* CommandHandler.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <map>
#include <string>
#include <sstream>
#include <iterator>
#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<std::string, Channel*> channels;
std::vector<std::string> 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

View File

@ -1,72 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Server.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <map>
#include <cerrno>
#include <cstdio>
#include <string>
#include <vector>
#include <sstream>
#include <cstring>
#include <iostream>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <algorithm>
#include <fcntl.h> // Include this for fcntl and O_NONBLOCK
#include <sys/epoll.h>
#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<int, Client*> clients; // Mapping de socket à Client
std::map<int, CommandHandler*> 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

View File

@ -1,28 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Utilities.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <sstream>
#include <algorithm>
#include <cctype>
#include <locale>
#include <string>
#include <vector>
namespace Utilities {
// Split a string by a delimiter and return a vector of substrings
std::vector<std::string> split(const std::string& str, char delimiter);
}
#endif // UTILITIES_HPP

View File

@ -1,27 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* color.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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

Binary file not shown.

View File

@ -1,35 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Channel.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <algorithm>
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);
}
}
}

View File

@ -1,70 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Client.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <cstring>
#include <sys/socket.h>
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;
}

View File

@ -1,105 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* CommandHandler.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<std::string, Channel*>::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<std::string> 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<std::string, Channel*>::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<std::string> 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<std::string> tokens = split(command, ' ');
if (tokens.size() > 1) {
client->setNickname(tokens[1]);
}
}
void CommandHandler::handlePrivmsg(const std::string& command, Client* client) {
std::vector<std::string> 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<std::string> CommandHandler::split(const std::string& s, char delimiter) {
std::vector<std::string> tokens;
std::string token;
std::istringstream tokenStream(s);
while (std::getline(tokenStream, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}

View File

@ -1,351 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Server.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<int, Client*>::iterator it;
for (it = clients.begin(); it != clients.end(); ++it)
{
delete it->second;
close(it->first);
}
std::map<int, CommandHandler*>::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<int, Client*>::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<int, Client*>::iterator it = clients.find(sockfd);
if (it != clients.end())
{
delete it->second;
clients.erase(it);
}
std::map<int, CommandHandler*>::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;
}

View File

@ -1,27 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* main.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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] << " <port> <password>" << 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;
}

View File

@ -1,27 +0,0 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* utilities.cpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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<std::string> split(const std::string& str, char delimiter) {
std::vector<std::string> tokens;
std::stringstream ss(str);
std::string token;
while (getline(ss, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
}

View File

@ -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++",

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/15 12:48:40 by fgras-ca ### ########.fr */
/* Updated: 2024/05/17 20:08:13 by fgras-ca ### ########.fr */
/* */
/* ************************************************************************** */
@ -16,6 +16,7 @@
#include <string>
#include <vector>
#include <algorithm>
#include <set>
class Client;
@ -29,10 +30,13 @@ public:
void removeClient(Client *client);
bool isEmpty() const;
const std::vector<Client *> &getClients() const;
void addOperator(Client *client);
bool isOperator(Client *client) const;
private:
std::string _name;
std::vector<Client *> _clients;
std::vector<Client *> _operators;
};
#endif

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/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);
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();
Client(int fd, const std::string &nickname, const std::string &user);
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 _password;
std::string _realname;
bool _authenticated;
bool _operator;
};
#endif

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/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;
};

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/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 <string>
#include <sstream>
#include <algorithm>
class Server;
class ModeWhoHandler;
class CommandHandler
{

View File

@ -1,36 +1,34 @@
/* ************************************************************************** */
/* */
/* ::: :::::::: */
/* Channel.hpp :+: :+: :+: */
/* ModeWhoHandler.hpp :+: :+: :+: */
/* +:+ +:+ +:+ */
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */
/* 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 <vector>
#include <string>
#include <algorithm>
#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<Client*> clients;
Server *_server;
};
#endif

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/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<std::string, Channel *> &getChannels();
std::map<int, Client *> &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:

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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())
// Si la cible est un utilisateur
else
{
Client *targetClient = server->getClientByName(target); // Utiliser getClientByName pour trouver le client par nom
if (targetClient)
{
Client *targetClient = clients[atoi(target.c_str())];
std::stringstream privMsg;
privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n";
server->sendToClient(targetClient->getFd(), privMsg.str());
}
else
{
std::stringstream ss;
ss << ":server 401 " << client->getNickname() << " " << target << " :No such nick/channel\r\n";
server->sendToClient(client->getFd(), ss.str());
// 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,13 +6,12 @@
/* 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)
@ -47,3 +46,16 @@ const std::vector<Client *> &Channel::getClients() const
{
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,30 +6,20 @@
/* 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)
int Client::getFd() const
{
_password = password;
}
const std::string &Client::getPassword() const
{
return _password;
}
void Client::setNickname(const std::string &nickname)
{
_nickname = nickname;
return _fd;
}
const std::string &Client::getNickname() const
@ -37,9 +27,9 @@ const std::string &Client::getNickname() const
return _nickname;
}
void Client::setUser(const std::string &user)
void Client::setNickname(const std::string &nickname)
{
_user = user;
_nickname = nickname;
}
const std::string &Client::getUser() const
@ -47,9 +37,19 @@ const std::string &Client::getUser() const
return _user;
}
void Client::setRealName(const std::string &realname)
void Client::setUser(const std::string &user)
{
_realname = realname;
_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
@ -57,6 +57,11 @@ const std::string &Client::getRealName() const
return _realname;
}
void Client::setRealName(const std::string &realname)
{
_realname = realname;
}
bool Client::isAuthenticated() const
{
return _authenticated;
@ -67,11 +72,17 @@ void Client::authenticate()
_authenticated = true;
}
int Client::getFd() const
bool Client::isOperator() const
{
return _fd;
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)

0
ft_irc3/target Normal file
View File