mirror of
https://github.com/Ladebeze66/ft_irc.git
synced 2025-12-16 05:58:09 +01:00
join
This commit is contained in:
parent
aaa1457b61
commit
3660d41dea
52
ft_irc/.vscode/settings.json
vendored
52
ft_irc/.vscode/settings.json
vendored
@ -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"
|
||||
}
|
||||
}
|
||||
@ -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.
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
@ -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
|
||||
BIN
ft_irc/ircserv
BIN
ft_irc/ircserv
Binary file not shown.
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
12
ft_irc3/.vscode/settings.json
vendored
12
ft_irc3/.vscode/settings.json
vendored
@ -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++",
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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
|
||||
@ -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:
|
||||
|
||||
BIN
ft_irc3/ircserv
BIN
ft_irc3/ircserv
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.
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
95
ft_irc3/src/ModeWhoHandler.cpp
Normal file
95
ft_irc3/src/ModeWhoHandler.cpp
Normal 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());
|
||||
}
|
||||
@ -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
0
ft_irc3/target
Normal file
Loading…
x
Reference in New Issue
Block a user