diff --git a/ft_irc/.vscode/settings.json b/ft_irc/.vscode/settings.json new file mode 100644 index 0000000..c875477 --- /dev/null +++ b/ft_irc/.vscode/settings.json @@ -0,0 +1,52 @@ +{ + "files.associations": { + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "compare": "cpp", + "concepts": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "map": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "random": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "typeinfo": "cpp" + } +} \ No newline at end of file diff --git a/ft_irc/build/Channel.o b/ft_irc/build/Channel.o index 1b17daf..4457dab 100644 Binary files a/ft_irc/build/Channel.o and b/ft_irc/build/Channel.o differ diff --git a/ft_irc/build/Client.o b/ft_irc/build/Client.o index d40aa38..82b2d77 100644 Binary files a/ft_irc/build/Client.o and b/ft_irc/build/Client.o differ diff --git a/ft_irc/build/CommandHandler.o b/ft_irc/build/CommandHandler.o index d867b84..57e7d6a 100644 Binary files a/ft_irc/build/CommandHandler.o and b/ft_irc/build/CommandHandler.o differ diff --git a/ft_irc/build/Server.o b/ft_irc/build/Server.o index b90c263..0baa7a9 100644 Binary files a/ft_irc/build/Server.o and b/ft_irc/build/Server.o differ diff --git a/ft_irc/include/Client.hpp b/ft_irc/include/Client.hpp index 85dc221..b550e0e 100644 --- a/ft_irc/include/Client.hpp +++ b/ft_irc/include/Client.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 14:07:00 by fgras-ca #+# #+# */ -/* Updated: 2024/05/09 14:33:20 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/10 14:10:35 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -17,6 +17,7 @@ #include #include #include +#include class Client { public: @@ -25,12 +26,16 @@ public: void sendMessage(const std::string& message); std::string receiveMessage(); - void setNickname(const std::string& newNickname); // Ajout de la méthode setNickname + void setNickname(const std::string& newNickname); + std::string getNickname() const; // Ajout de la méthode getNickname + int getSocket() const; private: int socket; - std::string nickname; + std::string nickname; // Assurez-vous que cette donnée membre est accessible via getNickname std::string username; }; #endif + + diff --git a/ft_irc/include/Server.hpp b/ft_irc/include/Server.hpp index 2a44f32..5d395d2 100644 --- a/ft_irc/include/Server.hpp +++ b/ft_irc/include/Server.hpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 14:01:12 by fgras-ca #+# #+# */ -/* Updated: 2024/05/09 14:39:02 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/10 14:10:44 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -15,8 +15,6 @@ #include #include -#include "Client.hpp" -#include "CommandHandler.hpp" #include #include #include @@ -24,7 +22,21 @@ #include #include #include +#include +#include "Client.hpp" // Assurez-vous que Client est inclus avant Server +#include "CommandHandler.hpp" + +class Server; // Déclaration anticipée de Server si nécessaire + +// Structure pour passer des données aux threads +struct ClientContext { + Client* client; + Server* server; + CommandHandler* cmdHandler; + + ClientContext(Client* c, Server* s, CommandHandler* ch) : client(c), server(s), cmdHandler(ch) {} +}; class Server { public: Server(int port, const std::string& password); @@ -37,9 +49,11 @@ private: 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 + std::vector threads; // List of threads for client management - void manageClient(Client* client, CommandHandler& cmdHandler); + static void *manageClient(void *clientContext); // Static to be compatible with pthread }; #endif // SERVER_HPP + + diff --git a/ft_irc/ircserv b/ft_irc/ircserv index ae7b473..e37856d 100755 Binary files a/ft_irc/ircserv and b/ft_irc/ircserv differ diff --git a/ft_irc/src/Client.cpp b/ft_irc/src/Client.cpp index 3f475da..22355da 100644 --- a/ft_irc/src/Client.cpp +++ b/ft_irc/src/Client.cpp @@ -6,11 +6,13 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 14:07:27 by fgras-ca #+# #+# */ -/* Updated: 2024/05/09 14:33:11 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/10 13:33:20 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ #include "Client.hpp" +#include +#include Client::Client(int socket, const std::string& nickname, const std::string& username) : socket(socket), nickname(nickname), username(username) {} @@ -20,19 +22,38 @@ Client::~Client() { } void Client::sendMessage(const std::string& message) { + std::cout << "Sending message: " << message << std::endl; send(socket, message.c_str(), message.size(), 0); } std::string Client::receiveMessage() { char buffer[1024]; std::memset(buffer, 0, sizeof(buffer)); - int len = recv(socket, buffer, sizeof(buffer), 0); + int len = recv(socket, buffer, sizeof(buffer) - 1, 0); if (len > 0) { - return std::string(buffer, len); + buffer[len] = '\0'; // Ensure null termination + std::string received(buffer); + // Erase newline and carriage return characters + size_t pos; + while ((pos = received.find_first_of("\r\n")) != std::string::npos) { + received.erase(pos, 1); + } + std::cout << "Received message: [" << received << "]" << std::endl; + return received; } return ""; } + void Client::setNickname(const std::string& newNickname) { nickname = newNickname; } + +std::string Client::getNickname() const { + return nickname; +} + +int Client::getSocket() const { + return socket; +} + diff --git a/ft_irc/src/CommandHandler.cpp b/ft_irc/src/CommandHandler.cpp index a605ea9..0ad09b2 100644 --- a/ft_irc/src/CommandHandler.cpp +++ b/ft_irc/src/CommandHandler.cpp @@ -6,7 +6,7 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 14:19:15 by fgras-ca #+# #+# */ -/* Updated: 2024/05/09 14:33:32 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/10 12:33:00 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ @@ -62,9 +62,11 @@ void CommandHandler::handleNick(const std::string& command, Client* client) { std::vector tokens = split(command, ' '); if (tokens.size() > 1) { client->setNickname(tokens[1]); + std::cout << "Nickname set to: " << tokens[1] << std::endl; // Afficher et enregistrer l'action } } + void CommandHandler::handlePrivmsg(const std::string& command, Client* client) { std::vector tokens = split(command, ' '); if (tokens.size() > 2) { diff --git a/ft_irc/src/Server.cpp b/ft_irc/src/Server.cpp index 56780e2..f487f5e 100644 --- a/ft_irc/src/Server.cpp +++ b/ft_irc/src/Server.cpp @@ -6,90 +6,115 @@ /* By: fgras-ca +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2024/05/09 14:01:34 by fgras-ca #+# #+# */ -/* Updated: 2024/05/09 14:48:31 by fgras-ca ### ########.fr */ +/* Updated: 2024/05/10 14:13:02 by fgras-ca ### ########.fr */ /* */ /* ************************************************************************** */ +// Server.cpp #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; + for (size_t i = 0; i < threads.size(); ++i) { + if (threads[i]) pthread_join(threads[i], NULL); } + close(listener); } 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 + if (listen(listener, 10) == -1) { std::cerr << "Error listening: " << strerror(errno) << std::endl; close(listener); return false; } std::cout << "Server initialized and listening on port " << port << std::endl; + running = true; return true; } void Server::run() { - running = true; - struct sockaddr_in client_addr; - socklen_t client_len = sizeof(client_addr); - CommandHandler cmdHandler; + if (!running) { + std::cerr << "Server not initialized or already running." << std::endl; + return; + } + CommandHandler cmdHandler; while (running) { + struct sockaddr_in client_addr; + socklen_t client_len = sizeof(client_addr); 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); - } + Client* newClient = new Client(client_sock, "DefaultNickname", "DefaultUsername"); + ClientContext* context = new ClientContext(newClient, this, &cmdHandler); + pthread_t thread; + pthread_create(&thread, NULL, &Server::manageClient, context); + pthread_detach(thread); + threads.push_back(thread); } } -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); +void* Server::manageClient(void *clientContext) { + ClientContext* ctx = static_cast(clientContext); + Client* client = ctx->client; + Server* server = ctx->server; + + client->sendMessage("Welcome to the IRC Server!\n"); + client->sendMessage("Password required:\n"); + + std::string passwordInput = client->receiveMessage(); + std::cout << "Received password: [" << passwordInput << "]" << std::endl; + + if (passwordInput != server->password) { + client->sendMessage("Incorrect password.\n"); + std::cout << "Password mismatch." << std::endl; + close(client->getSocket()); + delete client; + delete ctx; + return NULL; } - delete client; // Cleanup when client disconnects + + client->sendMessage("Password correct.\n"); + + std::string command; + while ((command = client->receiveMessage()) != "") { + ctx->cmdHandler->handleCommand(command, client); + if (command == "QUIT") break; + } + + close(client->getSocket()); + delete client; + delete ctx; + return NULL; } + + + + + + + + diff --git a/notessujet b/notessujet index a68890c..019fe59 100644 --- a/notessujet +++ b/notessujet @@ -317,3 +317,5 @@ Scalabilité : Pensez à la scalabilité de votre serveur avec ces nouvelles fon 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. + +Dans le cadre de notre projet nous utiliserons hexcat comme reference de client irc.