mirror of
https://github.com/Ladebeze66/ft_irc.git
synced 2025-12-15 21:57:08 +01:00
dede
This commit is contained in:
parent
58606f36a6
commit
aaa1457b61
18
ft_irc3/.vscode/c_cpp_properties.json
vendored
Normal file
18
ft_irc3/.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "linux-gcc-x64",
|
||||
"includePath": [
|
||||
"${workspaceFolder}/**"
|
||||
],
|
||||
"compilerPath": "/usr/bin/gcc",
|
||||
"cStandard": "${default}",
|
||||
"cppStandard": "${default}",
|
||||
"intelliSenseMode": "linux-gcc-x64",
|
||||
"compilerArgs": [
|
||||
""
|
||||
]
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
24
ft_irc3/.vscode/launch.json
vendored
Normal file
24
ft_irc3/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "C/C++ Runner: Debug Session",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"args": [],
|
||||
"stopAtEntry": false,
|
||||
"externalConsole": false,
|
||||
"cwd": "/home/fgras-ca/Bureau/ft_irc3/src",
|
||||
"program": "/home/fgras-ca/Bureau/ft_irc3/src/build/Debug/outDebug",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
"description": "Enable pretty-printing for gdb",
|
||||
"text": "-enable-pretty-printing",
|
||||
"ignoreFailures": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
110
ft_irc3/.vscode/settings.json
vendored
Normal file
110
ft_irc3/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,110 @@
|
||||
{
|
||||
"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",
|
||||
"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",
|
||||
"fstream": "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",
|
||||
"list": "cpp"
|
||||
},
|
||||
"C_Cpp_Runner.cCompilerPath": "gcc",
|
||||
"C_Cpp_Runner.cppCompilerPath": "g++",
|
||||
"C_Cpp_Runner.debuggerPath": "gdb",
|
||||
"C_Cpp_Runner.cStandard": "",
|
||||
"C_Cpp_Runner.cppStandard": "",
|
||||
"C_Cpp_Runner.msvcBatchPath": "",
|
||||
"C_Cpp_Runner.useMsvc": false,
|
||||
"C_Cpp_Runner.warnings": [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wpedantic",
|
||||
"-Wshadow",
|
||||
"-Wformat=2",
|
||||
"-Wcast-align",
|
||||
"-Wconversion",
|
||||
"-Wsign-conversion",
|
||||
"-Wnull-dereference"
|
||||
],
|
||||
"C_Cpp_Runner.msvcWarnings": [
|
||||
"/W4",
|
||||
"/permissive-",
|
||||
"/w14242",
|
||||
"/w14287",
|
||||
"/w14296",
|
||||
"/w14311",
|
||||
"/w14826",
|
||||
"/w44062",
|
||||
"/w44242",
|
||||
"/w14905",
|
||||
"/w14906",
|
||||
"/w14263",
|
||||
"/w44265",
|
||||
"/w14928"
|
||||
],
|
||||
"C_Cpp_Runner.enableWarnings": true,
|
||||
"C_Cpp_Runner.warningsAsError": false,
|
||||
"C_Cpp_Runner.compilerArgs": [],
|
||||
"C_Cpp_Runner.linkerArgs": [],
|
||||
"C_Cpp_Runner.includePaths": [],
|
||||
"C_Cpp_Runner.includeSearch": [
|
||||
"*",
|
||||
"**/*"
|
||||
],
|
||||
"C_Cpp_Runner.excludeSearch": [
|
||||
"**/build",
|
||||
"**/build/**",
|
||||
"**/.*",
|
||||
"**/.*/**",
|
||||
"**/.vscode",
|
||||
"**/.vscode/**"
|
||||
],
|
||||
"C_Cpp_Runner.useAddressSanitizer": false,
|
||||
"C_Cpp_Runner.useUndefinedSanitizer": false,
|
||||
"C_Cpp_Runner.useLeakSanitizer": false,
|
||||
"C_Cpp_Runner.showCompilationTime": false,
|
||||
"C_Cpp_Runner.useLinkTimeOptimization": false,
|
||||
"C_Cpp_Runner.msvcSecureNoWarnings": false
|
||||
}
|
||||
46
ft_irc3/Makefile
Normal file
46
ft_irc3/Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
# **************************************************************************** #
|
||||
# #
|
||||
# ::: :::::::: #
|
||||
# Makefile :+: :+: :+: #
|
||||
# +:+ +:+ +:+ #
|
||||
# By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ #
|
||||
# +#+#+#+#+#+ +#+ #
|
||||
# Created: 2024/05/15 12:13:50 by fgras-ca #+# #+# #
|
||||
# Updated: 2024/05/15 12:47:49 by fgras-ca ### ########.fr #
|
||||
# #
|
||||
# **************************************************************************** #
|
||||
|
||||
CXX = g++
|
||||
CXXFLAGS = -Wall -Wextra -Werror -std=c++98
|
||||
LDFLAGS = -pthread
|
||||
|
||||
SRC_DIR = src
|
||||
INC_DIR = includes
|
||||
OBJ_DIR = obj
|
||||
LOG_DIR = logs
|
||||
|
||||
SRCS = $(wildcard $(SRC_DIR)/*.cpp)
|
||||
OBJS = $(SRCS:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
|
||||
|
||||
NAME = ircserv
|
||||
|
||||
all: $(NAME)
|
||||
|
||||
$(NAME): $(OBJS)
|
||||
$(CXX) $(CXXFLAGS) -I$(INC_DIR) -o $@ $^ $(LDFLAGS)
|
||||
mkdir -p $(LOG_DIR)
|
||||
touch $(LOG_DIR)/irc_server.log
|
||||
|
||||
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
|
||||
mkdir -p $(OBJ_DIR)
|
||||
$(CXX) $(CXXFLAGS) -I$(INC_DIR) -c $< -o $@
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJ_DIR) $(NAME)
|
||||
|
||||
fclean: clean
|
||||
rm -rf $(LOG_DIR)
|
||||
|
||||
re: fclean all
|
||||
|
||||
.PHONY: all clean fclean re
|
||||
32
ft_irc3/includes/AdditionalCommands.hpp
Normal file
32
ft_irc3/includes/AdditionalCommands.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* AdditionalCommands.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/05/16 15:23:58 by fgras-ca #+# #+# */
|
||||
/* Updated: 2024/05/16 16:03:22 by fgras-ca ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef ADDITIONALCOMMANDS_HPP
|
||||
#define ADDITIONALCOMMANDS_HPP
|
||||
|
||||
#include "Client.hpp"
|
||||
#include "Server.hpp"
|
||||
#include "Channel.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
class Server;
|
||||
class Client;
|
||||
class Channel;
|
||||
|
||||
void handlePartCommand(Server *server, Client *client, const std::string &command);
|
||||
void handleNickCommand(Server *server, Client *client, const std::string &command);
|
||||
void handlePrivmsgCommand(Server *server, Client *client, const std::string &command);
|
||||
|
||||
#endif
|
||||
38
ft_irc3/includes/Channel.hpp
Normal file
38
ft_irc3/includes/Channel.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Channel.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CHANNEL_HPP
|
||||
#define CHANNEL_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
class Client;
|
||||
|
||||
class Channel {
|
||||
public:
|
||||
Channel(const std::string &name);
|
||||
~Channel();
|
||||
|
||||
const std::string &getName() const;
|
||||
void addClient(Client *client);
|
||||
void removeClient(Client *client);
|
||||
bool isEmpty() const;
|
||||
const std::vector<Client *> &getClients() const;
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
std::vector<Client *> _clients;
|
||||
};
|
||||
|
||||
#endif
|
||||
49
ft_irc3/includes/Client.hpp
Normal file
49
ft_irc3/includes/Client.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Client.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CLIENT_HPP
|
||||
#define CLIENT_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
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();
|
||||
|
||||
int getFd() const;
|
||||
|
||||
private:
|
||||
int _fd;
|
||||
std::string _password;
|
||||
std::string _nickname;
|
||||
std::string _user;
|
||||
std::string _realname;
|
||||
bool _authenticated;
|
||||
};
|
||||
|
||||
#endif
|
||||
45
ft_irc3/includes/ClientManager.hpp
Normal file
45
ft_irc3/includes/ClientManager.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ClientManager.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef CLIENTMANAGER_HPP
|
||||
#define CLIENTMANAGER_HPP
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "Client.hpp"
|
||||
#include "Channel.hpp"
|
||||
#include "Server.hpp"
|
||||
#include <poll.h>
|
||||
#include "CommandHandler.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <fcntl.h>
|
||||
|
||||
class Server;
|
||||
|
||||
class ClientManager
|
||||
{
|
||||
public:
|
||||
ClientManager(Server *server);
|
||||
void acceptClient();
|
||||
void handleClient(int client_fd);
|
||||
void removeClient(int client_fd);
|
||||
|
||||
private:
|
||||
Server *_server;
|
||||
};
|
||||
|
||||
#endif
|
||||
41
ft_irc3/includes/CommandHandler.hpp
Normal file
41
ft_irc3/includes/CommandHandler.hpp
Normal file
@ -0,0 +1,41 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* CommandHandler.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef COMMANDHANDLER_HPP
|
||||
#define COMMANDHANDLER_HPP
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Server.hpp"
|
||||
#include "Client.hpp"
|
||||
#include "Channel.hpp"
|
||||
#include "AdditionalCommands.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
class Server;
|
||||
|
||||
class CommandHandler
|
||||
{
|
||||
private:
|
||||
Server *_server;
|
||||
|
||||
public:
|
||||
CommandHandler(Server *server);
|
||||
void handleCommand(Client *client, const std::string &command);
|
||||
void processCommand(Client *client, const std::string &command);
|
||||
void handleJoinCommand(Client *client, const std::string &channelName);
|
||||
std::string getUsersList(Channel *channel);
|
||||
};
|
||||
|
||||
#endif
|
||||
76
ft_irc3/includes/Server.hpp
Normal file
76
ft_irc3/includes/Server.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Server.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef SERVER_HPP
|
||||
#define SERVER_HPP
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "Client.hpp"
|
||||
#include "Channel.hpp"
|
||||
#include "ClientManager.hpp"
|
||||
#include "CommandHandler.hpp"
|
||||
#include "AdditionalCommands.hpp"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <poll.h>
|
||||
|
||||
class Client;
|
||||
class Channel;
|
||||
class ClientManager;
|
||||
class CommandHandler;
|
||||
|
||||
class Server
|
||||
{
|
||||
public:
|
||||
Server(int port, const std::string &password);
|
||||
~Server();
|
||||
void run();
|
||||
void log(const std::string &message, const std::string &color = "\033[0m");
|
||||
void sendToClient(int client_fd, const std::string &message);
|
||||
|
||||
// Méthodes d'accès pour les canaux et les clients
|
||||
std::map<std::string, Channel *> &getChannels();
|
||||
std::map<int, Client *> &getClients();
|
||||
const std::string &getPassword() const;
|
||||
|
||||
|
||||
protected:
|
||||
int _server_fd;
|
||||
int _port;
|
||||
std::string _password;
|
||||
std::map<int, Client *> _clients;
|
||||
std::map<std::string, Channel *> _channels;
|
||||
std::vector<struct pollfd> _poll_fds;
|
||||
ClientManager *_clientManager;
|
||||
CommandHandler *_commandHandler;
|
||||
|
||||
friend class ClientManager;
|
||||
friend class CommandHandler;
|
||||
|
||||
private:
|
||||
void initServer();
|
||||
void handleServerCommands();
|
||||
void acceptClient();
|
||||
void removeClient(int client_fd);
|
||||
};
|
||||
|
||||
#endif
|
||||
30
ft_irc3/includes/Utils.hpp
Normal file
30
ft_irc3/includes/Utils.hpp
Normal file
@ -0,0 +1,30 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Utils.hpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/05/15 12:16:02 by fgras-ca #+# #+# */
|
||||
/* Updated: 2024/05/16 18:14:58 by fgras-ca ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#ifndef UTILS_HPP
|
||||
#define UTILS_HPP
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#define RESET "\033[0m"
|
||||
#define RED "\033[31m"
|
||||
#define GREEN "\033[32m"
|
||||
#define YELLOW "\033[33m"
|
||||
#define BLUE "\033[34m"
|
||||
#define MAGENTA "\033[35m"
|
||||
#define CYAN "\033[36m"
|
||||
|
||||
std::vector<std::string> split(const std::string &input, const std::string &delimiters);
|
||||
|
||||
#endif
|
||||
BIN
ft_irc3/ircserv
Executable file
BIN
ft_irc3/ircserv
Executable file
Binary file not shown.
0
ft_irc3/logs/irc_server.log
Normal file
0
ft_irc3/logs/irc_server.log
Normal file
BIN
ft_irc3/obj/AdditionalCommands.o
Normal file
BIN
ft_irc3/obj/AdditionalCommands.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/Channel.o
Normal file
BIN
ft_irc3/obj/Channel.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/Client.o
Normal file
BIN
ft_irc3/obj/Client.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/ClientManager.o
Normal file
BIN
ft_irc3/obj/ClientManager.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/CommandHandler.o
Normal file
BIN
ft_irc3/obj/CommandHandler.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/Server.o
Normal file
BIN
ft_irc3/obj/Server.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/Utils.o
Normal file
BIN
ft_irc3/obj/Utils.o
Normal file
Binary file not shown.
BIN
ft_irc3/obj/main.o
Normal file
BIN
ft_irc3/obj/main.o
Normal file
Binary file not shown.
108
ft_irc3/src/AdditionalCommands.cpp
Normal file
108
ft_irc3/src/AdditionalCommands.cpp
Normal file
@ -0,0 +1,108 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* AdditionalCommands.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "AdditionalCommands.hpp"
|
||||
|
||||
// Fonction pour gérer la commande PART
|
||||
void handlePartCommand(Server *server, 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())
|
||||
{
|
||||
Channel *channel = channels[channelName];
|
||||
channel->removeClient(client);
|
||||
|
||||
std::stringstream partMsg;
|
||||
partMsg << ":" << client->getNickname() << " PART " << channelName << "\r\n";
|
||||
server->sendToClient(client->getFd(), partMsg.str());
|
||||
|
||||
if (channel->isEmpty())
|
||||
{
|
||||
delete channel;
|
||||
channels.erase(channelName);
|
||||
}
|
||||
|
||||
server->log("Client " + client->getNickname() + " left channel " + channelName, MAGENTA);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << ":server 403 " << client->getNickname() << " " << channelName << " :No such channel\r\n";
|
||||
server->sendToClient(client->getFd(), ss.str());
|
||||
}
|
||||
}
|
||||
|
||||
// Fonction pour gérer la commande NICK
|
||||
void handleNickCommand(Server *server, Client *client, const std::string &command)
|
||||
{
|
||||
std::istringstream iss(command);
|
||||
std::string cmd, newNick;
|
||||
iss >> cmd >> newNick;
|
||||
|
||||
std::stringstream nickMsg;
|
||||
nickMsg << ":" << client->getNickname() << " NICK " << newNick << "\r\n";
|
||||
server->sendToClient(client->getFd(), nickMsg.str());
|
||||
|
||||
client->setNickname(newNick);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Client " << client->getFd() << " changed nickname to " << newNick;
|
||||
server->log(ss.str(), GREEN);
|
||||
}
|
||||
|
||||
// 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);
|
||||
if (!message.empty() && message[0] == ':')
|
||||
message = message.substr(1);
|
||||
|
||||
std::map<std::string, Channel *> &channels = server->getChannels();
|
||||
std::map<int, Client *> &clients = server->getClients();
|
||||
|
||||
if (channels.find(target) != channels.end())
|
||||
{
|
||||
Channel *channel = channels[target];
|
||||
std::vector<Client *> channelClients = channel->getClients();
|
||||
|
||||
for (size_t i = 0; i < channelClients.size(); ++i)
|
||||
{
|
||||
if (channelClients[i] != client)
|
||||
{
|
||||
std::stringstream privMsg;
|
||||
privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n";
|
||||
server->sendToClient(channelClients[i]->getFd(), privMsg.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (clients.find(atoi(target.c_str())) != clients.end())
|
||||
{
|
||||
Client *targetClient = clients[atoi(target.c_str())];
|
||||
std::stringstream privMsg;
|
||||
privMsg << ":" << client->getNickname() << " PRIVMSG " << target << " :" << message << "\r\n";
|
||||
server->sendToClient(targetClient->getFd(), privMsg.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << ":server 401 " << client->getNickname() << " " << target << " :No such nick/channel\r\n";
|
||||
server->sendToClient(client->getFd(), ss.str());
|
||||
}
|
||||
}
|
||||
49
ft_irc3/src/Channel.cpp
Normal file
49
ft_irc3/src/Channel.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Channel.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "Channel.hpp"
|
||||
#include "Client.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
Channel::Channel(const std::string &name)
|
||||
: _name(name)
|
||||
{
|
||||
}
|
||||
|
||||
Channel::~Channel()
|
||||
{
|
||||
}
|
||||
|
||||
const std::string &Channel::getName() const
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
void Channel::addClient(Client *client)
|
||||
{
|
||||
_clients.push_back(client);
|
||||
}
|
||||
|
||||
void Channel::removeClient(Client *client)
|
||||
{
|
||||
_clients.erase(std::remove(_clients.begin(), _clients.end(), client), _clients.end());
|
||||
}
|
||||
|
||||
bool Channel::isEmpty() const
|
||||
{
|
||||
return _clients.empty();
|
||||
}
|
||||
|
||||
const std::vector<Client *> &Channel::getClients() const
|
||||
{
|
||||
return _clients;
|
||||
}
|
||||
104
ft_irc3/src/Client.cpp
Normal file
104
ft_irc3/src/Client.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Client.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "Client.hpp"
|
||||
|
||||
Client::Client(int fd)
|
||||
: _fd(fd), _authenticated(false)
|
||||
{
|
||||
}
|
||||
|
||||
void Client::setPassword(const std::string &password)
|
||||
{
|
||||
_password = password;
|
||||
}
|
||||
|
||||
const std::string &Client::getPassword() const
|
||||
{
|
||||
return _password;
|
||||
}
|
||||
|
||||
void Client::setNickname(const std::string &nickname)
|
||||
{
|
||||
_nickname = nickname;
|
||||
}
|
||||
|
||||
const std::string &Client::getNickname() const
|
||||
{
|
||||
return _nickname;
|
||||
}
|
||||
|
||||
void Client::setUser(const std::string &user)
|
||||
{
|
||||
_user = user;
|
||||
}
|
||||
|
||||
const std::string &Client::getUser() const
|
||||
{
|
||||
return _user;
|
||||
}
|
||||
|
||||
void Client::setRealName(const std::string &realname)
|
||||
{
|
||||
_realname = realname;
|
||||
}
|
||||
|
||||
const std::string &Client::getRealName() const
|
||||
{
|
||||
return _realname;
|
||||
}
|
||||
|
||||
bool Client::isAuthenticated() const
|
||||
{
|
||||
return _authenticated;
|
||||
}
|
||||
|
||||
void Client::authenticate()
|
||||
{
|
||||
_authenticated = true;
|
||||
}
|
||||
|
||||
int Client::getFd() const
|
||||
{
|
||||
return _fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*Client::Client(int fd)
|
||||
|
||||
Description: Constructeur de la classe Client. Initialise le client avec le descripteur de fichier fourni.
|
||||
Paramètres:
|
||||
int fd: Le descripteur de fichier du client.
|
||||
Client::~Client()
|
||||
|
||||
Description: Destructeur de la classe Client. Gère la destruction de l'objet.
|
||||
int Client::getFd() const
|
||||
|
||||
Description: Renvoie le descripteur de fichier du client.
|
||||
Retourne: Le descripteur de fichier du client.
|
||||
void Client::setPassword(const std::string &password)
|
||||
|
||||
Description: Définit le mot de passe du client et le marque comme authentifié.
|
||||
Paramètres:
|
||||
const std::string &password: Le mot de passe à définir.
|
||||
bool Client::isAuthenticated() const
|
||||
|
||||
Description: Vérifie si le client est authentifié.
|
||||
Retourne: true si le client est authentifié, false sinon.
|
||||
void logMessage(const std::string &message, const std::string &color)
|
||||
|
||||
Description: Enregistre un message dans les logs et l'affiche avec des couleurs dans la console.
|
||||
Paramètres:
|
||||
const std::string &message: Le message à enregistrer.
|
||||
const std::string &color: La couleur du message.*/
|
||||
110
ft_irc3/src/ClientManager.cpp
Normal file
110
ft_irc3/src/ClientManager.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* ClientManager.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "ClientManager.hpp"
|
||||
|
||||
ClientManager::ClientManager(Server *server)
|
||||
: _server(server)
|
||||
{
|
||||
}
|
||||
|
||||
void ClientManager::acceptClient()
|
||||
{
|
||||
int client_fd = accept(_server->_server_fd, NULL, NULL);
|
||||
if (client_fd < 0)
|
||||
{
|
||||
_server->log("Accept failed.", RED);
|
||||
return;
|
||||
}
|
||||
fcntl(client_fd, F_SETFL, O_NONBLOCK);
|
||||
_server->_clients[client_fd] = new Client(client_fd);
|
||||
struct pollfd client_pollfd;
|
||||
client_pollfd.fd = client_fd;
|
||||
client_pollfd.events = POLLIN;
|
||||
_server->_poll_fds.push_back(client_pollfd);
|
||||
|
||||
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::handleClient(int client_fd)
|
||||
{
|
||||
char buffer[1024];
|
||||
std::memset(buffer, 0, sizeof(buffer));
|
||||
int bytes_received = recv(client_fd, buffer, sizeof(buffer), 0);
|
||||
if (bytes_received <= 0)
|
||||
{
|
||||
removeClient(client_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string message(buffer);
|
||||
std::stringstream ss;
|
||||
ss << "Received from client " << client_fd << ": " << message;
|
||||
_server->log(ss.str(), BLUE);
|
||||
|
||||
Client *client = _server->_clients[client_fd];
|
||||
std::istringstream message_stream(message);
|
||||
std::string line;
|
||||
|
||||
while (std::getline(message_stream, line))
|
||||
{
|
||||
// Suppression des caractères de fin de ligne
|
||||
line.erase(std::remove(line.begin(), line.end(), '\r'), line.end());
|
||||
line.erase(std::remove(line.begin(), line.end(), '\n'), line.end());
|
||||
|
||||
_server->_commandHandler->handleCommand(client, line);
|
||||
}
|
||||
}
|
||||
|
||||
void ClientManager::removeClient(int client_fd)
|
||||
{
|
||||
Client *client = _server->_clients[client_fd];
|
||||
if (client)
|
||||
{
|
||||
// Retirer le client de tous les canaux auxquels il appartient
|
||||
std::map<std::string, Channel *>::iterator it = _server->_channels.begin();
|
||||
while (it != _server->_channels.end())
|
||||
{
|
||||
it->second->removeClient(client);
|
||||
if (it->second->isEmpty())
|
||||
{
|
||||
delete it->second;
|
||||
std::map<std::string, Channel *>::iterator it_to_delete = it++;
|
||||
_server->_channels.erase(it_to_delete);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
delete client;
|
||||
_server->_clients.erase(client_fd);
|
||||
}
|
||||
|
||||
std::vector<struct pollfd>::iterator it_poll = _server->_poll_fds.begin();
|
||||
while (it_poll != _server->_poll_fds.end())
|
||||
{
|
||||
if (it_poll->fd == client_fd)
|
||||
{
|
||||
_server->_poll_fds.erase(it_poll);
|
||||
break;
|
||||
}
|
||||
++it_poll;
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Client disconnected: " << client_fd;
|
||||
_server->log(ss.str(), YELLOW);
|
||||
}
|
||||
152
ft_irc3/src/CommandHandler.cpp
Normal file
152
ft_irc3/src/CommandHandler.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* CommandHandler.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "CommandHandler.hpp"
|
||||
|
||||
CommandHandler::CommandHandler(Server *server)
|
||||
: _server(server)
|
||||
{
|
||||
}
|
||||
|
||||
void CommandHandler::handleCommand(Client *client, const std::string &command)
|
||||
{
|
||||
std::vector<std::string> tokens = split(command, " \n\r\t");
|
||||
|
||||
if (tokens.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::string commandType = tokens[0];
|
||||
|
||||
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->log("Client " + client->getNickname() + " provided correct password.", GREEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
_server->sendToClient(client->getFd(), ":server 464 " + client->getNickname() + " :Invalid password\r\n");
|
||||
_server->log("Client " + client->getNickname() + " failed authentication password.", RED);
|
||||
}
|
||||
}
|
||||
else if (commandType == "NICK")
|
||||
{
|
||||
if (tokens.size() > 1)
|
||||
{
|
||||
client->setNickname(tokens[1]);
|
||||
std::stringstream ss;
|
||||
ss << "Client " << client->getFd() << " Nickname: " << tokens[1];
|
||||
_server->log(ss.str(), GREEN);
|
||||
_server->sendToClient(client->getFd(), ":" + tokens[1] + " NICK " + tokens[1] + "\r\n");
|
||||
}
|
||||
}
|
||||
else if (commandType == "USER")
|
||||
{
|
||||
if (tokens.size() > 4)
|
||||
{
|
||||
client->setUser(tokens[1]);
|
||||
client->setRealName(tokens[4].substr(1)); // remove leading ':'
|
||||
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");
|
||||
_server->log("Client " + client->getNickname() + " authenticated.", GREEN);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!client->isAuthenticated())
|
||||
{
|
||||
_server->sendToClient(client->getFd(), ":server 451 " + client->getNickname() + " :Please provide the password first\r\n");
|
||||
_server->log("Client " + client->getNickname() + " failed authentication.", RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
processCommand(client, command);
|
||||
}
|
||||
}
|
||||
std::cout << "Client " << client->getFd() << " " << client->getNickname() << " " << client->getUser() << " " << client->getPassword() << " " << client->getRealName() << std::endl;
|
||||
}
|
||||
|
||||
void CommandHandler::processCommand(Client *client, const std::string &command)
|
||||
{
|
||||
if (command.find("JOIN") == 0)
|
||||
{
|
||||
std::string channelName = command.substr(5);
|
||||
handleJoinCommand(client, channelName);
|
||||
}
|
||||
else if (command.find("PART") == 0)
|
||||
{
|
||||
handlePartCommand(_server, client, command);
|
||||
}
|
||||
else if (command.find("NICK") == 0)
|
||||
{
|
||||
handleNickCommand(_server, client, command);
|
||||
}
|
||||
else if (command.find("PRIVMSG") == 0)
|
||||
{
|
||||
handlePrivmsgCommand(_server, client, command);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << ":server 421 " << client->getNickname() << " " << command << " :Unknown command\r\n";
|
||||
_server->sendToClient(client->getFd(), ss.str());
|
||||
_server->log("Message from client " + client->getNickname() + ": " + command, MAGENTA);
|
||||
}
|
||||
}
|
||||
|
||||
void CommandHandler::handleJoinCommand(Client *client, const std::string &channelName)
|
||||
{
|
||||
if (_server->getChannels().find(channelName) == _server->getChannels().end())
|
||||
{
|
||||
_server->getChannels()[channelName] = new Channel(channelName);
|
||||
_server->log("Channel created: " + channelName, GREEN);
|
||||
}
|
||||
Channel *channel = _server->getChannels()[channelName];
|
||||
channel->addClient(client);
|
||||
|
||||
std::stringstream joinMsg;
|
||||
joinMsg << ":" << client->getNickname() << " JOIN :" << channelName << "\r\n";
|
||||
_server->sendToClient(client->getFd(), joinMsg.str());
|
||||
|
||||
std::string usersList = getUsersList(channel);
|
||||
_server->sendToClient(client->getFd(), usersList);
|
||||
|
||||
std::stringstream endOfNamesMsg;
|
||||
endOfNamesMsg << ":server 366 " << client->getNickname() << " " << channelName << " :End of /NAMES list.\r\n";
|
||||
_server->sendToClient(client->getFd(), endOfNamesMsg.str());
|
||||
|
||||
std::stringstream ss;
|
||||
ss << "Client " << client->getNickname() << " joined channel " << channelName;
|
||||
_server->log(ss.str(), MAGENTA);
|
||||
}
|
||||
|
||||
std::string CommandHandler::getUsersList(Channel *channel)
|
||||
{
|
||||
std::vector<Client *> clients = channel->getClients();
|
||||
std::stringstream ss;
|
||||
ss << ":server 353 " << clients[0]->getNickname() << " = " << channel->getName() << " :";
|
||||
for (size_t i = 0; i < clients.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
ss << " ";
|
||||
ss << clients[i]->getNickname();
|
||||
}
|
||||
ss << "\r\n";
|
||||
return ss.str();
|
||||
}
|
||||
273
ft_irc3/src/Server.cpp
Normal file
273
ft_irc3/src/Server.cpp
Normal file
@ -0,0 +1,273 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Server.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* 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 */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "Server.hpp"
|
||||
|
||||
Server::Server(int port, const std::string &password)
|
||||
: _port(port), _password(password), _clientManager(new ClientManager(this)), _commandHandler(new CommandHandler(this))
|
||||
{
|
||||
initServer();
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
{
|
||||
delete _clientManager;
|
||||
delete _commandHandler;
|
||||
|
||||
for (std::map<int, Client*>::iterator it = _clients.begin(); it != _clients.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
for (std::map<std::string, Channel*>::iterator it = _channels.begin(); it != _channels.end(); ++it)
|
||||
{
|
||||
delete it->second;
|
||||
}
|
||||
close(_server_fd);
|
||||
}
|
||||
|
||||
void Server::initServer()
|
||||
{
|
||||
_server_fd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (_server_fd == -1)
|
||||
{
|
||||
log("Failed to create socket.", RED);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
std::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(_server_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1)
|
||||
{
|
||||
log("Failed to bind socket.", RED);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (listen(_server_fd, SOMAXCONN) == -1)
|
||||
{
|
||||
log("Failed to listen on socket.", RED);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
log("Server initialized.", GREEN);
|
||||
}
|
||||
|
||||
void Server::run()
|
||||
{
|
||||
struct pollfd server_pollfd;
|
||||
server_pollfd.fd = _server_fd;
|
||||
server_pollfd.events = POLLIN;
|
||||
server_pollfd.revents = 0;
|
||||
_poll_fds.push_back(server_pollfd);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int poll_count = poll(&_poll_fds[0], _poll_fds.size(), -1);
|
||||
if (poll_count == -1)
|
||||
{
|
||||
log("Poll error.", RED);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < _poll_fds.size(); ++i)
|
||||
{
|
||||
if (_poll_fds[i].revents & POLLIN)
|
||||
{
|
||||
if (_poll_fds[i].fd == _server_fd)
|
||||
{
|
||||
_clientManager->acceptClient();
|
||||
}
|
||||
else
|
||||
{
|
||||
_clientManager->handleClient(_poll_fds[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleServerCommands();
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handleServerCommands()
|
||||
{
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(STDIN_FILENO, &readfds);
|
||||
struct timeval tv = {0, 0}; // non-blocking
|
||||
|
||||
int activity = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &tv);
|
||||
|
||||
if (activity > 0 && FD_ISSET(STDIN_FILENO, &readfds))
|
||||
{
|
||||
std::string command;
|
||||
std::getline(std::cin, command);
|
||||
|
||||
if (command == "quit")
|
||||
{
|
||||
log("Server shutting down.", YELLOW);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
else if (command == "channels")
|
||||
{
|
||||
log("Listing all channels:", BLUE);
|
||||
for (std::map<std::string, Channel*>::iterator it = _channels.begin(); it != _channels.end(); ++it)
|
||||
{
|
||||
log(it->first, BLUE);
|
||||
}
|
||||
}
|
||||
else if (command == "clients")
|
||||
{
|
||||
log("Listing all clients:", BLUE);
|
||||
for (std::map<int, Client*>::iterator it = _clients.begin(); it != _clients.end(); ++it)
|
||||
{
|
||||
log(it->second->getNickname(), BLUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log("Unknown server command.", RED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Server::log(const std::string &message, const std::string &color)
|
||||
{
|
||||
std::cout << color << message << RESET << std::endl;
|
||||
}
|
||||
|
||||
void Server::sendToClient(int client_fd, const std::string &message)
|
||||
{
|
||||
int result = send(client_fd, message.c_str(), message.length(), 0);
|
||||
if (result < 0)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Failed to send message to client " << client_fd;
|
||||
log(ss.str(), RED);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Sent message to client " << client_fd << ": " << message;
|
||||
log(ss.str(), BLUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::map<int, Client *> &Server::getClients()
|
||||
{
|
||||
return _clients;
|
||||
}
|
||||
|
||||
std::map<std::string, Channel *> &Server::getChannels()
|
||||
{
|
||||
return _channels;
|
||||
}
|
||||
|
||||
const std::string &Server::getPassword() const
|
||||
{
|
||||
return _password;
|
||||
}
|
||||
|
||||
|
||||
/* Explications des Fonctions
|
||||
Server::Server(int port, const std::string &password)
|
||||
|
||||
Description: Constructeur de la classe Server. Initialise le serveur avec le port et le mot de passe fournis.
|
||||
Paramètres:
|
||||
int port: Le port sur lequel le serveur écoute.
|
||||
const std::string &password: Le mot de passe requis pour se connecter au serveur.
|
||||
Détails: Appelle initServer() pour initialiser les paramètres du socket et commencer l'écoute des connexions.
|
||||
Server::~Server()
|
||||
|
||||
Description: Destructeur de la classe Server. Ferme le socket du serveur et libère la mémoire des clients.
|
||||
Détails: Parcourt la map _clients et delete chaque objet Client.
|
||||
void Server::initServer()
|
||||
|
||||
Description: Initialise le socket du serveur et configure le binding et l'écoute.
|
||||
Détails: Crée un socket avec socket(), lie le socket à une adresse avec bind(), et met le socket en mode écoute avec listen().
|
||||
void Server::run()
|
||||
|
||||
Description: Boucle principale du serveur qui gère les connexions entrantes et les communications avec les clients.
|
||||
Détails: Utilise poll() pour surveiller les événements sur les sockets. Accepte les nouvelles connexions avec acceptClient() et gère les communications avec handleClient().
|
||||
void Server::acceptClient()
|
||||
|
||||
Description: Accepte une nouvelle connexion client et l'ajoute à la liste des clients.
|
||||
Détails: Crée un nouvel objet Client et l'ajoute à la map _clients. Ajoute le descripteur de fichier du client à _poll_fds.
|
||||
void Server::handleClient(int client_fd)
|
||||
|
||||
Description: Gère les messages entrants des clients.
|
||||
Paramètres:
|
||||
int client_fd: Le descripteur de fichier du client.
|
||||
Détails: Reçoit les messages du client et vérifie l'authentification. Si le client n'est pas authentifié, vérifie le mot de passe. Si le client est authentifié, répond au message.
|
||||
void Server::removeClient(int client_fd)
|
||||
|
||||
Description: Supprime un client de la liste et ferme la connexion.
|
||||
Paramètres:
|
||||
int client_fd: Le descripteur de fichier du client.
|
||||
Détails: Ferme le socket du client et le supprime de la map _clients et du vecteur _poll_fds.
|
||||
void Server::log(const std::string &message, const std::string &color)
|
||||
|
||||
Description: Enregistre un message dans les logs et l'affiche avec des couleurs dans la console.
|
||||
Paramètres:
|
||||
const std::string &message: Le message à enregistrer.
|
||||
const std::string &color: La couleur du message.
|
||||
Détails: Utilise logMessage() pour enregistrer et afficher le message.
|
||||
void Server::sendToClient(int client_fd, const std::string &message)
|
||||
|
||||
Description: Envoie un message à un client.
|
||||
Paramètres:
|
||||
int client_fd: Le descripteur de fichier du client.
|
||||
const std::string &message: Le message à envoyer.
|
||||
Détails: Utilise send() pour envoyer le message au client.
|
||||
|
||||
Lecture Ligne par Ligne : Utilisez std::istringstream pour lire le message ligne par ligne et traiter chaque commande séparément.
|
||||
Suppression des Caractères de Fin de Ligne : Utilisez erase et std::remove pour supprimer les caractères \r et \n de chaque ligne avant de traiter la commande.
|
||||
Vérification du Mot de Passe : Si le client n'est pas authentifié, vérifiez s'il envoie la commande PASS et validez le mot de passe. Sinon, répondez avec un message demandant le mot de passe.
|
||||
Explications des Modifications
|
||||
Notification de Jonction : Lorsque le client rejoint un canal, le serveur envoie une notification de jonction avec la commande JOIN.
|
||||
|
||||
|
||||
std::stringstream joinMsg;
|
||||
joinMsg << ":" << client->getFd() << " JOIN " << channelName << "\r\n";
|
||||
sendToClient(client->getFd(), joinMsg.str());
|
||||
Liste des Utilisateurs : Le serveur envoie la liste des utilisateurs dans le canal en utilisant le code de réponse 353.
|
||||
|
||||
|
||||
std::string usersList = getUsersList(channel);
|
||||
sendToClient(client->getFd(), usersList);
|
||||
Fin de la Liste des Utilisateurs : Le serveur envoie un message de fin de liste des utilisateurs avec le code de réponse 366.
|
||||
|
||||
std::stringstream endOfNamesMsg;
|
||||
endOfNamesMsg << ":server 366 " << client->getFd() << " " << channelName << " :End of /NAMES list.\r\n";
|
||||
sendToClient(client->getFd(), endOfNamesMsg.str());
|
||||
Fonction getUsersList : Cette fonction génère la liste des utilisateurs dans le canal en utilisant le format correct.
|
||||
|
||||
std::string Server::getUsersList(Channel *channel)
|
||||
{
|
||||
std::vector<Client *> clients = channel->getClients();
|
||||
std::stringstream ss;
|
||||
ss << ":server 353 " << clients[0]->getFd() << " = " << channel->getName() << " :";
|
||||
for (size_t i = 0; i < clients.size(); ++i)
|
||||
{
|
||||
if (i > 0)
|
||||
ss << " ";
|
||||
ss << clients[i]->getFd();
|
||||
}
|
||||
ss << "\r\n";
|
||||
return ss.str();
|
||||
}
|
||||
Avec ces modifications, votre serveur IRC devrait maintenant informer correctement le client HexChat des utilisateurs présents dans un canal, ce qui devrait faire apparaître les canaux et leurs utilisateurs correctement dans l'interface du client.
|
||||
|
||||
*/
|
||||
37
ft_irc3/src/Utils.cpp
Normal file
37
ft_irc3/src/Utils.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Utils.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/05/15 12:17:59 by fgras-ca #+# #+# */
|
||||
/* Updated: 2024/05/16 18:17:21 by fgras-ca ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "Utils.hpp"
|
||||
|
||||
std::vector<std::string> split(const std::string &input, const std::string &delimiters)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
size_t startPos = 0;
|
||||
size_t foundPos = input.find_first_of(delimiters, startPos);
|
||||
|
||||
while (foundPos != std::string::npos)
|
||||
{
|
||||
if (foundPos != startPos)
|
||||
{
|
||||
result.push_back(input.substr(startPos, foundPos - startPos));
|
||||
}
|
||||
startPos = foundPos + 1;
|
||||
foundPos = input.find_first_of(delimiters, startPos);
|
||||
}
|
||||
|
||||
if (startPos < input.length())
|
||||
{
|
||||
result.push_back(input.substr(startPos));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
33
ft_irc3/src/main.cpp
Normal file
33
ft_irc3/src/main.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* main.cpp :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: fgras-ca <fgras-ca@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2024/05/15 12:16:41 by fgras-ca #+# #+# */
|
||||
/* Updated: 2024/05/15 12:49:07 by fgras-ca ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
#include "Server.hpp"
|
||||
#include "Utils.hpp"
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
std::cerr << RED << "Usage: " << argv[0] << " <port> <password>" << RESET << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int port = std::atoi(argv[1]);
|
||||
std::string password = argv[2];
|
||||
|
||||
Server server(port, password);
|
||||
server.run();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user