commit a1a7eb5b5713b2bc21e37c5a0207f62dc1c39ea0 Author: Ladebeze66 Date: Thu May 9 14:57:34 2024 +0200 dd diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..c2098a2 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -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 +} \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1f13c6c --- /dev/null +++ b/.vscode/launch.json @@ -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_irc/ft_irc/src", + "program": "/home/fgras-ca/Bureau/ft_irc/ft_irc/src/build/Debug/outDebug", + "MIMode": "gdb", + "miDebuggerPath": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..5b9128d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,107 @@ +{ + "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, + "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", + "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" + } +} \ No newline at end of file diff --git a/en.subject (2).pdf b/en.subject (2).pdf new file mode 100644 index 0000000..e744cc1 --- /dev/null +++ b/en.subject (2).pdf @@ -0,0 +1,227 @@ + ft_irc + + Internet Relay Chat + + Summary: + This project is about creating your own IRC server. + You will use an actual IRC client to connect to your server and test it. +Internet is ruled by solid standards protocols that allow connected computers to interact + + with each other. + It’s always a good thing to know. + + Version: 8 + Contents + +I Introduction 2 + +II General rules 3 + +III Mandatory Part 4 + + III.1 Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 + + III.2 For MacOS only . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 + + III.3 Test example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6 + +IV Bonus part 7 + +V Submission and peer-evaluation 8 + + 1 + Chapter I +Introduction + +Internet Relay Chat or IRC is a text-based communication protocol on the Internet. +It offers real-time messaging that can be either public or private. Users can exchange +direct messages and join group channels. + + IRC clients connect to IRC servers in order to join channels. IRC servers are connected +together to form a network. + + 2 + Chapter II +General rules + + • Your program should not crash in any circumstances (even when it runs out of + memory), and should not quit unexpectedly. + If it happens, your project will be considered non-functional and your grade will be + 0. + + • You have to turn in a Makefile which will compile your source files. It must not + relink. + + • Your Makefile must at least contain the rules: + $(NAME), all, clean, fclean and re. + + • Compile your code with c++ and the flags -Wall -Wextra -Werror + • Your code must comply with the C++ 98 standard. Then, it should still compile + + if you add the flag -std=c++98. + • Try to always develop using the most C++ features you can (for example, choose + + over ). You are allowed to use C functions, but always prefer + their C++ versions if possible. + • Any external library and Boost libraries are forbidden. + + 3 + Chapter III +Mandatory Part + +Program name ircserv +Turn in files Makefile, *.{h, hpp}, *.cpp, *.tpp, *.ipp, +Makefile an optional configuration file +Arguments NAME, all, clean, fclean, re +External functs. port: The listening port + password: The connection password +Libft authorized Everything in C++ 98. +Description socket, close, setsockopt, getsockname, + getprotobyname, gethostbyname, getaddrinfo, + freeaddrinfo, bind, connect, listen, accept, htons, + htonl, ntohs, ntohl, inet_addr, inet_ntoa, send, + recv, signal, sigaction, lseek, fstat, fcntl, poll + (or equivalent) + n/a + An IRC server in C++ 98 + +You have to develop an IRC server in C++ 98. + +You mustn’t develop a client. +You mustn’t handle server-to-server communication. + +Your executable will be run as follows: + ./ircserv + +• port: The port number on which your IRC server will be listening to for incoming + IRC connections. + +• password: The connection password. It will be needed by any IRC client that tries + to connect to your server. + +Even if poll() is mentionned in the subject and the evaluation scale, +you can use any equivalent such as select(), kqueue(), or epoll(). + + 4 + ft_irc Internet Relay Chat + +III.1 Requirements + + • The server must be capable of handling multiple clients at the same time and never + hang. + + • Forking is not allowed. All I/O operations must be non-blocking. + + • Only 1 poll() (or equivalent) can be used for handling all these operations (read, + write, but also listen, and so forth). + + Because you have to use non-blocking file descriptors, it is + possible to use read/recv or write/send functions with no poll() + (or equivalent), and your server wouldn’t be blocking. + But it would consume more system resources. + + Thus, if you try to read/recv or write/send in any file descriptor + + without using poll() (or equivalent), your grade will be 0. + +• Several IRC clients exist. You have to choose one of them as a reference. Your + reference client will be used during the evaluation process. + +• Your reference client must be able to connect to your server without encountering + any error. + +• Communication between client and server has to be done via TCP/IP (v4 or v6). + +• Using your reference client with your server must be similar to using it with any + official IRC server. However, you only have to implement the following features: + + ◦ You must be able to authenticate, set a nickname, a username, join a channel, + send and receive private messages using your reference client. + + ◦ All the messages sent from one client to a channel have to be forwarded to + every other client that joined the channel. + + ◦ You must have operators and regular users. + + ◦ Then, you have to implement the commands that are specific to channel + operators: + ∗ KICK - Eject a client from the channel + ∗ INVITE - Invite a client to a channel + ∗ TOPIC - Change or view the channel topic + ∗ MODE - Change the channel’s mode: + · i: Set/remove Invite-only channel + · t: Set/remove the restrictions of the TOPIC command to channel + operators + · k: Set/remove the channel key (password) + · o: Give/take channel operator privilege + + 5 + ft_irc Internet Relay Chat + · l: Set/remove the user limit to channel + + • Of course, you are expected to write a clean code. + +III.2 For MacOS only + +Since MacOS doesn’t implement write() the same way as other Unix +OSes, you are allowed to use fcntl(). +You must use file descriptors in non-blocking mode in order to get a +behavior similar to the one of other Unix OSes. + +However, you are allowed to use fcntl() only as follows: +fcntl(fd, F_SETFL, O_NONBLOCK); +Any other flag is forbidden. + +III.3 Test example + +Verify absolutely every possible error and issue (receiving partial data, low bandwidth, +and so forth). + + To ensure that your server correctly processes everything that you send to it, the +following simple test using nc can be done: + + \$> nc 127.0.0.1 6667 + com^Dman^Dd + \$> + + Use ctrl+D to send the command in several parts: ’com’, then ’man’, then ’d\n’. + + In order to process a command, you have to first aggregate the received packets in +order to rebuild it. + +6 + Chapter IV +Bonus part + +Here are the extra features you can add to your IRC server so it looks even more like and +actual IRC server: + + • Handle file transfer. + • A bot. + + The bonus part will only be assessed if the mandatory part is + PERFECT. Perfect means the mandatory part has been integrally done + and works without malfunctioning. If you have not passed ALL the + mandatory requirements, your bonus part will not be evaluated at all. + + 7 + Chapter V +Submission and peer-evaluation + +Turn in your assignment in your Git repository as usual. Only the work inside your repos- +itory will be evaluated during the defense. Don’t hesitate to double check the names of +your files to ensure they are correct. + + You are encouraged to create test programs for your project even though they won’t +be submitted and won’t be graded. Those tests could be especially useful to test +your server during defense, but also your peer’s if you have to evaluate another ft_irc +one day. Indeed, you are free to use whatever tests you need during the evaluation process. + + Your reference client will be used during the evaluation process. + + 16D85ACC441674FBA2DF65190663F432222F81AA0248081A7C1C1823F7A96F0B74495 + 15056E97427E5B22F07132659EC8D88B574BD62C94BB654D5835AAD889B014E078705 + 709F6E02 + + 8 + diff --git a/ft_irc/Makefile b/ft_irc/Makefile new file mode 100644 index 0000000..f454d7a --- /dev/null +++ b/ft_irc/Makefile @@ -0,0 +1,53 @@ +# **************************************************************************** # +# # +# ::: :::::::: # +# Makefile :+: :+: :+: # +# +:+ +:+ +:+ # +# By: fgras-ca +#+ +:+ +#+ # +# +#+#+#+#+#+ +#+ # +# Created: 2024/05/09 13:54:36 by fgras-ca #+# #+# # +# Updated: 2024/05/09 13:54:48 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) -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 diff --git a/ft_irc/build/Channel.o b/ft_irc/build/Channel.o new file mode 100644 index 0000000..1b17daf Binary files /dev/null and b/ft_irc/build/Channel.o differ diff --git a/ft_irc/build/Client.o b/ft_irc/build/Client.o new file mode 100644 index 0000000..d40aa38 Binary files /dev/null and b/ft_irc/build/Client.o differ diff --git a/ft_irc/build/CommandHandler.o b/ft_irc/build/CommandHandler.o new file mode 100644 index 0000000..d867b84 Binary files /dev/null and b/ft_irc/build/CommandHandler.o differ diff --git a/ft_irc/build/Server.o b/ft_irc/build/Server.o new file mode 100644 index 0000000..b90c263 Binary files /dev/null and b/ft_irc/build/Server.o differ diff --git a/ft_irc/build/main.o b/ft_irc/build/main.o new file mode 100644 index 0000000..384cf5e Binary files /dev/null and b/ft_irc/build/main.o differ diff --git a/ft_irc/build/utilities.o b/ft_irc/build/utilities.o new file mode 100644 index 0000000..7efbe16 Binary files /dev/null and b/ft_irc/build/utilities.o differ diff --git a/ft_irc/include/Channel.hpp b/ft_irc/include/Channel.hpp new file mode 100644 index 0000000..ec30245 --- /dev/null +++ b/ft_irc/include/Channel.hpp @@ -0,0 +1,33 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Channel.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:07:50 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:33:01 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef CHANNEL_HPP +#define CHANNEL_HPP + +#include "Client.hpp" +#include +#include +#include + +class Channel { +public: + Channel(const std::string& name); + void addClient(Client* client); + void removeClient(Client* client); + void broadcastMessage(const std::string& message, Client* sender); + +private: + std::string name; + std::vector clients; +}; + +#endif diff --git a/ft_irc/include/Client.hpp b/ft_irc/include/Client.hpp new file mode 100644 index 0000000..85dc221 --- /dev/null +++ b/ft_irc/include/Client.hpp @@ -0,0 +1,36 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Client.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:07:00 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:33:20 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef CLIENT_HPP +#define CLIENT_HPP + +#include +#include +#include +#include + +class Client { +public: + Client(int socket, const std::string& nickname, const std::string& username); + ~Client(); + + void sendMessage(const std::string& message); + std::string receiveMessage(); + void setNickname(const std::string& newNickname); // Ajout de la méthode setNickname + +private: + int socket; + std::string nickname; + std::string username; +}; + +#endif diff --git a/ft_irc/include/CommandHandler.hpp b/ft_irc/include/CommandHandler.hpp new file mode 100644 index 0000000..0d841c3 --- /dev/null +++ b/ft_irc/include/CommandHandler.hpp @@ -0,0 +1,42 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* CommandHandler.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:19:30 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:49:16 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef COMMANDHANDLER_HPP +#define COMMANDHANDLER_HPP + +#include "Client.hpp" +#include "Channel.hpp" +#include "Utilities.hpp" +#include +#include +#include +#include + +class CommandHandler { +public: + CommandHandler(); + ~CommandHandler(); + void handleCommand(const std::string& command, Client* client); + +private: + std::map channels; + + 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); + + std::vector split(const std::string& s, char delimiter); +}; + +#endif // COMMANDHANDLER_HPP diff --git a/ft_irc/include/Server.hpp b/ft_irc/include/Server.hpp new file mode 100644 index 0000000..2a44f32 --- /dev/null +++ b/ft_irc/include/Server.hpp @@ -0,0 +1,45 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Server.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:01:12 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:39:02 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef SERVER_HPP +#define SERVER_HPP + +#include +#include +#include "Client.hpp" +#include "CommandHandler.hpp" +#include +#include +#include +#include +#include +#include +#include + +class Server { +public: + Server(int port, const std::string& password); + ~Server(); + bool initialize(); + void run(); + +private: + int listener; // Socket descriptor for the server + int port; // Port number to bind the server + std::string password; // Server password for client connections + bool running; // Server running status + std::vector clients; // List of connected clients + + void manageClient(Client* client, CommandHandler& cmdHandler); +}; + +#endif // SERVER_HPP diff --git a/ft_irc/include/Utilities.hpp b/ft_irc/include/Utilities.hpp new file mode 100644 index 0000000..ca3e665 --- /dev/null +++ b/ft_irc/include/Utilities.hpp @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utilities.hpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:22:54 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:35:04 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#ifndef UTILITIES_HPP +#define UTILITIES_HPP + +#include +#include +#include +#include +#include +#include + +namespace Utilities { + // Split a string by a delimiter and return a vector of substrings + std::vector split(const std::string& s, char delimiter); + + // Trim whitespace from the start and end of a string + std::string trim(const std::string& s); +} + +#endif // UTILITIES_HPP diff --git a/ft_irc/ircserv b/ft_irc/ircserv new file mode 100755 index 0000000..ae7b473 Binary files /dev/null and b/ft_irc/ircserv differ diff --git a/ft_irc/src/Channel.cpp b/ft_irc/src/Channel.cpp new file mode 100644 index 0000000..71b5d82 --- /dev/null +++ b/ft_irc/src/Channel.cpp @@ -0,0 +1,32 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Channel.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:08:13 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:38:23 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "Channel.hpp" +#include + +Channel::Channel(const std::string& name) : name(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()); +} + +void Channel::broadcastMessage(const std::string& message, Client* sender) { + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + if (*it != sender) { // Ensure we don't send the message back to the sender + (*it)->sendMessage(message); + } + } +} diff --git a/ft_irc/src/Client.cpp b/ft_irc/src/Client.cpp new file mode 100644 index 0000000..3f475da --- /dev/null +++ b/ft_irc/src/Client.cpp @@ -0,0 +1,38 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Client.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:33:11 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "Client.hpp" + +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) { + 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), 0); + if (len > 0) { + return std::string(buffer, len); + } + return ""; +} + +void Client::setNickname(const std::string& newNickname) { + nickname = newNickname; +} diff --git a/ft_irc/src/CommandHandler.cpp b/ft_irc/src/CommandHandler.cpp new file mode 100644 index 0000000..a605ea9 --- /dev/null +++ b/ft_irc/src/CommandHandler.cpp @@ -0,0 +1,93 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* CommandHandler.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:19:15 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:33:32 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "CommandHandler.hpp" + +CommandHandler::CommandHandler() {} + +CommandHandler::~CommandHandler() { + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { + delete it->second; + } + channels.clear(); +} + +void CommandHandler::handleCommand(const std::string& command, Client* client) { + if (command.find("JOIN ") == 0) { + handleJoin(command, client); + } else if (command.find("PART ") == 0) { + handlePart(command, client); + } else if (command.find("NICK ") == 0) { + handleNick(command, client); + } else if (command.find("PRIVMSG ") == 0) { + handlePrivmsg(command, client); + } else if (command == "QUIT") { + handleQuit(client); + } +} + +void CommandHandler::handleJoin(const std::string& command, Client* client) { + std::vector tokens = split(command, ' '); + if (tokens.size() > 1) { + std::string channelName = tokens[1]; + if (channels.find(channelName) == channels.end()) { + channels[channelName] = new Channel(channelName); + } + channels[channelName]->addClient(client); + channels[channelName]->broadcastMessage("JOIN " + channelName, client); + } +} + +void CommandHandler::handlePart(const std::string& command, Client* client) { + std::vector tokens = split(command, ' '); + if (tokens.size() > 1) { + std::string channelName = tokens[1]; + if (channels.find(channelName) != channels.end()) { + channels[channelName]->removeClient(client); + channels[channelName]->broadcastMessage("PART " + channelName, client); + } + } +} + +void CommandHandler::handleNick(const std::string& command, Client* client) { + std::vector tokens = split(command, ' '); + if (tokens.size() > 1) { + client->setNickname(tokens[1]); + } +} + +void CommandHandler::handlePrivmsg(const std::string& command, Client* client) { + std::vector tokens = split(command, ' '); + if (tokens.size() > 2) { + std::string target = tokens[1]; + std::string message = command.substr(command.find(" :") + 2); + if (channels.find(target) != channels.end()) { + channels[target]->broadcastMessage("PRIVMSG " + message, client); + } + } +} + +void CommandHandler::handleQuit(Client* client) { + for (std::map::iterator it = channels.begin(); it != channels.end(); ++it) { + it->second->removeClient(client); + } +} + +std::vector CommandHandler::split(const std::string& s, char delimiter) { + std::vector tokens; + std::stringstream ss(s); + std::string item; + while (getline(ss, item, delimiter)) { + tokens.push_back(item); + } + return tokens; +} diff --git a/ft_irc/src/Server.cpp b/ft_irc/src/Server.cpp new file mode 100644 index 0000000..56780e2 --- /dev/null +++ b/ft_irc/src/Server.cpp @@ -0,0 +1,95 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* Server.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:01:34 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:48:31 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "Server.hpp" + +Server::Server(int port, const std::string& password) : port(port), password(password), running(false) {} + +Server::~Server() { + // Nettoyage des ressources si nécessaire + close(listener); // Assurez-vous de fermer le socket d'écoute + // Nettoyage des clients dynamiquement alloués, si vous ne l'avez pas déjà fait + for (std::vector::iterator it = clients.begin(); it != clients.end(); ++it) { + delete *it; + } +} + +bool Server::initialize() { + struct sockaddr_in server_addr; + + // Création du socket + listener = socket(AF_INET, SOCK_STREAM, 0); + if (listener == -1) { + std::cerr << "Error creating socket: " << strerror(errno) << std::endl; + return false; + } + + // Préparation de l'adresse du serveur + 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); + + // Liaison du socket + if (bind(listener, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { + std::cerr << "Error binding socket: " << strerror(errno) << std::endl; + close(listener); + return false; + } + + // Mise en écoute du socket + if (listen(listener, 10) == -1) { // backlog set to 10 + std::cerr << "Error listening: " << strerror(errno) << std::endl; + close(listener); + return false; + } + + std::cout << "Server initialized and listening on port " << port << std::endl; + return true; +} + +void Server::run() { + running = true; + struct sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); + CommandHandler cmdHandler; + + while (running) { + int client_sock = accept(listener, (struct sockaddr *)&client_addr, &client_len); + if (client_sock == -1) { + std::cerr << "Error accepting connection: " << strerror(errno) << std::endl; + continue; + } + + std::cout << "Client connected: " << client_sock << std::endl; + try { + // Créez un nouvel objet Client avec des valeurs par défaut pour nickname et username + Client* newClient = new Client(client_sock, "DefaultNickname", "DefaultUsername"); + std::string welcomeMsg = "Welcome to the IRC Server!\n"; + newClient->sendMessage(welcomeMsg); + manageClient(newClient, cmdHandler); + } catch (const std::exception& e) { + std::cerr << "Exception handling client: " << e.what() << std::endl; + close(client_sock); + } + } +} + +void Server::manageClient(Client* client, CommandHandler& cmdHandler) { + // Boucle pour recevoir les commandes du client + while (running) { + std::string command = client->receiveMessage(); + if (command.empty()) break; // Client disconnected + cmdHandler.handleCommand(command, client); + } + delete client; // Cleanup when client disconnects +} diff --git a/ft_irc/src/main.cpp b/ft_irc/src/main.cpp new file mode 100644 index 0000000..366aabf --- /dev/null +++ b/ft_irc/src/main.cpp @@ -0,0 +1,31 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* main.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:00:46 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:00:52 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "Server.hpp" + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " " << std::endl; + return 1; + } + int port = std::atoi(argv[1]); + std::string password = argv[2]; + + Server ircServer(port, password); + if (!ircServer.initialize()) { + std::cerr << "Failed to initialize server." << std::endl; + return 1; + } + ircServer.run(); + + return 0; +} diff --git a/ft_irc/src/utilities.cpp b/ft_irc/src/utilities.cpp new file mode 100644 index 0000000..cf22ea1 --- /dev/null +++ b/ft_irc/src/utilities.cpp @@ -0,0 +1,35 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* utilities.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: fgras-ca +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2024/05/09 14:23:12 by fgras-ca #+# #+# */ +/* Updated: 2024/05/09 14:34:50 by fgras-ca ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "Utilities.hpp" + +namespace Utilities { + +std::vector split(const std::string& s, char delimiter) { + std::vector tokens; + std::string token; + std::istringstream tokenStream(s); + while (std::getline(tokenStream, token, delimiter)) { + tokens.push_back(trim(token)); + } + return tokens; +} + +std::string trim(const std::string& str) { + size_t first = str.find_first_not_of(' '); + if (first == std::string::npos) + return ""; + size_t last = str.find_last_not_of(' '); + return str.substr(first, (last - first + 1)); +} + +} diff --git a/notessujet b/notessujet new file mode 100644 index 0000000..a68890c --- /dev/null +++ b/notessujet @@ -0,0 +1,319 @@ +FT_IRC + +Ce projet consiste à créer votre propre serveur IRC (Internet Relay Chat). Vous utiliserez un client IRC actuel pour vous connecter à votre serveur et le tester. L'Internet est régi par des protocoles de standards solides qui permettent aux ordinateurs connectés de communiquer entre eux. C'est toujours bénéfique de connaître ces protocoles. + +Chapitre I - Introduction + +L'Internet Relay Chat, ou IRC, est un protocole de communication basé sur le texte sur Internet. Il offre des messageries en temps réel qui peuvent être publiques ou privées. Les utilisateurs peuvent échanger des messages directs et rejoindre des canaux de groupe. Les clients IRC se connectent aux serveurs IRC pour rejoindre ces canaux. Les serveurs IRC sont connectés entre eux pour former un réseau. + + La mise en place d'un serveur IRC implique plusieurs étapes clés que nous pouvons explorer brièvement : + +1. Initialisation du serveur +Création d'un socket serveur : C'est le premier point de contact entre votre serveur et les clients IRC. Vous utilisez la fonction socket() pour créer un socket. +Liaison du socket : Utilisez la fonction bind() pour associer le socket à une adresse IP et un numéro de port spécifiques. +Écoute des connexions entrantes : Avec listen(), votre serveur se met à écouter sur le port spécifié, prêt à accepter les connexions client. + +2. Gestion des connexions client +Acceptation des connexions : La fonction accept() permet au serveur d'accepter une connexion entrante d'un client. +Gestion multithread ou multiplexage : Pour gérer plusieurs clients en même temps, utilisez le multithreading (avec std::thread en C++11 ou plus) ou le multiplexage des entrées/sorties (par exemple, select() ou poll()). + +3. Interprétation des commandes IRC +Réception des messages : Les messages des clients sont reçus en continu. Chaque message doit être analysé pour identifier la commande (par exemple, JOIN, NICK, PRIVMSG). +Exécution des commandes : En fonction de la commande, le serveur exécutera différentes actions, comme rejoindre un canal ou envoyer un message à un autre utilisateur. + +4. Envoi de réponses et de messages +Formatage des réponses : Les réponses aux commandes doivent être formatées selon les spécifications du protocole IRC, puis envoyées au client concerné. +Diffusion : Pour les messages comme ceux d’un canal IRC, le serveur doit envoyer le message à tous les utilisateurs présents dans le canal. + +5. Gestion des erreurs et de la stabilité +Traitement des exceptions : Assurez-vous de gérer les exceptions pour éviter que le serveur ne se termine de manière inattendue. +Surveillance des ressources : Surveillez l'utilisation de la mémoire et les performances pour éviter les dépassements de mémoire et les fuites. + +6. Fermeture et nettoyage +Déconnexion propre : Lorsqu'un client se déconnecte ou lors de la fermeture du serveur, assurez-vous de fermer proprement tous les sockets et de libérer toutes les ressources utilisées. +Voici un petit exemple de code pour initialiser un socket serveur en C++ : + +#include +#include +#include +#include + +int main() { + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + std::cerr << "Erreur de création de socket" << std::endl; + return 1; + } + + sockaddr_in server_addr; + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(6667); // Port standard pour IRC + + if (bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "Erreur de liaison" << std::endl; + return 1; + } + + listen(sockfd, 5); + std::cout << "Serveur IRC en écoute sur le port 6667" << std::endl; + + // Ajouter ici le code pour accepter les connexions et traiter les clients + + return 0; +} + +Chapitre II - Règles générales + +Votre programme ne doit pas planter dans aucune circonstance (même en cas de pénurie de mémoire), et ne doit pas se terminer de manière inattendue. Si cela arrive, votre projet sera considéré comme non fonctionnel et votre note sera de 0. +Vous devez fournir un Makefile qui compilera vos fichiers sources. Ce Makefile ne doit pas recompiler les objets déjà compilés. +Votre Makefile doit contenir au minimum les règles : $(NAME), all, clean, fclean et re. +Compilez votre code avec g++ et les drapeaux -Wall -Wextra -Werror. +Votre code doit être conforme à la norme C++ 98. Il doit toujours être compilable si vous ajoutez le drapeau -std=c++98. +Essayez d'utiliser le plus possible les fonctionnalités de C++ (par exemple, préférez à ). Vous êtes autorisé à utiliser des fonctions C, mais préférez toujours leurs versions C++ si possible. +L'utilisation de toute bibliothèque externe et des bibliothèques Boost est interdite. + +Chapitre III - Partie Obligatoire + +Description du Programme +Nom du programme : ircserv +Fichiers à rendre : Makefile, *.{h, hpp}, *.cpp, *.tpp, *.ipp, un fichier de configuration optionnel +Règles du Makefile : NAME, all, clean, fclean, re +Arguments du programme : + +port : Le port d'écoute pour les connexions entrantes IRC. +password : Le mot de passe de connexion, nécessaire pour tout client IRC tentant de se connecter au serveur. + +Fonctions externes autorisées +Toutes ces fonctions doivent être utilisées conformément à la norme C++ 98 : + +Fonctions de gestion de socket +Bibliothèque +close() : Ferme un descripteur de fichier, donc le socket, libérant toutes les ressources. +Bibliothèque +socket() : Crée un point de communication (socket) et renvoie un descripteur de fichier. +setsockopt() : Configure les options du socket, permettant de modifier son comportement à divers niveaux. +bind() : Associe une adresse locale à un socket, spécifiant le port et l'adresse IP pour les connexions entrantes. +connect() : Initie une connexion sur un socket spécifié à une adresse distante. +listen() : Écoute les connexions sur un socket spécifique. +accept() : Accepte une connexion entrante sur un socket en écoute, créant un nouveau socket connecté pour cette connexion. +send() : Envoie des données à la connexion spécifiée par le descripteur de socket. +recv() : Reçoit des données d'une connexion spécifiée par le descripteur de socket. + +Fonctions de manipulation de données réseau +Bibliothèque +htons() : Convertit un short (16 bits) de l'ordre des octets de l'hôte à celui du réseau. +htonl() : Convertit un long (32 bits) de l'ordre des octets de l'hôte à celui du réseau. +ntohs() : Convertit un short (16 bits) de l'ordre des octets du réseau à celui de l'hôte. +ntohl() : Convertit un long (32 bits) de l'ordre des octets du réseau à celui de l'hôte. +Bibliothèque +inet_addr() : Convertit une chaîne de caractères représentant une adresse IPv4 en un entier approprié. +inet_ntoa() : Convertit une adresse IP de sa forme numérique en une chaîne de caractères. + +Fonctions de résolution de noms +Bibliothèque +getprotobyname() : Renvoie des informations sur un protocole spécifique (par exemple "tcp") identifié par son nom. +gethostbyname() : Renvoie des informations sur un hôte, y compris son adresse IP, identifié par son nom. +getaddrinfo() : Fournit des informations d'adresse pour configurer des connexions socket. +freeaddrinfo() : Libère la mémoire allouée par getaddrinfo(). + +Fonctions de signalisation et multiplexage +Bibliothèque +signal() : Permet de gérer des signaux, tels que SIGINT, en définissant la fonction appelée lors de la réception d'un signal. +sigaction() : Permet de gérer des signaux de manière plus précise que signal(), offrant plus de contrôle sur le comportement du signal. +poll() : Attends un événement sur un ensemble de descripteurs de fichiers, très utile pour gérer plusieurs connexions. +Bibliothèque + +Fonctions de manipulation de fichiers et contrôles +lseek() : Positionne le descripteur de fichier (par exemple, pour revenir au début d'un fichier). +Bibliothèque et +fstat() : Obtient les informations d'état d'un fichier ouvert. +Bibliothèque +fcntl() : Manipule les propriétés d'un fichier ouvert, comme le blocage ou le comportement non-blocant de l'opération. +Ces fonctions offrent une base solide pour gérer les sockets, les connexions réseau, la conversion d'adresses, la gestion des signaux, et la manipulation basique des fichiers, tous essentiels pour construire un serveur IRC robuste. + +(Notez que d'autres fonctions comme select(), epoll() et kqueue() peuvent venir de différentes bibliothèques, notamment , et pour kqueue() si vous utilisez un système comme BSD ou macOS.) + +Même si pool() est mentionné dans le sujet, vous pouvez utiliser n'importe quel équivalent comme select(), kqueue(), ou epoll(). + +Exemple de démarrage du serveur IRC +Voici un exemple de code simplifié montrant comment initialiser un serveur en écoutant sur un port et en utilisant un mot de passe pour authentifier les clients. Ce code est purement illustratif pour vous donner une idée de la structure : + +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + if (argc != 3) { + std::cerr << "Usage: ./ircserv " << std::endl; + return 1; + } + + int port = std::atoi(argv[1]); + const char* password = argv[2]; + + int sockfd = socket(AF_INET, SOCK_STREAM, 0); + if (sockfd < 0) { + std::cerr << "Could not create socket" << std::endl; + return 1; + } + + sockaddr_in server_addr; + 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(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { + std::cerr << "Bind failed" << std::endl; + close(sockfd); + return 1; + } + + listen(sockfd, 5); + std::cout << "Server listening on port " << port << std::endl; + + // Ajout d'une boucle ici pour accepter les connexions et vérifier le mot de passe + + close(sockfd); + return 0; +} + +Chapitre III.1 - Exigences de votre serveur IRC + +Gestion des clients + +Multiclient : Le serveur doit être capable de gérer plusieurs clients simultanément sans jamais se bloquer. +Opérations non-bloquantes : Toutes les opérations d'entrée/sortie doivent être non-bloquantes. L'utilisation de fork() n'est pas autorisée. +Utilisation unique de poll() : Seul un appel à poll() (ou équivalent comme select(), epoll()) peut être utilisé pour gérer toutes les opérations (lecture, écriture, écoute, etc.). Bien que les opérations de lecture/écriture puissent être réalisées sans poll() pour rendre les descripteurs de fichiers non-bloquants, cela consommerait plus de ressources système. Si poll() n'est pas utilisé là où nécessaire, la note sera de 0. + +Choix et compatibilité du client IRC + +Client de référence : Vous devez choisir un client IRC spécifique comme référence, qui sera utilisé pendant le processus d'évaluation pour tester votre serveur. +Compatibilité : Votre client de référence doit pouvoir se connecter à votre serveur sans rencontrer d'erreurs. +Communication : La communication entre le client et le serveur doit se faire via TCP/IP (IPv4 ou IPv6). + +Fonctionnalités requises + +Authentification et gestion de l'utilisateur : Les utilisateurs doivent pouvoir s'authentifier, définir un pseudonyme (nickname), un nom d'utilisateur (username), rejoindre un canal, envoyer et recevoir des messages privés. +Gestion des canaux : Tous les messages envoyés à un canal doivent être transmis à tous les autres clients présents dans ce canal. +Utilisateurs et opérateurs : Votre serveur doit distinguer les opérateurs de canal des utilisateurs réguliers. + +Commandes spécifiques aux opérateurs de canal : +KICK : Expulser un client du canal. +INVITE : Inviter un client à rejoindre un canal. +TOPIC : Modifier ou afficher le sujet du canal. +MODE : Changer le mode du canal : +i : Activer/désactiver le canal sur invitation seulement. +t : Activer/désactiver les restrictions de la commande TOPIC aux opérateurs de canal. +k : Définir/supprimer la clé du canal (mot de passe). +o : Donner/retirer les privilèges d'opérateur de canal. +l : Définir/supprimer la limite d'utilisateurs dans le canal. + +Qualité du code + +Code propre : Un code bien organisé, clair et maintenable est attendu. + +Conseils de mise en œuvre +Architecture : Pensez à une architecture modulaire où chaque fonctionnalité (gestion des utilisateurs, gestion des canaux, traitement des commandes) est isolée pour faciliter le développement et la maintenance. +Tests : Développez des tests unitaires pour chaque composant pour assurer la fiabilité de votre serveur. +Sécurité : Soyez vigilant avec la gestion de la mémoire et la validation des entrées pour éviter les failles de sécurité. +Ces exigences définissent clairement les fonctionnalités que votre serveur doit implémenter et comment il doit être conçu pour interagir efficacement avec les clients IRC. + +Chapitre III.3 - Exemple de Test +Objectif du test +L'objectif de ce test est de vérifier la robustesse de votre serveur IRC en simulant des conditions réseau défavorables telles que la réception de données partielles ou une bande passante limitée. Ce type de test est crucial pour s'assurer que votre serveur peut gérer des situations où les données envoyées par les clients n'arrivent pas en une seule pièce mais plutôt en fragments. + +Description du test +Le test utilise l'outil nc (Netcat), qui est un utilitaire permettant de lire et écrire des données à travers des connexions réseau. Il est utilisé ici pour envoyer des commandes à votre serveur en plusieurs parties, pour simuler un client IRC envoyant des données de manière fragmentée. + +Procédure de test +1.Ouverture de la connexion : + +$> nc 127.0.0.1 6667 + +Cette commande ouvre une connexion TCP sur le port 6667 à l'adresse localhost (127.0.0.1), où votre serveur IRC est censé écouter. + +2.Envoi de commandes fragmentées : + +Tapez com puis appuyez sur Ctrl+D pour envoyer cette partie de la commande. +Tapez ensuite man et appuyez de nouveau sur Ctrl+D. +Enfin, tapez d\n et appuyez une dernière fois sur Ctrl+D pour terminer l'envoi. +Ctrl+D est utilisé ici pour simuler la fin de l'envoi de données, poussant Netcat à envoyer les données sans fermer la connexion. Cela permet de simuler l'envoi de données en morceaux, comme cela pourrait se produire dans des conditions de réseau réel avec des délais ou des interruptions. +Traitement des données fragmentées +Agrégation des paquets : Votre serveur doit être capable de reconstruire la commande complète à partir de ces fragments. Cela signifie que vous devez implémenter une logique pour stocker temporairement les fragments de données reçus jusqu'à ce que la commande soit complètement reçue et prête à être traitée. +Traitement de la commande : Une fois la commande entièrement reconstituée, votre serveur devrait la traiter comme il le ferait pour toute commande reçue en une seule fois. +Importance du test +Ce test est essentiel pour vérifier que votre serveur gère correctement les aspects de la transmission TCP tels que la segmentation des données et les délais de transmission, qui sont des réalités courantes dans les communications sur Internet. Il garantit que les commandes sont correctement reçues et traitées même lorsque les données arrivent en plusieurs morceaux. + +Ce type de test est crucial pour assurer la fiabilité et la robustesse de votre serveur dans des conditions réseau réalistes. Il est conseillé de réaliser des tests supplémentaires pour d'autres scénarios d'erreur possibles et de s'assurer que votre serveur est capable de gérer toutes sortes de situations sans planter ou sans perdre de données. + +Utilisation de Netcat + +Écouter sur un port spécifique +Pour démarrer Netcat en mode écoute (serveur) sur un port spécifique : + +nc -l 1234 + +Ceci configure Netcat pour écouter sur le port 1234. + +Se connecter à un serveur +Pour utiliser Netcat comme client et se connecter à un serveur : + +nc [adresse IP ou nom de domaine] [port] + +Par exemple, pour se connecter à un serveur local sur le port 1234 : + +nc 127.0.0.1 1234 + +Transférer un fichier +Netcat peut être utilisé pour transférer des fichiers entre un serveur et un client. + +Sur le serveur (réception) : + +nc -l 1234 > fichier_de_sortie.txt + +Sur le client (envoi) : + +nc [adresse IP du serveur] 1234 < fichier_à_envoyer.txt + +Chat simple +Netcat peut être utilisé pour créer un chat basique en réseau entre deux machines. + +Sur la machine A (serveur) : + +nc -l 1234 + +Sur la machine B (client) : + +nc [adresse IP de A] 1234 + +Après ces commandes, chaque texte entré dans la console de Netcat sera envoyé à l'autre partie. + +Chapitre IV - Partie Bonus + +Si vous avez complété avec succès toutes les exigences obligatoires de votre projet de serveur IRC et que tout fonctionne parfaitement, vous pouvez envisager d'ajouter des fonctionnalités supplémentaires pour enrichir votre serveur. Voici quelques suggestions pour la partie bonus : + +1. Gestion du transfert de fichiers + +Implémentation de DCC (Direct Client-to-Client) : Le protocole DCC permet aux utilisateurs de votre serveur IRC de transférer des fichiers directement entre eux. Cette fonctionnalité peut être complexe, car elle implique la gestion de connexions peer-to-peer en plus des communications client-serveur habituelles. +Sécurité et validation : Assurez-vous que le transfert de fichiers est sécurisé et que les fichiers sont correctement validés pour éviter le transfert de malwares. + +2. Création d'un bot IRC + +Fonctionnalités du bot : Le bot pourrait offrir des services comme la gestion des commandes administratives, la fourniture d'informations en temps réel (météo, nouvelles), des jeux, ou des rappels. +Interaction avec les utilisateurs : Le bot devrait être capable de répondre aux commandes des utilisateurs et d'effectuer des actions spécifiques basées sur ces commandes. +Automatisation : Le bot pourrait également surveiller les conversations dans les canaux pour modérer les discussions ou notifier les opérateurs de certains événements. + +Points à considérer pour les fonctionnalités bonus +Intégrité de la partie obligatoire : Avant de vous lancer dans le développement des fonctionnalités bonus, assurez-vous que toutes les fonctionnalités obligatoires sont complètement fonctionnelles et exemptes de bugs. Les fonctionnalités bonus ne seront évaluées que si la partie obligatoire est jugée "parfaite". +Documentation et tests : Tout comme pour les fonctionnalités obligatoires, documentez bien vos fonctionnalités bonus et assurez-vous qu'elles sont bien testées. Les tests devraient couvrir non seulement les cas d'utilisation normaux mais aussi les cas d'erreur et les limites de performance. + +Conseils de développement +Modularité : Essayez de garder votre code aussi modulaire que possible. Cela vous permettra d'ajouter des fonctionnalités bonus sans perturber le fonctionnement de base de votre serveur. +Scalabilité : Pensez à la scalabilité de votre serveur avec ces nouvelles fonctionnalités. Assurez-vous que l'ajout de fonctionnalités comme le transfert de fichiers et un bot n'impactera pas négativement la performance générale du serveur. +Conformité aux standards : Même pour les fonctionnalités bonus, tenez-vous aux standards IRC et aux bonnes pratiques de programmation pour garantir que votre serveur peut interagir correctement avec d'autres clients et serveurs IRC. + +Ces fonctionnalités bonus peuvent grandement enrichir l'expérience utilisateur sur votre serveur IRC, le rendant plus attractif et plus utile pour vos utilisateurs. diff --git a/plan b/plan new file mode 100644 index 0000000..ca570f5 --- /dev/null +++ b/plan @@ -0,0 +1,84 @@ +Plan d'action pour le développement + +Étape 1: Configuration de l'environnement de développement + +Installation des outils : Assurez-vous d'avoir un compilateur C++ qui supporte C++98, comme g++. +Structure de base du projet : Créez un répertoire de projet avec des sous-répertoires pour les fichiers sources (src), les en-têtes (include), et les objets (build). + +Étape 2: Conception de l'architecture de base + +Définition des modules : Identifiez les principaux composants du serveur, tels que la gestion des connexions réseau, le traitement des commandes IRC, et la gestion des utilisateurs et des canaux. +Création des fichiers : +main.cpp : Le point d'entrée du programme. +Server.cpp et Server.hpp : Gérer la logique du serveur, les sockets, et les connexions. +Client.cpp et Client.hpp : Gérer les informations et interactions spécifiques aux clients. +Channel.cpp et Channel.hpp : Gérer les opérations liées aux canaux. +CommandHandler.cpp et CommandHandler.hpp : Interpréter et exécuter les commandes IRC. +Utilities.cpp et Utilities.hpp : Fonctions utilitaires, comme la manipulation de chaînes et le logging. + +Étape 3: Implémentation des fonctionnalités de base + +Gestion des sockets : Écrivez le code pour créer, lier, et écouter les sockets. +Connexion des clients : Implémentez la logique pour accepter les nouvelles connexions des clients. +Réception et envoi de messages : Codez la réception des commandes des clients et l'envoi de réponses. + +Étape 4: Gestion des commandes et des canaux + +Traitement des commandes : Développez le traitement des commandes telles que JOIN, NICK, PRIVMSG. +Gestion des canaux : Implémentez la logique pour créer, modifier, et gérer les canaux. + +Étape 5: Tests et débogage + +Tests unitaires : Écrivez des tests pour chaque composant. +Tests d'intégration : Testez le fonctionnement global du serveur avec des clients IRC. +Débogage : Corrigez les bugs identifiés lors des tests. + +Étape 6: Préparation pour les fonctionnalités bonus + +Architecture extensible : Assurez-vous que votre conception permet facilement l'ajout de nouvelles fonctionnalités, comme le transfert de fichiers ou un bot IRC. +Documentation : Documentez les points d'extension pour les fonctionnalités bonus. + +Étape 7: Documentation et finalisation + +Documentation du code : Assurez-vous que chaque fonction et module est bien documenté. +Nettoyage du code : Revoyez votre code pour vous assurer qu'il est propre et bien organisé. +Intégration des fonctionnalités bonus +Planification conditionnelle : Les fonctionnalités bonus ne doivent être abordées que si la partie obligatoire est parfaitement fonctionnelle et testée. +Modularité : Gardez les modules bonus séparés et veillez à ce qu'ils ne perturbent pas le fonctionnement de base. + +Arborescence du pojet: + +irc_server/ +│ +├── src/ +│ ├── main.cpp # Point d'entrée du programme. +│ ├── Server.cpp # Implémentation des fonctionnalités du serveur. +│ ├── Client.cpp # Gestion des clients. +│ ├── Channel.cpp # Gestion des canaux. +│ ├── CommandHandler.cpp # Traitement et exécution des commandes IRC. +│ ├── Utilities.cpp # Fonctions utilitaires. +│ ├── FileTransfer.cpp # Gestion du transfert de fichiers (bonus). +│ └── Bot.cpp # Logique du bot IRC (bonus). +│ +├── include/ +│ ├── Server.hpp # Déclarations pour la gestion du serveur. +│ ├── Client.hpp # Déclarations pour la gestion des clients. +│ ├── Channel.hpp # Déclarations pour la gestion des canaux. +│ ├── CommandHandler.hpp # Déclarations pour le traitement des commandes. +│ ├── Utilities.hpp # Déclarations pour les fonctions utilitaires. +│ ├── FileTransfer.hpp # Déclarations pour la gestion du transfert de fichiers (bonus). +│ └── Bot.hpp # Déclarations pour la logique du bot IRC (bonus). +│ +├── build/ +│ └── (fichiers objets et binaires générés lors de la compilation) +│ +├── tests/ +│ ├── server_tests.cpp # Tests unitaires pour le serveur. +│ ├── client_tests.cpp # Tests pour les fonctionnalités client. +│ ├── channel_tests.cpp # Tests pour les canaux. +│ ├── file_transfer_tests.cpp # Tests pour le transfert de fichiers (bonus). +│ └── bot_tests.cpp # Tests pour le bot IRC (bonus). +│ +├── Makefile # Makefile pour compiler le projet. +│ +└── README.md # Instructions de base et documentation.